aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2019-08-28 02:03:48 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2019-08-28 02:03:48 +0000
commit14da3939da3adcef84816573caa9d93c7367507e (patch)
tree1bc500d3505ce6feb8743a102df9a66cbb3bf3d4
parent4719ac2f2d1d770a840316d02e68fdff8e223129 (diff)
downloadgcc-14da3939da3adcef84816573caa9d93c7367507e.zip
gcc-14da3939da3adcef84816573caa9d93c7367507e.tar.gz
gcc-14da3939da3adcef84816573caa9d93c7367507e.tar.bz2
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. * g++.dg/cpp2a/is-constant-evaluated9.C: New test. From-SVN: r274981
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/semantics.c36
-rw-r--r--gcc/cp/typeck.c2
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated9.C49
6 files changed, 101 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 162b2c8..c2f1967 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 42f180d..225dbb6 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 1f774593..8603e57 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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);
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index e2a4f28..c09bb30 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index cd6fb7f..ade1a69 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..3783369
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated9.C
@@ -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;
+}