implement rdar://6091492 - ?: with __builtin_constant_p as the operand is an i-c-e.




git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60934 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/docs/InternalsManual.html b/docs/InternalsManual.html
index 9e8a21e..5d32d8d 100644
--- a/docs/InternalsManual.html
+++ b/docs/InternalsManual.html
@@ -1152,7 +1152,10 @@
     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
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 728b135..8d11356 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1017,13 +1017,22 @@
   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;
diff --git a/test/Sema/i-c-e3.c b/test/Sema/i-c-e3.c
index 46b74de..e6e67d6 100644
--- a/test/Sema/i-c-e3.c
+++ b/test/Sema/i-c-e3.c
@@ -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];
+