Skip to content

Commit

Permalink
Added an AST matcher for declarations that are in the std namespace
Browse files Browse the repository at this point in the history
Reviewers: alexfh

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D61480

llvm-svn: 359876
  • Loading branch information
gribozavr authored and MrSidims committed May 24, 2019
1 parent 519a2ad commit 70b151f
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 5 deletions.
Expand Up @@ -17,10 +17,6 @@ namespace clang {
namespace tidy {
namespace bugprone {

namespace {
AST_MATCHER(Decl, isInStdNamespace) { return Node.isInStdNamespace(); }
}

void InaccurateEraseCheck::registerMatchers(MatchFinder *Finder) {
// Only register the matchers for C++; the functionality currently does not
// provide any benefit to other languages, despite being benign.
Expand Down
23 changes: 23 additions & 0 deletions clang/docs/LibASTMatchersReference.html
Expand Up @@ -2827,6 +2827,29 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
</pre></td></tr>


<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</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&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</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.

Expand Down
23 changes: 23 additions & 0 deletions clang/include/clang/ASTMatchers/ASTMatchers.h
Expand Up @@ -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.
///
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/AST/DeclBase.cpp
Expand Up @@ -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() {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/ASTMatchers/Dynamic/Registry.cpp
Expand Up @@ -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);
Expand Down
51 changes: 51 additions & 0 deletions clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
Expand Up @@ -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")),
Expand Down

0 comments on commit 70b151f

Please sign in to comment.