[cfe-commits] r57153 - in /cfe/trunk: include/clang/Basic/DiagnosticKinds.def lib/Sema/SemaDecl.cpp test/Sema/constant-builtins.c

Chris Lattner sabre at nondot.org
Sun Oct 5 22:42:40 PDT 2008


Author: lattner
Date: Mon Oct  6 00:42:39 2008
New Revision: 57153

URL: http://llvm.org/viewvc/llvm-project?rev=57153&view=rev
Log:
"Enhance" CheckArithmeticConstantExpression to accept ?: with a constant 
condition as a constant even if the unevaluated side is a not a constant.
We don't do this when extensions are off, and we emit a warning when this 
happens:

t.c:22:11: warning: expression is not a constant, but is accepted as one by GNU extensions
short t = __builtin_constant_p(5353) ? 42 : somefunc();
          ^                                 ~~~~~~~~~~

suggestions for improvement are welcome.  This is obviously horrible, but
is required for real-world code.


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/Sema/constant-builtins.c

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=57153&r1=57152&r2=57153&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Mon Oct  6 00:42:39 2008
@@ -1096,6 +1096,8 @@
      "pointer type mismatch ('%0' and '%1')")
 DIAG(err_typecheck_choose_expr_requires_constant, ERROR,
      "'__builtin_choose_expr' requires a constant expression")
+DIAG(ext_typecheck_expression_not_constant_but_accepted, EXTENSION,
+     "expression is not a constant, but is accepted as one by GNU extensions")
 DIAG(warn_unused_expr, WARNING,
      "expression result unused")
 DIAG(err_pascal_string_too_long, ERROR,

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=57153&r1=57152&r2=57153&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Oct  6 00:42:39 2008
@@ -1190,12 +1190,47 @@
   }
   case Expr::ConditionalOperatorClass: {
     const ConditionalOperator *Exp = cast<ConditionalOperator>(Init);
-    if (CheckArithmeticConstantExpression(Exp->getCond()))
-      return true;
-    if (Exp->getLHS() &&
-        CheckArithmeticConstantExpression(Exp->getLHS()))
+    
+    // If GNU extensions are disabled, we require all operands to be arithmetic
+    // constant expressions.
+    if (getLangOptions().NoExtensions) {
+      return CheckArithmeticConstantExpression(Exp->getCond()) ||
+          (Exp->getLHS() && CheckArithmeticConstantExpression(Exp->getLHS())) ||
+             CheckArithmeticConstantExpression(Exp->getRHS());
+    }
+
+    // Otherwise, we have to emulate some of the behavior of fold here.
+    // Basically GCC treats things like "4 ? 1 : somefunc()" as a constant
+    // because it can constant fold things away.  To retain compatibility with
+    // GCC code, we see if we can fold the condition to a constant (which we
+    // should always be able to do in theory).  If so, we only require the
+    // specified arm of the conditional to be a constant.  This is a horrible
+    // hack, but is require by real world code that uses __builtin_constant_p.
+    APValue Val;
+    if (!Exp->getCond()->tryEvaluate(Val, Context)) {
+      // If the tryEvaluate couldn't fold it, CheckArithmeticConstantExpression
+      // won't be able to either.  Use it to emit the diagnostic though.
+      bool Res = CheckArithmeticConstantExpression(Exp->getCond());
+      assert(Res && "tryEvaluate couldn't evaluate this constant?");
+      return Res;
+    }
+    
+    // Verify that the side following the condition is also a constant.
+    const Expr *TrueSide = Exp->getLHS(), *FalseSide = Exp->getRHS();
+    if (Val.getInt() == 0) 
+      std::swap(TrueSide, FalseSide);
+    
+    if (TrueSide && CheckArithmeticConstantExpression(TrueSide))
       return true;
-    return CheckArithmeticConstantExpression(Exp->getRHS());
+      
+    // Okay, the evaluated side evaluates to a constant, so we accept this.
+    // Check to see if the other side is obviously not a constant.  If so, 
+    // emit a warning that this is a GNU extension.
+    if (FalseSide && !FalseSide->tryEvaluate(Val, Context))
+      Diag(Init->getExprLoc(), 
+           diag::ext_typecheck_expression_not_constant_but_accepted,
+           FalseSide->getSourceRange());
+    return false;
   }
   }
 }
@@ -1211,20 +1246,8 @@
     return CheckForConstantInitializer(e->getInitializer(), DclT);
 
   if (Init->getType()->isReferenceType()) {
-    // FIXME: Work out how the heck reference types work
+    // FIXME: Work out how the heck references work.
     return false;
-#if 0
-    // A reference is constant if the address of the expression
-    // is constant
-    // We look through initlists here to simplify
-    // CheckAddressConstantExpressionLValue.
-    if (InitListExpr *Exp = dyn_cast<InitListExpr>(Init)) {
-      assert(Exp->getNumInits() > 0 &&
-             "Refernce initializer cannot be empty");
-      Init = Exp->getInit(0);
-    }
-    return CheckAddressConstantExpressionLValue(Init);
-#endif
   }
 
   if (InitListExpr *Exp = dyn_cast<InitListExpr>(Init)) {

Modified: cfe/trunk/test/Sema/constant-builtins.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/constant-builtins.c?rev=57153&r1=57152&r2=57153&view=diff

==============================================================================
--- cfe/trunk/test/Sema/constant-builtins.c (original)
+++ cfe/trunk/test/Sema/constant-builtins.c Mon Oct  6 00:42:39 2008
@@ -1,4 +1,4 @@
-// RUN: clang -fsyntax-only %s
+// RUN: clang -fsyntax-only %s -verify -pedantic
 
 // Math stuff
 
@@ -13,6 +13,11 @@
 
 extern int f();
 
-int h0 = __builtin_types_compatible_p(int,float);
+int h0 = __builtin_types_compatible_p(int,float); // expected-warning {{extension}}
 //int h1 = __builtin_choose_expr(1, 10, f());
 //int h2 = __builtin_expect(0, 0);
+
+short somefunc();
+
+short t = __builtin_constant_p(5353) ? 42 : somefunc(); // expected-warning {{expression is not a constant, but is accepted as one by GNU extensions}}
+





More information about the cfe-commits mailing list