summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDávid Bolvanský <david.bolvansky@gmail.com>2019-10-29 19:06:48 +0100
committerDávid Bolvanský <david.bolvansky@gmail.com>2019-10-31 10:03:11 +0100
commitb06305e44949fb843310d27b139e5064b214a838 (patch)
tree7e0305af30caff001e8e7f34be3b50ec24df45dd
parentc9504954052a7630a6e760006297b5fc73a03e4a (diff)
downloadbcm5719-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.td4
-rw-r--r--clang/lib/AST/ExprConstant.cpp18
-rw-r--r--clang/test/SemaCXX/builtin-is-constant-evaluated.cpp2
-rw-r--r--clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp56
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;
+}
OpenPOWER on IntegriCloud