diff options
author | Ted Kremenek <kremenek@apple.com> | 2014-03-20 06:44:35 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2014-03-20 06:44:35 +0000 |
commit | f5ae0bc671a40126450655c78ade7d8bb36b71c0 (patch) | |
tree | e4675afa59dda6829e8dc7e37e82cab071a56c54 /clang/lib/Analysis/ReachableCode.cpp | |
parent | 798e548955556eef47820910174118abbfa933e3 (diff) | |
download | bcm5719-llvm-f5ae0bc671a40126450655c78ade7d8bb36b71c0.tar.gz bcm5719-llvm-f5ae0bc671a40126450655c78ade7d8bb36b71c0.zip |
[-Wunreachable-code] Look through member accesses for 'static const bool' configuration values.
llvm-svn: 204315
Diffstat (limited to 'clang/lib/Analysis/ReachableCode.cpp')
-rw-r--r-- | clang/lib/Analysis/ReachableCode.cpp | 50 |
1 files changed, 27 insertions, 23 deletions
diff --git a/clang/lib/Analysis/ReachableCode.cpp b/clang/lib/Analysis/ReachableCode.cpp index ffe576cd052..0a9e82bb0ad 100644 --- a/clang/lib/Analysis/ReachableCode.cpp +++ b/clang/lib/Analysis/ReachableCode.cpp @@ -122,6 +122,8 @@ static bool isExpandedFromConfigurationMacro(const Stmt *S, return false; } +static bool isConfigurationValue(const ValueDecl *D, Preprocessor &PP); + /// Returns true if the statement represents a configuration value. /// /// A configuration value is something usually determined at compile-time @@ -144,34 +146,15 @@ static bool isConfigurationValue(const Stmt *S, dyn_cast_or_null<FunctionDecl>(cast<CallExpr>(S)->getCalleeDecl()); return Callee ? Callee->isConstexpr() : false; } - case Stmt::DeclRefExprClass: { - const DeclRefExpr *DR = cast<DeclRefExpr>(S); - const ValueDecl *D = DR->getDecl(); - if (const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D)) - 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 - // condition to a constant expression, which means the global - // had to be declared in a way to be a truly constant value. - // We could generalize this to local variables, but it isn't - // clear if those truly represent configuration values that - // gate unreachable code. - if (!VD->hasLocalStorage()) - return true; - - // As a heuristic, locals that have been marked 'const' explicitly - // can be treated as configuration values as well. - return VD->getType().isLocalConstQualified(); - } - return false; - } + case Stmt::DeclRefExprClass: + return isConfigurationValue(cast<DeclRefExpr>(S)->getDecl(), PP); case Stmt::IntegerLiteralClass: return IncludeIntegers ? isExpandedFromConfigurationMacro(S, PP) : false; + case Stmt::MemberExprClass: + return isConfigurationValue(cast<MemberExpr>(S)->getMemberDecl(), PP); case Stmt::ObjCBoolLiteralExprClass: return isExpandedFromConfigurationMacro(S, PP, /* IgnoreYES_NO */ true); - case Stmt::UnaryExprOrTypeTraitExprClass: return true; case Stmt::BinaryOperatorClass: { @@ -193,6 +176,27 @@ static bool isConfigurationValue(const Stmt *S, } } +static bool isConfigurationValue(const ValueDecl *D, Preprocessor &PP) { + if (const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D)) + 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 + // condition to a constant expression, which means the global + // had to be declared in a way to be a truly constant value. + // We could generalize this to local variables, but it isn't + // clear if those truly represent configuration values that + // gate unreachable code. + if (!VD->hasLocalStorage()) + return true; + + // As a heuristic, locals that have been marked 'const' explicitly + // can be treated as configuration values as well. + return VD->getType().isLocalConstQualified(); + } + return false; +} + /// Returns true if we should always explore all successors of a block. static bool shouldTreatSuccessorsAsReachable(const CFGBlock *B, Preprocessor &PP) { |