Skip to content

Commit a742741

Browse files
authored
[Clang] Handle [[noreturn]] constructors in CFG (llvm#115558)
Fixes llvm#63009.
1 parent aaba840 commit a742741

File tree

4 files changed

+57
-11
lines changed

4 files changed

+57
-11
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,9 @@ Improvements to Clang's diagnostics
561561

562562
- Clang now diagnoses missing return value in functions containing ``if consteval`` (#GH116485).
563563

564+
- Clang now correctly recognises code after a call to a ``[[noreturn]]`` constructor
565+
as unreachable (#GH63009).
566+
564567
Improvements to Clang's time-trace
565568
----------------------------------
566569

clang/lib/Analysis/CFG.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,7 @@ class CFGBuilder {
760760
void cleanupConstructionContext(Expr *E);
761761

762762
void autoCreateBlock() { if (!Block) Block = createBlock(); }
763+
763764
CFGBlock *createBlock(bool add_successor = true);
764765
CFGBlock *createNoReturnBlock();
765766

@@ -818,15 +819,21 @@ class CFGBuilder {
818819
B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
819820
}
820821

821-
void appendConstructor(CFGBlock *B, CXXConstructExpr *CE) {
822+
void appendConstructor(CXXConstructExpr *CE) {
823+
CXXConstructorDecl *C = CE->getConstructor();
824+
if (C && C->isNoReturn())
825+
Block = createNoReturnBlock();
826+
else
827+
autoCreateBlock();
828+
822829
if (const ConstructionContext *CC =
823830
retrieveAndCleanupConstructionContext(CE)) {
824-
B->appendConstructor(CE, CC, cfg->getBumpVectorContext());
831+
Block->appendConstructor(CE, CC, cfg->getBumpVectorContext());
825832
return;
826833
}
827834

828835
// No valid construction context found. Fall back to statement.
829-
B->appendStmt(CE, cfg->getBumpVectorContext());
836+
Block->appendStmt(CE, cfg->getBumpVectorContext());
830837
}
831838

832839
void appendCall(CFGBlock *B, CallExpr *CE) {
@@ -4832,9 +4839,7 @@ CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C,
48324839
// construct these objects. Construction contexts we find here aren't for the
48334840
// constructor C, they're for its arguments only.
48344841
findConstructionContextsForArguments(C);
4835-
4836-
autoCreateBlock();
4837-
appendConstructor(Block, C);
4842+
appendConstructor(C);
48384843

48394844
return VisitChildren(C);
48404845
}
@@ -4892,16 +4897,15 @@ CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
48924897
return Visit(E->getSubExpr(), asc);
48934898
}
48944899

4895-
CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
4900+
CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E,
48964901
AddStmtChoice asc) {
48974902
// If the constructor takes objects as arguments by value, we need to properly
48984903
// construct these objects. Construction contexts we find here aren't for the
48994904
// constructor C, they're for its arguments only.
4900-
findConstructionContextsForArguments(C);
4905+
findConstructionContextsForArguments(E);
4906+
appendConstructor(E);
49014907

4902-
autoCreateBlock();
4903-
appendConstructor(Block, C);
4904-
return VisitChildren(C);
4908+
return VisitChildren(E);
49054909
}
49064910

49074911
CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,

clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,20 @@ void check() {
4949
test_type(g);
5050
test_type(h); // expected-note {{instantiation}}
5151
}
52+
53+
namespace GH63009 {
54+
struct S1 {
55+
[[noreturn]] S1() { throw int {}; }
56+
};
57+
struct S2 {
58+
[[noreturn]] ~S2() { throw int {}; }
59+
};
60+
61+
int test_no_return_constructor() { S1(); } // ok
62+
int test_no_return_destructor() { S2(); } // ok
63+
64+
int main() {
65+
test_no_return_constructor();
66+
test_no_return_destructor();
67+
}
68+
}

clang/test/SemaCXX/warn-missing-noreturn.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,25 @@ namespace PR10801 {
122122
thingy(b);
123123
}
124124
}
125+
126+
namespace GH63009 {
127+
struct S1 {
128+
[[noreturn]] S1();
129+
};
130+
131+
struct S2 {
132+
[[noreturn]] ~S2();
133+
};
134+
135+
int foo();
136+
137+
int test_1() {
138+
S1 s1;
139+
foo();
140+
}
141+
142+
int test_2() {
143+
S2 s2;
144+
foo();
145+
}
146+
}

0 commit comments

Comments
 (0)