]> granicus.if.org Git - clang/commitdiff
implement rdar://6091492 - ?: with __builtin_constant_p as the operand is an i-c-e.
authorChris Lattner <sabre@nondot.org>
Fri, 12 Dec 2008 06:55:44 +0000 (06:55 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 12 Dec 2008 06:55:44 +0000 (06:55 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60934 91177308-0d34-0410-b5e6-96231b3b80d8

docs/InternalsManual.html
lib/AST/Expr.cpp
test/Sema/i-c-e3.c

index 9e8a21e708ef92011b62b27e73353c786d8a089a..5d32d8df6d7dd1f7ded66bdc8bb4cdabed7cc404 100644 (file)
@@ -1152,7 +1152,10 @@ interacts with constant evaluation:</p>
     any evaluatable subexpression to be accepted as an integer constant
     expression.</li>
 <li><b><tt>__builtin_constant_p</tt></b>: This returns true (as a integer
-    constant expression) if the operand is any evaluatable constant.</li>
+    constant expression) if the operand is any evaluatable constant.  As a
+    special case, if <tt>__builtin_constant_p</tt> is the (potentially
+    parenthesized) condition of a conditional operator expression ("?:"), only
+    the true side of the conditional operator is considered.</li>
 <li><b><tt>__builtin_choose_expr</tt></b>: The condition is required to be an
     integer constant expression, but we accept any constant as an "extension of
     an extension".  This only evaluates one operand depending on which way the
index 728b13534a349f0bb974fc42f17f91540a27b4cc..8d1135692594233a3bc47127fe90cb70748e00a1 100644 (file)
@@ -1017,13 +1017,22 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
   case ConditionalOperatorClass: {
     const ConditionalOperator *Exp = cast<ConditionalOperator>(this);
     
-    if (!Exp->getCond()->isIntegerConstantExpr(Result, Ctx, Loc, isEvaluated))
+    const Expr *Cond = Exp->getCond();
+    
+    if (!Cond->isIntegerConstantExpr(Result, Ctx, Loc, isEvaluated))
       return false;
     
     const Expr *TrueExp  = Exp->getLHS();
     const Expr *FalseExp = Exp->getRHS();
     if (Result == 0) std::swap(TrueExp, FalseExp);
     
+    // If the condition (ignoring parens) is a __builtin_constant_p call, 
+    // then only the true side is actually considered in an integer constant
+    // expression.  This is an important GNU extension.
+    if (const CallExpr *CallCE = dyn_cast<CallExpr>(Cond->IgnoreParenCasts()))
+      if (CallCE->isBuiltinCall() == Builtin::BI__builtin_constant_p)
+        FalseExp = 0;
+    
     // Evaluate the false one first, discard the result.
     if (FalseExp && !FalseExp->isIntegerConstantExpr(Result, Ctx, Loc, false))
       return false;
index 46b74decefaf7e85bed384a9c4354a8783e5fc87..e6e67d643d7b00eaeb169f6aad90e991ac739600 100644 (file)
@@ -1,3 +1,8 @@
-// RUN: clang %s -fsyntax-only -verify
+// RUN: clang %s -fsyntax-only -verify -pedantic
 
 int a() {int p; *(1 ? &p : (void*)(0 && (a(),1))) = 10;}
+
+// rdar://6091492 - ?: with __builtin_constant_p as the operand is an i-c-e.
+int expr;
+char w[__builtin_constant_p(expr) ? expr : 1];
+