Skip to content

Commit 25292d1

Browse files
committed
Merging r355743:
------------------------------------------------------------------------ r355743 | ericwf | 2019-03-08 23:06:48 +0100 (Fri, 08 Mar 2019) | 26 lines [8.0 Regression] Fix handling of `__builtin_constant_p` inside template arguments, enumerators, case statements, and the enable_if attribute. Summary: The following code is accepted by Clang 7 and prior but rejected by the upcoming 8 release and in trunk [1] ``` // error {{never produces a constant expression}} void foo(const char* s) __attribute__((enable_if(__builtin_constant_p(*s) == false, "trap"))) {} void test() { foo("abc"); } ``` Prior to Clang 8, the call to `__builtin_constant_p` was a constant expression returning false. Currently, it's not a valid constant expression. The bug is caused because we failed to set `InConstantContext` when attempting to evaluate unevaluated constant expressions. [1] https://godbolt.org/z/ksAjmq Reviewers: rsmith, hans, sbenza Reviewed By: rsmith Subscribers: kristina, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D59038 ------------------------------------------------------------------------ llvm-svn: 355898
1 parent 60c0551 commit 25292d1

File tree

3 files changed

+35
-0
lines changed

3 files changed

+35
-0
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10985,6 +10985,7 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, ConstExprUsage Usage,
1098510985
const ASTContext &Ctx) const {
1098610986
EvalInfo::EvaluationMode EM = EvalInfo::EM_ConstantExpression;
1098710987
EvalInfo Info(Ctx, Result, EM);
10988+
Info.InConstantContext = true;
1098810989
if (!::Evaluate(Result.Val, Info, this))
1098910990
return false;
1099010991

@@ -11625,6 +11626,7 @@ bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,
1162511626
const Expr *This) const {
1162611627
Expr::EvalStatus Status;
1162711628
EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpressionUnevaluated);
11629+
Info.InConstantContext = true;
1162811630

1162911631
LValue ThisVal;
1163011632
const LValue *ThisPtr = nullptr;
@@ -11708,6 +11710,7 @@ bool Expr::isPotentialConstantExprUnevaluated(Expr *E,
1170811710

1170911711
EvalInfo Info(FD->getASTContext(), Status,
1171011712
EvalInfo::EM_PotentialConstantExpressionUnevaluated);
11713+
Info.InConstantContext = true;
1171111714

1171211715
// Fabricate a call stack frame to give the arguments a plausible cover story.
1171311716
ArrayRef<const Expr*> Args;

clang/test/SemaCXX/constant-expression-cxx1y.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,3 +1135,27 @@ constexpr bool indirect_builtin_constant_p(const char *__s) {
11351135
return __builtin_constant_p(*__s);
11361136
}
11371137
constexpr bool n = indirect_builtin_constant_p("a");
1138+
1139+
__attribute__((enable_if(indirect_builtin_constant_p("a") == n, "OK")))
1140+
int test_in_enable_if() { return 0; }
1141+
int n2 = test_in_enable_if();
1142+
1143+
template <bool n = indirect_builtin_constant_p("a")>
1144+
int test_in_template_param() { return 0; }
1145+
int n3 = test_in_template_param();
1146+
1147+
void test_in_case(int n) {
1148+
switch (n) {
1149+
case indirect_builtin_constant_p("abc"):
1150+
break;
1151+
}
1152+
}
1153+
enum InEnum1 {
1154+
ONE = indirect_builtin_constant_p("abc")
1155+
};
1156+
enum InEnum2 : int {
1157+
TWO = indirect_builtin_constant_p("abc")
1158+
};
1159+
enum class InEnum3 {
1160+
THREE = indirect_builtin_constant_p("abc")
1161+
};

clang/test/SemaCXX/enable_if.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,3 +514,11 @@ namespace TypeOfFn {
514514

515515
static_assert(is_same<__typeof__(foo)*, decltype(&foo)>::value, "");
516516
}
517+
518+
namespace InConstantContext {
519+
void foo(const char *s) __attribute__((enable_if(((void)__builtin_constant_p(*s), true), "trap"))) {}
520+
521+
void test() {
522+
InConstantContext::foo("abc");
523+
}
524+
} // namespace InConstantContext

0 commit comments

Comments
 (0)