Rakete1111 updated this revision to Diff 171609. Rakete1111 added a comment.
Remove unneeded -Wc++2a-compat flag in tests. Repository: rC Clang https://reviews.llvm.org/D53847 Files: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/Parser.cpp lib/Sema/SemaDecl.cpp test/CXX/drs/dr1xx.cpp test/CXX/drs/dr2xx.cpp test/CXX/drs/dr4xx.cpp test/CXX/drs/dr5xx.cpp test/CXX/temp/temp.res/p5.cpp test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp test/FixIt/fixit.cpp test/SemaCXX/MicrosoftCompatibility.cpp test/SemaCXX/MicrosoftExtensions.cpp test/SemaCXX/MicrosoftSuper.cpp test/SemaCXX/PR11358.cpp test/SemaCXX/unknown-type-name.cpp
Index: test/SemaCXX/unknown-type-name.cpp =================================================================== --- test/SemaCXX/unknown-type-name.cpp +++ test/SemaCXX/unknown-type-name.cpp @@ -36,39 +36,39 @@ static int n; static type m; - static int h(T::type, int); // expected-error{{missing 'typename'}} - static int h(T::type x, char); // expected-error{{missing 'typename'}} + static int h(T::type, int); // expected-warning {{implicit 'typename' is a C++2a extension}} + static int h(T::type x, char); // expected-warning {{implicit 'typename' is a C++2a extension}} }; template<typename T> -A<T>::type g(T t) { return t; } // expected-error{{missing 'typename'}} +A<T>::type g(T t) { return t; } // expected-warning {{implicit 'typename' is a C++2a extension}} template<typename T> -A<T>::type A<T>::f() { return type(); } // expected-error{{missing 'typename'}} +A<T>::type A<T>::f() { return type(); } // expected-warning {{implicit 'typename' is a C++2a extension}} template<typename T> -void f(T::type) { } // expected-error{{missing 'typename'}} +void f(T::type) { } // expected-warning {{implicit 'typename' is a C++2a extension}} template<typename T> -void g(T::type x) { } // expected-error{{missing 'typename'}} +void g(T::type x) { } // expected-warning {{implicit 'typename' is a C++2a extension}} template<typename T> -void f(T::type, int) { } // expected-error{{missing 'typename'}} +void f(T::type, int) { } // expected-warning {{implicit 'typename' is a C++2a extension}} template<typename T> -void f(T::type x, char) { } // expected-error{{missing 'typename'}} +void f(T::type x, char) { } // expected-warning {{implicit 'typename' is a C++2a extension}} template<typename T> -void f(int, T::type) { } // expected-error{{missing 'typename'}} +void f(int, T::type) { } // expected-warning {{implicit 'typename' is a C++2a extension}} template<typename T> -void f(char, T::type x) { } // expected-error{{missing 'typename'}} +void f(char, T::type x) { } // expected-warning {{implicit 'typename' is a C++2a extension}} template<typename T> -void f(int, T::type, int) { } // expected-error{{missing 'typename'}} +void f(int, T::type, int) { } // expected-warning {{implicit 'typename' is a C++2a extension}} template<typename T> -void f(int, T::type x, char) { } // expected-error{{missing 'typename'}} +void f(int, T::type x, char) { } // expected-warning {{implicit 'typename' is a C++2a extension}} int *p; @@ -86,26 +86,26 @@ template<typename T> int A<T>::n(T::value); // ok template<typename T> -A<T>::type // expected-error{{missing 'typename'}} +A<T>::type // expected-warning {{implicit 'typename' is a C++2a extension}} A<T>::m(T::value, 0); // ok -template<typename T> int A<T>::h(T::type, int) {} // expected-error{{missing 'typename'}} -template<typename T> int A<T>::h(T::type x, char) {} // expected-error{{missing 'typename'}} +template<typename T> int A<T>::h(T::type, int) {} // expected-warning {{implicit 'typename' is a C++2a extension}} +template<typename T> int A<T>::h(T::type x, char) {} // expected-warning {{implicit 'typename' is a C++2a extension}} -template<typename T> int h(T::type, int); // expected-error{{missing 'typename'}} -template<typename T> int h(T::type x, char); // expected-error{{missing 'typename'}} +template<typename T> int h(T::type, int); // expected-warning {{implicit 'typename' is a C++2a extension}} +template<typename T> int h(T::type x, char); // expected-warning {{implicit 'typename' is a C++2a extension}} template<typename T> int junk1(T::junk); #if __cplusplus <= 201103L // expected-warning@-2 {{variable templates are a C++14 extension}} #endif -template<typename T> int junk2(T::junk) throw(); // expected-error{{missing 'typename'}} -template<typename T> int junk3(T::junk) = delete; // expected-error{{missing 'typename'}} +template<typename T> int junk2(T::junk) throw(); // expected-warning {{implicit 'typename' is a C++2a extension}} +template<typename T> int junk3(T::junk) = delete; // expected-warning {{implicit 'typename' is a C++2a extension}} #if __cplusplus <= 199711L //expected-warning@-2 {{deleted function definitions are a C++11 extension}} #endif -template<typename T> int junk4(T::junk j); // expected-error{{missing 'typename'}} +template<typename T> int junk4(T::junk j); // expected-warning {{implicit 'typename' is a C++2a extension}} // FIXME: We can tell this was intended to be a function because it does not // have a dependent nested name specifier. @@ -118,4 +118,5 @@ // FIXME: We know which type specifier should have been specified here. Provide // a fix-it to add 'typename A<T>::type' template<typename T> -A<T>::g() { } // expected-error{{requires a type specifier}} +A<T>::g() { } // expected-error{{expected unqualified-id}} +// expected-warning@-1{{implicit 'typename' is a C++2a extension}} Index: test/SemaCXX/PR11358.cpp =================================================================== --- test/SemaCXX/PR11358.cpp +++ test/SemaCXX/PR11358.cpp @@ -12,7 +12,7 @@ struct Test { typedef container<T> Container; void test() { - Container::iterator i = c.begin(); // expected-error{{missing 'typename'}} + Container::iterator i = c.begin(); // expected-warning{{implicit 'typename' is a C++2a extension}} } Container c; }; @@ -28,7 +28,7 @@ template <typename KeyType, typename ValueType> void MapTest(hash_map<KeyType, ValueType> map) { - for (hash_map<KeyType, ValueType>::const_iterator it = map.begin(); // expected-error{{missing 'typename'}} + for (hash_map<KeyType, ValueType>::const_iterator it = map.begin(); // expected-warning {{implicit 'typename' is a C++2a extension}} it != map.end(); it++) { } } @@ -44,7 +44,7 @@ struct Test { typedef container<T> Container; void test() { - Container::iterator const i; // expected-error{{missing 'typename'}} + Container::iterator const i; // expected-warning {{implicit 'typename' is a C++2a extension}} } Container c; }; Index: test/SemaCXX/MicrosoftSuper.cpp =================================================================== --- test/SemaCXX/MicrosoftSuper.cpp +++ test/SemaCXX/MicrosoftSuper.cpp @@ -108,15 +108,15 @@ typename __super::XXX a; typedef typename __super::XXX b; - __super::XXX c; // expected-error {{missing 'typename'}} - typedef __super::XXX d; // expected-error {{missing 'typename'}} + __super::XXX c; // expected-warning {{implicit 'typename' is a C++2a extension}} + typedef __super::XXX d; // expected-warning {{implicit 'typename' is a C++2a extension}} void foo() { typename __super::XXX e; typedef typename __super::XXX f; - __super::XXX g; // expected-error {{missing 'typename'}} - typedef __super::XXX h; // expected-error {{missing 'typename'}} + __super::XXX g; // expected-warning {{implicit 'typename' is a C++2a extension}} + typedef __super::XXX h; // expected-warning {{implicit 'typename' is a C++2a extension}} int x = __super::foo(); } @@ -127,15 +127,15 @@ typename __super::XXX a; typedef typename __super::XXX b; - __super::XXX c; // expected-error {{missing 'typename'}} - typedef __super::XXX d; // expected-error {{missing 'typename'}} + __super::XXX c; // expected-warning {{implicit 'typename' is a C++2a extension}} + typedef __super::XXX d; // expected-warning {{implicit 'typename' is a C++2a extension}} void foo() { typename __super::XXX e; typedef typename __super::XXX f; - __super::XXX g; // expected-error {{missing 'typename'}} - typedef __super::XXX h; // expected-error {{missing 'typename'}} + __super::XXX g; // expected-warning {{implicit 'typename' is a C++2a extension}} + typedef __super::XXX h; // expected-warning {{implicit 'typename' is a C++2a extension}} __super::foo(1); } Index: test/SemaCXX/MicrosoftExtensions.cpp =================================================================== --- test/SemaCXX/MicrosoftExtensions.cpp +++ test/SemaCXX/MicrosoftExtensions.cpp @@ -526,7 +526,7 @@ namespace PR32750 { template<typename T> struct A {}; -template<typename T> struct B : A<A<T>> { A<T>::C::D d; }; // expected-error {{missing 'typename' prior to dependent type name 'A<T>::C::D'}} +template<typename T> struct B : A<A<T>> { A<T>::C::D d; }; // expected-warning {{implicit 'typename' is a C++2a extension}} } #else Index: test/SemaCXX/MicrosoftCompatibility.cpp =================================================================== --- test/SemaCXX/MicrosoftCompatibility.cpp +++ test/SemaCXX/MicrosoftCompatibility.cpp @@ -199,25 +199,25 @@ typedef B<U> Base2; typedef A<U> Base3; - A<T>::TYPE a1; // expected-warning {{missing 'typename' prior to dependent type name}} - Base1::TYPE a2; // expected-warning {{missing 'typename' prior to dependent type name}} + A<T>::TYPE a1; // expected-warning {{implicit 'typename' is a C++2a extension}} + Base1::TYPE a2; // expected-warning {{implicit 'typename' is a C++2a extension}} - B<U>::TYPE a3; // expected-warning {{missing 'typename' prior to dependent type name}} - Base2::TYPE a4; // expected-warning {{missing 'typename' prior to dependent type name}} + B<U>::TYPE a3; // expected-warning {{implicit 'typename' is a C++2a extension}} + Base2::TYPE a4; // expected-warning {{implicit 'typename' is a C++2a extension}} - A<U>::TYPE a5; // expected-error {{missing 'typename' prior to dependent type name}} - Base3::TYPE a6; // expected-error {{missing 'typename' prior to dependent type name}} + A<U>::TYPE a5; // expected-warning {{implicit 'typename' is a C++2a extension}} + Base3::TYPE a6; // expected-warning {{implicit 'typename' is a C++2a extension}} }; class D { public: typedef int Type; }; template <class T> -void function_missing_typename(const T::Type param)// expected-warning {{missing 'typename' prior to dependent type name}} +void function_missing_typename(const T::Type param)// expected-warning {{implicit 'typename' is a C++2a extension}} { - const T::Type var = 2; // expected-warning {{missing 'typename' prior to dependent type name}} + const T::Type var = 2; // expected-warning {{implicit 'typename' is a C++2a extension}} } template void function_missing_typename<D>(const D::Type param); Index: test/FixIt/fixit.cpp =================================================================== --- test/FixIt/fixit.cpp +++ test/FixIt/fixit.cpp @@ -208,13 +208,6 @@ virtual void g(), // expected-error {{expected ';' at end of declaration}} }; -template<class T> struct Mystery; -template<class T> typedef Mystery<T>::type getMysteriousThing() { // \ - expected-error {{function definition declared 'typedef'}} \ - expected-error {{missing 'typename' prior to dependent}} - return Mystery<T>::get(); -} - template<template<typename> Foo, // expected-error {{template template parameter requires 'class' after the parameter list}} template<typename> typename Bar, // expected-warning {{template template parameter using 'typename' is a C++17 extension}} template<typename> struct Baz> // expected-error {{template template parameter requires 'class' after the parameter list}} Index: test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp =================================================================== --- test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp +++ test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp @@ -17,7 +17,7 @@ template<class T> struct A<A<A<T>>> { struct C {}; - B<B<T>>::C bc; // expected-error {{missing 'typename'}} + B<B<T>>::C bc; // expected-warning {{implicit 'typename' is a C++2a extension}} }; } Index: test/CXX/temp/temp.res/p5.cpp =================================================================== --- /dev/null +++ test/CXX/temp/temp.res/p5.cpp @@ -0,0 +1,88 @@ +// RUN: %clang_cc1 -std=c++2a -pedantic -verify %s + +struct X { + using type = int; + static constexpr int value = 1; + class tclass {}; +}; + +// [temp.res]p5 +// A qualified-id is assumed to name a type if + +template <typename T> +void f() { + // it is a qualified name in a type-id-only context (see below), or + // [it's smallest enclosing [/new/defining/]-type-id is]: + // - a new-type-id + auto *Ptr = new T::type(); + // - a defining-type-id + class T::tclass Empty1; + T::tclass Empty2; + // - a trailing-return-type + auto f()->T::type; + // - default argument of a type-parameter of a template [see below] + + // - type-id of a + // static_cast, + T::type StaticCast = static_cast<T::type>(1.2); + // const_cast, + const auto *ConstCast = const_cast<const T::type *>(Ptr); + // reinterpret_cast, + int ReinterpretCast = reinterpret_cast<T::type>(short(4.)); + // dynamic_cast + struct B { + ~B() = default; + }; + struct D : T::tclass {}; + auto *Base = dynamic_cast<T::tclass>(new B); +} + +// As default argument. +template <typename T, typename = T::type> +struct DefaultArg {}; + +// it is a decl-specifier of the decl-specifier-seq of a +// - simple-declaration or a function-definition in namespace scope +template <typename T> +T::type VarTemp = 1; + +template <typename T> +T::type FuncDef() { return 1; } + +template <typename T> +struct MemberDecl { + // member-declaration, + T::type Member; + + // parameter-declaration in a member-declaration, unless that + // parameter-declaration appears in a default argument + void NoDefault(T::type); + void Default(int A = T::value); +}; + +// parameter-declaration in a declarator of a function or function template +// declaration where the declarator-id is qualified, unless that +// parameter-declaration appears in a default argument, +struct QualifiedFunc { + template <typename T> + void foo(typename T::type); // No implicit typename here. +}; + +// FIXME: This is ok. +template <typename T> +void QualifiedFunc::foo(T::type) {} // expected-error{{out-of-line definition}} + +template <typename T> +void g() { + // parameter-declaration in a lambda-declarator, unless that + // parameter-declaration appears in a default argument, or + auto Lambda1 = [](T::type) {}; + auto Lambda2 = [](int A = T::value) {}; +} + +// parameter-declaration of a (non-type) template-parameter. +template <typename T, T::type> +void NonTypeArg(); + +template <typename T> +void var(T::type); // expected-error{{variable has incomplete type 'void'}} Index: test/CXX/drs/dr5xx.cpp =================================================================== --- test/CXX/drs/dr5xx.cpp +++ test/CXX/drs/dr5xx.cpp @@ -228,8 +228,8 @@ template<int N> struct X { typedef int type; X<N>::type v1; - X<(N)>::type v2; // expected-error {{missing 'typename'}} - X<+N>::type v3; // expected-error {{missing 'typename'}} + X<(N)>::type v2; // expected-error {{implicit 'typename' is a C++2a extension}} + X<+N>::type v3; // expected-error {{implicit 'typename' is a C++2a extension}} }; } Index: test/CXX/drs/dr4xx.cpp =================================================================== --- test/CXX/drs/dr4xx.cpp +++ test/CXX/drs/dr4xx.cpp @@ -173,7 +173,7 @@ B b1; A::B b2; A<T>::B b3; - A<T*>::B b4; // expected-error {{missing 'typename'}} + A<T*>::B b4; // expected-error {{implicit 'typename' is a C++2a extension}} }; } Index: test/CXX/drs/dr2xx.cpp =================================================================== --- test/CXX/drs/dr2xx.cpp +++ test/CXX/drs/dr2xx.cpp @@ -242,53 +242,53 @@ typedef int type; A::type a; A<T>::type b; - A<T*>::type c; // expected-error {{missing 'typename'}} + A<T*>::type c; // expected-error {{implicit 'typename' is a C++2a extension}} ::dr224::example1::A<T>::type d; class B { typedef int type; A::type a; A<T>::type b; - A<T*>::type c; // expected-error {{missing 'typename'}} + A<T*>::type c; // expected-error {{implicit 'typename' is a C++2a extension}} ::dr224::example1::A<T>::type d; B::type e; A<T>::B::type f; - A<T*>::B::type g; // expected-error {{missing 'typename'}} + A<T*>::B::type g; // expected-error {{implicit 'typename' is a C++2a extension}} typename A<T*>::B::type h; }; }; template <class T> class A<T*> { typedef int type; A<T*>::type a; - A<T>::type b; // expected-error {{missing 'typename'}} + A<T>::type b; // expected-error {{implicit 'typename' is a C++2a extension}} }; template <class T1, class T2, int I> struct B { typedef int type; B<T1, T2, I>::type b1; - B<T2, T1, I>::type b2; // expected-error {{missing 'typename'}} + B<T2, T1, I>::type b2; // expected-error {{implicit 'typename' is a C++2a extension}} typedef T1 my_T1; static const int my_I = I; static const int my_I2 = I+0; static const int my_I3 = my_I; - B<my_T1, T2, my_I>::type b3; // FIXME: expected-error {{missing 'typename'}} - B<my_T1, T2, my_I2>::type b4; // expected-error {{missing 'typename'}} - B<my_T1, T2, my_I3>::type b5; // FIXME: expected-error {{missing 'typename'}} + B<my_T1, T2, my_I>::type b3; // FIXME: expected-error {{implicit 'typename' is a C++2a extension}} + B<my_T1, T2, my_I2>::type b4; // expected-error {{implicit 'typename' is a C++2a extension}} + B<my_T1, T2, my_I3>::type b5; // FIXME: expected-error {{implicit 'typename' is a C++2a extension}} }; } namespace example2 { template <int, typename T> struct X { typedef T type; }; template <class T> class A { static const int i = 5; - X<i, int>::type w; // FIXME: expected-error {{missing 'typename'}} - X<A::i, char>::type x; // FIXME: expected-error {{missing 'typename'}} - X<A<T>::i, double>::type y; // FIXME: expected-error {{missing 'typename'}} - X<A<T*>::i, long>::type z; // expected-error {{missing 'typename'}} + X<i, int>::type w; // FIXME: expected-error {{implicit 'typename' is a C++2a extension}} + X<A::i, char>::type x; // FIXME: expected-error {{implicit 'typename' is a C++2a extension}} + X<A<T>::i, double>::type y; // FIXME: expected-error {{implicit 'typename' is a C++2a extension}} + X<A<T*>::i, long>::type z; // expected-error {{implicit 'typename' is a C++2a extension}} int f(); }; template <class T> int A<T>::f() { Index: test/CXX/drs/dr1xx.cpp =================================================================== --- test/CXX/drs/dr1xx.cpp +++ test/CXX/drs/dr1xx.cpp @@ -58,7 +58,7 @@ namespace dr108 { // dr108: yes template<typename T> struct A { struct B { typedef int X; }; - B::X x; // expected-error {{missing 'typename'}} + B::X x; // expected-error {{implicit 'typename' is a C++2a extension}} struct C : B { X x; }; // expected-error {{unknown type name}} }; template<> struct A<int>::B { int X; }; Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -281,6 +281,7 @@ bool IsCtorOrDtorName, bool WantNontrivialTypeSourceInfo, bool IsClassTemplateDeductionContext, + bool AllowImplicitTypename, IdentifierInfo **CorrectedII) { // FIXME: Consider allowing this outside C++1z mode as an extension. bool AllowDeducedTemplate = IsClassTemplateDeductionContext && @@ -307,9 +308,16 @@ // // We therefore do not perform any name lookup if the result would // refer to a member of an unknown specialization. - if (!isClassName && !IsCtorOrDtorName) + // In C++2a, in several contexts a 'typename' is not required. Also + // allow this as an extension. + if (!AllowImplicitTypename && !isClassName && !IsCtorOrDtorName) return nullptr; + if (!isClassName && !IsCtorOrDtorName) + Diag(NameLoc, getLangOpts().CPlusPlus2a + ? diag::warn_cxx17_compat_implicit_typename + : diag::ext_implicit_typename); + // We know from the grammar that this name refers to a type, // so build a dependent node to describe the type. if (WantNontrivialTypeSourceInfo) @@ -395,7 +403,8 @@ isClassName, HasTrailingDot, ObjectTypePtr, IsCtorOrDtorName, WantNontrivialTypeSourceInfo, - IsClassTemplateDeductionContext); + IsClassTemplateDeductionContext, + AllowImplicitTypename); if (Ty) { diagnoseTypo(Correction, PDiag(diag::err_unknown_type_or_class_name_suggest) Index: lib/Parse/Parser.cpp =================================================================== --- lib/Parse/Parser.cpp +++ lib/Parse/Parser.cpp @@ -1774,7 +1774,8 @@ false, NextToken().is(tok::period), nullptr, /*IsCtorOrDtorName=*/false, /*NonTrivialTypeSourceInfo*/true, - /*IsClassTemplateDeductionContext*/true)) { + /*IsClassTemplateDeductionContext*/true, + /*AllowImplicitTypename*/false)) { SourceLocation BeginLoc = Tok.getLocation(); if (SS.isNotEmpty()) // it was a C++ qualified type name. BeginLoc = SS.getBeginLoc(); Index: lib/Parse/ParseDeclCXX.cpp =================================================================== --- lib/Parse/ParseDeclCXX.cpp +++ lib/Parse/ParseDeclCXX.cpp @@ -1175,7 +1175,8 @@ *Id, IdLoc, getCurScope(), &SS, /*IsClassName=*/true, false, nullptr, /*IsCtorOrDtorName=*/false, /*NonTrivialTypeSourceInfo=*/true, - /*IsClassTemplateDeductionContext*/ false, &CorrectedII); + /*IsClassTemplateDeductionContext*/ false, + /*AllowImplicitTypename*/true, &CorrectedII); if (!Type) { Diag(IdLoc, diag::err_expected_class_name); return true; Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -3101,7 +3101,8 @@ getCurScope(), &SS, false, false, nullptr, /*IsCtorOrDtorName=*/false, /*WantNonTrivialSourceInfo=*/true, - isClassTemplateDeductionContext(DSContext)); + isClassTemplateDeductionContext(DSContext), + /*AllowImplicitTypename=*/true); // If the referenced identifier is not a type, then this declspec is // erroneous: We already checked about that it has no type specifier, and Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -1698,6 +1698,7 @@ bool IsCtorOrDtorName = false, bool WantNontrivialTypeSourceInfo = false, bool IsClassTemplateDeductionContext = true, + bool AllowImplicitTypename = false, IdentifierInfo **CorrectedII = nullptr); TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S); bool isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S); Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -4456,6 +4456,11 @@ "%0 in %1">; def note_using_value_decl_missing_typename : Note< "add 'typename' to treat this using declaration as a type">; +def warn_cxx17_compat_implicit_typename : Warning<"use of implicit 'typename' is " + "incompatible with C++ standards before C++2a">, InGroup<CXX2aCompat>, + DefaultIgnore; +def ext_implicit_typename : ExtWarn<"implicit 'typename' is a C++2a extension">, + InGroup<CXX2a>; def err_template_kw_refers_to_non_template : Error< "%0 following the 'template' keyword does not refer to a template">;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits