diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 1f681e7f9a0a..8b757f127664 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -1774,6 +1774,21 @@ cxxMethodDecl(isConst()) matches A::foo() but not A::bar() +
Matches if the given method declaration declares a copy assignment +operator. + +Given +struct A { + A &operator=(const A &); + A &operator=(A &&); +}; + +cxxMethodDecl(isCopyAssignmentOperator()) matches the first method but not +the second one. +
Matches if the given method or class declaration is final. @@ -2749,6 +2764,20 @@ Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
Matches a variable declaration that has automatic storage duration. + +Example matches x, but not y, z, or a. +(matcher = varDecl(hasAutomaticStorageDuration()) +void f() { + int x; + static int y; + thread_local int z; +} +int a; +
Matches a variable declaration that does not have local storage. @@ -2774,6 +2803,34 @@ int z;
Matches a variable declaration that has static storage duration. + +Example matches y and a, but not x or z. +(matcher = varDecl(hasStaticStorageDuration()) +void f() { + int x; + static int y; + thread_local int z; +} +int a; +
Matches a variable declaration that has thread storage duration. + +Example matches z, but not x, z, or a. +(matcher = varDecl(hasThreadStorageDuration()) +void f() { + int x; + static int y; + thread_local int z; +} +int a; +
Matches constexpr variable and function declarations. @@ -3040,6 +3097,22 @@ arraySubscriptExpression(hasIndex(integerLiteral()))
Matches the left hand side of binary operator expressions. + +Example matches a (matcher = binaryOperator(hasLHS())) + a || b +
Matches the right hand side of binary operator expressions. + +Example matches b (matcher = binaryOperator(hasRHS())) + a || b +
Matches arrays and C99 complex types that have a specific element type. diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 8147de426e37..e640f511f1c5 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -2544,6 +2544,54 @@ AST_MATCHER(VarDecl, hasGlobalStorage) { return Node.hasGlobalStorage(); } +/// \brief Matches a variable declaration that has automatic storage duration. +/// +/// Example matches x, but not y, z, or a. +/// (matcher = varDecl(hasAutomaticStorageDuration()) +/// \code +/// void f() { +/// int x; +/// static int y; +/// thread_local int z; +/// } +/// int a; +/// \endcode +AST_MATCHER(VarDecl, hasAutomaticStorageDuration) { + return Node.getStorageDuration() == SD_Automatic; +} + +/// \brief Matches a variable declaration that has static storage duration. +/// +/// Example matches y and a, but not x or z. +/// (matcher = varDecl(hasStaticStorageDuration()) +/// \code +/// void f() { +/// int x; +/// static int y; +/// thread_local int z; +/// } +/// int a; +/// \endcode +AST_MATCHER(VarDecl, hasStaticStorageDuration) { + return Node.getStorageDuration() == SD_Static; +} + +/// \brief Matches a variable declaration that has thread storage duration. +/// +/// Example matches z, but not x, z, or a. +/// (matcher = varDecl(hasThreadStorageDuration()) +/// \code +/// void f() { +/// int x; +/// static int y; +/// thread_local int z; +/// } +/// int a; +/// \endcode +AST_MATCHER(VarDecl, hasThreadStorageDuration) { + return Node.getStorageDuration() == SD_Thread; +} + /// \brief Matches a variable declaration that is an exception variable from /// a C++ catch block, or an Objective-C \@catch statement. /// diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index eb41de1b6aba..ff79244f9a3d 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -194,6 +194,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasArgument); REGISTER_MATCHER(hasArgumentOfType); REGISTER_MATCHER(hasAttr); + REGISTER_MATCHER(hasAutomaticStorageDuration); REGISTER_MATCHER(hasBase); REGISTER_MATCHER(hasBody); REGISTER_MATCHER(hasCanonicalType); @@ -238,9 +239,11 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasSize); REGISTER_MATCHER(hasSizeExpr); REGISTER_MATCHER(hasSourceExpression); + REGISTER_MATCHER(hasThreadStorageDuration); REGISTER_MATCHER(hasTargetDecl); REGISTER_MATCHER(hasTemplateArgument); REGISTER_MATCHER(hasThen); + REGISTER_MATCHER(hasThreadStorageDuration); REGISTER_MATCHER(hasTrueExpression); REGISTER_MATCHER(hasTypeLoc); REGISTER_MATCHER(hasUnaryOperand); diff --git a/clang/unittests/ASTMatchers/ASTMatchersTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTest.cpp index 476a0be29040..6d81bd88b9e2 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTest.cpp @@ -1355,6 +1355,29 @@ TEST(Matcher, VarDecl_Storage) { EXPECT_TRUE(matches("void f() { static int X; }", M)); } +TEST(Matcher, VarDecl_StorageDuration) { + std::string T = + "void f() { int x; static int y; thread_local int z; } int a;"; + + EXPECT_TRUE(matches(T, varDecl(hasName("x"), hasAutomaticStorageDuration()))); + EXPECT_TRUE( + notMatches(T, varDecl(hasName("y"), hasAutomaticStorageDuration()))); + EXPECT_TRUE( + notMatches(T, varDecl(hasName("z"), hasAutomaticStorageDuration()))); + EXPECT_TRUE( + notMatches(T, varDecl(hasName("a"), hasAutomaticStorageDuration()))); + + EXPECT_TRUE(matches(T, varDecl(hasName("y"), hasStaticStorageDuration()))); + EXPECT_TRUE(matches(T, varDecl(hasName("a"), hasStaticStorageDuration()))); + EXPECT_TRUE(notMatches(T, varDecl(hasName("x"), hasStaticStorageDuration()))); + EXPECT_TRUE(notMatches(T, varDecl(hasName("z"), hasStaticStorageDuration()))); + + EXPECT_TRUE(matches(T, varDecl(hasName("z"), hasThreadStorageDuration()))); + EXPECT_TRUE(notMatches(T, varDecl(hasName("x"), hasThreadStorageDuration()))); + EXPECT_TRUE(notMatches(T, varDecl(hasName("y"), hasThreadStorageDuration()))); + EXPECT_TRUE(notMatches(T, varDecl(hasName("a"), hasThreadStorageDuration()))); +} + TEST(Matcher, FindsVarDeclInFunctionParameter) { EXPECT_TRUE(matches( "void f(int i) {}",