Skip to content

Indexing gap: C++ function-like macro with type argument #1071

Description

@WarGloom

Summary

The C++ parser records a parse_partial gap for valid function-like macro invocations when a macro argument is a type token rather than an ordinary expression. This is systematic rather than an isolated source-file problem.

The strongest signal is argument syntax:

First macro argument form Flagged invocations
Built-in type 43 / 45
Pointer type 17 / 17
Named type 1 / 38

In an anonymized scan of a private C++ corpus, 61 invocations of this allocation-macro shape were inside persisted parse_partial ranges across 37 files. Sixty were additional occurrences beyond the initially reported case. No private filenames, paths, identifiers, or source excerpts are included here.

Verified synthetic reproduction

The following code is synthetic and contains no code or identifiers from the affected private corpus:

#include <cstddef>
#include <cstdlib>

#define SYNTH_ALLOC_ARRAY(Type, Count) \
  ((Type*)std::malloc(sizeof(Type) * (Count)))

struct Buffer {
  char* data;
  std::size_t size;
};

void initialize(Buffer& buffer) {
  buffer.data = SYNTH_ALLOC_ARRAY(char, buffer.size);
}

Reproduction steps

  1. Save the snippet as repro.cpp in an otherwise empty directory.
  2. Index the directory in fast mode:
index_repository({"repo_path":"/path/to/synthetic-repro","mode":"fast","name":"synthetic-macro-type-repro","persistence":false})
  1. Query the persisted coverage signal:
index_status({"project":"synthetic-macro-type-repro"})

Actual result

The reproduction was verified against codebase-memory-mcp dev. Indexing succeeds, but coverage reports:

{
  "parse_partial": {
    "files": [
      {
        "path": "repro.cpp",
        "error_ranges": "13-13"
      }
    ],
    "count": 1
  }
}

The flagged line is the otherwise valid macro invocation in initialize.

Expected result

  • parse_partial.count is zero.
  • The surrounding function and assignment remain available in the graph.
  • Function-like macro arguments that are type-token sequences do not need to be interpreted as ordinary C++ expressions before macro expansion.

Likely cause

Without macro-aware handling, the invocation resembles an ordinary function call. In an ordinary call argument list, char is a type keyword and is not a valid expression. Pointer-type arguments introduce an additional * token that is also invalid in that position. Plain named types are lexically identifiers and therefore usually survive the expression grammar, which explains the observed distribution.

The macro expansion itself is valid C++: the type token is used in a cast and in sizeof.

Suggested fix direction

Treat arguments of unexpanded function-like macros as token sequences, or add tolerant recovery for macro invocations in expression positions, rather than requiring each argument to parse as a normal expression. A regression test based on the synthetic snippet should assert that indexing succeeds without a parse_partial entry for repro.cpp.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions