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(); +} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits