Commit 2a9fb712 by Jason Merrill Committed by Jason Merrill

Implement N4268, Do constant evaluation of all non-type template args.

gcc/c-family/
	* c-cppbuiltin.c (c_cpp_builtins): Define
	__cpp_nontype_template_args.
gcc/cp/
	* parser.c (cp_parser_template_argument): For C++1z just parse a
	constant-expression.
	* pt.c (convert_nontype_argument): For C++1z always call
	maybe_constant_value.

From-SVN: r229019
parent dcdbc004
2015-10-19 Jason Merrill <jason@redhat.com>
* c-cppbuiltin.c (c_cpp_builtins): Define
__cpp_nontype_template_args.
2015-10-19 Jason Merrill <jason@redhat.com>
* c-cppbuiltin.c (c_cpp_builtins): Define
__cpp_enumerator_attributes, __cpp_fold_expressions,
__cpp_unicode_characters.
......
......@@ -876,6 +876,7 @@ c_cpp_builtins (cpp_reader *pfile)
cpp_define (pfile, "__cpp_enumerator_attributes=201411");
cpp_define (pfile, "__cpp_nested_namespace_definitions=201411");
cpp_define (pfile, "__cpp_fold_expressions=201411");
cpp_define (pfile, "__cpp_nontype_template_args=201411");
}
if (flag_concepts)
/* Use a value smaller than the 201507 specified in
......
2015-10-19 Jason Merrill <jason@redhat.com>
Implement N4268, Do constant evaluation of all non-type template args.
* parser.c (cp_parser_template_argument): For C++1z just parse a
constant-expression.
* pt.c (convert_nontype_argument): For C++1z always call
maybe_constant_value.
* constexpr.c (cxx_eval_constant_expression): Expand PTRMEM_CST
only when necessary.
(cxx_eval_component_reference): Like here.
......
......@@ -14977,8 +14977,12 @@ cp_parser_template_argument (cp_parser* parser)
warn_deprecated_use (argument, NULL_TREE);
return argument;
}
/* It must be a non-type argument. There permitted cases are given
in [temp.arg.nontype]:
/* It must be a non-type argument. In C++17 any constant-expression is
allowed. */
if (cxx_dialect > cxx14)
goto general_expr;
/* Otherwise, the permitted cases are given in [temp.arg.nontype]:
-- an integral constant-expression of integral or enumeration
type; or
......@@ -15090,6 +15094,7 @@ cp_parser_template_argument (cp_parser* parser)
return error_mark_node;
}
general_expr:
/* If the argument wasn't successfully parsed as a type-id followed
by '>>', the argument can only be a constant expression now.
Otherwise, we try parsing the constant-expression tentatively,
......@@ -6233,6 +6233,17 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
CONSTRUCTOR. */;
else if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
expr = maybe_constant_value (expr);
else if (cxx_dialect >= cxx1z)
{
if (TREE_CODE (type) != REFERENCE_TYPE)
expr = maybe_constant_value (expr);
else if (REFERENCE_REF_P (expr))
{
expr = TREE_OPERAND (expr, 0);
expr = maybe_constant_value (expr);
expr = convert_from_reference (expr);
}
}
else if (TYPE_PTR_OR_PTRMEM_P (type))
{
tree folded = maybe_constant_value (expr);
......
// { dg-options -std=c++1z }
struct S { int m; static int s; } s;
struct T: S { };
template<int* p> class X { };
template<const int S::*> class M {};
template<const S&> class SP {};
constexpr int *p = &S::s;
constexpr int S::*sp = &T::m;
constexpr S& sr = s;
constexpr S& sf() { return s; }
// { dg-final { scan-assembler "_Z1g1XIXadL_ZN1S1sEEEE" } }
void g (X<&s.s>) { }
// { dg-final { scan-assembler "_Z1f1XIXadL_ZN1S1sEEEE" } }
void f (X<p>) { }
// { dg-final { scan-assembler "_Z1f1MIXadL_ZN1S1mEEEE" } }
void f (M<sp>) {}
// { dg-final { scan-assembler "_Z1f2SPIL_Z1sEE" } }
void f (SP<sr>) {}
// { dg-final { scan-assembler "_Z1g2SPIL_Z1sEE" } }
void g (SP<sf()>) {}
// { dg-options -std=c++1z }
#include <typeinfo>
struct S { int m; static int s; } s;
template<int* p> class X { };
template<const char *s> class Y {};
template<const std::type_info &> class Z {};
X<&s.m> x7; // { dg-error "" }
Y<"foo"> y1; // { dg-error "string literal" }
Z<typeid(p)> z1; // { dg-error "" }
void f()
{
Y<__func__> y; // { dg-error "" }
}
// { dg-options "-std=c++1z" }
#ifndef __cpp_nontype_template_args
#error __cpp_nontype_template_args not defined
#endif
#if __cpp_nontype_template_args != 201411
#error Wrong value for __cpp_nontype_template_args
#endif
// This macro should not be defined without -std=c++1z.
#ifdef __cpp_nontype_template_args
#error __cpp_nontype_template_args defined
#endif
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