Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -2843,6 +2843,39 @@ +
Matches FunctionDecls that have a noreturn attribute. + +Given + void nope(); + [[noreturn]] void a0(); + [[noreturn]] void a1() {} + __attribute__((noreturn)) void a2(); + __attribute__((noreturn)) void a3() {} + struct b0 { [[noreturn]] b0(); }; + struct b1 { [[noreturn]] b1() {} }; + struct b2 { __attribute__((noreturn)) b2(); }; + struct b3 { __attribute__((noreturn)) b3() {} }; + struct c0 { [[noreturn]] int A(); }; + struct c1 { [[noreturn]] int A() {} }; + struct c2 { __attribute__((noreturn)) int A(); }; + struct c3 { __attribute__((noreturn)) int A() {} }; + struct d0 { [[noreturn]] static int A(); }; + struct d1 { [[noreturn]] static int A() {} }; + struct d2 { __attribute__((noreturn)) static int A(); }; + struct d3 { __attribute__((noreturn)) static int A() {} }; + extern "C" { void cNope(); } + extern "C" { __attribute__((noreturn)) void e0(); } + extern "C" { __attribute__((noreturn)) void e1() {} } + extern "C" { _Noreturn void e2(); } + extern "C" { _Noreturn void e3() {} } +functionDecl(isNoReturn()) + matches all of those except + void nope(); + extern "C" { void cNope(); } +
Matches functions that have a non-throwing exception specification. Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -3567,6 +3567,43 @@ return Node.getNumParams() == N; } +/// \brief Matches \c FunctionDecls that have a noreturn attribute. +/// +/// Given +/// \code +/// void nope(); +/// [[noreturn]] void a0(); +/// [[noreturn]] void a1() {} +/// __attribute__((noreturn)) void a2(); +/// __attribute__((noreturn)) void a3() {} +/// struct b0 { [[noreturn]] b0(); }; +/// struct b1 { [[noreturn]] b1() {} }; +/// struct b2 { __attribute__((noreturn)) b2(); }; +/// struct b3 { __attribute__((noreturn)) b3() {} }; +/// struct c0 { [[noreturn]] int A(); }; +/// struct c1 { [[noreturn]] int A() {} }; +/// struct c2 { __attribute__((noreturn)) int A(); }; +/// struct c3 { __attribute__((noreturn)) int A() {} }; +/// struct d0 { [[noreturn]] static int A(); }; +/// struct d1 { [[noreturn]] static int A() {} }; +/// struct d2 { __attribute__((noreturn)) static int A(); }; +/// struct d3 { __attribute__((noreturn)) static int A() {} }; +/// extern "C" { void cNope(); } +/// extern "C" { __attribute__((noreturn)) void e0(); } +/// extern "C" { __attribute__((noreturn)) void e1() {} } +/// extern "C" { _Noreturn void e2(); } +/// extern "C" { _Noreturn void e3() {} } +/// \endcode +/// functionDecl(isNoReturn()) +/// matches all of those except +/// \code +/// void nope(); +/// extern "C" { void cNope(); } +/// \endcode +AST_MATCHER(FunctionDecl, isNoReturn) { + return Node.isNoReturn(); +} + /// \brief Matches the return type of a function declaration. /// /// Given: Index: lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- lib/ASTMatchers/Dynamic/Registry.cpp +++ lib/ASTMatchers/Dynamic/Registry.cpp @@ -354,6 +354,7 @@ REGISTER_MATCHER(isMemberInitializer); REGISTER_MATCHER(isMoveAssignmentOperator); REGISTER_MATCHER(isMoveConstructor); + REGISTER_MATCHER(isNoReturn); REGISTER_MATCHER(isNoThrow); REGISTER_MATCHER(isOverride); REGISTER_MATCHER(isPrivate); Index: unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -1770,6 +1770,84 @@ functionDecl(isExplicitTemplateSpecialization()))); } +TEST(TypeMatching, MatchesNoReturn) { + EXPECT_TRUE(notMatches("void func();", functionDecl(isNoReturn()))); + EXPECT_TRUE(notMatches("void func() {}", functionDecl(isNoReturn()))); + + EXPECT_TRUE(notMatchesC("void func();", functionDecl(isNoReturn()))); + EXPECT_TRUE(notMatchesC("void func() {}", functionDecl(isNoReturn()))); + + EXPECT_TRUE( + notMatches("struct S { void func(); };", functionDecl(isNoReturn()))); + EXPECT_TRUE( + notMatches("struct S { void func() {} };", functionDecl(isNoReturn()))); + + EXPECT_TRUE(notMatches("struct S { static void func(); };", + functionDecl(isNoReturn()))); + EXPECT_TRUE(notMatches("struct S { static void func() {} };", + functionDecl(isNoReturn()))); + + EXPECT_TRUE(notMatches("struct S { S(); };", functionDecl(isNoReturn()))); + EXPECT_TRUE(notMatches("struct S { S() {} };", functionDecl(isNoReturn()))); + + // --- + + EXPECT_TRUE(matches("[[noreturn]] void func();", functionDecl(isNoReturn()))); + EXPECT_TRUE( + matches("[[noreturn]] void func() {}", functionDecl(isNoReturn()))); + + EXPECT_TRUE(matches("struct S { [[noreturn]] void func(); };", + functionDecl(isNoReturn()))); + EXPECT_TRUE(matches("struct S { [[noreturn]] void func() {} };", + functionDecl(isNoReturn()))); + + EXPECT_TRUE(matches("struct S { [[noreturn]] static void func(); };", + functionDecl(isNoReturn()))); + EXPECT_TRUE(matches("struct S { [[noreturn]] static void func() {} };", + functionDecl(isNoReturn()))); + + EXPECT_TRUE( + matches("struct S { [[noreturn]] S(); };", functionDecl(isNoReturn()))); + EXPECT_TRUE(matches("struct S { [[noreturn]] S() {} };", + functionDecl(isNoReturn()))); + + // --- + + EXPECT_TRUE(matches("__attribute__((noreturn)) void func();", + functionDecl(isNoReturn()))); + EXPECT_TRUE(matches("__attribute__((noreturn)) void func() {}", + functionDecl(isNoReturn()))); + + EXPECT_TRUE(matches("struct S { __attribute__((noreturn)) void func(); };", + functionDecl(isNoReturn()))); + EXPECT_TRUE(matches("struct S { __attribute__((noreturn)) void func() {} };", + functionDecl(isNoReturn()))); + + EXPECT_TRUE( + matches("struct S { __attribute__((noreturn)) static void func(); };", + functionDecl(isNoReturn()))); + EXPECT_TRUE( + matches("struct S { __attribute__((noreturn)) static void func() {} };", + functionDecl(isNoReturn()))); + + EXPECT_TRUE(matches("struct S { __attribute__((noreturn)) S(); };", + functionDecl(isNoReturn()))); + EXPECT_TRUE(matches("struct S { __attribute__((noreturn)) S() {} };", + functionDecl(isNoReturn()))); + + // --- + + EXPECT_TRUE(matchesC("__attribute__((noreturn)) void func();", + functionDecl(isNoReturn()))); + EXPECT_TRUE(matchesC("__attribute__((noreturn)) void func() {}", + functionDecl(isNoReturn()))); + + EXPECT_TRUE(matchesC("_Noreturn void func();", + functionDecl(isNoReturn()))); + EXPECT_TRUE(matchesC("_Noreturn void func() {}", + functionDecl(isNoReturn()))); +} + TEST(TypeMatching, MatchesBool) { EXPECT_TRUE(matches("struct S { bool func(); };", cxxMethodDecl(returns(booleanType()))));