diff options
| author | Dávid Bolvanský <david.bolvansky@gmail.com> | 2019-10-29 19:06:48 +0100 |
|---|---|---|
| committer | Dávid Bolvanský <david.bolvansky@gmail.com> | 2019-10-31 10:03:11 +0100 |
| commit | b06305e44949fb843310d27b139e5064b214a838 (patch) | |
| tree | 7e0305af30caff001e8e7f34be3b50ec24df45dd | |
| parent | c9504954052a7630a6e760006297b5fc73a03e4a (diff) | |
| download | bcm5719-llvm-b06305e44949fb843310d27b139e5064b214a838.tar.gz bcm5719-llvm-b06305e44949fb843310d27b139e5064b214a838.zip | |
[Diagnostics] Warn for std::is_constant_evaluated in constexpr mode
Summary:
constexpr int fn1() {
if constexpr (std::is_constant_evaluated()) // condition is always true!
return 0;
else
return 1;
}
constexpr int fn2() {
if (std::is_constant_evaluated())
return 0;
else
return 1;
}
Solves PR42977
Reviewers: rsmith, aaron.ballman
Reviewed By: rsmith
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D69518
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticASTKinds.td | 4 | ||||
| -rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 18 | ||||
| -rw-r--r-- | clang/test/SemaCXX/builtin-is-constant-evaluated.cpp | 2 | ||||
| -rw-r--r-- | clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp | 56 |
4 files changed, 78 insertions, 2 deletions
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index 04d767445a8..814e1e61bd7 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -329,6 +329,10 @@ def warn_integer_constant_overflow : Warning< def note_unimplemented_constexpr_lambda_feature_ast : Note< "unimplemented constexpr lambda feature: %0 (coming soon!)">; +def warn_is_constant_evaluated_always_true_constexpr : Warning< + "'%0' will always evaluate to 'true' in a manifestly constant-evaluated expression">, + InGroup<DiagGroup<"constant-evaluated">>; + // inline asm related. let CategoryName = "Inline Assembly Issue" in { def err_asm_invalid_escape : Error< diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index ecd9eda7648..f4ca2284224 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -10593,8 +10593,24 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return false; } - case Builtin::BI__builtin_is_constant_evaluated: + case Builtin::BI__builtin_is_constant_evaluated: { + const auto *Callee = Info.CurrentCall->getCallee(); + if (Info.InConstantContext && !Info.CheckingPotentialConstantExpression && + (Info.CallStackDepth == 1 || + (Info.CallStackDepth == 2 && Callee->isInStdNamespace() && + Callee->getIdentifier() && + Callee->getIdentifier()->isStr("is_constant_evaluated")))) { + // FIXME: Find a better way to avoid duplicated diagnostics. + if (Info.EvalStatus.Diag) + Info.report((Info.CallStackDepth == 1) ? E->getExprLoc() + : Info.CurrentCall->CallLoc, + diag::warn_is_constant_evaluated_always_true_constexpr) + << (Info.CallStackDepth == 1 ? "__builtin_is_constant_evaluated" + : "std::is_constant_evaluated"); + } + return Success(Info.InConstantContext, E); + } case Builtin::BI__builtin_ctz: case Builtin::BI__builtin_ctzl: diff --git a/clang/test/SemaCXX/builtin-is-constant-evaluated.cpp b/clang/test/SemaCXX/builtin-is-constant-evaluated.cpp index b2ec5cb9fa0..4af2b494751 100644 --- a/clang/test/SemaCXX/builtin-is-constant-evaluated.cpp +++ b/clang/test/SemaCXX/builtin-is-constant-evaluated.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++2a -verify %s -fcxx-exceptions -triple=x86_64-linux-gnu +// RUN: %clang_cc1 -std=c++2a -verify %s -fcxx-exceptions -Wno-constant-evaluated -triple=x86_64-linux-gnu using size_t = decltype(sizeof(int)); diff --git a/clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp b/clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp new file mode 100644 index 00000000000..35dc69cccb3 --- /dev/null +++ b/clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -std=c++2a -fsyntax-only -verify %s + +namespace std { +constexpr bool is_constant_evaluated() noexcept { + return __builtin_is_constant_evaluated(); +} +} // namespace std + +constexpr int fn1() { + if constexpr (std::is_constant_evaluated()) // expected-warning {{'std::is_constant_evaluated' will always evaluate to 'true' in a manifestly constant-evaluated expression}} + return 0; + else + return 1; +} + +constexpr int fn2() { + if constexpr (!std::is_constant_evaluated()) // expected-warning {{'std::is_constant_evaluated' will always evaluate to 'true' in a manifestly constant-evaluated expression}} + return 0; + else + return 1; +} + +constexpr int fn3() { + if constexpr (std::is_constant_evaluated() == false) // expected-warning {{'std::is_constant_evaluated' will always evaluate to 'true' in a manifestly constant-evaluated expression}} + return 0; + else + return 1; +} + +constexpr int fn4() { + if constexpr (__builtin_is_constant_evaluated() == true) // expected-warning {{'__builtin_is_constant_evaluated' will always evaluate to 'true' in a manifestly constant-evaluated expression}} + return 0; + else + return 1; +} + +constexpr int fn5() { + if constexpr (__builtin_is_constant_evaluated()) // expected-warning {{'__builtin_is_constant_evaluated' will always evaluate to 'true' in a manifestly constant-evaluated expression}} + return 0; + else + return 1; +} + +constexpr int nowarn1() { + if (std::is_constant_evaluated()) + return 0; + else + return 1; +} + +constexpr int nowarn2() { + if (!__builtin_is_constant_evaluated()) + return 0; + else + return 1; +} |

