RFC: Extending ASTMatchers to Support C++20 Concepts

Summary

This proposal describes the extension of the existing ASTMatchers interface to include C++20 concepts. This would allow users of the ASTMatchers interface to match against C++20 concepts, as they can already do with other fundamental C++ constructs such as structs, functions, etc.

Motivation

We are part of a team that is developing the hdoc documentation tool for C++, which is currently missing support for C++20 concepts. Our tool is built on the ASTMatchers interface, which does not support matching ConceptDecls. Consequently, we are unable to index these decls and present them to users as part of the documentation that hdoc generates. We would like to contribute support for C++20 concepts to Clang as part of our work in adding this feature to hdoc. Prior to beginning such an effort, we would like to solicit comments from the community.

Implementation

Adding support for ConceptDecls to ASTMatchers would require adding a new Matcher to the public interface, and an implementation of it which would derive from the existing VariadicDynCaseAllOfMatcher. The diff for the core functionality of this PR would look something like this:

diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index dfea432c16ad..0c2490484e1b 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -440,6 +440,16 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, RecordDecl> recordDecl;
 extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl>
     cxxRecordDecl;

+/// Matches C++ concept declarations.
+///
+/// Example matches \c C
+/// \code
+///   template<class T>
+///   concept C = true;
+/// \endcode
+extern const internal::VariadicDynCastAllOfMatcher<Decl, ConceptDecl>
+    conceptDecl;
+
 /// Matches C++ class template declarations.
 ///
 /// Example matches \c Z

diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index f9a1a59401ac..f0aa98e97d3d 100644
--- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -743,6 +743,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl>
     namespaceAliasDecl;
 const internal::VariadicDynCastAllOfMatcher<Decl, RecordDecl> recordDecl;
 const internal::VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl> cxxRecordDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, ConceptDecl> conceptDecl;
 const internal::VariadicDynCastAllOfMatcher<Decl, ClassTemplateDecl>
     classTemplateDecl;
 const internal::VariadicDynCastAllOfMatcher<Decl,

Additionally, test cases would need to be added to ensure that the matcher works as expected and would be a part of any PR implementing this proposal.

This implementation would likely satisfy hdoc’s needs for C++20 concepts in Clang. This would allow us to find out which concepts are present in a codebase, and then use the resulting ConceptDecls to probe how each concept is constrained. The constraints would then be catalogued and presented to the user in a friendly way to help document the code for others.

Comments and suggestions are welcome.

2 Likes

Thank you for this! Our support for concepts in Clang is still under active development, so I’d be wary about adding too many AST matchers around concepts at the moment because the AST is still in flux. However, it sounds like you only want to add the matcher for the concept declaration itself and that sounds very reasonable to me. So I support this RFC (and it’s a small enough change, I think you’re fine to consider the RFC accepted and start upstreaming your implementation if you’d like).