From 9155a6ddc40af0eed7079eac318e6dd864dcdbc9 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 25 Jul 2012 10:56:57 -0400 Subject: [PATCH] re PR c++/54020 ([c++0x] incorrectly accepted constexpr functions) PR c++/54020 * semantics.c (potential_constant_expression_1) [COND_EXPR]: Call maybe_constant_value. From-SVN: r189851 --- gcc/cp/ChangeLog | 4 +++ gcc/cp/semantics.c | 19 +++++++++++---- gcc/testsuite/g++.dg/cpp0x/constexpr-neg2.C | 27 +++++++++++++++++++++ 3 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-neg2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e7b47111e26..f5fbb5cf7db 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2012-07-25 Jason Merrill + PR c++/54020 + * semantics.c (potential_constant_expression_1) [COND_EXPR]: Call + maybe_constant_value. + * cp-tree.h (tsubst_flags): Remove tf_no_access_control. * call.c (standard_conversion): Don't set it. * class.c (resolve_address_of_overloaded_function): Don't check it. diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 6381949a664..b27e8ab128b 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -8497,10 +8497,17 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) case TRUTH_ORIF_EXPR: tmp = boolean_false_node; truth: - if (TREE_OPERAND (t, 0) == tmp) - return potential_constant_expression_1 (TREE_OPERAND (t, 1), rval, flags); - else - return potential_constant_expression_1 (TREE_OPERAND (t, 0), rval, flags); + { + tree op = TREE_OPERAND (t, 0); + if (!potential_constant_expression_1 (op, rval, flags)) + return false; + if (!processing_template_decl) + op = maybe_constant_value (op); + if (tree_int_cst_equal (op, tmp)) + return potential_constant_expression_1 (TREE_OPERAND (t, 1), rval, flags); + else + return true; + } case PLUS_EXPR: case MULT_EXPR: @@ -8556,7 +8563,9 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) tmp = TREE_OPERAND (t, 0); if (!potential_constant_expression_1 (tmp, rval, flags)) return false; - else if (integer_zerop (tmp)) + if (!processing_template_decl) + tmp = maybe_constant_value (tmp); + if (integer_zerop (tmp)) return potential_constant_expression_1 (TREE_OPERAND (t, 2), want_rval, flags); else if (TREE_CODE (tmp) == INTEGER_CST) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-neg2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-neg2.C new file mode 100644 index 00000000000..793b4c3f5d3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-neg2.C @@ -0,0 +1,27 @@ +// PR c++/54020 +// { dg-do compile { target c++11 } } + +// Preliminaries. +extern int nonconst_func(int); +constexpr int identity(int x) { return x; } +constexpr int zero() { return identity(0); } +constexpr int one() { return identity(1); } + +// Correctly accepted. +constexpr int three = one() ? 3 : nonconst_func(0); + +// Incorrectly accepted. See [dcl.constexpr] #5: +// For a constexpr function, if no function argument values exist +// such that the function invocation sub-stitution would produce a +// constant expression (5.19), the program is ill-formed; no diagnostic +// required. +constexpr int bogus() { return zero () ? 3 : nonconst_func(0); } // { dg-error "nonconst_func" } + +// Correctly rejected (not sure why). +constexpr int correct_error() { return nonconst_func(0); } // { dg-error "nonconst_func" } + +// Correctly rejected. +constexpr int z = bogus(); // { dg-error "" } + +// This is also correctly rejected. +constexpr int correct_failure() { return 0 ? 3 : nonconst_func(0); } // { dg-error "nonconst_func" }