* 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
+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.
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);
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. */
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);
}
/* Returns true if DECL is in the std namespace. */
-static bool
+bool
decl_in_std_namespace_p (tree decl)
{
return (decl != NULL_TREE
+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
--- /dev/null
+// 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;
+}