diff options
author | Dmitri Gribenko <gribozavr@gmail.com> | 2019-05-03 12:50:00 +0000 |
---|---|---|
committer | Dmitri Gribenko <gribozavr@gmail.com> | 2019-05-03 12:50:00 +0000 |
commit | 54eb12a115eb4fbdc59b1335d721d0415ca1f7a8 (patch) | |
tree | 6c6d7a7e8db17eb2fd40a6cd4d15abe8e4d3cece | |
parent | 6ef4cf339ce48cf922534c163eaec4bcbf85604f (diff) |
Added an AST matcher for declarations that are in the `std` namespace
Reviewers: alexfh
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D61480
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@359876 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | docs/LibASTMatchersReference.html | 23 | ||||
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchers.h | 23 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 3 | ||||
-rw-r--r-- | lib/ASTMatchers/Dynamic/Registry.cpp | 1 | ||||
-rw-r--r-- | unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp | 51 |
5 files changed, 100 insertions, 1 deletions
diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index f0e965568d..a053bd1bb5 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -2827,6 +2827,29 @@ by the compiler (eg. implicit default/copy constructors). </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('isInStdNamespace0')"><a name="isInStdNamespace0Anchor">isInStdNamespace</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isInStdNamespace0"><pre>Matches declarations in the namespace `std`, but not in nested namespaces. + +Given + class vector {}; + namespace foo { + class vector {}; + namespace std { + class vector {}; + } + } + namespace std { + inline namespace __1 { + class vector {}; // #1 + namespace experimental { + class vector {}; + } + } + } +cxxRecordDecl(hasName("vector"), isInStdNamespace()) will match only #1. +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('isPrivate0')"><a name="isPrivate0Anchor">isPrivate</a></td><td></td></tr> <tr><td colspan="4" class="doc" id="isPrivate0"><pre>Matches private C++ declarations. diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index 661dcbc767..8bd4429f0b 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -6212,6 +6212,29 @@ AST_MATCHER(NamespaceDecl, isAnonymous) { return Node.isAnonymousNamespace(); } +/// Matches declarations in the namespace `std`, but not in nested namespaces. +/// +/// Given +/// \code +/// class vector {}; +/// namespace foo { +/// class vector {}; +/// namespace std { +/// class vector {}; +/// } +/// } +/// namespace std { +/// inline namespace __1 { +/// class vector {}; // #1 +/// namespace experimental { +/// class vector {}; +/// } +/// } +/// } +/// \endcode +/// cxxRecordDecl(hasName("vector"), isInStdNamespace()) will match only #1. +AST_MATCHER(Decl, isInStdNamespace) { return Node.isInStdNamespace(); } + /// If the given case statement does not use the GNU case range /// extension, matches the constant given in the statement. /// diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 5a6d85cd00..f40896da48 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -354,7 +354,8 @@ bool Decl::isInAnonymousNamespace() const { } bool Decl::isInStdNamespace() const { - return getDeclContext()->isStdNamespace(); + const DeclContext *DC = getDeclContext(); + return DC && DC->isStdNamespace(); } TranslationUnitDecl *Decl::getTranslationUnitDecl() { diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp index 37f1a0077a..fedb9dd2ab 100644 --- a/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/lib/ASTMatchers/Dynamic/Registry.cpp @@ -366,6 +366,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(isExternC); REGISTER_MATCHER(isFinal); REGISTER_MATCHER(isImplicit); + REGISTER_MATCHER(isInStdNamespace); REGISTER_MATCHER(isInTemplateInstantiation); REGISTER_MATCHER(isInline); REGISTER_MATCHER(isInstanceMessage); diff --git a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp index 012ca117c2..01b168da2b 100644 --- a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -2031,6 +2031,57 @@ TEST(NS, Anonymous) { EXPECT_TRUE(matches("namespace {}", namespaceDecl(isAnonymous()))); } +TEST(DeclarationMatcher, InStdNamespace) { + EXPECT_TRUE(notMatches("class vector {};" + "namespace foo {" + " class vector {};" + "}" + "namespace foo {" + " namespace std {" + " class vector {};" + " }" + "}", + cxxRecordDecl(hasName("vector"), isInStdNamespace()))); + + EXPECT_TRUE(matches("namespace std {" + " class vector {};" + "}", + cxxRecordDecl(hasName("vector"), isInStdNamespace()))); + EXPECT_TRUE(matches("namespace std {" + " inline namespace __1 {" + " class vector {};" + " }" + "}", + cxxRecordDecl(hasName("vector"), isInStdNamespace()))); + EXPECT_TRUE(notMatches("namespace std {" + " inline namespace __1 {" + " inline namespace __fs {" + " namespace filesystem {" + " inline namespace v1 {" + " class path {};" + " }" + " }" + " }" + " }" + "}", + cxxRecordDecl(hasName("path"), isInStdNamespace()))); + EXPECT_TRUE( + matches("namespace std {" + " inline namespace __1 {" + " inline namespace __fs {" + " namespace filesystem {" + " inline namespace v1 {" + " class path {};" + " }" + " }" + " }" + " }" + "}", + cxxRecordDecl(hasName("path"), + hasAncestor(namespaceDecl(hasName("filesystem"), + isInStdNamespace()))))); +} + TEST(EqualsBoundNodeMatcher, QualType) { EXPECT_TRUE(matches( "int i = 1;", varDecl(hasType(qualType().bind("type")), |