diff options
author | Hans Wennborg <hans@hanshq.net> | 2019-03-12 08:29:08 +0000 |
---|---|---|
committer | Hans Wennborg <hans@hanshq.net> | 2019-03-12 08:29:08 +0000 |
commit | 25292d1cd55b9a4c788b1c6b0c78647ab88822dd (patch) | |
tree | 32ae5b88a1341a6d0fa920bffe0f8dcd1d7f65d4 | |
parent | 60c055135da0c00c07875c7e9b6b8627088860c5 (diff) | |
download | llvm-25292d1cd55b9a4c788b1c6b0c78647ab88822dd.zip llvm-25292d1cd55b9a4c788b1c6b0c78647ab88822dd.tar.gz llvm-25292d1cd55b9a4c788b1c6b0c78647ab88822dd.tar.bz2 |
Merging r355743:llvmorg-8.0.0-rc5
------------------------------------------------------------------------
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
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 3 | ||||
-rw-r--r-- | clang/test/SemaCXX/constant-expression-cxx1y.cpp | 24 | ||||
-rw-r--r-- | clang/test/SemaCXX/enable_if.cpp | 8 |
3 files changed, 35 insertions, 0 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 1f82b4a..bfe6c78 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -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; @@ -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; @@ -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; diff --git a/clang/test/SemaCXX/constant-expression-cxx1y.cpp b/clang/test/SemaCXX/constant-expression-cxx1y.cpp index 3c57ac5..ed51cca 100644 --- a/clang/test/SemaCXX/constant-expression-cxx1y.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx1y.cpp @@ -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") +}; diff --git a/clang/test/SemaCXX/enable_if.cpp b/clang/test/SemaCXX/enable_if.cpp index ba520b0..4bc974d 100644 --- a/clang/test/SemaCXX/enable_if.cpp +++ b/clang/test/SemaCXX/enable_if.cpp @@ -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 |