diff options
author | Ted Kremenek <kremenek@apple.com> | 2014-03-06 06:50:46 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2014-03-06 06:50:46 +0000 |
commit | ec2dc73e8638eecc7c95404d575ea9d94e197cf3 (patch) | |
tree | 5924b2745d9a736042348c9b461108b8d728a9a2 /clang/lib/Analysis/ReachableCode.cpp | |
parent | b3fd21a42fc3bf620c1c81cc1c131c24e142cee7 (diff) | |
download | bcm5719-llvm-ec2dc73e8638eecc7c95404d575ea9d94e197cf3.tar.gz bcm5719-llvm-ec2dc73e8638eecc7c95404d575ea9d94e197cf3.zip |
[-Wunreachable-code] don't warn about dead 'return <string literal>' dominated by a 'noreturn' call, where literal becomes an std::string.
I have mixed feelings about this one. It's used all over the codebase,
and is analogous to the current heuristic for ordinary C string literals.
This requires some ad hoc pattern matching of the AST. While the
test case mirrors what we see std::string in libc++, it's not really
testing the libc++ headers.
llvm-svn: 203091
Diffstat (limited to 'clang/lib/Analysis/ReachableCode.cpp')
-rw-r--r-- | clang/lib/Analysis/ReachableCode.cpp | 54 |
1 files changed, 52 insertions, 2 deletions
diff --git a/clang/lib/Analysis/ReachableCode.cpp b/clang/lib/Analysis/ReachableCode.cpp index 8b192d2d612..79e8d8cb018 100644 --- a/clang/lib/Analysis/ReachableCode.cpp +++ b/clang/lib/Analysis/ReachableCode.cpp @@ -251,7 +251,10 @@ static bool bodyEndsWithNoReturn(const CFGBlock *B) { for (CFGBlock::const_reverse_iterator I = B->rbegin(), E = B->rend(); I != E; ++I) { if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) { - if (const CallExpr *CE = dyn_cast<CallExpr>(CS->getStmt())) { + const Stmt *S = CS->getStmt(); + if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S)) + S = EWC->getSubExpr(); + if (const CallExpr *CE = dyn_cast<CallExpr>(S)) { QualType CalleeType = CE->getCallee()->getType(); if (getFunctionExtInfo(*CalleeType).getNoReturn()) return true; @@ -290,6 +293,53 @@ static bool isEnumConstant(const Expr *Ex) { return isa<EnumConstantDecl>(DR->getDecl()); } +static const Expr *stripStdStringCtor(const Expr *Ex) { + // Go crazy pattern matching an implicit construction of std::string(""). + const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Ex); + if (!EWC) + return 0; + const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(EWC->getSubExpr()); + if (!CCE) + return 0; + QualType Ty = CCE->getType(); + if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Ty)) + Ty = ET->getNamedType(); + const TypedefType *TT = dyn_cast<TypedefType>(Ty); + StringRef Name = TT->getDecl()->getName(); + if (Name != "string") + return 0; + if (CCE->getNumArgs() != 1) + return 0; + const MaterializeTemporaryExpr *MTE = + dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0)); + if (!MTE) + return 0; + CXXBindTemporaryExpr *CBT = + dyn_cast<CXXBindTemporaryExpr>(MTE->GetTemporaryExpr()->IgnoreParenCasts()); + if (!CBT) + return 0; + Ex = CBT->getSubExpr()->IgnoreParenCasts(); + CCE = dyn_cast<CXXConstructExpr>(Ex); + if (!CCE) + return 0; + if (CCE->getNumArgs() != 1) + return 0; + return dyn_cast<StringLiteral>(CCE->getArg(0)->IgnoreParenCasts()); +} + +/// Strip away "sugar" around trivial expressions that are for the +/// purpose of this analysis considered uninteresting for dead code warnings. +static const Expr *stripExprSugar(const Expr *Ex) { + Ex = Ex->IgnoreParenCasts(); + // If 'Ex' is a constructor for a std::string, strip that + // away. We can only get here if the trivial expression was + // something like a C string literal, with the std::string + // just wrapping that value. + if (const Expr *StdStringVal = stripStdStringCtor(Ex)) + return StdStringVal; + return Ex; +} + static bool isTrivialExpression(const Expr *Ex) { Ex = Ex->IgnoreParenCasts(); return isa<IntegerLiteral>(Ex) || isa<StringLiteral>(Ex) || @@ -324,7 +374,7 @@ static bool isTrivialReturnOrDoWhile(const CFGBlock *B, const Stmt *S) { if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) { if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) { const Expr *RE = RS->getRetValue(); - if (RE && RE->IgnoreParenCasts() == Ex) + if (RE && stripExprSugar(RE->IgnoreParenCasts()) == Ex) return bodyEndsWithNoReturn(*B->pred_begin()); } break; |