diff options
author | Jason Merrill <jason@redhat.com> | 2017-06-09 16:13:44 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2017-06-09 16:13:44 -0400 |
commit | 3d2e25a240c7115c3deaaa9dea856588300dd05b (patch) | |
tree | d62877692ea79f92fd2ed3df7896feb329728f5f | |
parent | 55c5c0ad3c32a5c9e5be4a606b9c9925f5416046 (diff) | |
download | gcc-3d2e25a240c7115c3deaaa9dea856588300dd05b.zip gcc-3d2e25a240c7115c3deaaa9dea856588300dd05b.tar.gz gcc-3d2e25a240c7115c3deaaa9dea856588300dd05b.tar.bz2 |
Fix array decay handling in constant expressions.
* parser.c (cp_parser_constant_expression): Check
potential_rvalue_constant_expression after decay_conversion.
* pt.c (convert_nontype_argument): Don't require linkage in C++17.
From-SVN: r249079
-rw-r--r-- | gcc/cp/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/cp/parser.c | 8 | ||||
-rw-r--r-- | gcc/cp/pt.c | 35 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/function1.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/nontype-array1.C | 27 |
5 files changed, 72 insertions, 6 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 944b695..7bc9c20 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2017-06-09 Jason Merrill <jason@redhat.com> + * parser.c (cp_parser_constant_expression): Check + potential_rvalue_constant_expression after decay_conversion. + * pt.c (convert_nontype_argument): Don't require linkage in C++17. + PR c++/80384 - ICE with dependent noexcept-specifier * pt.c (dependent_type_p_r) [FUNCTION_TYPE]: Check for dependent noexcept-specifier. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 891341d..78f7d66 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -9462,10 +9462,14 @@ cp_parser_constant_expression (cp_parser* parser, /* Require an rvalue constant expression here; that's what our callers expect. Reference constant expressions are handled separately in e.g. cp_parser_template_argument. */ - bool is_const = potential_rvalue_constant_expression (expression); + tree decay = expression; + if (TREE_TYPE (expression) + && TREE_CODE (TREE_TYPE (expression)) == ARRAY_TYPE) + decay = build_address (expression); + bool is_const = potential_rvalue_constant_expression (decay); parser->non_integral_constant_expression_p = !is_const; if (!is_const && !allow_non_constant_p) - require_potential_rvalue_constant_expression (expression); + require_potential_rvalue_constant_expression (decay); } if (allow_non_constant_p) *non_constant_p = parser->non_integral_constant_expression_p; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 99f5b12..d8f8d46 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -6683,13 +6683,46 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) expr, type, decl); return NULL_TREE; } - else if (cxx_dialect >= cxx11 && decl_linkage (decl) == lk_none) + else if ((cxx_dialect >= cxx11 && cxx_dialect < cxx1z) + && decl_linkage (decl) == lk_none) { if (complain & tf_error) error ("%qE is not a valid template argument of type %qT " "because %qD has no linkage", expr, type, decl); return NULL_TREE; } + /* C++17: For a non-type template-parameter of reference or pointer + type, the value of the constant expression shall not refer to (or + for a pointer type, shall not be the address of): + * a subobject (4.5), + * a temporary object (15.2), + * a string literal (5.13.5), + * the result of a typeid expression (8.2.8), or + * a predefined __func__ variable (11.4.1). */ + else if (DECL_ARTIFICIAL (decl)) + { + if (complain & tf_error) + error ("the address of %qD is not a valid template argument", + decl); + return NULL_TREE; + } + else if (!same_type_ignoring_top_level_qualifiers_p + (strip_array_types (TREE_TYPE (type)), + strip_array_types (TREE_TYPE (decl)))) + { + if (complain & tf_error) + error ("the address of the %qT subobject of %qD is not a " + "valid template argument", TREE_TYPE (type), decl); + return NULL_TREE; + } + else if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl)) + { + if (complain & tf_error) + error ("the address of %qD is not a valid template argument " + "because it does not have static storage duration", + decl); + return NULL_TREE; + } } expr = decay_conversion (expr, complain); diff --git a/gcc/testsuite/g++.dg/template/function1.C b/gcc/testsuite/g++.dg/template/function1.C index f234585..4bab2e4 100644 --- a/gcc/testsuite/g++.dg/template/function1.C +++ b/gcc/testsuite/g++.dg/template/function1.C @@ -1,10 +1,8 @@ // PR c++/38647 -// { dg-do compile { target { ! c++1z } } } -// { dg-prune-output "note" } template<const char *, int> struct A {}; const char func[] = "abc"; -template<int N> struct A<func, N> {}; // { dg-error "cannot appear|is invalid|not a valid|constant expression" } +template<int N> struct A<func, N> {}; // { dg-error "cannot appear|is invalid|not a valid|constant expression" "" { target c++98_only } } char a1[1]; A<a1, 0> a; diff --git a/gcc/testsuite/g++.dg/template/nontype-array1.C b/gcc/testsuite/g++.dg/template/nontype-array1.C new file mode 100644 index 0000000..cf21908 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/nontype-array1.C @@ -0,0 +1,27 @@ +// { dg-do compile { target c++11 } } + +template <char const* STR> +class Message { +}; + +extern char const s1[] = "hi"; +char const s2[] = "hi"; +constexpr char const s3[] = "hi"; // OK since C++11 + +constexpr char const * f() { return s3; } + +int main() +{ + Message<s1> m1; // OK (all versions) + Message<s2> m2; // OK for clang since C++14, for gcc since C++17 + Message<s3> m3; // OK for clang/gcc since C++11 + + static char const s4[] = "hi"; + static constexpr char const s5[] = "hi"; // OK since C++11 + Message<s4> m4; // { dg-error "no linkage" "" { target c++14_down } } + Message<s5> m5; // { dg-error "no linkage" "" { target c++14_down } } + Message<f()> m6; // { dg-error "" "" { target c++14_down } } + + char const s8[] = "hi"; + Message<s8> m8; // { dg-error "" } +} |