forked from OSchip/llvm-project
Revert Fix interactions between __builtin_constant_p and constexpr to match current trunk GCC.
This reverts r359059 (git commit 0b098754b7
)
llvm-svn: 359361
This commit is contained in:
parent
b58561baa5
commit
1dbd42ab5b
|
@ -7801,33 +7801,19 @@ EvaluateBuiltinClassifyType(const CallExpr *E, const LangOptions &LangOpts) {
|
|||
}
|
||||
|
||||
/// EvaluateBuiltinConstantPForLValue - Determine the result of
|
||||
/// __builtin_constant_p when applied to the given pointer.
|
||||
/// __builtin_constant_p when applied to the given lvalue.
|
||||
///
|
||||
/// A pointer is only "constant" if it is null (or a pointer cast to integer)
|
||||
/// or it points to the first character of a string literal.
|
||||
static bool EvaluateBuiltinConstantPForLValue(const APValue &LV) {
|
||||
APValue::LValueBase Base = LV.getLValueBase();
|
||||
if (Base.isNull()) {
|
||||
// A null base is acceptable.
|
||||
return true;
|
||||
} else if (const Expr *E = Base.dyn_cast<const Expr *>()) {
|
||||
if (!isa<StringLiteral>(E))
|
||||
return false;
|
||||
return LV.getLValueOffset().isZero();
|
||||
} else {
|
||||
// Any other base is not constant enough for GCC.
|
||||
return false;
|
||||
}
|
||||
/// An lvalue is only "constant" if it is a pointer or reference to the first
|
||||
/// character of a string literal.
|
||||
template<typename LValue>
|
||||
static bool EvaluateBuiltinConstantPForLValue(const LValue &LV) {
|
||||
const Expr *E = LV.getLValueBase().template dyn_cast<const Expr*>();
|
||||
return E && isa<StringLiteral>(E) && LV.getLValueOffset().isZero();
|
||||
}
|
||||
|
||||
/// EvaluateBuiltinConstantP - Evaluate __builtin_constant_p as similarly to
|
||||
/// GCC as we can manage.
|
||||
static bool EvaluateBuiltinConstantP(EvalInfo &Info, const Expr *Arg) {
|
||||
// Constant-folding is always enabled for the operand of __builtin_constant_p
|
||||
// (even when the enclosing evaluation context otherwise requires a strict
|
||||
// language-specific constant expression).
|
||||
FoldConstant Fold(Info, true);
|
||||
|
||||
static bool EvaluateBuiltinConstantP(ASTContext &Ctx, const Expr *Arg) {
|
||||
QualType ArgType = Arg->getType();
|
||||
|
||||
// __builtin_constant_p always has one operand. The rules which gcc follows
|
||||
|
@ -7835,27 +7821,34 @@ static bool EvaluateBuiltinConstantP(EvalInfo &Info, const Expr *Arg) {
|
|||
//
|
||||
// - If the operand is of integral, floating, complex or enumeration type,
|
||||
// and can be folded to a known value of that type, it returns 1.
|
||||
// - If the operand can be folded to a pointer to the first character
|
||||
// of a string literal (or such a pointer cast to an integral type)
|
||||
// or to a null pointer or an integer cast to a pointer, it returns 1.
|
||||
// - If the operand and can be folded to a pointer to the first character
|
||||
// of a string literal (or such a pointer cast to an integral type), it
|
||||
// returns 1.
|
||||
//
|
||||
// Otherwise, it returns 0.
|
||||
//
|
||||
// FIXME: GCC also intends to return 1 for literals of aggregate types, but
|
||||
// its support for this does not currently work.
|
||||
if (ArgType->isIntegralOrEnumerationType() || ArgType->isFloatingType() ||
|
||||
ArgType->isAnyComplexType() || ArgType->isPointerType() ||
|
||||
ArgType->isNullPtrType()) {
|
||||
APValue V;
|
||||
if (!::EvaluateAsRValue(Info, Arg, V))
|
||||
if (ArgType->isIntegralOrEnumerationType()) {
|
||||
Expr::EvalResult Result;
|
||||
if (!Arg->EvaluateAsRValue(Result, Ctx) || Result.HasSideEffects)
|
||||
return false;
|
||||
|
||||
// For a pointer (possibly cast to integer), there are special rules.
|
||||
APValue &V = Result.Val;
|
||||
if (V.getKind() == APValue::Int)
|
||||
return true;
|
||||
if (V.getKind() == APValue::LValue)
|
||||
return EvaluateBuiltinConstantPForLValue(V);
|
||||
|
||||
// Otherwise, any constant value is good enough.
|
||||
return V.getKind() != APValue::Uninitialized;
|
||||
} else if (ArgType->isFloatingType() || ArgType->isAnyComplexType()) {
|
||||
return Arg->isEvaluatable(Ctx);
|
||||
} else if (ArgType->isPointerType() || Arg->isGLValue()) {
|
||||
LValue LV;
|
||||
Expr::EvalStatus Status;
|
||||
EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold);
|
||||
if ((Arg->isGLValue() ? EvaluateLValue(Arg, LV, Info)
|
||||
: EvaluatePointer(Arg, LV, Info)) &&
|
||||
!Status.HasSideEffects)
|
||||
return EvaluateBuiltinConstantPForLValue(LV);
|
||||
}
|
||||
|
||||
// Anything else isn't considered to be sufficiently constant.
|
||||
|
@ -8266,7 +8259,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
|
|||
|
||||
case Builtin::BI__builtin_constant_p: {
|
||||
auto Arg = E->getArg(0);
|
||||
if (EvaluateBuiltinConstantP(Info, Arg))
|
||||
if (EvaluateBuiltinConstantP(Info.Ctx, Arg))
|
||||
return Success(true, E);
|
||||
auto ArgTy = Arg->IgnoreImplicit()->getType();
|
||||
if (!Info.InConstantContext && !Arg->HasSideEffects(Info.Ctx) &&
|
||||
|
|
|
@ -1199,14 +1199,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
|
|||
if (checkArgCount(*this, TheCall, 1)) return true;
|
||||
TheCall->setType(Context.IntTy);
|
||||
break;
|
||||
case Builtin::BI__builtin_constant_p: {
|
||||
case Builtin::BI__builtin_constant_p:
|
||||
if (checkArgCount(*this, TheCall, 1)) return true;
|
||||
ExprResult Arg = DefaultFunctionArrayLvalueConversion(TheCall->getArg(0));
|
||||
if (Arg.isInvalid()) return true;
|
||||
TheCall->setArg(0, Arg.get());
|
||||
TheCall->setType(Context.IntTy);
|
||||
break;
|
||||
}
|
||||
case Builtin::BI__builtin_launder:
|
||||
return SemaBuiltinLaunder(*this, TheCall);
|
||||
case Builtin::BI__sync_fetch_and_add:
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
// RUN: %clang_cc1 -std=c++17 -verify %s
|
||||
|
||||
using intptr_t = __INTPTR_TYPE__;
|
||||
|
||||
// Test interaction of constexpr and __builtin_constant_p.
|
||||
|
||||
template<typename T> constexpr bool bcp(T t) {
|
||||
return __builtin_constant_p(t);
|
||||
}
|
||||
template<typename T> constexpr bool bcp_fold(T t) {
|
||||
return __builtin_constant_p(((void)(intptr_t)&t, t));
|
||||
}
|
||||
|
||||
constexpr intptr_t ensure_fold_is_generally_not_enabled = // expected-error {{constant expression}}
|
||||
(intptr_t)&ensure_fold_is_generally_not_enabled; // expected-note {{cast}}
|
||||
|
||||
constexpr intptr_t ptr_to_int(const void *p) {
|
||||
return __builtin_constant_p(1) ? (intptr_t)p : (intptr_t)p;
|
||||
}
|
||||
|
||||
constexpr int *int_to_ptr(intptr_t n) {
|
||||
return __builtin_constant_p(1) ? (int*)n : (int*)n;
|
||||
}
|
||||
|
||||
int x;
|
||||
|
||||
// Integer and floating point constants encountered during constant expression
|
||||
// evaluation are considered constant. So is nullptr_t.
|
||||
static_assert(bcp(1));
|
||||
static_assert(bcp_fold(1));
|
||||
static_assert(bcp(1.0));
|
||||
static_assert(bcp_fold(1.0));
|
||||
static_assert(bcp(nullptr));
|
||||
static_assert(bcp_fold(nullptr));
|
||||
|
||||
// Pointers to the start of strings are considered constant.
|
||||
static_assert(bcp("foo"));
|
||||
static_assert(bcp_fold("foo"));
|
||||
|
||||
// Null pointers are considered constant.
|
||||
static_assert(bcp<int*>(nullptr));
|
||||
static_assert(bcp_fold<int*>(nullptr));
|
||||
static_assert(bcp<const char*>(nullptr));
|
||||
static_assert(bcp_fold<const char*>(nullptr));
|
||||
|
||||
// Other pointers are not.
|
||||
static_assert(!bcp(&x));
|
||||
static_assert(!bcp_fold(&x));
|
||||
|
||||
// Pointers cast to integers follow the rules for pointers.
|
||||
static_assert(bcp(ptr_to_int("foo")));
|
||||
static_assert(bcp_fold(ptr_to_int("foo")));
|
||||
static_assert(!bcp(ptr_to_int(&x)));
|
||||
static_assert(!bcp_fold(ptr_to_int(&x)));
|
||||
|
||||
// Integers cast to pointers follow the integer rules.
|
||||
static_assert(bcp(int_to_ptr(0)));
|
||||
static_assert(bcp_fold(int_to_ptr(0)));
|
||||
static_assert(bcp(int_to_ptr(123))); // GCC rejects these due to not recognizing
|
||||
static_assert(bcp_fold(int_to_ptr(123))); // the bcp conditional in 'int_to_ptr' ...
|
||||
static_assert(__builtin_constant_p((int*)123)); // ... but GCC accepts this
|
|
@ -522,14 +522,3 @@ void test() {
|
|||
InConstantContext::foo("abc");
|
||||
}
|
||||
} // namespace InConstantContext
|
||||
|
||||
namespace StringLiteralDetector {
|
||||
void need_string_literal(const char *p) __attribute__((enable_if(__builtin_constant_p(p), "argument is not a string literal"))); // expected-note 2{{not a string literal}}
|
||||
void test(const char *unknown) {
|
||||
need_string_literal("foo");
|
||||
need_string_literal(unknown); // expected-error {{no matching function}}
|
||||
constexpr char str[] = "bar";
|
||||
need_string_literal(str); // expected-error {{no matching function}}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue