2
0
mirror of git://gcc.gnu.org/git/gcc.git synced 2025-04-10 01:20:56 +08:00

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
This commit is contained in:
Marek Polacek 2019-08-28 02:03:48 +00:00 committed by Marek Polacek
parent 4719ac2f2d
commit 14da3939da
6 changed files with 101 additions and 1 deletions

@ -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.

@ -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);

@ -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);
}

@ -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

@ -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

@ -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;
}