Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -2518,6 +2518,20 @@ +
Matches functions that have a throwing exception specification. + +Given: + void f(); + void g() noexcept; + void h() throw(); + void i() throw(int); + void j() noexcept(false); +functionDecl(isThrow()) + matches the declarations of f, i, and j but not g or h. +
Matches if a function declaration is variadic. @@ -4465,6 +4479,24 @@
Matches functions that have a dynamic exception specification. + +Given: + void f(); + void g() noexcept; + void h() noexcept(true); + void i() noexcept(false); + void j() throw(); + void k() throw(int); + void l() throw(...); +functionDecl(hasDynamicExceptionSpec(isThrow())) + matches the declarations of k and l, but not f, g, h, i, or j. +functionDecl(hasDynamicExceptionSpec(isNoThrow())) + only matches the declaration of j. +
Matches the n'th parameter of a function declaration. Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -3212,6 +3212,48 @@ return Node.isDefaulted(); } +/// \brief Matches functions that have a dynamic exception specification. +/// +/// Given: +/// \code +/// void f(); +/// void g() noexcept; +/// void h() noexcept(true); +/// void i() noexcept(false); +/// void j() throw(); +/// void k() throw(int); +/// void l() throw(...); +/// \endcode +/// functionDecl(hasDynamicExceptionSpec(isThrow())) +/// matches the declarations of k and l, but not f, g, h, i, or j. +/// functionDecl(hasDynamicExceptionSpec(isNoThrow())) +/// only matches the declaration of j. +AST_MATCHER_P(FunctionDecl, hasDynamicExceptionSpec, + internal::Matcher, InnerMatcher) { + const auto *FnTy = Node.getType()->getAs (); + if (FnTy && FnTy->hasDynamicExceptionSpec()) + return InnerMatcher.matches(Node, Finder, Builder); + return false; +} + +/// \brief Matches functions that have a throwing exception specification. +/// +/// Given: +/// \code +/// void f(); +/// void g() noexcept; +/// void h() throw(); +/// void i() throw(int); +/// void j() noexcept(false); +/// \endcode +/// functionDecl(isThrow()) +/// matches the declarations of f, i, and j but not g or h. +AST_MATCHER(FunctionDecl, isThrow) { + if (const auto *FnTy = Node.getType()->getAs ()) + return !FnTy->isNothrow(Node.getASTContext()); + return false; +} + /// \brief Matches functions that have a non-throwing exception specification. /// /// Given: Index: lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- lib/ASTMatchers/Dynamic/Registry.cpp +++ lib/ASTMatchers/Dynamic/Registry.cpp @@ -218,6 +218,7 @@ REGISTER_MATCHER(hasDeducedType); REGISTER_MATCHER(hasDescendant); REGISTER_MATCHER(hasDestinationType); + REGISTER_MATCHER(hasDynamicExceptionSpec); REGISTER_MATCHER(hasEitherOperand); REGISTER_MATCHER(hasElementType); REGISTER_MATCHER(hasElse); @@ -308,6 +309,7 @@ REGISTER_MATCHER(isMoveAssignmentOperator); REGISTER_MATCHER(isMoveConstructor); REGISTER_MATCHER(isNoThrow); + REGISTER_MATCHER(isThrow); REGISTER_MATCHER(isOverride); REGISTER_MATCHER(isPrivate); REGISTER_MATCHER(isProtected); Index: unittests/ASTMatchers/ASTMatchersTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersTest.cpp +++ unittests/ASTMatchers/ASTMatchersTest.cpp @@ -1891,6 +1891,15 @@ functionDecl(hasName("Func"), isDeleted()))); } +TEST(IsThrow, MatchesThrowFunctionDeclarations) { + EXPECT_TRUE(matches("void f();", functionDecl(isThrow()))); + EXPECT_TRUE(matches("void f() throw(int);", functionDecl(isThrow()))); + EXPECT_TRUE( + matches("void f() noexcept(false);", functionDecl(isThrow()))); + EXPECT_TRUE(notMatches("void f() throw();", functionDecl(isThrow()))); + EXPECT_TRUE(notMatches("void f() noexcept;", functionDecl(isThrow()))); +} + TEST(IsNoThrow, MatchesNoThrowFunctionDeclarations) { EXPECT_TRUE(notMatches("void f();", functionDecl(isNoThrow()))); EXPECT_TRUE(notMatches("void f() throw(int);", functionDecl(isNoThrow()))); @@ -3552,6 +3561,38 @@ pointsTo(TypeMatcher(anything())))))); } +TEST(hasDynamicExceptionSpec, MatchesDynamicExceptionSpecifications) { + EXPECT_TRUE(notMatches("void f();", + functionDecl(hasDynamicExceptionSpec(isThrow())))); + EXPECT_TRUE(notMatches("void f();", + functionDecl(hasDynamicExceptionSpec(isNoThrow())))); + EXPECT_TRUE(notMatches("void g() noexcept;", + functionDecl(hasDynamicExceptionSpec(isThrow())))); + EXPECT_TRUE(notMatches("void g() noexcept;", + functionDecl(hasDynamicExceptionSpec(isNoThrow())))); + EXPECT_TRUE(notMatches("void h() noexcept(true);", + functionDecl(hasDynamicExceptionSpec(isThrow())))); + EXPECT_TRUE(notMatches("void h() noexcept(true);", + functionDecl(hasDynamicExceptionSpec(isNoThrow())))); + EXPECT_TRUE(notMatches("void i() noexcept(false);", + functionDecl(hasDynamicExceptionSpec(isThrow())))); + EXPECT_TRUE(notMatches("void i() noexcept(false);", + functionDecl(hasDynamicExceptionSpec(isNoThrow())))); + + EXPECT_TRUE(notMatches("void j() throw();", + functionDecl(hasDynamicExceptionSpec(isThrow())))); + EXPECT_TRUE(matches("void j() throw();", + functionDecl(hasDynamicExceptionSpec(isNoThrow())))); + EXPECT_TRUE(matches("void k() throw(int);", + functionDecl(hasDynamicExceptionSpec(isThrow())))); + EXPECT_TRUE(notMatches("void k() throw(int);", + functionDecl(hasDynamicExceptionSpec(isNoThrow())))); + EXPECT_TRUE(matches("void l() throw(...);", + functionDecl(hasDynamicExceptionSpec(isThrow())))); + EXPECT_TRUE(notMatches("void l() throw(...);", + functionDecl(hasDynamicExceptionSpec(isNoThrow())))); +} + TEST(HasImplicitDestinationType, MatchesSimpleCase) { // This test creates an implicit const cast. EXPECT_TRUE(matches("int x; const int i = x;",