Commit 96c35892 by Marek Polacek Committed by Marek Polacek

Implement P0634R3, Down with typename!

	* parser.c (CP_PARSER_FLAGS_TYPENAME_OPTIONAL): New enumerator.
	(cp_parser_type_name): Remove declaration.
	(cp_parser_postfix_expression): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL
	to cp_parser_type_id.
	(cp_parser_new_type_id): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL to
	cp_parser_type_specifier_seq.
	(cp_parser_lambda_declarator_opt): Pass
	CP_PARSER_FLAGS_TYPENAME_OPTIONAL to
	cp_parser_parameter_declaration_clause.
	(cp_parser_condition): Pass CP_PARSER_FLAGS_NONE to
	cp_parser_declarator.
	(cp_parser_simple_declaration): Pass CP_PARSER_FLAGS_NONE to
	cp_parser_init_declarator.
	(cp_parser_conversion_type_id): Pass CP_PARSER_FLAGS_NONE to
	cp_parser_type_specifier_seq.
	(cp_parser_default_type_template_argument): Pass
	CP_PARSER_FLAGS_TYPENAME_OPTIONAL to cp_parser_type_id.
	(cp_parser_template_parameter): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL
	to cp_parser_parameter_declaration.
	(cp_parser_explicit_instantiation): Pass CP_PARSER_FLAGS_NONE to
	cp_parser_declarator.
	(cp_parser_simple_type_specifier): Adjust call to cp_parser_type_name
	to relay if we should treat the typename keyword as optional.  Maybe
	call cp_parser_make_typename_type is parsing a template-id and it's
	not a TYPE_DECL.
	(cp_parser_type_name): Remove unused function.
	(cp_parser_enum_specifier): Pass to CP_PARSER_FLAGS_NONE
	cp_parser_type_specifier_seq.
	(cp_parser_alias_declaration): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL
	to cp_parser_type_id.
	(cp_parser_init_declarator): New parameter.  Pass it down to
	cp_parser_declarator.
	(cp_parser_declarator): New parameter.  Pass CP_PARSER_FLAGS_NONE to
	cp_parser_declarator.  Pass the new parameter to
	cp_parser_direct_declarator.
	(cp_parser_direct_declarator): New parameter.  Pass it to
	cp_parser_parameter_declaration_clause and cp_parser_declarator.
	(cp_parser_declarator_id):
	(cp_parser_type_id_1): New parameter.  Pass it to
	cp_parser_type_specifier_seq.  Adjust call to cp_parser_declarator.
	(cp_parser_type_id): New parameter.  Pass it to cp_parser_type_id_1.
	(cp_parser_template_type_arg): Pass CP_PARSER_FLAGS_NONE to
	cp_parser_type_id_1.
	(cp_parser_trailing_type_id): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL
	to cp_parser_type_id_1.
	(cp_parser_type_specifier_seq): New parameter.
	(function_being_declared_is_template_p):
	(cp_parser_parameter_declaration_clause): New parameter.  Pass it to
	cp_parser_parameter_declaration_list.
	(cp_parser_parameter_declaration_list): New parameter.  Pass it to
	cp_parser_parameter_declaration.
	(cp_parser_parameter_declaration): New parameter.  Pass it to
	cp_parser_decl_specifier_seq.  Pass CP_PARSER_FLAGS_NONE to
	cp_parser_declarator.
	(cp_parser_member_declaration): Adjust call to
	cp_parser_decl_specifier_seq to also include
	CP_PARSER_FLAGS_TYPENAME_OPTIONAL.  Pass
	CP_PARSER_FLAGS_TYPENAME_OPTIONAL to cp_parser_declarator.
	(cp_parser_exception_declaration): Pass CP_PARSER_FLAGS_NONE to
	cp_parser_type_specifier_seq and cp_parser_declarator.
	(cp_parser_requirement_parameter_list): Pass CP_PARSER_FLAGS_NONE to
	cp_parser_parameter_declaration_clause.
	(cp_parser_constructor_declarator_p): Resolve the TYPENAME_TYPE.
	(cp_parser_single_declaration): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL
	to cp_parser_decl_specifier_seq and cp_parser_init_declarator.
	(cp_parser_cache_defarg): Pass CP_PARSER_FLAGS_NONE to
	cp_parser_declarator and cp_parser_parameter_declaration_list.
	(cp_parser_objc_method_tail_params_opt): Pass CP_PARSER_FLAGS_NONE to
	cp_parser_parameter_declaration.
	(cp_parser_objc_class_ivars): Pass CP_PARSER_FLAGS_NONE to
	cp_parser_declarator.
	(cp_parser_objc_try_catch_finally_statement): Pass CP_PARSER_FLAGS_NONE
	to cp_parser_parameter_declaration
	(cp_parser_objc_struct_declaration): Pass CP_PARSER_FLAGS_NONE to
	cp_parser_declarator.
	(cp_parser_omp_for_loop_init): Pass CP_PARSER_FLAGS_NONE to
	cp_parser_declarator and cp_parser_type_specifier_seq.

	* g++.dg/cpp0x/alias-decl-43.C: Adjust dg-error.
	* g++.dg/cpp0x/decltype67.C: Only expect error in c++17_down.
	* g++.dg/cpp1z/typename1.C: New test.
	* g++.dg/cpp2a/typename1.C: New test.
	* g++.dg/cpp2a/typename10.C: New test.
	* g++.dg/cpp2a/typename11.C: New test.
	* g++.dg/cpp2a/typename2.C: New test.
	* g++.dg/cpp2a/typename3.C: New test.
	* g++.dg/cpp2a/typename4.C: New test.
	* g++.dg/cpp2a/typename5.C: New test.
	* g++.dg/cpp2a/typename6.C: New test.
	* g++.dg/cpp2a/typename7.C: New test.
	* g++.dg/cpp2a/typename8.C: New test.
	* g++.dg/cpp2a/typename9.C: New test.
	* g++.dg/diagnostic/missing-typename.C: Only run the test in
	c++17_down.
	* g++.dg/other/crash-9.C: Add template disambiguator.
	* g++.dg/other/nontype-1.C: Only expect error in c++17_down.
	* g++.dg/parse/crash13.C: Likewise.
	* g++.dg/parse/error36.C: Likewise.
	* g++.dg/parse/no-typename1.C: Likewise.
	* g++.dg/parse/typedef2.C: Likewise.
	* g++.dg/parse/typename11.C: Likewise.
	* g++.dg/template/crash48.C: Adjust dg-error.
	* g++.dg/template/dependent-name5.C: Only expect error in c++17_down.
	Add dg-error.
	* g++.dg/template/error29.C: Only expect error in c++17_down.
	* g++.dg/template/nested5.C: Add template disambiguator.
	* g++.dg/template/pr84789.C: Only expect error in c++17_down.
	* g++.dg/template/static30.C: Add dg-error.
	* g++.dg/template/typedef6.C: Adjust dg-error.
	* g++.dg/template/typename3.C: Only expect error in c++17_down.

From-SVN: r266710
parent e770ab19
2018-12-01 Marek Polacek <polacek@redhat.com>
Implement P0634R3, Down with typename!
* parser.c (CP_PARSER_FLAGS_TYPENAME_OPTIONAL): New enumerator.
(cp_parser_type_name): Remove declaration.
(cp_parser_postfix_expression): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL
to cp_parser_type_id.
(cp_parser_new_type_id): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL to
cp_parser_type_specifier_seq.
(cp_parser_lambda_declarator_opt): Pass
CP_PARSER_FLAGS_TYPENAME_OPTIONAL to
cp_parser_parameter_declaration_clause.
(cp_parser_condition): Pass CP_PARSER_FLAGS_NONE to
cp_parser_declarator.
(cp_parser_simple_declaration): Pass CP_PARSER_FLAGS_NONE to
cp_parser_init_declarator.
(cp_parser_conversion_type_id): Pass CP_PARSER_FLAGS_NONE to
cp_parser_type_specifier_seq.
(cp_parser_default_type_template_argument): Pass
CP_PARSER_FLAGS_TYPENAME_OPTIONAL to cp_parser_type_id.
(cp_parser_template_parameter): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL
to cp_parser_parameter_declaration.
(cp_parser_explicit_instantiation): Pass CP_PARSER_FLAGS_NONE to
cp_parser_declarator.
(cp_parser_simple_type_specifier): Adjust call to cp_parser_type_name
to relay if we should treat the typename keyword as optional. Maybe
call cp_parser_make_typename_type is parsing a template-id and it's
not a TYPE_DECL.
(cp_parser_type_name): Remove unused function.
(cp_parser_enum_specifier): Pass to CP_PARSER_FLAGS_NONE
cp_parser_type_specifier_seq.
(cp_parser_alias_declaration): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL
to cp_parser_type_id.
(cp_parser_init_declarator): New parameter. Pass it down to
cp_parser_declarator.
(cp_parser_declarator): New parameter. Pass CP_PARSER_FLAGS_NONE to
cp_parser_declarator. Pass the new parameter to
cp_parser_direct_declarator.
(cp_parser_direct_declarator): New parameter. Pass it to
cp_parser_parameter_declaration_clause and cp_parser_declarator.
(cp_parser_declarator_id):
(cp_parser_type_id_1): New parameter. Pass it to
cp_parser_type_specifier_seq. Adjust call to cp_parser_declarator.
(cp_parser_type_id): New parameter. Pass it to cp_parser_type_id_1.
(cp_parser_template_type_arg): Pass CP_PARSER_FLAGS_NONE to
cp_parser_type_id_1.
(cp_parser_trailing_type_id): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL
to cp_parser_type_id_1.
(cp_parser_type_specifier_seq): New parameter.
(function_being_declared_is_template_p):
(cp_parser_parameter_declaration_clause): New parameter. Pass it to
cp_parser_parameter_declaration_list.
(cp_parser_parameter_declaration_list): New parameter. Pass it to
cp_parser_parameter_declaration.
(cp_parser_parameter_declaration): New parameter. Pass it to
cp_parser_decl_specifier_seq. Pass CP_PARSER_FLAGS_NONE to
cp_parser_declarator.
(cp_parser_member_declaration): Adjust call to
cp_parser_decl_specifier_seq to also include
CP_PARSER_FLAGS_TYPENAME_OPTIONAL. Pass
CP_PARSER_FLAGS_TYPENAME_OPTIONAL to cp_parser_declarator.
(cp_parser_exception_declaration): Pass CP_PARSER_FLAGS_NONE to
cp_parser_type_specifier_seq and cp_parser_declarator.
(cp_parser_requirement_parameter_list): Pass CP_PARSER_FLAGS_NONE to
cp_parser_parameter_declaration_clause.
(cp_parser_constructor_declarator_p): Resolve the TYPENAME_TYPE.
(cp_parser_single_declaration): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL
to cp_parser_decl_specifier_seq and cp_parser_init_declarator.
(cp_parser_cache_defarg): Pass CP_PARSER_FLAGS_NONE to
cp_parser_declarator and cp_parser_parameter_declaration_list.
(cp_parser_objc_method_tail_params_opt): Pass CP_PARSER_FLAGS_NONE to
cp_parser_parameter_declaration.
(cp_parser_objc_class_ivars): Pass CP_PARSER_FLAGS_NONE to
cp_parser_declarator.
(cp_parser_objc_try_catch_finally_statement): Pass CP_PARSER_FLAGS_NONE
to cp_parser_parameter_declaration
(cp_parser_objc_struct_declaration): Pass CP_PARSER_FLAGS_NONE to
cp_parser_declarator.
(cp_parser_omp_for_loop_init): Pass CP_PARSER_FLAGS_NONE to
cp_parser_declarator and cp_parser_type_specifier_seq.
2018-11-30 David Malcolm <dmalcolm@redhat.com>
* typeck2.c: Include "gcc-rich-location.h".
......
2018-12-01 Marek Polacek <polacek@redhat.com>
Implement P0634R3, Down with typename!
* g++.dg/cpp0x/alias-decl-43.C: Adjust dg-error.
* g++.dg/cpp0x/decltype67.C: Only expect error in c++17_down.
* g++.dg/cpp1z/typename1.C: New test.
* g++.dg/cpp2a/typename1.C: New test.
* g++.dg/cpp2a/typename10.C: New test.
* g++.dg/cpp2a/typename11.C: New test.
* g++.dg/cpp2a/typename2.C: New test.
* g++.dg/cpp2a/typename3.C: New test.
* g++.dg/cpp2a/typename4.C: New test.
* g++.dg/cpp2a/typename5.C: New test.
* g++.dg/cpp2a/typename6.C: New test.
* g++.dg/cpp2a/typename7.C: New test.
* g++.dg/cpp2a/typename8.C: New test.
* g++.dg/cpp2a/typename9.C: New test.
* g++.dg/diagnostic/missing-typename.C: Only run the test in
c++17_down.
* g++.dg/other/crash-9.C: Add template disambiguator.
* g++.dg/other/nontype-1.C: Only expect error in c++17_down.
* g++.dg/parse/crash13.C: Likewise.
* g++.dg/parse/error36.C: Likewise.
* g++.dg/parse/no-typename1.C: Likewise.
* g++.dg/parse/typedef2.C: Likewise.
* g++.dg/parse/typename11.C: Likewise.
* g++.dg/template/crash48.C: Adjust dg-error.
* g++.dg/template/dependent-name5.C: Only expect error in c++17_down.
Add dg-error.
* g++.dg/template/error29.C: Only expect error in c++17_down.
* g++.dg/template/nested5.C: Add template disambiguator.
* g++.dg/template/pr84789.C: Only expect error in c++17_down.
* g++.dg/template/static30.C: Add dg-error.
* g++.dg/template/typedef6.C: Adjust dg-error.
* g++.dg/template/typename3.C: Only expect error in c++17_down.
2018-12-01 Jeff Law <law@redhat.com>
* gcc.dg/predict-22.c: Update expected output.
......
// PR c++/59120
// { dg-do compile { target c++11 } }
template<typename T> using X = int T::T*; // { dg-error "expected" }
template<typename T> using X = int T::T*; // { dg-error "expected|two or more" }
......@@ -3,5 +3,5 @@
template<typename T> struct A
{
void foo(decltype(T())::Y); // { dg-error {decltype\(T\(\)\)::Y} }
void foo(decltype(T())::Y); // { dg-error "decltype\\(T\\(\\)\\)::Y" "" { target c++17_down } }
};
// P0634R3
// { dg-do compile { target c++17_only } }
// (5.2.1) simple-declaration or a function-definition in namespace scope
template<typename T>
T::X fn1 (int); // { dg-error "need .typename." }
template<typename T>
T::X fn1 (int) // { dg-error "need .typename." }
{
return 42;
}
template<typename T>
T::X v1; // { dg-error "need .typename." }
namespace N {
template<typename T>
T::X v2; // { dg-error "need .typename." }
}
// (5.2.2) member-declaration
template<typename T>
struct S {
[[noreturn]] T::X fn2 (); // { dg-error "need .typename." }
T::X fn3 (); // { dg-error "need .typename." }
T::X fn4 () { return 5; } // { dg-error "need .typename." }
T::X fn5 () final; // { dg-error "need .typename." }
T::X fn6 () = 0; // { dg-error "need .typename." }
T::X fn8 () override; // { dg-error "need .typename." }
T::X v3; // { dg-error "need .typename." }
T::X *v4; // { dg-error "need .typename." }
T::X v5[5]; // { dg-error "need .typename." }
T::X v6 = 0; // { dg-error "need .typename." }
T::X v7{0}; // { dg-error "need .typename.|;" }
T::X v8 : 16; // { dg-error "need .typename." }
static constexpr T::X v9 = 0; // { dg-error "need .typename." }
typedef T::X T2; // { dg-error "need .typename." }
friend T::X fn7<int> (); // { dg-error "need .typename." }
static inline T::X v10; // { dg-error "need .typename." }
};
// (5.2.3) parameter-declaration in a member-declaration,
// unless that parameter-declaration appears in a default argument
template<typename T>
struct S2 {
friend int fn1<T::X> (); // { dg-error "" }
int fn2 (T::X p); // { dg-error "not a type" }
int fn5 (int = T::X);
};
// (5.2.4) parameter-declaration in a declarator of a function or function
// template declaration whose declarator-id is qualified,
// unless that parameter-declaration appears in a default argument
template<typename T>
int fn3 (T::X);
template<typename T>
int fn4 (T::X p) { return p; } // { dg-error "" }
// (5.2.6) parameter-declaration of a (non-type) template-parameter
template<typename T, T::X N> // { dg-error "not a type" }
struct S3 { };
// default argument of a type-parameter of a template
template<typename T, typename U = T::X> // { dg-error "need .typename." }
struct S4 { };
// type-id of a static_cast, const_cast, reinterpret_cast, or dynamic_cast
template<typename T>
struct S5 {
void fn6 (T::X p) // { dg-error "not a type" }
{
int i = static_cast<T::Y>(p); // { dg-error "need .typename." }
i = dynamic_cast<T::Y>(p); // { dg-error "need .typename." }
i = reinterpret_cast<T::Y>(p); // { dg-error "need .typename." }
i = const_cast<T::Y>(p); // { dg-error "need .typename." }
}
};
template<typename T>
void fn7 (T::X p) // { dg-error "" }
{
int i = static_cast<T::Y>(p);
i = dynamic_cast<T::Y>(p);
i = reinterpret_cast<T::Y>(p);
i = const_cast<T::Y>(p);
}
// new-type-id
template<typename T>
void
fn8 ()
{
new T::X[10]; // { dg-error "need .typename." }
}
// defining-type-id
template<typename T>
struct W { typedef int M; };
template<typename T>
struct S6 {
using TT = T::X; // { dg-error "need .typename." }
using TT2 = W<T>::M; // { dg-error "need .typename." }
};
// trailing-return-type
template<typename T>
struct S7 {
auto fn9() -> W<T>::M; // { dg-error "need .typename." }
};
// P0634R3
// { dg-do compile { target c++2a } }
// OK, return type of a function declaration at global scope.
template<class T> T::R f();
// Ill-formed (no diagnostic required), attempt to declare
// a void variable template
template<class T> void f(T::R);
template <class T> struct A;
template <class T> using B = A<T>::U;
template<typename T>
struct PtrTraits { typedef int Ptr; };
template<class T> struct S {
// OK, in a defining-type-id.
using Ptr = PtrTraits<T>::Ptr;
// OK, trailing-return-type.
auto g() -> S<T*>::Ptr;
// OK, class scope
T::R
f (T::P p)
{
// OK, type-id of a static_cast
return static_cast<T::R>(p);
}
};
template<typename T>
void f ()
{
// Variable pf of type void* initialized with T::X
void (*pf)(T::X);
// Error: T::X at block scope does not denote a type
// (attempt to declare a void variable)
void g(T::X); // { dg-error "declared void" }
}
// P0634R3
// { dg-do compile { target c++2a } }
namespace N {
// template<typename T> extern T::type v; // #1a
template<typename T> T::type v(typename T::value); // #1b
}
template<typename T> T::type N::v(T::value); // #2
namespace N2 {
template<typename T> extern T::type v; // #1a
//template<typename T> T::type v(typename T::value); // #1b
}
template<typename T> T::type N2::v(T::value); // { dg-error "" }
namespace A {
inline namespace B { template<typename T> int f(typename T::foo); }
inline namespace C { template<typename T> extern int f; }
}
template<typename T> int A::f(T::foo); // { dg-error "ambiguous" }
// P0634R3
// { dg-do compile { target c++2a } }
template<typename T>
struct A
{
typedef int I;
};
template<typename T> struct B
{
A<T>::I i;
typename A<T>::I i2;
A<int>::I i3;
typename A<int>::I i4;
};
// P0634R3
// { dg-do compile { target c++2a } }
template<class T> typename T::R f();
template <class T> struct A;
template <class T> using B = typename A<T>::U;
template<typename T>
struct PtrTraits { typedef int Ptr; };
template<class T> struct S {
using Ptr = typename PtrTraits<T>::Ptr;
auto g() -> typename S<T*>::Ptr;
typename T::R
f (typename T::P p)
{
return static_cast<typename T::R>(p);
}
};
// P0634R3
// { dg-do compile { target c++2a } }
template<class T>
void f(int i)
{
T::x * i; // { dg-error "dependent-name" }
}
struct Foo {
typedef int x;
};
struct Bar {
static int const x = 5;
};
int
main ()
{
f<Bar>(1);
f<Foo>(1);
}
// P0634R3
// { dg-do compile { target c++2a } }
template<class T>
struct A {
typedef int B;
B b;
};
// P0634R3
// { dg-do compile { target c++2a } }
struct X {
template<typename T>
struct N { };
};
template <typename T>
struct Y {
template<typename U>
struct N { };
};
template <typename T>
struct A
{
template <typename U>
struct N { };
typedef typename A::template N<int> a1;
typedef typename A::template N<T> a2;
typename A::template N<int> a3;
typename A::template N<T> a4;
A::template N<int> a9;
A::template N<T> a10;
typedef A<T>::template N<int> a13;
typedef A<T>::template N<T> a14;
typedef typename X::template N<int> x1;
typedef typename X::template N<T> x2;
typename X::template N<int> x3;
typename X::template N<T> x4;
typedef X::N<int> x5;
typedef X::N<T> x6;
typedef typename X::N<int> x7;
typedef typename X::N<T> x8;
X::N<int> x9;
X::N<T> x10;
typename X::N<int> x11;
typename X::N<T> x12;
typedef typename Y<int>::template N<int> y1;
typedef typename Y<int>::template N<T> y2;
typedef typename Y<T>::template N<int> y3;
typedef typename Y<T>::template N<T> y4;
typename Y<int>::template N<int> y5;
typename Y<int>::template N<T> y6;
typename Y<T>::template N<int> y7;
typename Y<T>::template N<T> y8;
typedef Y<int>::N<int> y9;
typedef Y<int>::N<T> y10;
typedef Y<T>::template N<int> y11;
typedef Y<T>::template N<T> y12;
typedef typename Y<int>::N<int> y13;
typedef typename Y<int>::N<T> y14;
Y<int>::N<int> y17;
Y<int>::N<T> y18;
typename Y<int>::N<int> y21;
typename Y<int>::N<T> y22;
typedef Y<int>::N<int> y25;
typedef Y<int>::N<T> y26;
typedef Y<T>::template N<int> y27;
typedef Y<T>::template N<T> y28;
};
// P0634R3
// { dg-do compile { target c++2a } }
// (5.2.1) simple-declaration or a function-definition in namespace scope
template<typename T>
T::X fn1 (int);
template<typename T>
T::X fn1 (int)
{
return 42;
}
template<typename T>
T::X v1;
namespace N {
template<typename T>
T::X v2;
}
// (5.2.2) member-declaration
template<typename T>
struct S {
[[noreturn]] T::X fn2 ();
T::X fn3 ();
T::X fn4 () { return 5; }
T::X fn5 () final;
T::X fn6 () = 0;
T::X fn8 () override;
T::X v3;
T::X *v4;
T::X v5[5];
T::X v6 = 0;
T::X v7{0};
T::X v8 : 16;
static constexpr T::X v9 = 0;
typedef T::X T2;
friend T::X fn7<int> ();
static inline T::X v10;
};
// (5.2.3) parameter-declaration in a member-declaration,
// unless that parameter-declaration appears in a default argument
template<typename T>
struct S2 {
friend int fn1<T::X> ();
int fn2 (T::X p);
int fn5 (int = T::X);
};
// (5.2.4) parameter-declaration in a declarator of a function or function
// template declaration whose declarator-id is qualified,
// unless that parameter-declaration appears in a default argument
template<typename T>
int fn3 (T::X);
template<typename T>
int fn4 (T::X p) { return p; }
// (5.2.5) parameter-declaration in a lambda-declarator,
// unless that parameter-declaration appears in a default argument
void
fn5 ()
{
auto j = []<typename T>(T::X t, int i) { return i; };
}
// (5.2.6) parameter-declaration of a (non-type) template-parameter
template<typename T, T::X N>
struct S3 { };
// default argument of a type-parameter of a template
template<typename T, typename U = T::X>
struct S4 { };
// type-id of a static_cast, const_cast, reinterpret_cast, or dynamic_cast
template<typename T>
struct S5 {
void fn6 (T::X p)
{
int i = static_cast<T::Y>(p);
i = dynamic_cast<T::Y>(p);
i = reinterpret_cast<T::Y>(p);
i = const_cast<T::Y>(p);
}
};
template<typename T>
void fn7 (T::X p)
{
int i = static_cast<T::Y>(p);
i = dynamic_cast<T::Y>(p);
i = reinterpret_cast<T::Y>(p);
i = const_cast<T::Y>(p);
}
// new-type-id
template<typename T>
void
fn8 ()
{
new T::X[10];
}
// defining-type-id
template<typename T>
struct W { typedef int M; };
template<typename T>
struct S6 {
using TT = T::X;
using TT2 = W<T>::M;
};
// trailing-return-type
template<typename T>
struct S7 {
auto fn9() -> W<T>::M;
};
// P0634R3
// { dg-do compile { target c++2a } }
// Not in namespace scope.
template<typename T>
void fn1 ()
{
// init-statement -> simple-declaration
if (T::X r = 0; 0) // { dg-error "need .typename.|expected" }
;
for (T::X g = 0; ;) // { dg-error "need .typename.|expected" }
;
}
template<typename T>
void
fn2 ()
{
T::X fn3 (); // { dg-error "need .typename.|expected" }
T::X v1; // { dg-error "need .typename.|expected" }
T::X v2 = 0; // { dg-error "need .typename.|expected" }
T::X v3{0}; // { dg-error "need .typename.|expected" }
static constexpr T::X v4 = 0; // { dg-error "need .typename." }
typedef T::X T2; // { dg-error "need .typename." }
}
// P0634R3
// { dg-do compile { target c++2a } }
template<typename T>
struct S {
static int foo ();
};
template<typename T>
int
f ()
{
return S<T>::foo();
}
void
test ()
{
f<int>();
}
// P0634R3
// { dg-do compile { target c++2a } }
// { dg-options "-fconcepts" }
template <typename, typename> class A { class B; };
template <typename T, typename U> class A<T, U>::B {
B(A &);
};
template <typename T, typename U>
A<T, U>::B::B(A<T, U> &) {}
// fix-it hint for missing "typename" (PR c++/63392)
// { dg-do compile { target c++17_down } }
// { dg-options "-fdiagnostics-show-caret" }
template<typename T>
......
......@@ -11,5 +11,5 @@ class A
};
};
template <typename T> template <typename U>
A<T>::B<U> A<T>::B<U>::foo() {}
A<T>::template B<U> A<T>::B<U>::foo() {}
template <class Op>
bool asfun(Op f,
Op::first_argument_type a, // { dg-error "not a type" }
Op::second_argument_type b) // { dg-error "not a type" }
Op::first_argument_type a, // { dg-error "not a type" "" { target c++17_down } }
Op::second_argument_type b) // { dg-error "not a type" "" { target c++17_down } }
{
return Op(a, b);
}
......@@ -12,11 +12,11 @@ struct A
};
template <typename T>
void func(A<T>::B* ) // { dg-error "variable|template|expression" }
void func(A<T>::B* ) // { dg-error "variable|template|expression" "" { target c++17_down } }
{
}
int main()
{
func<void>(0); // { dg-error "not declared|expression|;" }
func<void>(0); // { dg-error "not declared|expression|;" "" { target c++17_down } }
}
......@@ -25,7 +25,7 @@ template <class T> struct B
// PR c++/40738
template <class T>
void g(const A<T>::type &t); // { dg-error "typename" "typename" }
void g(const A<T>::type &t); // { dg-error "typename" "" { target c++17_down } }
// PR c++/18451
template <class T> A<T>::B A<T>::b; // { dg-error "typename" }
template <class T> A<T>::B A<T>::b; // { dg-error "typename" "" { target c++17_down } }
......@@ -6,6 +6,6 @@ template <typename T> struct A
{
template <typename U> struct B
{
A<T>::template B<U> foo(); // { dg-error "" }
A<T>::template B<U> foo(); // { dg-error "" "" { target c++17_down } }
};
};
template <typename T> struct B { typedef typename T::X X; };
template <typename T> struct A { typedef B<T>::X::Y Z; }; // { dg-error "before 'B<T>::X::Y' because 'B<T>::X'" }
template <typename T> struct A { typedef B<T>::X::Y Z; }; // { dg-error "before 'B<T>::X::Y' because 'B<T>::X'" "" { target c++17_down } }
......@@ -10,7 +10,7 @@ template <int dim> struct Y : X<dim> {
// note: I is nested type in X, not Y!
template <int dim>
Y<dim>::I::I () {} // { dg-error "dependent typedef" "typedef" }
// { dg-error "no type|dependent type" "no type" { target *-*-* } .-1 }
Y<dim>::I::I () {} // { dg-error "expected|dependent typedef" "typedef" }
// { dg-error "no type|dependent type" "no type" { target c++17_down } .-1 }
template struct Y<1>;
......@@ -7,4 +7,4 @@ template<typename T> struct A
typedef typename T::X X;
};
template<typename T> A<T>::X::X() {} // { dg-error "no type|invalid use|not a type|dependent" }
template<typename T> A<T>::X::X() {} // { dg-error "expected|no type|invalid use|not a type|dependent" }
......@@ -17,13 +17,15 @@ struct A
typedef Bar type1;
typedef A::Bar type2;
typedef A<T>::Bar type3;
typedef A<T*>::Bar type4; // { dg-error "" }
typedef A<T*>::Bar type4; // { dg-error "" "" { target c++17_down } }
typedef typename A<T*>::Bar type5;
typedef N<int> type6;
typedef A::N<int> type7;
// { dg-error "" "" { target c++2a } .-1 }
typedef A<T>::N<int> type8;
typedef A<T*>::template N<int> type9; // { dg-error "" }
// { dg-error "" "" { target c++2a } .-1 }
typedef A<T*>::template N<int> type9; // { dg-error "" "" { target c++17_down } }
typedef typename A<T*>::template N<int> type10;
typedef D Bar2;
......@@ -36,7 +38,7 @@ struct A
typedef A::N2 type12;
typedef typename type12::K k2;
typedef type12::K k1; // { dg-error "" }
typedef type12::K k1; // { dg-error "" "" { target c++17_down } }
// Check that A::Bar2 is not considered dependent even if we use
// the typename keyword.
......
// PR c++/33209
template<typename T> void foo(int, T::x); // { dg-error "T::x" }
template<typename T> void foo(int, T::x); // { dg-error "T::x" "" { target c++17_down } }
template<template<typename> class T> void foo2(int, T<int>::x); // { dg-error "T<int>::x" }
template<template<typename> class T> void foo2(int, T<int>::x); // { dg-error "T<int>::x" "" { target c++17_down } }
......@@ -6,7 +6,7 @@ template <typename T> struct A
{
template <typename U> struct D {};
};
template <typename S> static C::D<S> bar (S const &);
template <typename S> static C::template D<S> bar (S const &);
};
struct E {};
......
......@@ -9,5 +9,5 @@ template<typename> struct B : A {};
template<typename T> struct C : B<T>
{
B<T>::A::I::I i; // { dg-error "not a class type|does not name a type|typename" }
B<T>::A::I::I i; // { dg-error "not a class type|does not name a type|typename" "" { target c++17_down } }
};
......@@ -6,5 +6,5 @@ template <int> struct A
static const int i2;
};
template <int N> const int A<N>::i1(A<N>::i);
template <int N> const int A<N>::i1(A<N>::i); // { dg-error "no declaration matches" "" { target c++2a } }
template <int N> const int A<N>::i2(3, A<N>::i); // { dg-error "expression list" }
......@@ -5,4 +5,4 @@ template<typename T> struct A
typedef struct typename T::X X; // { dg-error "expected identifier|two or more" }
};
template<typename T> A<T>::X::X() {} // { dg-error "not a type|forbids declaration|invalid use of" }
template<typename T> A<T>::X::X() {} // { dg-error "expected|not a type|forbids declaration|invalid use of" }
......@@ -3,5 +3,5 @@
template <class A>
struct B {
typedef A::C::D E; // { dg-error "" }
typedef A::C::D E; // { dg-error "" "" { target c++17_down } }
};
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