r204315 - [-Wunreachable-code] Look through member accesses for 'static const bool' configuration values.

Ted Kremenek kremenek at apple.com
Wed Mar 19 23:44:35 PDT 2014


Author: kremenek
Date: Thu Mar 20 01:44:35 2014
New Revision: 204315

URL: http://llvm.org/viewvc/llvm-project?rev=204315&view=rev
Log:
[-Wunreachable-code] Look through member accesses for 'static const bool' configuration values.

Modified:
    cfe/trunk/lib/Analysis/ReachableCode.cpp
    cfe/trunk/test/SemaCXX/warn-unreachable.cpp

Modified: cfe/trunk/lib/Analysis/ReachableCode.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ReachableCode.cpp?rev=204315&r1=204314&r2=204315&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ReachableCode.cpp (original)
+++ cfe/trunk/lib/Analysis/ReachableCode.cpp Thu Mar 20 01:44:35 2014
@@ -122,6 +122,8 @@ static bool isExpandedFromConfigurationM
   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 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 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) {

Modified: cfe/trunk/test/SemaCXX/warn-unreachable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-unreachable.cpp?rev=204315&r1=204314&r2=204315&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-unreachable.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-unreachable.cpp Thu Mar 20 01:44:35 2014
@@ -236,22 +236,41 @@ Frobozz test_return_object_control_flow(
 
 void somethingToCall();
 
- static constexpr bool isConstExprConfigValue() { return true; }
- 
- int test_const_expr_config_value() {
-   if (isConstExprConfigValue()) {
-     somethingToCall();
-     return 0;
-   }
-   somethingToCall(); // no-warning
-   return 1;
- }
- int test_const_expr_config_value_2() {
-   if (!isConstExprConfigValue()) {
-     somethingToCall(); // no-warning
-     return 0;
-   }
+static constexpr bool isConstExprConfigValue() { return true; }
+
+int test_const_expr_config_value() {
+ if (isConstExprConfigValue()) {
    somethingToCall();
-   return 1;
+   return 0;
+ }
+ somethingToCall(); // no-warning
+ return 1;
+}
+int test_const_expr_config_value_2() {
+ if (!isConstExprConfigValue()) {
+   somethingToCall(); // no-warning
+   return 0;
  }
+ somethingToCall();
+ return 1;
+}
+
+class Frodo {
+public:
+  static const bool aHobbit = true;
+};
+
+void test_static_class_var() {
+  if (Frodo::aHobbit)
+    somethingToCall();
+  else
+    somethingToCall(); // no-warning
+}
+
+void test_static_class_var(Frodo &F) {
+  if (F.aHobbit)
+    somethingToCall();
+  else
+    somethingToCall(); // no-warning
+}
 





More information about the cfe-commits mailing list