Skip to content

Commit

Permalink
Merging r355743:
Browse files Browse the repository at this point in the history
------------------------------------------------------------------------
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
  • Loading branch information
zmodem committed Mar 12, 2019
1 parent 60c0551 commit 25292d1
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 0 deletions.
3 changes: 3 additions & 0 deletions clang/lib/AST/ExprConstant.cpp
Expand Up @@ -10985,6 +10985,7 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, ConstExprUsage Usage,
const ASTContext &Ctx) const {
EvalInfo::EvaluationMode EM = EvalInfo::EM_ConstantExpression;
EvalInfo Info(Ctx, Result, EM);
Info.InConstantContext = true;
if (!::Evaluate(Result.Val, Info, this))
return false;

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

LValue ThisVal;
const LValue *ThisPtr = nullptr;
Expand Down Expand Up @@ -11708,6 +11710,7 @@ bool Expr::isPotentialConstantExprUnevaluated(Expr *E,

EvalInfo Info(FD->getASTContext(), Status,
EvalInfo::EM_PotentialConstantExpressionUnevaluated);
Info.InConstantContext = true;

// Fabricate a call stack frame to give the arguments a plausible cover story.
ArrayRef<const Expr*> Args;
Expand Down
24 changes: 24 additions & 0 deletions clang/test/SemaCXX/constant-expression-cxx1y.cpp
Expand Up @@ -1135,3 +1135,27 @@ constexpr bool indirect_builtin_constant_p(const char *__s) {
return __builtin_constant_p(*__s);
}
constexpr bool n = indirect_builtin_constant_p("a");

__attribute__((enable_if(indirect_builtin_constant_p("a") == n, "OK")))
int test_in_enable_if() { return 0; }
int n2 = test_in_enable_if();

template <bool n = indirect_builtin_constant_p("a")>
int test_in_template_param() { return 0; }
int n3 = test_in_template_param();

void test_in_case(int n) {
switch (n) {
case indirect_builtin_constant_p("abc"):
break;
}
}
enum InEnum1 {
ONE = indirect_builtin_constant_p("abc")
};
enum InEnum2 : int {
TWO = indirect_builtin_constant_p("abc")
};
enum class InEnum3 {
THREE = indirect_builtin_constant_p("abc")
};
8 changes: 8 additions & 0 deletions clang/test/SemaCXX/enable_if.cpp
Expand Up @@ -514,3 +514,11 @@ namespace TypeOfFn {

static_assert(is_same<__typeof__(foo)*, decltype(&foo)>::value, "");
}

namespace InConstantContext {
void foo(const char *s) __attribute__((enable_if(((void)__builtin_constant_p(*s), true), "trap"))) {}

void test() {
InConstantContext::foo("abc");
}
} // namespace InConstantContext

0 comments on commit 25292d1

Please sign in to comment.