diff options
author | Marek Polacek <polacek@redhat.com> | 2019-08-28 02:03:48 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2019-08-28 02:03:48 +0000 |
commit | 14da3939da3adcef84816573caa9d93c7367507e (patch) | |
tree | 1bc500d3505ce6feb8743a102df9a66cbb3bf3d4 | |
parent | 4719ac2f2d1d770a840316d02e68fdff8e223129 (diff) | |
download | gcc-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/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 36 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated9.C | 49 |
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; +} |