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

Andrey Karlov via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 15 07:55:04 PDT 2025


================
@@ -6298,10 +6308,60 @@ static bool isImmediateSinkBlock(const CFGBlock *Blk) {
   // at least for now, but once we have better support for exceptions,
   // we'd need to carefully handle the case when the throw is being
   // immediately caught.
-  if (llvm::any_of(*Blk, [](const CFGElement &Elm) {
+  if (llvm::any_of(*Blk, [](const CFGElement &Elm) -> bool {
+        if (std::optional<CFGStmt> StmtElm = Elm.getAs<CFGStmt>())
+          return isa<CXXThrowExpr>(StmtElm->getStmt());
+        return false;
+      }))
+    return true;
+
+  auto HasNoReturnCall = [&](const CallExpr *CE) {
+    if (!CE)
+      return false;
+
+    auto *FD = CE->getDirectCallee();
+
+    if (!FD)
+      return false;
+
+    auto *CanCD = FD->getCanonicalDecl();
+    auto *DefFD = CanCD->getDefinition();
+    auto NoRetAttrOpt = CanCD->getAnalyzerNoReturn();
+    auto NoReturn = false;
+
+    if (!NoRetAttrOpt && DefFD && DefFD->getBody()) {
+      // HACK: we are gonna cache analysis result as implicit
+      // `analyzer_noreturn` attribute
+      auto *MutCD = const_cast<FunctionDecl *>(CanCD);
----------------
negativ wrote:

I don't think we should treat recursive calls as creating 'no-return' sinks - it would make the `CFG` logic way too complex, and from my perspective, `CFG` wasn't built for this kind of analysis anyway. My simple implementation already feels like a hack since `CFG` was never supposed to do inter-procedural stuff. :D

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


More information about the cfe-commits mailing list