Skip to content
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
----------------------------------

Expand Down
26 changes: 15 additions & 11 deletions clang/lib/Analysis/CFG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,7 @@ class CFGBuilder {
void cleanupConstructionContext(Expr *E);

void autoCreateBlock() { if (!Block) Block = createBlock(); }

CFGBlock *createBlock(bool add_successor = true);
CFGBlock *createNoReturnBlock();

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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,
Expand Down
17 changes: 17 additions & 0 deletions clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
22 changes: 22 additions & 0 deletions clang/test/SemaCXX/warn-missing-noreturn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
Loading