PR c++/91428 - warn about std::is_constant_evaluated in if constexpr.
authorMarek Polacek <polacek@redhat.com>
Wed, 28 Aug 2019 02:03:48 +0000 (02:03 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Wed, 28 Aug 2019 02:03:48 +0000 (02:03 +0000)
* cp-tree.h (decl_in_std_namespace_p): Declare.
* semantics.c (is_std_constant_evaluated_p): New.
(finish_if_stmt_cond): Warn about "std::is_constant_evaluated ()" in
an if-constexpr.
* typeck.c (decl_in_std_namespace_p): No longer static.

* g++.dg/cpp2a/is-constant-evaluated9.C: New test.

From-SVN: r274981

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/semantics.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated9.C [new file with mode: 0644]

index 162b2c81c75a71d0fca8f968109497c3e18ffdb3..c2f19670a249d8bfe3fa3c511c57bb43b89ecdfd 100644 (file)
@@ -1,3 +1,12 @@
+2019-08-27  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/91428 - warn about std::is_constant_evaluated in if constexpr.
+       * cp-tree.h (decl_in_std_namespace_p): Declare.
+       * semantics.c (is_std_constant_evaluated_p): New.
+       (finish_if_stmt_cond): Warn about "std::is_constant_evaluated ()" in
+       an if-constexpr.
+       * typeck.c (decl_in_std_namespace_p): No longer static.
+
 2019-08-26  Jason Merrill  <jason@redhat.com>
 
        * decl.c (duplicate_decls): Always merge DECL_DECLARED_CONSTEXPR_P.
index 42f180d1dd3669d23f69d62a4fb541967b7f5314..225dbb67c635ce214613173978a849bf58e5980d 100644 (file)
@@ -7496,6 +7496,7 @@ extern tree finish_left_unary_fold_expr      (tree, int);
 extern tree finish_right_unary_fold_expr     (tree, int);
 extern tree finish_binary_fold_expr          (tree, tree, int);
 extern bool treat_lvalue_as_rvalue_p        (tree, bool);
+extern bool decl_in_std_namespace_p         (tree);
 
 /* in typeck2.c */
 extern void require_complete_eh_spec_types     (tree, tree);
index 1f7745933f95aff9378b3d19034c53c30b0b792f..8603e57e7f7a9637d1f9cf92cc26cfbdc0ab4e07 100644 (file)
@@ -723,6 +723,28 @@ begin_if_stmt (void)
   return r;
 }
 
+/* Returns true if FN, a CALL_EXPR, is a call to
+   std::is_constant_evaluated or __builtin_is_constant_evaluated.  */
+
+static bool
+is_std_constant_evaluated_p (tree fn)
+{
+  /* std::is_constant_evaluated takes no arguments.  */
+  if (call_expr_nargs (fn) != 0)
+    return false;
+
+  tree fndecl = cp_get_callee_fndecl_nofold (fn);
+  if (fndecl_built_in_p (fndecl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
+                        BUILT_IN_FRONTEND))
+    return true;
+
+  if (!decl_in_std_namespace_p (fndecl))
+    return false;
+
+  tree name = DECL_NAME (fndecl);
+  return name && id_equal (name, "is_constant_evaluated");
+}
+
 /* Process the COND of an if-statement, which may be given by
    IF_STMT.  */
 
@@ -738,6 +760,20 @@ finish_if_stmt_cond (tree cond, tree if_stmt)
         converted to bool.  */
       && TYPE_MAIN_VARIANT (TREE_TYPE (cond)) == boolean_type_node)
     {
+      /* if constexpr (std::is_constant_evaluated()) is always true,
+        so give the user a clue.  */
+      if (warn_tautological_compare)
+       {
+         tree t = cond;
+         if (TREE_CODE (t) == CLEANUP_POINT_EXPR)
+           t = TREE_OPERAND (t, 0);
+         if (TREE_CODE (t) == CALL_EXPR
+             && is_std_constant_evaluated_p (t))
+           warning_at (EXPR_LOCATION (cond), OPT_Wtautological_compare,
+                       "%qs always evaluates to true in %<if constexpr%>",
+                       "std::is_constant_evaluated");
+       }
+
       cond = instantiate_non_dependent_expr (cond);
       cond = cxx_constant_value (cond, NULL_TREE);
     }
index e2a4f285a726191d9b358dfba68e865893126530..c09bb309142d7b52970c5bfe525e3353b6ea4d3e 100644 (file)
@@ -9328,7 +9328,7 @@ maybe_warn_about_returning_address_of_local (tree retval)
 
 /* Returns true if DECL is in the std namespace.  */
 
-static bool
+bool
 decl_in_std_namespace_p (tree decl)
 {
   return (decl != NULL_TREE
index cd6fb7fc8f6a4a633da73008e6842edbb190d1f4..ade1a69767fc7373637cd3ee07a63f8588075d88 100644 (file)
@@ -1,3 +1,8 @@
+2019-08-27  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/91428 - warn about std::is_constant_evaluated in if constexpr.
+       * g++.dg/cpp2a/is-constant-evaluated9.C: New test.
+
 2019-08-27  Martin Sebor  <msebor@redhat.com>
 
        PR tree-optimization/91567
diff --git a/gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated9.C b/gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated9.C
new file mode 100644 (file)
index 0000000..3783369
--- /dev/null
@@ -0,0 +1,49 @@
+// PR c++/91428 - warn about std::is_constant_evaluated in if constexpr.
+// { dg-do compile { target c++2a } }
+// { dg-options "-Wtautological-compare" }
+
+namespace std {
+  constexpr inline bool
+  is_constant_evaluated () noexcept
+  {
+    return __builtin_is_constant_evaluated (); 
+  }
+}
+
+constexpr int
+foo(int i)
+{
+  if constexpr (std::is_constant_evaluated ()) // { dg-warning ".std::is_constant_evaluated. always evaluates to true in .if constexpr." }
+    return 42;
+  else
+    return i;
+}
+
+constexpr int
+foo2(int i)
+{
+  if constexpr (__builtin_is_constant_evaluated ()) // { dg-warning ".std::is_constant_evaluated. always evaluates to true in .if constexpr." }
+    return 42;
+  else
+    return i;
+}
+
+constexpr int
+foo3(int i)
+{
+  // I is not a constant expression but we short-circuit it.
+  if constexpr (__builtin_is_constant_evaluated () || i)
+    return 42;
+  else
+    return i;
+}
+
+constexpr int
+foo4(int i)
+{
+  const int j = 0;
+  if constexpr (j && __builtin_is_constant_evaluated ())
+    return 42;
+  else
+    return i;
+}