[PATCH] D35190: __builtin_constant_p should consider the parameter of a constexpr function as constant
Olivier Goffart via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 10 01:00:45 PDT 2017
ogoffart created this revision.
This allows to do something like:
constexpr int func(int x) {
return __builtin_constant_p(x) ? compute_constexpr(x) : compute_runtime(x);
}
This kind of code is accepted by GCC since GCC 4.8.
The problem was that EvaluateBuiltinConstantP was discarding the EvalInfo and its frames. So just keep the EvalInfo
https://reviews.llvm.org/D35190
Files:
lib/AST/ExprConstant.cpp
test/SemaCXX/constant-expression-cxx11.cpp
test/SemaCXX/constant-expression-cxx1y.cpp
Index: test/SemaCXX/constant-expression-cxx1y.cpp
===================================================================
--- test/SemaCXX/constant-expression-cxx1y.cpp
+++ test/SemaCXX/constant-expression-cxx1y.cpp
@@ -982,3 +982,8 @@
int *p = &n;
p += (__int128)(unsigned long)-1; // expected-note {{cannot refer to element 18446744073709551615 of non-array object in a constant expression}}
}
+
+namespace BuiltinConstantP {
+ constexpr int f1(int i) { return __builtin_constant_p(i += 4) ? 0 : i += 3; }
+ static_assert(f1(10) == 13, "");
+}
Index: test/SemaCXX/constant-expression-cxx11.cpp
===================================================================
--- test/SemaCXX/constant-expression-cxx11.cpp
+++ test/SemaCXX/constant-expression-cxx11.cpp
@@ -2169,3 +2169,13 @@
constexpr int *q = (&n + 1) - (unsigned __int128)-1; // expected-error {{constant expression}} expected-note {{cannot refer to element -3402}}
constexpr int *r = &(&n + 1)[(unsigned __int128)-1]; // expected-error {{constant expression}} expected-note {{cannot refer to element 3402}}
}
+
+namespace BuiltinConstantP {
+ int computeRuntime(int);
+ constexpr int compute(int x) {
+ return __builtin_constant_p(x) ? x + 2 : computeRuntime(x);
+ }
+ constexpr int x = compute(25);
+ int n; // expected-note{{declared here}}
+ constexpr int z = compute(n); // expected-error {{constant expression}} expected-note{{non-const variable}}
+}
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -7203,7 +7203,7 @@
/// EvaluateBuiltinConstantP - Evaluate __builtin_constant_p as similarly to
/// GCC as we can manage.
-static bool EvaluateBuiltinConstantP(ASTContext &Ctx, const Expr *Arg) {
+static bool EvaluateBuiltinConstantP(EvalInfo &Info, const Expr *Arg) {
QualType ArgType = Arg->getType();
// __builtin_constant_p always has one operand. The rules which gcc follows
@@ -7219,25 +7219,24 @@
//
// FIXME: GCC also intends to return 1 for literals of aggregate types, but
// its support for this does not currently work.
- if (ArgType->isIntegralOrEnumerationType()) {
- Expr::EvalResult Result;
- if (!Arg->EvaluateAsRValue(Result, Ctx) || Result.HasSideEffects)
+ SpeculativeEvaluationRAII SpeculativeEval(Info);
+ FoldConstant Fold(Info, true);
+ if (ArgType->isIntegralOrEnumerationType() || ArgType->isFloatingType() ||
+ ArgType->isAnyComplexType()) {
+ APValue V;
+ if (!EvaluateAsRValue(Info, Arg, V) || Info.EvalStatus.HasSideEffects)
return false;
-
- APValue &V = Result.Val;
- if (V.getKind() == APValue::Int)
+ if (V.getKind() == APValue::Int || V.getKind() == APValue::Float ||
+ V.getKind() == APValue::ComplexInt ||
+ V.getKind() == APValue::ComplexFloat)
return true;
if (V.getKind() == APValue::LValue)
return EvaluateBuiltinConstantPForLValue(V);
- } 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)
+ !Info.EvalStatus.HasSideEffects)
return EvaluateBuiltinConstantPForLValue(LV);
}
@@ -7628,7 +7627,7 @@
}
case Builtin::BI__builtin_constant_p:
- return Success(EvaluateBuiltinConstantP(Info.Ctx, E->getArg(0)), E);
+ return Success(EvaluateBuiltinConstantP(Info, E->getArg(0)), E);
case Builtin::BI__builtin_ctz:
case Builtin::BI__builtin_ctzl:
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D35190.105817.patch
Type: text/x-patch
Size: 3787 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170710/6ee92359/attachment.bin>
More information about the cfe-commits
mailing list