feat: support macros - #1192
Conversation
✨ Highlights
🧾 Changes by Scope
🔝 Top Files
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #1192 +/- ##
========================================
Coverage 83.16% 83.16%
========================================
Files 35 35
Lines 3660 3660
Branches 844 844
========================================
Hits 3044 3044
Misses 409 409
Partials 207 207
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
An automated preview of the documentation is available at https://1192.mrdocs.prtest2.cppalliance.org/index.html If more commits are pushed to the pull request, the docs will rebuild at the same URL. 2026-07-29 03:09:00 UTC |
c1ce891 to
a42ad72
Compare
|
Thanks for exploring this. This is a complex issue.
Interesting. I thought it would be easier to have a preprocessor step just for macros.
This seems extremely problematic because the counterexamples where it doesn't work would be kind of obvious. Clang doesn't even attach comments to anything if there's not close to a symbol, which is probably the case when there's a macro. My intuition is we can't really implement this feature unless clang wants to attach comments to macros or we implement our own parser (which we also intend to).
How do these compare to doxygen? Shouldn't we have some special options for macros? I'm not sure. I assume macros are somewhat special in terms of what's typically hidden or shown, but I haven't thought too much about it. I think @mizvekov would probably be more qualified to review this issue and PR. |
a42ad72 to
32e9ccf
Compare
Hmm... I'm listening for
Why? The current condition for accepting a preceding comment is that it is separated from the macro definition by blank lines only (and it is a doc-comment). We could tighten that to "no lines at all between the comment and the macro definition"; or maybe we can accept at most one line that is blank.
I surveyed Doxygen's options. They are:
Would you like to add any of these to MrDocs? |
Oh... OK. That's good. I had only made the comment because your previous comment only said by "source location", which implied there could be content between the macro and the source location. But what you mentioned sounds great.
No. Great survey. Thanks. I think my original comment was more specific about filtering macros. But that’s great. If there are no specific options to filter macros by name, let's just go with what we have. Sounds great. One more question: if clang doesn't attach comments to macros like it does to the Decls, how do we find these comments? Do we look for comments attached to something else that should be attached to macros and then move them to the macros? I don't really understand it yet. |
|
Good question. Clang's |
|
FYI the need for this approach will soon be made obsolete by llvm/llvm-project#198452 |
|
@mizvekov: Thanks for the heads-up! @alandefreitas: I think we can use the current approach for the moment being, and update it when the upstream patch lands and we switch to a new Clang version. |
32e9ccf to
81953ee
Compare
I think the current approach could be reasonable. But I also think if llvm/llvm-project#198452 gets merged in two weeks or so, using the next version will be easier and clearer. We won’t notice the difference; we have about 10 PRs in line. |
Yes, if we also plan to switch to a new Clang version as soon as it is released. |
It's more like a commit than a version, but yes. It'd be the same major. It's about time to upgrade anyway. |
|
@alandefreitas: The patch has been merged upstream. |
🚀🔥 |
|
How's the situation with LLVM going so far? |
The new pin includes llvm/llvm-project#198452, which attaches documentation comments to macro definitions. That is the prerequisite for reading them from Clang directly instead of scanning the source, as we were initially doing in PR cppalliance#1192. The pin was about six months behind, so this also adapts MrDocs to the Clang API changes across that range: - USRGeneration.h moved from clang/Index to clang/UnifiedSymbolResolution; the `clang::index` namespace and signatures are unchanged. - `clang::DiagnosticConsumer::finish()` was removed, so the collecting diagnostic consumer relies on the forwarded `EndSourceFile()` instead. - The driver option table moved to clang/Options/Options.h, with its enumerators now in `clang::options` and `getDriverOptTable()` in `clang`. - `cl::getRegisteredOptions()` now returns a `DenseMap`, so its entries expose `.second` instead of `getValue()`. - `SubstituteConstraintExpressionWithoutSatisfaction` was re-synced with Clang's current implementation. `getRawCommentForDeclNoCache`, the old per-declaration comment lookup, is no longer public. `getDocumentation` now uses the public `getRawCommentForAnyRedecl`, and a new `ASTVisitor` pass (`attachComments`) attaches a comment to every declaration up front via `ASTContext::attachCommentsToJustParsedDecls`, so that lookup returns a declaration's own comment instead of collapsing its redeclaration chain to a single comment. Parsing the newer libc++ also needs a new vcruntime_new.h stub and C++ guards so stdbool.h, stdalign.h, and threads.h stop redefining `bool`, `alignas`, and `thread_local`, which are keywords, not macros, in C++. The regenerated goldens reflect two effects and are otherwise unchanged: - `getRawCommentForAnyRedecl` follows the redeclaration chain, which the old lookup did not, so a declaration with no comment of its own now resolves to a documented redeclaration's comment. This adds `<documented>` markers on redeclaration locations (merge-params, merge-tparams, friend-fn-*, no-extract-all, class-template-array-spec), gives inherited members their base's doc comment (template-base), and shows an operator's written brief in place of a synthesized one (inherited-members-specialization). Declarations that each carry their own distinct comment keep it, thanks to the up-front attach pass. - Clang's output drifted over the six months: constrained templates and destructors get different symbol IDs because USR generation changed, though their structure is identical (requires-clause, dtor-overloads), and a few declaration locations shifted by a line or column (auto, param-types, function-template).
The new pin includes llvm/llvm-project#198452, which attaches documentation comments to macro definitions. That is the prerequisite for reading them from Clang directly instead of scanning the source, as we were initially doing in PR cppalliance#1192. The pin was about six months behind, so this also adapts MrDocs to the Clang API changes across that range: - USRGeneration.h moved from clang/Index to clang/UnifiedSymbolResolution; the `clang::index` namespace and signatures are unchanged. - `clang::DiagnosticConsumer::finish()` was removed, so the collecting diagnostic consumer relies on the forwarded `EndSourceFile()` instead. - The driver option table moved to clang/Options/Options.h, with its enumerators now in `clang::options` and `getDriverOptTable()` in `clang`. - `cl::getRegisteredOptions()` now returns a `DenseMap`, so its entries expose `.second` instead of `getValue()`. - `SubstituteConstraintExpressionWithoutSatisfaction` was re-synced with Clang's current implementation. `getRawCommentForDeclNoCache`, the per-declaration comment lookup `getDocumentation` relied on, is no longer public. Its only public replacement, `getRawCommentForAnyRedecl`, follows the redeclaration chain and so cannot return a single declaration's own comment. `getDocumentation` keeps the per-declaration behavior by porting Clang's declaration-path comment search (`getLocsForCommentSearch` and `getRawCommentNoCacheImpl`) as file-local helpers. Parsing the newer libc++ also needs a new vcruntime_new.h stub and C++ guards so stdbool.h, stdalign.h, and threads.h stop redefining `bool`, `alignas`, and `thread_local`, which are keywords, not macros, in C++. The LLVM commit hash also feeds the CI cache key, so ci-matrix.yml and the test_cache_keys.py unit test that mirrors it are bumped to match; otherwise CI restores the previous libc++ install and builds the new one over it. The regenerated goldens change only because Clang's output drifted over the six months: constrained templates and destructors get different symbol IDs from USR generation, though their structure is identical (requires-clause, dtor-overloads), and a few declaration locations shifted by a line or column (auto, param-types, function-template).
The new pin includes llvm/llvm-project#198452, which attaches documentation comments to macro definitions. That is the prerequisite for reading them from Clang directly instead of scanning the source, as we were initially doing in PR cppalliance#1192. The pin was about six months behind, so this also adapts MrDocs to the Clang API changes across that range: - USRGeneration.h moved from clang/Index to clang/UnifiedSymbolResolution; the `clang::index` namespace and signatures are unchanged. - `clang::DiagnosticConsumer::finish()` was removed, so the collecting diagnostic consumer relies on the forwarded `EndSourceFile()` instead. - The driver option table moved to clang/Options/Options.h, with its enumerators now in `clang::options` and `getDriverOptTable()` in `clang`. - `cl::getRegisteredOptions()` now returns a `DenseMap`, so its entries expose `.second` instead of `getValue()`. - `SubstituteConstraintExpressionWithoutSatisfaction` was re-synced with Clang's current implementation. `getRawCommentForDeclNoCache`, the per-declaration comment lookup `getDocumentation` relied on, is no longer public. Its only public replacement, `getRawCommentForAnyRedecl`, follows the redeclaration chain and so cannot return a single declaration's own comment. `getDocumentation` keeps the per-declaration behavior by porting Clang's declaration-path comment search (`getLocsForCommentSearch` and `getRawCommentNoCacheImpl`) as file-local helpers. Parsing the newer libc++ also needs a new vcruntime_new.h stub and C++ guards so stdbool.h, stdalign.h, and threads.h stop redefining `bool`, `alignas`, and `thread_local`, which are keywords, not macros, in C++. The regenerated goldens change only because Clang's output drifted over the six months: constrained templates and destructors get different symbol IDs from USR generation, though their structure is identical (requires-clause, dtor-overloads), and a few declaration locations changed.
The new pin includes llvm/llvm-project#198452, which attaches documentation comments to macro definitions. That is the prerequisite for reading them from Clang directly instead of scanning the source, as we were initially doing in PR cppalliance#1192. The pin was about six months behind, so this also adapts MrDocs to the Clang API changes across that range: - USRGeneration.h moved from clang/Index to clang/UnifiedSymbolResolution; the `clang::index` namespace and signatures are unchanged. - `clang::DiagnosticConsumer::finish()` was removed, so the collecting diagnostic consumer relies on the forwarded `EndSourceFile()` instead. - The driver option table moved to clang/Options/Options.h, with its enumerators now in `clang::options` and `getDriverOptTable()` in `clang`. - `cl::getRegisteredOptions()` now returns a `DenseMap`, so its entries expose `.second` instead of `getValue()`. - `SubstituteConstraintExpressionWithoutSatisfaction` was re-synced with Clang's current implementation. Parsing the newer libc++ also needs a new vcruntime_new.h stub and C++ guards so stdbool.h, stdalign.h, and threads.h stop redefining `bool`, `alignas`, and `thread_local`, which are keywords, not macros, in C++. The regenerated goldens change only because Clang's output drifted over the six months: constrained templates and destructors get different symbol IDs from USR generation, though their structure is identical (requires-clause, dtor-overloads), and a few declaration locations changed.
The new pin includes llvm/llvm-project#198452, which attaches documentation comments to macro definitions. That is the prerequisite for reading them from Clang directly instead of scanning the source, as we were initially doing in PR cppalliance#1192. The pin was about six months behind, so this also adapts MrDocs to the Clang API changes across that range: - USRGeneration.h moved from clang/Index to clang/UnifiedSymbolResolution; the `clang::index` namespace and signatures are unchanged. - `clang::DiagnosticConsumer::finish()` was removed, so the collecting diagnostic consumer relies on the forwarded `EndSourceFile()` instead. - The driver option table moved to clang/Options/Options.h, with its enumerators now in `clang::options` and `getDriverOptTable()` in `clang`. - `cl::getRegisteredOptions()` now returns a `DenseMap`, so its entries expose `.second` instead of `getValue()`. - `SubstituteConstraintExpressionWithoutSatisfaction` was re-synced with Clang's current implementation. Parsing the newer libc++ also needs a new vcruntime_new.h stub, since its align_val_t.h now includes vcruntime_new.h under the vcruntime ABI. The regenerated goldens change only because Clang's output drifted over the six months: constrained templates and destructors get different symbol IDs from USR generation, though their structure is identical (requires-clause, dtor-overloads), and a few declaration locations changed.
The new pin includes llvm/llvm-project#198452, which attaches documentation comments to macro definitions. That is the prerequisite for reading them from Clang directly instead of scanning the source, as we were initially doing in PR cppalliance#1192. The pin was about six months behind, so this also adapts MrDocs to the Clang API changes across that range: - USRGeneration.h moved from clang/Index to clang/UnifiedSymbolResolution; the `clang::index` namespace and signatures are unchanged. - `clang::DiagnosticConsumer::finish()` was removed, so the collecting diagnostic consumer relies on the forwarded `EndSourceFile()` instead. - The driver option table moved to clang/Options/Options.h, with its enumerators now in `clang::options` and `getDriverOptTable()` in `clang`. - `cl::getRegisteredOptions()` now returns a `DenseMap`, so its entries expose `.second` instead of `getValue()`. - `SubstituteConstraintExpressionWithoutSatisfaction` was re-synced with Clang's current implementation. Parsing the newer libc++ also needs a new vcruntime_new.h stub (its align_val_t.h now includes it under the vcruntime ABI) and C++ guards so stdbool.h, stdalign.h, and threads.h stop redefining some C++ keywords as macros. The regenerated goldens change only because Clang's output drifted over the six months: constrained templates and destructors get different symbol IDs from USR generation, though their structure is identical (requires-clause, dtor-overloads), and a few declaration locations changed.
The new pin includes llvm/llvm-project#198452, which attaches documentation comments to macro definitions. That is the prerequisite for reading them from Clang directly instead of scanning the source, as we were initially doing in PR cppalliance#1192. The pin was about six months behind, so this also adapts MrDocs to the Clang API changes across that range: - USRGeneration.h moved from clang/Index to clang/UnifiedSymbolResolution; the `clang::index` namespace and signatures are unchanged. - `clang::DiagnosticConsumer::finish()` was removed, so the collecting diagnostic consumer relies on the forwarded `EndSourceFile()` instead. - The driver option table moved to clang/Options/Options.h, with its enumerators now in `clang::options` and `getDriverOptTable()` in `clang`. - `cl::getRegisteredOptions()` now returns a `DenseMap`, so its entries expose `.second` instead of `getValue()`. - `SubstituteConstraintExpressionWithoutSatisfaction` was re-synced with Clang's current implementation. Parsing the newer libc++ also needs a new vcruntime_new.h stub (its align_val_t.h now includes it under the vcruntime ABI) and C++ guards so stdbool.h, stdalign.h, and threads.h stop redefining some C++ keywords as macros. The regenerated goldens change only because Clang's output drifted over the six months: constrained templates and destructors get different symbol IDs from USR generation, though their structure is identical (requires-clause, dtor-overloads), and a few declaration locations changed.
The new pin includes llvm/llvm-project#198452, which attaches documentation comments to macro definitions. That is the prerequisite for reading them from Clang directly instead of scanning the source, as we were initially doing in PR cppalliance#1192. The pin was about six months behind, so this also adapts MrDocs to the Clang API changes across that range: - USRGeneration.h moved from clang/Index/ to clang/UnifiedSymbolResolution/; the `clang::index` namespace and signatures are unchanged. - `clang::DiagnosticConsumer::finish()` was removed, so the collecting diagnostic consumer relies on the forwarded `EndSourceFile()` instead. - The driver option table moved to clang/Options/Options.h, with its enumerators now in `clang::options` and `getDriverOptTable()` in `clang`. - `cl::getRegisteredOptions()` now returns a `DenseMap`, so its entries expose `.second` instead of `getValue()`. - `SubstituteConstraintExpressionWithoutSatisfaction` was re-synced with Clang's current implementation. Parsing the newer libc++ also needs a new vcruntime_new.h stub (its align_val_t.h now includes it under the vcruntime ABI) and C++ guards so stdbool.h, stdalign.h, and threads.h stop redefining some C++ keywords as macros. The regenerated goldens change only because Clang's output drifted over the six months: constrained templates and destructors get different symbol IDs from USR generation, though their structure is identical (requires-clause, dtor-overloads), and a few declaration locations changed.
95096eb to
3970523
Compare
This adds support for preprocessing macros: `#define` directives are
captured via a `clang::PPCallbacks` subclass and exposed as
`MacroSymbol` instances at the corpus root (macros aren't in any C++
scope, so they sit alongside the global namespace rather than under it).
Include guard macros are recognized and skipped.
Filters apply to macros, too:
- `extract-all`: when off, undocumented macros are dropped.
- `exclude-symbols`, `include-symbols`, `implementation-defined`,
`see-below`: matched against the macro name.
- File-pattern filters: matched against the directive's source location.
New output pages: multipage mode now produces `macros.{ext}` at the
output root, listing every macro with a link to its per-symbol page. The
global-namespace page gains a "See also: Macros" navigation hint
(multipage-only) so the new page is discoverable.
Macro `@param` blocks are validated.
Closes cppalliance#1127.
3970523 to
3801993
Compare
This adds support for preprocessing macros:
#definedirectives are captured via aclang::PPCallbackssubclass and exposed asMacroSymbolinstances at the corpus root (since macros aren't in any C++ scope). Include guard macros are recognized and skipped.Filters apply to macros, too:
extract-all: when off, undocumented macros are dropped.exclude-symbols,include-symbols,implementation-defined,see-below: matched against the macro name.Multipage mode produces a
macros.{ext}page at the output root listing every macro with a link to its per-symbol page, and the global-namespace page gains a "See also: Macros" navigation hint (multipage-only) so the new page is discoverable. Macro@paramblocks are validated.Changes
clang::PPCallbackssubclass, exposed as a corpus-rootMacroSymbol. The Handlebars generators render the macro synopsis, the single-page section heading, the multipagemacrospage, and the "See also: Macros" link from templates.mrdocs.rncgains a<macro>element, a sibling of<namespace>, with<source>carrying the verbatim definition.<macro>element, so downstream tooling that enumerates top-level elements should add a clause for it.Testing
Covered by the golden tests above. No CI workflow changes are needed.
Documentation
No user-facing documentation in this PR. A reference page describing what is captured, how the filters apply, and the new
macrospage is worth a follow-up so the feature is discoverable from the docs rather than the schema.Closes #1127.