Tyker updated this revision to Diff 205559. Tyker marked 3 inline comments as done. Tyker added a comment.
fixed requested changes. > Are you getting errors from running it, or just incorrect output? the issue happens to me even on master so i suppose the input is correct. here is the error report: [tyker@tyker tools]$ ./dump_ast_matchers.py *** Unparsable: " #ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H #define LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H " *** *** Unparsable: " #include "clang/AST/ASTContext.h" #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/OpenMPClause.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtOpenMP.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/ASTMatchers/ASTMatchersInternal.h" #include "clang/ASTMatchers/ASTMatchersMacros.h" #include "clang/Basic/AttrKinds.h" #include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TypeTraits.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Regex.h" #include <cassert> #include <cstddef> #include <iterator> #include <limits> #include <string> #include <utility> #include <vector> " *** *** Unparsable: " namespace clang {" *** *** Unparsable: " using DeclarationMatcher = internal::Matcher<Decl>;" *** *** Unparsable: " using StatementMatcher = internal::Matcher<Stmt>;" *** *** Unparsable: " using TypeMatcher = internal::Matcher<QualType>;" *** *** Unparsable: " using TypeLocMatcher = internal::Matcher<TypeLoc>;" *** *** Unparsable: " using NestedNameSpecifierMatcher = internal::Matcher<NestedNameSpecifier>;" *** *** Unparsable: " using NestedNameSpecifierLocMatcher = internal::Matcher<NestedNameSpecifierLoc>;" *** *** Unparsable: " using CXXCtorInitializerMatcher = internal::Matcher<CXXCtorInitializer>;" *** Probing https://clang.llvm.org/doxygen/classclang_1_1Decl.html... after this the script keep probing with no issues. i tested using python 2.7 and python 3.7 the same error occurs CHANGES SINCE LAST ACTION https://reviews.llvm.org/D61552/new/ https://reviews.llvm.org/D61552 Files: clang/include/clang/AST/DeclCXX.h clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -1735,6 +1735,56 @@ llvm::make_unique<VerifyIdIsBoundTo<CaseStmt>>("x", 3))); } +TEST(Declaration, HasExplicitSpecifier) { + EXPECT_TRUE(matchesConditionally( + "void f();", functionDecl(hasExplicitSpecifier(constantExpr())), false, + "-std=c++2a")); + EXPECT_TRUE(matchesConditionally( + "template<bool b> struct S { explicit operator int(); };", + cxxConversionDecl(hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))), + false, "-std=c++2a")); + EXPECT_TRUE(matchesConditionally( + "template<bool b> struct S { explicit(b) operator int(); };", + cxxConversionDecl(hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))), + false, "-std=c++2a")); + EXPECT_TRUE(matchesConditionally( + "struct S { explicit(true) operator int(); };", + cxxConversionDecl(hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))), + true, "-std=c++2a")); + EXPECT_TRUE(matchesConditionally( + "struct S { explicit(false) operator int(); };", + cxxConversionDecl(hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))), + true, "-std=c++2a")); + EXPECT_TRUE(matchesConditionally( + "template<bool b> struct S { explicit(b) S(int); };", + cxxConstructorDecl(hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))), + false, "-std=c++2a")); + EXPECT_TRUE(matchesConditionally( + "struct S { explicit(true) S(int); };", + cxxConstructorDecl(hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))), + true, "-std=c++2a")); + EXPECT_TRUE(matchesConditionally( + "struct S { explicit(false) S(int); };", + cxxConstructorDecl(hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))), + true, "-std=c++2a")); + EXPECT_TRUE(matchesConditionally( + "template<typename T> struct S { S(int); };" + "template<bool b = true> explicit(b) S(int) -> S<int>;", + cxxDeductionGuideDecl( + hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))), + false, "-std=c++2a")); + EXPECT_TRUE(matchesConditionally("template<typename T> struct S { S(int); };" + "explicit(true) S(int) -> S<int>;", + cxxDeductionGuideDecl(hasExplicitSpecifier( + constantExpr(has(cxxBoolLiteral())))), + true, "-std=c++2a")); + EXPECT_TRUE(matchesConditionally("template<typename T> struct S { S(int); };" + "explicit(false) S(int) -> S<int>;", + cxxDeductionGuideDecl(hasExplicitSpecifier( + constantExpr(has(cxxBoolLiteral())))), + true, "-std=c++2a")); +} + TEST(ForEachConstructorInitializer, MatchesInitializers) { EXPECT_TRUE(matches( "struct X { X() : i(42), j(42) {} int i, j; };", Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -878,6 +878,15 @@ cxxConversionDecl(isExplicit()))); EXPECT_TRUE(notMatches("struct S { operator int(); };", cxxConversionDecl(isExplicit()))); + EXPECT_TRUE(matchesConditionally( + "template<bool b> struct S { explicit(b) operator int(); };", + cxxConversionDecl(isExplicit()), false, "-std=c++2a")); + EXPECT_TRUE(matchesConditionally( + "struct S { explicit(true) operator int(); };", + cxxConversionDecl(isExplicit()), true, "-std=c++2a")); + EXPECT_TRUE(matchesConditionally( + "struct S { explicit(false) operator int(); };", + cxxConversionDecl(isExplicit()), false, "-std=c++2a")); } TEST(Matcher, ArgumentCount) { @@ -1197,6 +1206,38 @@ cxxConstructorDecl(isExplicit()))); EXPECT_TRUE(notMatches("struct S { S(int); };", cxxConstructorDecl(isExplicit()))); + EXPECT_TRUE(matchesConditionally( + "template<bool b> struct S { explicit(b) S(int);};", + cxxConstructorDecl(isExplicit()), false, "-std=c++2a")); + EXPECT_TRUE(matchesConditionally("struct S { explicit(true) S(int);};", + cxxConstructorDecl(isExplicit()), true, + "-std=c++2a")); + EXPECT_TRUE(matchesConditionally("struct S { explicit(false) S(int);};", + cxxConstructorDecl(isExplicit()), false, + "-std=c++2a")); +} + +TEST(DeductionGuideDeclaration, IsExplicit) { + EXPECT_TRUE(matchesConditionally("template<typename T> struct S { S(int);};" + "S(int) -> S<int>;", + cxxDeductionGuideDecl(isExplicit()), false, + "-std=c++17")); + EXPECT_TRUE(matchesConditionally("template<typename T> struct S { S(int);};" + "explicit S(int) -> S<int>;", + cxxDeductionGuideDecl(isExplicit()), true, + "-std=c++17")); + EXPECT_TRUE(matchesConditionally("template<typename T> struct S { S(int);};" + "explicit(true) S(int) -> S<int>;", + cxxDeductionGuideDecl(isExplicit()), true, + "-std=c++2a")); + EXPECT_TRUE(matchesConditionally("template<typename T> struct S { S(int);};" + "explicit(false) S(int) -> S<int>;", + cxxDeductionGuideDecl(isExplicit()), false, + "-std=c++2a")); + EXPECT_TRUE(matchesConditionally( + "template<typename T> struct S { S(int);};" + "template<bool b = true> explicit(b) S(int) -> S<int>;", + cxxDeductionGuideDecl(isExplicit()), false, "-std=c++2a")); } TEST(ConstructorDeclaration, Kinds) { Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -169,6 +169,7 @@ REGISTER_MATCHER(cxxConstructorDecl); REGISTER_MATCHER(cxxConversionDecl); REGISTER_MATCHER(cxxCtorInitializer); + REGISTER_MATCHER(cxxDeductionGuideDecl); REGISTER_MATCHER(cxxDefaultArgExpr); REGISTER_MATCHER(cxxDeleteExpr); REGISTER_MATCHER(cxxDependentScopeMemberExpr); @@ -267,6 +268,7 @@ REGISTER_MATCHER(hasEitherOperand); REGISTER_MATCHER(hasElementType); REGISTER_MATCHER(hasElse); + REGISTER_MATCHER(hasExplicitSpecifier); REGISTER_MATCHER(hasExternalFormalLinkage); REGISTER_MATCHER(hasFalseExpression); REGISTER_MATCHER(hasGlobalStorage); Index: clang/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchers.h +++ clang/include/clang/ASTMatchers/ASTMatchers.h @@ -1138,6 +1138,17 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl> cxxConversionDecl; +/// Matches user-defined and implicitly generated deduction guide. +/// +/// Example matches the deduction guide. +/// \code +/// template<typename T> +/// class X { X(int) }; +/// X(int) -> X<int>; +/// \endcode +extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXDeductionGuideDecl> + cxxDeductionGuideDecl; + /// Matches variable declarations. /// /// Note: this does not match declarations of member variables, which are @@ -6154,29 +6165,66 @@ return Node.isDelegatingConstructor(); } -/// Matches constructor and conversion declarations that are marked with -/// the explicit keyword. +/// Matches constructor, conversion function, and deduction guide declarations +/// that have an explicit specifier if this explicit specifier is resolved to +/// true. /// /// Given /// \code +/// template<bool b> /// struct S { /// S(int); // #1 /// explicit S(double); // #2 /// operator int(); // #3 /// explicit operator bool(); // #4 +/// explicit(false) S(bool) // # 7 +/// explicit(true) S(char) // # 8 +/// explicit(b) S(S) // # 9 /// }; +/// S(int) -> S<true> // #5 +/// explicit S(double) -> S<false> // #6 /// \endcode /// cxxConstructorDecl(isExplicit()) will match #2, but not #1. /// cxxConversionDecl(isExplicit()) will match #4, but not #3. -AST_POLYMORPHIC_MATCHER(isExplicit, - AST_POLYMORPHIC_SUPPORTED_TYPES(CXXConstructorDecl, - CXXConversionDecl)) { - // FIXME : it's not clear whether this should match a dependent - // explicit(....). this matcher should also be able to match - // CXXDeductionGuideDecl with explicit specifier. +/// cxxDeductionGuideDecl(isExplicit()) will match #6, but not #5. +/// cxxConstructorDecl(isExplicit()) will match #8, but not #7 or #9. +AST_POLYMORPHIC_MATCHER(isExplicit, AST_POLYMORPHIC_SUPPORTED_TYPES( + CXXConstructorDecl, CXXConversionDecl, + CXXDeductionGuideDecl)) { return Node.isExplicit(); } +/// Matches the expression in an explicit specifier if present in the given +/// declaration. +/// +/// Given +/// \code +/// template<bool b> +/// struct S { +/// S(int); // #1 +/// explicit S(double); // #2 +/// operator int(); // #3 +/// explicit operator bool(); // #4 +/// explicit(false) S(bool) // # 7 +/// explicit(true) S(char) // # 8 +/// explicit(b) S(S) // # 9 +/// }; +/// S(int) -> S<true> // #5 +/// explicit S(double) -> S<false> // #6 +/// \endcode +/// cxxConstructorDecl(hasExplicitSpecifier(constantExpr())) will match #7, #8 and +/// #9, but not #1 or #2. cxxConversionDecl(hasExplicitSpecifier(constantExpr())) +/// will not match #3 or #4. +/// cxxDeductionGuideDecl(hasExplicitSpecifier(constantExpr())) will not match #5 or +/// #6. +AST_MATCHER_P(FunctionDecl, hasExplicitSpecifier, internal::Matcher<Expr>, + InnerMatcher) { + ExplicitSpecifier ES = ExplicitSpecifier::getFromDecl(&Node); + if (!ES.getExpr()) + return false; + return InnerMatcher.matches(*ES.getExpr(), Finder, Builder); +} + /// Matches function and namespace declarations that are marked with /// the inline keyword. /// Index: clang/include/clang/AST/DeclCXX.h =================================================================== --- clang/include/clang/AST/DeclCXX.h +++ clang/include/clang/AST/DeclCXX.h @@ -2033,6 +2033,9 @@ // if the given declaration has no explicit. the returned explicit specifier // is defaulted. .isSpecified() will be false. static ExplicitSpecifier getFromDecl(FunctionDecl *Function); + static const ExplicitSpecifier getFromDecl(const FunctionDecl *Function) { + return getFromDecl(const_cast<FunctionDecl *>(Function)); + } static ExplicitSpecifier Invalid() { return ExplicitSpecifier(nullptr, ExplicitSpecKind::Unresolved); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits