[clang] [clang-tools-extra] [clang]: Propagate `*noreturn` attributes in `CFG` (PR #146355)

Andrey Karlov via cfe-commits cfe-commits at lists.llvm.org
Fri Jul 18 01:16:19 PDT 2025


================
@@ -693,6 +703,153 @@ TEST_F(NoreturnDestructorTest, ConditionalOperatorNestedBranchReturns) {
   // FIXME: Called functions at point `p` should contain only "foo".
 }
 
+class AnalyzerNoreturnTest : public Test {
+protected:
+  template <typename Matcher>
+  void runDataflow(llvm::StringRef Code, Matcher Expectations) {
+    tooling::FileContentMappings FilesContents;
+    FilesContents.push_back(
+        std::make_pair<std::string, std::string>("noreturn_test_defs.h", R"(
+      void assertionHandler() __attribute__((analyzer_noreturn));
+
+      void assertionTrampoline() {
+        assertionHandler();
+      }
+
+      void trap() {}
+    )"));
+    FilesContents.push_back(std::make_pair<std::string, std::string>(
+        "noreturn_test_defs_canonical.h", R"(
+      extern void assertionHandler();
+
+      void assertionSecondTrampoline() {
+        assertionHandler();
+      }
+    )"));
+    FilesContents.push_back(std::make_pair<std::string, std::string>(
+        "noreturn_test_defs_noretcfg.h", R"(
+      // will be marged as noreturn by CFG
+      void assertionHandler() {
+          for (;;) {}
+      }
+
+      void assertionTrampoline() {
+        assertionHandler();
+      }
+
+      void trap() {}
+    )"));
+
+    ASSERT_THAT_ERROR(
+        test::checkDataflow<FunctionCallAnalysis>(
+            AnalysisInputs<FunctionCallAnalysis>(
+                Code, ast_matchers::hasName("target"),
+                [](ASTContext &C, Environment &) {
+                  return FunctionCallAnalysis(C);
+                })
+                .withASTBuildArgs({"-fsyntax-only", "-std=c++17"})
+                .withASTBuildVirtualMappedFiles(std::move(FilesContents)),
+            /*VerifyResults=*/
+            [&Expectations](
+                const llvm::StringMap<
+                    DataflowAnalysisState<FunctionCallLattice>> &Results,
+                const AnalysisOutputs &) {
+              EXPECT_THAT(Results, Expectations);
+            }),
+        llvm::Succeeded());
+  }
+};
+
+TEST_F(AnalyzerNoreturnTest, Breathing) {
+  std::string Code = R"(
+    #include "noreturn_test_defs.h"
+
+    void target() {
+      trap();
+      // [[p]]
+    }
+  )";
+  runDataflow(Code, UnorderedElementsAre(IsStringMapEntry(
+                        "p", HoldsFunctionCallLattice(HasCalledFunctions(
+                                 UnorderedElementsAre("trap"))))));
+}
----------------
negativ wrote:

> BTW is there a reason why you are testing this CFG algorithm in the FlowSensitive testing framework? We had a couple of lit tests in the past in the `clang/Analysis` director for noreturn stuff, that were testing the implementation of [AnalysisBasedWarnings.cpp](https://github.com/llvm/llvm-project/blob/main/clang/lib/Sema/AnalysisBasedWarnings.cpp).

I started out trying to fix false-positives in the `clang-tidy`'s `unchecked-optional-access` checker - kind of working backwards from that problem =) Not saying my solution is perfect by any means, but the `FlowSensetive` testing framework seemed like a good fit for this feature.

https://github.com/llvm/llvm-project/pull/146355


More information about the cfe-commits mailing list