Reinstate r359059, reverted in r359361, with a fix to properly prevent
us emitting the operand of __builtin_constant_p if it has side-effects.
Original commit message:
Fix interactions between __builtin_constant_p and constexpr to match
current trunk GCC.
GCC permits information from outside the operand of
__builtin_constant_p (but in the same constant evaluation context) to be
used within that operand; clang now does so too. A few other minor
deviations from GCC's behavior showed up in my testing and are also
fixed (matching GCC):
* Clang now supports nullptr_t as the argument type for
__builtin_constant_p
* Clang now returns true from __builtin_constant_p if called with a
null pointer
* Clang now returns true from __builtin_constant_p if called with an
integer cast to pointer type
llvm-svn: 359367
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index bc5f6cf..5abb62c 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -2027,8 +2027,17 @@
const Expr *Arg = E->getArg(0);
QualType ArgType = Arg->getType();
- if (!hasScalarEvaluationKind(ArgType) || ArgType->isFunctionType())
- // We can only reason about scalar types.
+ // FIXME: The allowance for Obj-C pointers and block pointers is historical
+ // and likely a mistake.
+ if (!ArgType->isIntegralOrEnumerationType() && !ArgType->isFloatingType() &&
+ !ArgType->isObjCObjectPointerType() && !ArgType->isBlockPointerType())
+ // Per the GCC documentation, only numeric constants are recognized after
+ // inlining.
+ return RValue::get(ConstantInt::get(ResultType, 0));
+
+ if (Arg->HasSideEffects(getContext()))
+ // The argument is unevaluated, so be conservative if it might have
+ // side-effects.
return RValue::get(ConstantInt::get(ResultType, 0));
Value *ArgValue = EmitScalarExpr(Arg);