[-Wunreachable-code] Look through member accesses for 'static const bool' configuration values.
llvm-svn: 204315
diff --git a/clang/lib/Analysis/ReachableCode.cpp b/clang/lib/Analysis/ReachableCode.cpp
index ffe576c..0a9e82b 100644
--- a/clang/lib/Analysis/ReachableCode.cpp
+++ b/clang/lib/Analysis/ReachableCode.cpp
@@ -122,6 +122,8 @@
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 @@
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 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) {