Skip to content
Snippets Groups Projects
Commit 1de85338 authored by John McCall's avatar John McCall
Browse files

Teach CFG building how to deal with CXXMemberCallExprs and BoundMemberTy,

then teach -Wreturn-type to handle the same.  Net effect:  we now correctly
handle noreturn attributes on member calls in the CFG.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131178 91177308-0d34-0410-b5e6-96231b3b80d8
parent be57cf41
No related branches found
No related tags found
No related merge requests found
......@@ -320,7 +320,6 @@ private:
AddStmtChoice asc);
CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
AddStmtChoice asc);
CFGBlock *VisitCXXMemberCallExpr(CXXMemberCallExpr *C, AddStmtChoice asc);
CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc);
CFGBlock *VisitCaseStmt(CaseStmt *C);
CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc);
......@@ -868,6 +867,7 @@ tryAgain:
case Stmt::CallExprClass:
case Stmt::CXXOperatorCallExprClass:
case Stmt::CXXMemberCallExprClass:
return VisitCallExpr(cast<CallExpr>(S), asc);
case Stmt::CaseStmtClass:
......@@ -903,9 +903,6 @@ tryAgain:
case Stmt::CXXTemporaryObjectExprClass:
return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);
case Stmt::CXXMemberCallExprClass:
return VisitCXXMemberCallExpr(cast<CXXMemberCallExpr>(S), asc);
case Stmt::CXXThrowExprClass:
return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
......@@ -1153,12 +1150,19 @@ static bool CanThrow(Expr *E, ASTContext &Ctx) {
}
CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
// If this is a call to a no-return function, this stops the block here.
bool NoReturn = false;
if (getFunctionExtInfo(*C->getCallee()->getType()).getNoReturn()) {
NoReturn = true;
// Compute the callee type.
QualType calleeType = C->getCallee()->getType();
if (calleeType == Context->BoundMemberTy) {
QualType boundType = Expr::findBoundMemberType(C->getCallee());
// We should only get a null bound type if processing a dependent
// CFG. Recover by assuming nothing.
if (!boundType.isNull()) calleeType = boundType;
}
// If this is a call to a no-return function, this stops the block here.
bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn();
bool AddEHEdge = false;
// Languages without exceptions are assumed to not throw.
......@@ -2691,13 +2695,6 @@ CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
return VisitChildren(C);
}
CFGBlock *CFGBuilder::VisitCXXMemberCallExpr(CXXMemberCallExpr *C,
AddStmtChoice asc) {
autoCreateBlock();
appendStmt(Block, C);
return VisitChildren(C);
}
CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,
AddStmtChoice asc) {
if (asc.alwaysAdd(*this, E)) {
......
......@@ -196,7 +196,12 @@ static ControlFlowKind CheckFallThrough(AnalysisContext &AC) {
continue;
}
Expr *CEE = C->getCallee()->IgnoreParenCasts();
if (getFunctionExtInfo(CEE->getType()).getNoReturn()) {
QualType calleeType = CEE->getType();
if (calleeType == AC.getASTContext().BoundMemberTy) {
calleeType = Expr::findBoundMemberType(CEE);
assert(!calleeType.isNull() && "analyzing unresolved call?");
}
if (getFunctionExtInfo(calleeType).getNoReturn()) {
NoReturnEdge = true;
HasFakeEdge = true;
} else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
......
// RUN: %clang_cc1 -fsyntax-only -verify %s
// Reachability tests have to come first because they get suppressed
// if any errors have occurred.
namespace test5 {
struct A {
__attribute__((noreturn)) void fail();
void nofail();
} a;
int &test1() {
a.nofail();
} // expected-warning {{control reaches end of non-void function}}
int &test2() {
a.fail();
}
}
// PR5620
void f0() __attribute__((__noreturn__));
void f1(void (*)());
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment