From: Chris Lattner
Date: Fri, 12 Dec 2008 06:55:44 +0000 (+0000)
Subject: implement rdar://6091492 - ?: with __builtin_constant_p as the operand is an i-c-e.
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=28daa53db73341b7ee7f269924ccfca1c6d179ac;p=clang
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 9e8a21e708..5d32d8df6d 100644
--- a/docs/InternalsManual.html
+++ b/docs/InternalsManual.html
@@ -1152,7 +1152,10 @@ interacts with constant evaluation:
any evaluatable subexpression to be accepted as an integer constant
expression.
__builtin_constant_p: This returns true (as a integer
- constant expression) if the operand is any evaluatable constant.
+ constant expression) if the operand is any evaluatable constant. As a
+ special case, if __builtin_constant_p is the (potentially
+ parenthesized) condition of a conditional operator expression ("?:"), only
+ the true side of the conditional operator is considered.
__builtin_choose_expr: 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 728b13534a..8d11356925 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1017,13 +1017,22 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
case ConditionalOperatorClass: {
const ConditionalOperator *Exp = cast(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(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 46b74decef..e6e67d643d 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];
+