[clang] a742741 - [Clang] Handle `[[noreturn]]` constructors in CFG (#115558)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 21 02:33:14 PST 2024
Author: Oleksandr T.
Date: 2024-11-21T11:33:11+01:00
New Revision: a7427410dd71072cbd1d44a6f78a08268b19a73b
URL: https://github.com/llvm/llvm-project/commit/a7427410dd71072cbd1d44a6f78a08268b19a73b
DIFF: https://github.com/llvm/llvm-project/commit/a7427410dd71072cbd1d44a6f78a08268b19a73b.diff
LOG: [Clang] Handle `[[noreturn]]` constructors in CFG (#115558)
Fixes #63009.
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/Analysis/CFG.cpp
clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp
clang/test/SemaCXX/warn-missing-noreturn.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 999c88455b64a5..49464e457da681 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -561,6 +561,9 @@ Improvements to Clang's diagnostics
- Clang now diagnoses missing return value in functions containing ``if consteval`` (#GH116485).
+- Clang now correctly recognises code after a call to a ``[[noreturn]]`` constructor
+ as unreachable (#GH63009).
+
Improvements to Clang's time-trace
----------------------------------
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 7a6bd8b6f8d070..304bbb2b422c61 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -760,6 +760,7 @@ class CFGBuilder {
void cleanupConstructionContext(Expr *E);
void autoCreateBlock() { if (!Block) Block = createBlock(); }
+
CFGBlock *createBlock(bool add_successor = true);
CFGBlock *createNoReturnBlock();
@@ -818,15 +819,21 @@ class CFGBuilder {
B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
}
- void appendConstructor(CFGBlock *B, CXXConstructExpr *CE) {
+ void appendConstructor(CXXConstructExpr *CE) {
+ CXXConstructorDecl *C = CE->getConstructor();
+ if (C && C->isNoReturn())
+ Block = createNoReturnBlock();
+ else
+ autoCreateBlock();
+
if (const ConstructionContext *CC =
retrieveAndCleanupConstructionContext(CE)) {
- B->appendConstructor(CE, CC, cfg->getBumpVectorContext());
+ Block->appendConstructor(CE, CC, cfg->getBumpVectorContext());
return;
}
// No valid construction context found. Fall back to statement.
- B->appendStmt(CE, cfg->getBumpVectorContext());
+ Block->appendStmt(CE, cfg->getBumpVectorContext());
}
void appendCall(CFGBlock *B, CallExpr *CE) {
@@ -4832,9 +4839,7 @@ CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C,
// construct these objects. Construction contexts we find here aren't for the
// constructor C, they're for its arguments only.
findConstructionContextsForArguments(C);
-
- autoCreateBlock();
- appendConstructor(Block, C);
+ appendConstructor(C);
return VisitChildren(C);
}
@@ -4892,16 +4897,15 @@ CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
return Visit(E->getSubExpr(), asc);
}
-CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
+CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E,
AddStmtChoice asc) {
// If the constructor takes objects as arguments by value, we need to properly
// construct these objects. Construction contexts we find here aren't for the
// constructor C, they're for its arguments only.
- findConstructionContextsForArguments(C);
+ findConstructionContextsForArguments(E);
+ appendConstructor(E);
- autoCreateBlock();
- appendConstructor(Block, C);
- return VisitChildren(C);
+ return VisitChildren(E);
}
CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,
diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp
index 56920ea8e8cf20..afcb133e48a1a8 100644
--- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp
@@ -49,3 +49,20 @@ void check() {
test_type(g);
test_type(h); // expected-note {{instantiation}}
}
+
+namespace GH63009 {
+struct S1 {
+ [[noreturn]] S1() { throw int {}; }
+};
+struct S2 {
+ [[noreturn]] ~S2() { throw int {}; }
+};
+
+int test_no_return_constructor() { S1(); } // ok
+int test_no_return_destructor() { S2(); } // ok
+
+int main() {
+ test_no_return_constructor();
+ test_no_return_destructor();
+}
+}
diff --git a/clang/test/SemaCXX/warn-missing-noreturn.cpp b/clang/test/SemaCXX/warn-missing-noreturn.cpp
index 400b471600e027..32b49e0a325f26 100644
--- a/clang/test/SemaCXX/warn-missing-noreturn.cpp
+++ b/clang/test/SemaCXX/warn-missing-noreturn.cpp
@@ -122,3 +122,25 @@ namespace PR10801 {
thingy(b);
}
}
+
+namespace GH63009 {
+struct S1 {
+ [[noreturn]] S1();
+};
+
+struct S2 {
+ [[noreturn]] ~S2();
+};
+
+int foo();
+
+int test_1() {
+ S1 s1;
+ foo();
+}
+
+int test_2() {
+ S2 s2;
+ foo();
+}
+}
More information about the cfe-commits
mailing list