diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index 1f681e7f9a0a6cb2623c06542e57b77f874ac940..8b757f127664099318fc68497e2992ff7a05b7a3 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -1774,6 +1774,21 @@ cxxMethodDecl(isConst()) matches A::foo() but not A::bar() </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>></td><td class="name" onclick="toggle('isCopyAssignmentOperator0')"><a name="isCopyAssignmentOperator0Anchor">isCopyAssignmentOperator</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isCopyAssignmentOperator0"><pre>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. +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>></td><td class="name" onclick="toggle('isFinal1')"><a name="isFinal1Anchor">isFinal</a></td><td></td></tr> <tr><td colspan="4" class="doc" id="isFinal1"><pre>Matches if the given method or class declaration is final. @@ -2749,6 +2764,20 @@ Example matches a || b (matcher = binaryOperator(hasOperatorName("||"))) </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>></td><td class="name" onclick="toggle('hasAutomaticStorageDuration0')"><a name="hasAutomaticStorageDuration0Anchor">hasAutomaticStorageDuration</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="hasAutomaticStorageDuration0"><pre>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; +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>></td><td class="name" onclick="toggle('hasGlobalStorage0')"><a name="hasGlobalStorage0Anchor">hasGlobalStorage</a></td><td></td></tr> <tr><td colspan="4" class="doc" id="hasGlobalStorage0"><pre>Matches a variable declaration that does not have local storage. @@ -2774,6 +2803,34 @@ int z; </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>></td><td class="name" onclick="toggle('hasStaticStorageDuration0')"><a name="hasStaticStorageDuration0Anchor">hasStaticStorageDuration</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="hasStaticStorageDuration0"><pre>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; +</pre></td></tr> + + +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>></td><td class="name" onclick="toggle('hasThreadStorageDuration0')"><a name="hasThreadStorageDuration0Anchor">hasThreadStorageDuration</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="hasThreadStorageDuration0"><pre>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; +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>></td><td class="name" onclick="toggle('isConstexpr0')"><a name="isConstexpr0Anchor">isConstexpr</a></td><td></td></tr> <tr><td colspan="4" class="doc" id="isConstexpr0"><pre>Matches constexpr variable and function declarations. @@ -3040,6 +3097,22 @@ arraySubscriptExpression(hasIndex(integerLiteral())) </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html">ArraySubscriptExpr</a>></td><td class="name" onclick="toggle('hasLHS1')"><a name="hasLHS1Anchor">hasLHS</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasLHS1"><pre>Matches the left hand side of binary operator expressions. + +Example matches a (matcher = binaryOperator(hasLHS())) + a || b +</pre></td></tr> + + +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html">ArraySubscriptExpr</a>></td><td class="name" onclick="toggle('hasRHS1')"><a name="hasRHS1Anchor">hasRHS</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasRHS1"><pre>Matches the right hand side of binary operator expressions. + +Example matches b (matcher = binaryOperator(hasRHS())) + a || b +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ArrayTypeLoc.html">ArrayTypeLoc</a>></td><td class="name" onclick="toggle('hasElementTypeLoc0')"><a name="hasElementTypeLoc0Anchor">hasElementTypeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td></tr> <tr><td colspan="4" class="doc" id="hasElementTypeLoc0"><pre>Matches arrays and C99 complex types that have a specific element type. diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index 8147de426e37535dc5d8c053efc93789ec44d627..e640f511f1c57f2af0dafd4d05e368e8bc9b9e31 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/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/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp index eb41de1b6abae407253935f502310b450eec06d4..5b7b918a93419952e01149674294b6d1194fbafa 100644 --- a/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/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(hasStaticStorageDuration); REGISTER_MATCHER(hasTargetDecl); REGISTER_MATCHER(hasTemplateArgument); REGISTER_MATCHER(hasThen); + REGISTER_MATCHER(hasThreadStorageDuration); REGISTER_MATCHER(hasTrueExpression); REGISTER_MATCHER(hasTypeLoc); REGISTER_MATCHER(hasUnaryOperand); diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp index 476a0be29040123701790aa4288ede059c76594d..6d81bd88b9e2ef7ef0da25335003a3ee43189a5b 100644 --- a/unittests/ASTMatchers/ASTMatchersTest.cpp +++ b/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) {}",