* C++ PATCH for c++/91428 - warn about std::is_constant_evaluated in if constexpr
@ 2019-08-27 23:03 Marek Polacek
2019-08-28 7:06 ` Jason Merrill
0 siblings, 1 reply; 2+ messages in thread
From: Marek Polacek @ 2019-08-27 23:03 UTC (permalink / raw)
To: GCC Patches, Jason Merrill
As discussed in 91428 and in
<https://stackoverflow.com/questions/54251530/stdis-constant-evaluated-behavior>,
if constexpr (std::is_constant_evaluated ())
// ...
else
// ...
always evaluates the true branch. Someone in the SO post said "But hopefully
compilers will just diagnose that case" so I'm adding a warning.
I didn't want to invent a completely new warning so I'm tagging along
-Wtautological-compare.
Bootstrapped/regtested on x86_64-linux, ok for trunk?
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.
* g++.dg/cpp2a/is-constant-evaluated9.C: New test.
diff --git gcc/cp/cp-tree.h gcc/cp/cp-tree.h
index 42f180d1dd3..225dbb67c63 100644
--- gcc/cp/cp-tree.h
+++ 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 gcc/cp/semantics.c gcc/cp/semantics.c
index 1f7745933f9..8603e57e7f7 100644
--- gcc/cp/semantics.c
+++ 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 gcc/cp/typeck.c gcc/cp/typeck.c
index e2a4f285a72..c09bb309142 100644
--- gcc/cp/typeck.c
+++ 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 gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated9.C gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated9.C
new file mode 100644
index 00000000000..37833698992
--- /dev/null
+++ 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;
+}
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: C++ PATCH for c++/91428 - warn about std::is_constant_evaluated in if constexpr
2019-08-27 23:03 C++ PATCH for c++/91428 - warn about std::is_constant_evaluated in if constexpr Marek Polacek
@ 2019-08-28 7:06 ` Jason Merrill
0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2019-08-28 7:06 UTC (permalink / raw)
To: Marek Polacek; +Cc: GCC Patches
On Tue, Aug 27, 2019 at 5:50 PM Marek Polacek <polacek@redhat.com> wrote:
>
> As discussed in 91428 and in
> <https://stackoverflow.com/questions/54251530/stdis-constant-evaluated-behavior>,
>
> if constexpr (std::is_constant_evaluated ())
> // ...
> else
> // ...
>
> always evaluates the true branch. Someone in the SO post said "But hopefully
> compilers will just diagnose that case" so I'm adding a warning.
>
> I didn't want to invent a completely new warning so I'm tagging along
> -Wtautological-compare.
>
> Bootstrapped/regtested on x86_64-linux, ok for trunk?
OK.
Jason
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2019-08-28 1:53 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-27 23:03 C++ PATCH for c++/91428 - warn about std::is_constant_evaluated in if constexpr Marek Polacek
2019-08-28 7:06 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).