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.
/* 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;
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;
--- /dev/null
+// { 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 "" }
+}