Add AST narrowing matchers for inline and anonymous namespaces. Since the inline keyword can also be specified on a FunctionDecl, this is a polymorphic matcher.

llvm-svn: 245337
This commit is contained in:
Aaron Ballman 2015-08-18 19:55:20 +00:00
parent 29f11b381f
commit 11825f2592
4 changed files with 4597 additions and 4504 deletions

File diff suppressed because it is too large Load Diff

View File

@ -4211,6 +4211,44 @@ AST_POLYMORPHIC_MATCHER(isExplicit,
return Node.isExplicit();
}
/// \brief Matches function and namespace declarations that are marked with
/// the inline keyword.
///
/// Given
/// \code
/// inline void f();
/// void g();
/// namespace n {
/// inline namespace m {}
/// }
/// \endcode
/// functionDecl(isInline()) will match ::f().
/// namespaceDecl(isInline()) will match n::m.
AST_POLYMORPHIC_MATCHER(isInline,
AST_POLYMORPHIC_SUPPORTED_TYPES(NamespaceDecl,
FunctionDecl)) {
// This is required because the spelling of the function used to determine
// whether inline is specified or not differs between the polymorphic types.
if (const auto *FD = dyn_cast<FunctionDecl>(&Node))
return FD->isInlineSpecified();
else if (const auto *NSD = dyn_cast<NamespaceDecl>(&Node))
return NSD->isInline();
llvm_unreachable("Not a valid polymorphic type");
}
/// \brief Matches anonymous namespace declarations.
///
/// Given
/// \code
/// namespace n {
/// namespace {} // #1
/// }
/// \endcode
/// namespaceDecl(isAnonymous()) will match #1 but not ::n.
AST_MATCHER(NamespaceDecl, isAnonymous) {
return Node.isAnonymousNamespace();
}
/// \brief If the given case statement does not use the GNU case range
/// extension, matches the constant given in the statement.
///

View File

@ -240,6 +240,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(initListExpr);
REGISTER_MATCHER(innerType);
REGISTER_MATCHER(integerLiteral);
REGISTER_MATCHER(isAnonymous);
REGISTER_MATCHER(isArrow);
REGISTER_MATCHER(isBaseInitializer);
REGISTER_MATCHER(isCatchAll);
@ -255,6 +256,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(isExpr);
REGISTER_MATCHER(isExternC);
REGISTER_MATCHER(isFinal);
REGISTER_MATCHER(isInline);
REGISTER_MATCHER(isImplicit);
REGISTER_MATCHER(isExpansionInFileMatching);
REGISTER_MATCHER(isExpansionInMainFile);

View File

@ -4352,6 +4352,11 @@ TEST(NullStatement, SimpleCases) {
EXPECT_TRUE(notMatches("void f() {int i;}", nullStmt()));
}
TEST(NS, Anonymous) {
EXPECT_TRUE(notMatches("namespace N {}", namespaceDecl(isAnonymous())));
EXPECT_TRUE(matches("namespace {}", namespaceDecl(isAnonymous())));
}
TEST(NNS, MatchesTypes) {
NestedNameSpecifierMatcher Matcher = nestedNameSpecifier(
specifiesType(hasDeclaration(recordDecl(hasName("A")))));
@ -4771,6 +4776,13 @@ TEST(TypeDefDeclMatcher, Match) {
typedefDecl(hasName("typedefDeclTest"))));
}
TEST(IsInlineMatcher, IsInline) {
EXPECT_TRUE(matches("void g(); inline void f();",
functionDecl(isInline(), hasName("f"))));
EXPECT_TRUE(matches("namespace n { inline namespace m {} }",
namespaceDecl(isInline(), hasName("m"))));
}
// FIXME: Figure out how to specify paths so the following tests pass on Windows.
#ifndef LLVM_ON_WIN32