Hi,
in the language of our implementations details, submitter noticed that
in terms of warnings we handle in a different way COND_EXPRs in
tsubst_copy_and_build - we use fold_non_dependent_expr and integer_zerop
to suppress undesired warnings by bumping c_inhibit_evaluation_warnings
- and IF_STMTs in tsubst_expr, where we don't. My patch below, which
passes testing, tries in a rather straightforward way to adopt the same
mechanisms in the latter. There are quite a few details I'm not sure
about: whether we should only use fold_non_dependent_expr for the
purpose of suppressing the warnings - thus never touching 'tmp' in the
pt.c code handling IF_STMTs - which would be completely conservative in
terms of code generation; whether there are subtle interactions with the
new if constexpr, which I'm missing at the moment.
Thanks!
Paolo.
//
Index: cp/pt.c
===
--- cp/pt.c (revision 241297)
+++ cp/pt.c (working copy)
@@ -15403,26 +15403,46 @@
break;
case IF_STMT:
- stmt = begin_if_stmt ();
- IF_STMT_CONSTEXPR_P (stmt) = IF_STMT_CONSTEXPR_P (t);
- tmp = RECUR (IF_COND (t));
- tmp = finish_if_stmt_cond (tmp, stmt);
- if (IF_STMT_CONSTEXPR_P (t) && integer_zerop (tmp))
- /* Don't instantiate the THEN_CLAUSE. */;
- else
- RECUR (THEN_CLAUSE (t));
- finish_then_clause (stmt);
+ {
+ tree folded_tmp;
+ bool zerop, nonzerop;
- if (IF_STMT_CONSTEXPR_P (t) && integer_nonzerop (tmp))
- /* Don't instantiate the ELSE_CLAUSE. */;
- else if (ELSE_CLAUSE (t))
- {
- begin_else_clause (stmt);
- RECUR (ELSE_CLAUSE (t));
- finish_else_clause (stmt);
- }
+ stmt = begin_if_stmt ();
+ IF_STMT_CONSTEXPR_P (stmt) = IF_STMT_CONSTEXPR_P (t);
+ tmp = RECUR (IF_COND (t));
+ folded_tmp = fold_non_dependent_expr (tmp);
+ if (TREE_CODE (folded_tmp) == INTEGER_CST)
+ tmp = folded_tmp;
+ tmp = finish_if_stmt_cond (tmp, stmt);
+ zerop = integer_zerop (tmp);
+ nonzerop = integer_nonzerop (tmp);
+ if (IF_STMT_CONSTEXPR_P (t) && zerop)
+ /* Don't instantiate the THEN_CLAUSE. */;
+ else
+ {
+ if (zerop)
+ ++c_inhibit_evaluation_warnings;
+ RECUR (THEN_CLAUSE (t));
+ if (zerop)
+ --c_inhibit_evaluation_warnings;
+ }
+ finish_then_clause (stmt);
- finish_if_stmt (stmt);
+ if (IF_STMT_CONSTEXPR_P (t) && nonzerop)
+ /* Don't instantiate the ELSE_CLAUSE. */;
+ else if (ELSE_CLAUSE (t))
+ {
+ begin_else_clause (stmt);
+ if (nonzerop)
+ ++c_inhibit_evaluation_warnings;
+ RECUR (ELSE_CLAUSE (t));
+ if (nonzerop)
+ --c_inhibit_evaluation_warnings;
+ finish_else_clause (stmt);
+ }
+
+ finish_if_stmt (stmt);
+ }
break;
case BIND_EXPR:
Index: testsuite/g++.dg/cpp1y/pr67980.C
===
--- testsuite/g++.dg/cpp1y/pr67980.C(revision 0)
+++ testsuite/g++.dg/cpp1y/pr67980.C(working copy)
@@ -0,0 +1,23 @@
+// { dg-do compile { target c++14 } }
+
+template
+constexpr T cpp14_constexpr_then(T value) {
+ if (Y < 0)
+return (value << -Y);
+ else
+return 0;
+}
+
+template
+constexpr T cpp14_constexpr_else(T value) {
+ if (Y > 0)
+return 0;
+ else
+return (value << -Y);
+}
+
+int main()
+{
+ cpp14_constexpr_then<1>(0);
+ cpp14_constexpr_else<1>(0);
+}