r203380 - [-Wunreachable-code] Handle Objective-C bool literals in 'isConfigurationValue'.
Ted Kremenek
kremenek at apple.com
Sun Mar 9 00:13:49 PST 2014
Author: kremenek
Date: Sun Mar 9 03:13:49 2014
New Revision: 203380
URL: http://llvm.org/viewvc/llvm-project?rev=203380&view=rev
Log:
[-Wunreachable-code] Handle Objective-C bool literals in 'isConfigurationValue'.
This includes special casing 'YES' and 'NO', which are constants
defined as macros.
Modified:
cfe/trunk/include/clang/Analysis/Analyses/ReachableCode.h
cfe/trunk/lib/Analysis/ReachableCode.cpp
cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
cfe/trunk/test/SemaObjC/warn-unreachable.m
Modified: cfe/trunk/include/clang/Analysis/Analyses/ReachableCode.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/ReachableCode.h?rev=203380&r1=203379&r2=203380&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/ReachableCode.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/ReachableCode.h Sun Mar 9 03:13:49 2014
@@ -27,6 +27,7 @@ namespace llvm {
namespace clang {
class AnalysisDeclContext;
class CFGBlock;
+ class Preprocessor;
}
//===----------------------------------------------------------------------===//
@@ -49,7 +50,8 @@ public:
unsigned ScanReachableFromBlock(const CFGBlock *Start,
llvm::BitVector &Reachable);
-void FindUnreachableCode(AnalysisDeclContext &AC, Callback &CB);
+void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP,
+ Callback &CB);
}} // end namespace clang::reachable_code
Modified: cfe/trunk/lib/Analysis/ReachableCode.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ReachableCode.cpp?rev=203380&r1=203379&r2=203380&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ReachableCode.cpp (original)
+++ cfe/trunk/lib/Analysis/ReachableCode.cpp Sun Mar 9 03:13:49 2014
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/Analyses/ReachableCode.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
@@ -172,14 +173,39 @@ static bool isTrivialReturnOrDoWhile(con
return false;
}
+static SourceLocation getTopMostMacro(SourceLocation Loc, SourceManager &SM) {
+ assert(Loc.isMacroID());
+ SourceLocation Last;
+ while (Loc.isMacroID()) {
+ Last = Loc;
+ Loc = SM.getImmediateMacroCallerLoc(Loc);
+ }
+ return Last;
+}
+
/// Returns true if the statement is expanded from a configuration macro.
-static bool isExpandedFromConfigurationMacro(const Stmt *S) {
+static bool isExpandedFromConfigurationMacro(const Stmt *S,
+ Preprocessor &PP,
+ bool IgnoreYES_NO = false) {
// FIXME: This is not very precise. Here we just check to see if the
// value comes from a macro, but we can do much better. This is likely
// to be over conservative. This logic is factored into a separate function
// so that we can refine it later.
SourceLocation L = S->getLocStart();
- return L.isMacroID();
+ if (L.isMacroID()) {
+ if (IgnoreYES_NO) {
+ // The Objective-C constant 'YES' and 'NO'
+ // are defined as macros. Do not treat them
+ // as configuration values.
+ SourceManager &SM = PP.getSourceManager();
+ SourceLocation TopL = getTopMostMacro(L, SM);
+ StringRef MacroName = PP.getImmediateMacroName(TopL);
+ if (MacroName == "YES" || MacroName == "NO")
+ return false;
+ }
+ return true;
+ }
+ return false;
}
/// Returns true if the statement represents a configuration value.
@@ -190,6 +216,7 @@ static bool isExpandedFromConfigurationM
/// to report as unreachable, and may mask truly unreachable code within
/// those blocks.
static bool isConfigurationValue(const Stmt *S,
+ Preprocessor &PP,
bool IncludeIntegers = true) {
if (!S)
return false;
@@ -202,7 +229,7 @@ static bool isConfigurationValue(const S
const DeclRefExpr *DR = cast<DeclRefExpr>(S);
const ValueDecl *D = DR->getDecl();
if (const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D))
- return isConfigurationValue(ED->getInitExpr());
+ return isConfigurationValue(ED->getInitExpr(), PP);
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
// As a heuristic, treat globals as configuration values. Note
// that we only will get here if Sema evaluated this
@@ -216,8 +243,11 @@ static bool isConfigurationValue(const S
return false;
}
case Stmt::IntegerLiteralClass:
- return IncludeIntegers ? isExpandedFromConfigurationMacro(S)
+ return IncludeIntegers ? isExpandedFromConfigurationMacro(S, PP)
: false;
+ case Stmt::ObjCBoolLiteralExprClass:
+ return isExpandedFromConfigurationMacro(S, PP, /* IgnoreYES_NO */ true);
+
case Stmt::UnaryExprOrTypeTraitExprClass:
return true;
case Stmt::BinaryOperatorClass: {
@@ -226,13 +256,13 @@ static bool isConfigurationValue(const S
// values if they are used in a logical or comparison operator
// (not arithmetic).
IncludeIntegers &= (B->isLogicalOp() || B->isComparisonOp());
- return isConfigurationValue(B->getLHS(), IncludeIntegers) ||
- isConfigurationValue(B->getRHS(), IncludeIntegers);
+ return isConfigurationValue(B->getLHS(), PP, IncludeIntegers) ||
+ isConfigurationValue(B->getRHS(), PP, IncludeIntegers);
}
case Stmt::UnaryOperatorClass: {
const UnaryOperator *UO = cast<UnaryOperator>(S);
return UO->getOpcode() == UO_LNot &&
- isConfigurationValue(UO->getSubExpr());
+ isConfigurationValue(UO->getSubExpr(), PP);
}
default:
return false;
@@ -240,20 +270,22 @@ static bool isConfigurationValue(const S
}
/// Returns true if we should always explore all successors of a block.
-static bool shouldTreatSuccessorsAsReachable(const CFGBlock *B) {
+static bool shouldTreatSuccessorsAsReachable(const CFGBlock *B,
+ Preprocessor &PP) {
if (const Stmt *Term = B->getTerminator()) {
if (isa<SwitchStmt>(Term))
return true;
// Specially handle '||' and '&&'.
if (isa<BinaryOperator>(Term))
- return isConfigurationValue(Term);
+ return isConfigurationValue(Term, PP);
}
- return isConfigurationValue(B->getTerminatorCondition());
+ return isConfigurationValue(B->getTerminatorCondition(), PP);
}
static unsigned scanFromBlock(const CFGBlock *Start,
llvm::BitVector &Reachable,
+ Preprocessor *PP,
bool IncludeSometimesUnreachableEdges) {
unsigned count = 0;
@@ -291,9 +323,11 @@ static unsigned scanFromBlock(const CFGB
if (!UB)
break;
- if (!TreatAllSuccessorsAsReachable.hasValue())
+ if (!TreatAllSuccessorsAsReachable.hasValue()) {
+ assert(PP);
TreatAllSuccessorsAsReachable =
- shouldTreatSuccessorsAsReachable(item);
+ shouldTreatSuccessorsAsReachable(item, *PP);
+ }
if (TreatAllSuccessorsAsReachable.getValue()) {
B = UB;
@@ -316,8 +350,9 @@ static unsigned scanFromBlock(const CFGB
}
static unsigned scanMaybeReachableFromBlock(const CFGBlock *Start,
+ Preprocessor &PP,
llvm::BitVector &Reachable) {
- return scanFromBlock(Start, Reachable, true);
+ return scanFromBlock(Start, Reachable, &PP, true);
}
//===----------------------------------------------------------------------===//
@@ -329,6 +364,7 @@ namespace {
llvm::BitVector Visited;
llvm::BitVector &Reachable;
SmallVector<const CFGBlock *, 10> WorkList;
+ Preprocessor &PP;
typedef SmallVector<std::pair<const CFGBlock *, const Stmt *>, 12>
DeferredLocsTy;
@@ -336,9 +372,10 @@ namespace {
DeferredLocsTy DeferredLocs;
public:
- DeadCodeScan(llvm::BitVector &reachable)
+ DeadCodeScan(llvm::BitVector &reachable, Preprocessor &PP)
: Visited(reachable.size()),
- Reachable(reachable) {}
+ Reachable(reachable),
+ PP(PP) {}
void enqueue(const CFGBlock *block);
unsigned scanBackwards(const CFGBlock *Start,
@@ -450,13 +487,13 @@ unsigned DeadCodeScan::scanBackwards(con
// Specially handle macro-expanded code.
if (S->getLocStart().isMacroID()) {
- count += scanMaybeReachableFromBlock(Block, Reachable);
+ count += scanMaybeReachableFromBlock(Block, PP, Reachable);
continue;
}
if (isDeadCodeRoot(Block)) {
reportDeadCode(Block, S, CB);
- count += scanMaybeReachableFromBlock(Block, Reachable);
+ count += scanMaybeReachableFromBlock(Block, PP, Reachable);
}
else {
// Record this statement as the possibly best location in a
@@ -476,7 +513,7 @@ unsigned DeadCodeScan::scanBackwards(con
if (Reachable[Block->getBlockID()])
continue;
reportDeadCode(Block, I->second, CB);
- count += scanMaybeReachableFromBlock(Block, Reachable);
+ count += scanMaybeReachableFromBlock(Block, PP, Reachable);
}
}
@@ -576,19 +613,21 @@ void Callback::anchor() { }
unsigned ScanReachableFromBlock(const CFGBlock *Start,
llvm::BitVector &Reachable) {
- return scanFromBlock(Start, Reachable, false);
+ return scanFromBlock(Start, Reachable, /* SourceManager* */ 0, false);
}
-void FindUnreachableCode(AnalysisDeclContext &AC, Callback &CB) {
+void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP,
+ Callback &CB) {
+
CFG *cfg = AC.getCFG();
if (!cfg)
return;
- // Scan for reachable blocks from the entrance of the CFG.
+ // Scan for reachable blocks from the entrance of the CFG.
// If there are no unreachable blocks, we're done.
llvm::BitVector reachable(cfg->getNumBlockIDs());
unsigned numReachable =
- scanMaybeReachableFromBlock(&cfg->getEntry(), reachable);
+ scanMaybeReachableFromBlock(&cfg->getEntry(), PP, reachable);
if (numReachable == cfg->getNumBlockIDs())
return;
@@ -597,7 +636,7 @@ void FindUnreachableCode(AnalysisDeclCon
if (!AC.getCFGBuildOptions().AddEHEdges) {
for (CFG::try_block_iterator I = cfg->try_blocks_begin(),
E = cfg->try_blocks_end() ; I != E; ++I) {
- numReachable += scanMaybeReachableFromBlock(*I, reachable);
+ numReachable += scanMaybeReachableFromBlock(*I, PP, reachable);
}
if (numReachable == cfg->getNumBlockIDs())
return;
@@ -611,7 +650,7 @@ void FindUnreachableCode(AnalysisDeclCon
if (reachable[block->getBlockID()])
continue;
- DeadCodeScan DS(reachable);
+ DeadCodeScan DS(reachable, PP);
numReachable += DS.scanBackwards(block, CB);
if (numReachable == cfg->getNumBlockIDs())
Modified: cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp?rev=203380&r1=203379&r2=203380&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp (original)
+++ cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp Sun Mar 9 03:13:49 2014
@@ -84,7 +84,7 @@ static void CheckUnreachable(Sema &S, An
return;
UnreachableCodeHandler UC(S);
- reachable_code::FindUnreachableCode(AC, UC);
+ reachable_code::FindUnreachableCode(AC, S.getPreprocessor(), UC);
}
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/test/SemaObjC/warn-unreachable.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/warn-unreachable.m?rev=203380&r1=203379&r2=203380&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/warn-unreachable.m (original)
+++ cfe/trunk/test/SemaObjC/warn-unreachable.m Sun Mar 9 03:13:49 2014
@@ -15,3 +15,28 @@ void test_unreachable() {
return; // expected-warning {{will never be executed}}
}
+#define NO __objc_no
+#define YES __objc_yes
+#define CONFIG NO
+
+// Test that 'NO' and 'YES' are not treated as configuration macros.
+int test_NO() {
+ if (NO)
+ return 1; // expected-warning {{will never be executed}}
+ else
+ return 0;
+}
+
+int test_YES() {
+ if (YES)
+ return 1;
+ else
+ return 0; // expected-warning {{will never be executed}}
+}
+
+int test_CONFIG() {
+ if (CONFIG)
+ return 1;
+ else
+ return 0;
+}
More information about the cfe-commits
mailing list