[PATCH] D69518: [Diagnostics] Warn for std::is_constant_evaluated in constexpr mode

Dávid Bolvanský via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 28 15:21:05 PDT 2019


xbolva00 updated this revision to Diff 226758.
xbolva00 added a comment.

Support !E.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D69518/new/

https://reviews.llvm.org/D69518

Files:
  clang/include/clang/AST/Expr.h
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/SemaCXX/warn-std-is-constant-evaluated-constexpr.cpp


Index: clang/test/SemaCXX/warn-std-is-constant-evaluated-constexpr.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/warn-std-is-constant-evaluated-constexpr.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -std=c++2a -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++2a -fsyntax-only -verify -Wtautological-compare %s
+
+namespace std {
+constexpr bool is_constant_evaluated() noexcept {
+  return __builtin_is_constant_evaluated();
+}
+}
+
+constexpr int fn1() {
+  if constexpr (std::is_constant_evaluated()) // expected-warning {{'std::is_constant_evaluated' will always evaluate to 'true' in constexpr mode}}
+    return 0;
+  else
+    return 1;
+}
+
+constexpr int fn2() {
+  if (std::is_constant_evaluated())
+    return 0;
+  else
+    return 1;
+}
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -3664,6 +3664,22 @@
   llvm_unreachable("unexpected condition kind");
 }
 
+static void checkStdIsConstantEvaluated(Sema &S, Expr *BoolExpr,
+                                        bool IsConstexpr) {
+  if (!IsConstexpr)
+    return;
+  BoolExpr = BoolExpr->IgnoreParens();
+  CallExpr *Call = nullptr;
+  UnaryOperator *UO = dyn_cast<UnaryOperator>(BoolExpr);
+  if (UO && UO->getOpcode() == UO_LNot)
+    BoolExpr = UO->getSubExpr();
+
+  Call = dyn_cast<CallExpr>(BoolExpr);
+  if (Call && Call->isCallToStdIsConstantEvaluated())
+    S.Diag(Call->getBeginLoc(),
+         diag::warn_std_is_constant_evaluated_always_true_constexpr);
+}
+
 /// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid.
 ExprResult Sema::CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr) {
   // C++ 6.4p4:
@@ -3675,6 +3691,7 @@
   // expression, implicitly converted to bool.
   //
   // FIXME: Return this value to the caller so they don't need to recompute it.
+  checkStdIsConstantEvaluated(*this, CondExpr, IsConstexpr);
   llvm::APSInt Value(/*BitWidth*/1);
   return (IsConstexpr && !CondExpr->isValueDependent())
              ? CheckConvertedConstantExpression(CondExpr, Context.BoolTy, Value,
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8405,6 +8405,9 @@
   "%select{self-|array }0comparison always evaluates to "
   "%select{a constant|true|false|'std::strong_ordering::equal'}1">,
   InGroup<TautologicalCompare>;
+def warn_std_is_constant_evaluated_always_true_constexpr : Warning<
+  "'std::is_constant_evaluated' will always evaluate to "
+  "'true' in constexpr mode">, InGroup<TautologicalCompare>;
 def warn_comparison_bitwise_always : Warning<
   "bitwise comparison always evaluates to %select{false|true}0">,
   InGroup<TautologicalBitwiseCompare>, DefaultIgnore;
Index: clang/include/clang/AST/Expr.h
===================================================================
--- clang/include/clang/AST/Expr.h
+++ clang/include/clang/AST/Expr.h
@@ -2777,6 +2777,13 @@
            FD->getIdentifier() && FD->getIdentifier()->isStr("move");
   }
 
+  bool isCallToStdIsConstantEvaluated() const {
+    const FunctionDecl *FD = getDirectCallee();
+    return getNumArgs() == 0 && FD && FD->isInStdNamespace() &&
+           FD->getIdentifier() &&
+           FD->getIdentifier()->isStr("is_constant_evaluated");
+  }
+
   static bool classof(const Stmt *T) {
     return T->getStmtClass() >= firstCallExprConstant &&
            T->getStmtClass() <= lastCallExprConstant;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D69518.226758.patch
Type: text/x-patch
Size: 3680 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20191028/3f55a239/attachment.bin>


More information about the cfe-commits mailing list