diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index c308635e31e5..49880539bc98 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -1966,6 +1966,31 @@ Example matches a || b (matcher = binaryOperator(hasOperatorName("||"))) +
Matches a variable declaration that does not have local storage. + +Example matches y and z (matcher = varDecl(hasGlobalStorage()) +void f() { + int x; + static int y; +} +int z; +
Matches a variable declaration that has function scope and is a +non-static local variable. + +Example matches x (matcher = varDecl(hasLocalStorage()) +void f() { + int x; + static int y; +} +int z; +
Matches if a declaration has a body attached. diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index f81c282624e1..ed0e657dc169 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -2058,6 +2058,35 @@ AST_MATCHER_P( InnerMatcher.matches(*Initializer, Finder, Builder)); } +/// \brief Matches a variable declaration that has function scope and is a +/// non-static local variable. +/// +/// Example matches x (matcher = varDecl(hasLocalStorage()) +/// \code +/// void f() { +/// int x; +/// static int y; +/// } +/// int z; +/// \endcode +AST_MATCHER(VarDecl, hasLocalStorage) { + return Node.hasLocalStorage(); +} + +/// \brief Matches a variable declaration that does not have local storage. +/// +/// Example matches y and z (matcher = varDecl(hasGlobalStorage()) +/// \code +/// void f() { +/// int x; +/// static int y; +/// } +/// int z; +/// \endcode +AST_MATCHER(VarDecl, hasGlobalStorage) { + return Node.hasGlobalStorage(); +} + /// \brief Checks that a call expression or a constructor call expression has /// a specific number of arguments (including absent default arguments). /// diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index 87fe043406bf..cea5039526c3 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -189,12 +189,14 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasEitherOperand); REGISTER_MATCHER(hasElementType); REGISTER_MATCHER(hasFalseExpression); + REGISTER_MATCHER(hasGlobalStorage); REGISTER_MATCHER(hasImplicitDestinationType); REGISTER_MATCHER(hasIncrement); REGISTER_MATCHER(hasIndex); REGISTER_MATCHER(hasInitializer); REGISTER_MATCHER(hasLHS); REGISTER_MATCHER(hasLocalQualifiers); + REGISTER_MATCHER(hasLocalStorage); REGISTER_MATCHER(hasLoopInit); REGISTER_MATCHER(hasMethod); REGISTER_MATCHER(hasName); diff --git a/clang/unittests/ASTMatchers/ASTMatchersTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTest.cpp index 691719c04e4f..bcdc10ab6c03 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTest.cpp @@ -1165,6 +1165,18 @@ TEST(Matcher, VariableUsage) { "}", Reference)); } +TEST(Matcher, VarDecl_Storage) { + auto M = varDecl(hasName("X"), hasLocalStorage()); + EXPECT_TRUE(matches("void f() { int X; }", M)); + EXPECT_TRUE(notMatches("int X;", M)); + EXPECT_TRUE(notMatches("void f() { static int X; }", M)); + + M = varDecl(hasName("X"), hasGlobalStorage()); + EXPECT_TRUE(notMatches("void f() { int X; }", M)); + EXPECT_TRUE(matches("int X;", M)); + EXPECT_TRUE(matches("void f() { static int X; }", M)); +} + TEST(Matcher, FindsVarDeclInFunctionParameter) { EXPECT_TRUE(matches( "void f(int i) {}",