Commit 3d2e25a2 by Jason Merrill Committed by Jason Merrill

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
parent 55c5c0ad
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.
......
......@@ -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;
......@@ -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);
......
// 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;
......
// { 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 "" }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment