diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index f18e9cf1341696..ddc99020604c94 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -1842,6 +1842,12 @@
Matches expressions that refer to dependent scope declarations. + +Example matches T::v + templateclass X : T { void f() { T::v; } }; +
Matches declaration statements. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 8b984ecaefecaf..2a84a4704f0c21 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -1101,6 +1101,8 @@ AST Matchers - Ensure ``pointee`` matches Objective-C pointer types. +- Add ``dependentScopeDeclRefExpr`` matcher to match expressions that refer to dependent scope declarations. + clang-format ------------ diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 897aa25dc95cc1..22e2546ab81e0a 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -2125,6 +2125,16 @@ extern const internal::VariadicDynCastAllOfMatcherexpr; extern const internal::VariadicDynCastAllOfMatcher declRefExpr; +/// Matches expressions that refer to dependent scope declarations. +/// +/// example matches T::v; +/// \code +/// template class X : T { void f() { T::v; } }; +/// \endcode +extern const internal::VariadicDynCastAllOfMatcher + dependentScopeDeclRefExpr; + /// Matches a reference to an ObjCIvar. /// /// Example: matches "a" in "init" method: diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index bf9dc5f2373f9e..8c744eebbdfb50 100644 --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -924,6 +924,8 @@ const internal::VariadicDynCastAllOfMatcher const internal::VariadicDynCastAllOfMatcher cxxFoldExpr; const internal::VariadicDynCastAllOfMatcher expr; const internal::VariadicDynCastAllOfMatcher declRefExpr; +const internal::VariadicDynCastAllOfMatcher + dependentScopeDeclRefExpr; const internal::VariadicDynCastAllOfMatcher objcIvarRefExpr; const internal::VariadicDynCastAllOfMatcher blockExpr; const internal::VariadicDynCastAllOfMatcher ifStmt; diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index 837633fb2f0601..685d626d2978bf 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -222,6 +222,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(decompositionDecl); REGISTER_MATCHER(declCountIs); REGISTER_MATCHER(declRefExpr); + REGISTER_MATCHER(dependentScopeDeclRefExpr); REGISTER_MATCHER(declStmt); REGISTER_MATCHER(declaratorDecl); REGISTER_MATCHER(decltypeType); diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index f3f314b723dfc6..ec062a5cc953b8 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -3172,9 +3172,6 @@ TEST_P(ImportDecl, ImportFieldOrder) { recordDecl(hasFieldOrder({"b", "a"}))); } -const internal::VariadicDynCastAllOfMatcher - dependentScopeDeclRefExpr; - TEST_P(ImportExpr, DependentScopeDeclRefExpr) { MatchVerifier Verifier; testImport("template struct S { static T foo; };" diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index 9bc287e07224aa..a3baad367a27b1 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -556,6 +556,21 @@ TEST_P(ASTMatchersTest, DeclRefExpr) { Reference)); } +TEST_P(ASTMatchersTest, DependentScopeDeclRefExpr) { + if (!GetParam().isCXX() || GetParam().hasDelayedTemplateParsing()) { + // FIXME: Fix this test to work with delayed template parsing. + return; + } + + EXPECT_TRUE(matches("template class X : T { void f() { T::v; } };", + dependentScopeDeclRefExpr())); + + EXPECT_TRUE( + matches("template struct S { static T Foo; };" + "template void declToImport() { (void)S ::Foo; }", + dependentScopeDeclRefExpr())); +} + TEST_P(ASTMatchersTest, CXXMemberCallExpr) { if (!GetParam().isCXX()) { return; @@ -629,10 +644,8 @@ TEST_P(ASTMatchersTest, MemberExpr_MatchesVariable) { EXPECT_TRUE(matches("template " "class X : T { void f() { this->T::v; } };", cxxDependentScopeMemberExpr())); - // FIXME: Add a matcher for DependentScopeDeclRefExpr. - EXPECT_TRUE( - notMatches("template class X : T { void f() { T::v; } };", - cxxDependentScopeMemberExpr())); + EXPECT_TRUE(matches("template class X : T { void f() { T::v; } };", + dependentScopeDeclRefExpr())); EXPECT_TRUE(matches("template void x() { T t; t.v; }", cxxDependentScopeMemberExpr())); }