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

llvm-svn: 359876
This commit is contained in:
Dmitri Gribenko 2019-05-03 12:50:00 +00:00
parent 6d08b8dbae
commit b641b914a3
6 changed files with 100 additions and 5 deletions

View File

@ -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.

View File

@ -2827,6 +2827,29 @@ by the compiler (eg. implicit default/copy constructors).
</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.

View File

@ -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.
///

View File

@ -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() {

View File

@ -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);

View File

@ -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")),