diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 6 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 21 | ||||
-rw-r--r-- | test/SemaObjCXX/message.mm | 6 | ||||
-rw-r--r-- | test/SemaTemplate/nested-name-spec-template.cpp | 2 | ||||
-rw-r--r-- | test/SemaTemplate/template-id-expr.cpp | 11 | ||||
-rw-r--r-- | test/SemaTemplate/typename-specifier-4.cpp | 2 | ||||
-rw-r--r-- | test/SemaTemplate/typename-specifier.cpp | 9 |
7 files changed, 41 insertions, 16 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 337bd10fbf..4ad76e4678 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1611,6 +1611,9 @@ def note_typename_refers_here : Note< "referenced member %0 is declared here">; def err_typename_missing : Error< "missing 'typename' prior to dependent type name '%0%1'">; +def ext_typename_nondependent : ExtWarn< + "'typename' refers to a non-dependent type name; accepted as a C++0x " + "extension">; def err_template_kw_refers_to_non_template : Error< "%0 following the 'template' keyword does not refer to a template">; @@ -1622,6 +1625,9 @@ def note_referenced_class_template : Error< "class template declared here">; def err_template_kw_missing : Error< "missing 'template' keyword prior to dependent template name '%0%1'">; +def ext_template_nondependent : ExtWarn< + "'template' refers to a non-dependent template name; accepted as a C++0x " + "extension">; // C++0x Variadic Templates def err_template_param_pack_default_arg : Error< diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 0c75cda57e..21d5702ea2 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1714,7 +1714,7 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, // the "template" keyword prior to a template-name that was not a // dependent name. C++ DR468 relaxed this requirement (the // "template" keyword is now permitted). We follow the C++0x - // rules, even in C++03 mode, retroactively applying the DR. + // rules, even in C++03 mode with a warning, retroactively applying the DR. TemplateTy Template; bool MemberOfUnknownSpecialization; TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType, @@ -1733,6 +1733,15 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, return TemplateTy(); } else { // We found something; return it. + if (ActiveTemplateInstantiations.empty() && + !getLangOptions().CPlusPlus0x && + !SS.isEmpty() && !isDependentScopeSpecifier(SS)) + Diag(TemplateKWLoc.isValid()? TemplateKWLoc + : Name.getSourceRange().getBegin(), + diag::ext_template_nondependent) + << SourceRange(Name.getSourceRange().getBegin()) + << FixItHint::CreateRemoval(TemplateKWLoc); + return Template; } } @@ -5368,7 +5377,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, // the "typename" keyword itself is superfluous. In C++03, the // program is actually ill-formed. However, DR 382 (in C++0x CD1) // allows such extraneous "typename" keywords, and we retroactively - // apply this DR to C++03 code. In any case we continue. + // apply this DR to C++03 code with only a warning. In any case we continue. if (RequireCompleteDeclContext(SS, Ctx)) return QualType(); @@ -5389,6 +5398,14 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, case LookupResult::Found: if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) { + if (ActiveTemplateInstantiations.empty() && + !getLangOptions().CPlusPlus0x && !SS.isEmpty() && + !isDependentScopeSpecifier(SS)) + Diag(KeywordLoc.isValid()? KeywordLoc : IILoc, + diag::ext_typename_nondependent) + << SourceRange(IILoc) + << FixItHint::CreateRemoval(KeywordLoc); + // We found a type. Build an ElaboratedType, since the // typename-specifier was just sugar. return Context.getElaboratedType(ETK_Typename, NNS, diff --git a/test/SemaObjCXX/message.mm b/test/SemaObjCXX/message.mm index b75608e232..10b886b203 100644 --- a/test/SemaObjCXX/message.mm +++ b/test/SemaObjCXX/message.mm @@ -62,15 +62,15 @@ struct identity { // or typename-specifiers. if (false) { if (true) - return [typename identity<I3>::type method]; + return [typename identity<I3>::type method]; // expected-warning{{'typename' refers to a non-dependent type name; accepted as a C++0x extension}} return [::I3 method]; } int* ip1 = {[super method]}; int* ip2 = {[::I3 method]}; - int* ip3 = {[typename identity<I3>::type method]}; - int* ip4 = {[typename identity<I2_holder>::type().get() method]}; + int* ip3 = {[typename identity<I3>::type method]}; // expected-warning{{'typename' refers to a non-dependent type name; accepted as a C++0x extension}} + int* ip4 = {[typename identity<I2_holder>::type().get() method]}; // expected-warning{{'typename' refers to a non-dependent type name; accepted as a C++0x extension}} int array[5] = {[3] = 2}; return [super method]; } diff --git a/test/SemaTemplate/nested-name-spec-template.cpp b/test/SemaTemplate/nested-name-spec-template.cpp index 54e615b4ab..e542507a2f 100644 --- a/test/SemaTemplate/nested-name-spec-template.cpp +++ b/test/SemaTemplate/nested-name-spec-template.cpp @@ -21,7 +21,7 @@ namespace N { } M::Promote<int>::type *ret_intptr3(int* ip) { return ip; } - M::template Promote<int>::type *ret_intptr4(int* ip) { return ip; } + M::template Promote<int>::type *ret_intptr4(int* ip) { return ip; } // expected-warning{{'template' refers to a non-dependent template name; accepted as a C++0x extension}} } N::M::Promote<int>::type *ret_intptr5(int* ip) { return ip; } diff --git a/test/SemaTemplate/template-id-expr.cpp b/test/SemaTemplate/template-id-expr.cpp index de8d7f6c91..e8974211b6 100644 --- a/test/SemaTemplate/template-id-expr.cpp +++ b/test/SemaTemplate/template-id-expr.cpp @@ -62,12 +62,12 @@ struct Y0 { template<typename U> void f() { - Y0::template f1<U>(0); - Y0::template f1(0); + Y0::template f1<U>(0); // expected-warning{{'template' refers to a non-dependent template name}} + Y0::template f1(0); // expected-warning{{'template' refers to a non-dependent template name}} this->template f1(0); - Y0::template f2<U>(0); - Y0::template f2(0); + Y0::template f2<U>(0); // expected-warning{{'template' refers to a non-dependent template name}} + Y0::template f2(0);// expected-warning{{'template' refers to a non-dependent template name}} Y0::template f3(0); // expected-error {{'f3' following the 'template' keyword does not refer to a template}} Y0::template f3(); // expected-error {{'f3' following the 'template' keyword does not refer to a template}} @@ -75,7 +75,8 @@ struct Y0 { int x; x = Y0::f4(0); x = Y0::f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} - x = Y0::template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} + x = Y0::template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} \ + // expected-warning{{'template' refers to a non-dependent template name}} x = this->f4(0); x = this->f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} diff --git a/test/SemaTemplate/typename-specifier-4.cpp b/test/SemaTemplate/typename-specifier-4.cpp index 8dfb60d707..da11119e5b 100644 --- a/test/SemaTemplate/typename-specifier-4.cpp +++ b/test/SemaTemplate/typename-specifier-4.cpp @@ -27,7 +27,7 @@ struct make_pair { int a0[is_same<metafun_apply2<make_pair, int, float>::type, pair<int, float> >::value? 1 : -1]; int a1[is_same< - typename make_pair::template apply<int, float>, + typename make_pair::template apply<int, float>, // expected-warning{{'template' refers to a non-dependent template name}} make_pair::apply<int, float> >::value? 1 : -1]; diff --git a/test/SemaTemplate/typename-specifier.cpp b/test/SemaTemplate/typename-specifier.cpp index 3f6fe343f5..e066475be9 100644 --- a/test/SemaTemplate/typename-specifier.cpp +++ b/test/SemaTemplate/typename-specifier.cpp @@ -15,19 +15,20 @@ namespace N { int i; -typename N::A::type *ip1 = &i; +typename N::A::type *ip1 = &i; // expected-warning{{'typename' refers to a non-dependent type name}} typename N::B::type *ip2 = &i; // expected-error{{no type named 'type' in 'N::B'}} typename N::C::type *ip3 = &i; // expected-error{{typename specifier refers to non-type member 'type'}} void test(double d) { - typename N::A::type f(typename N::A::type(a)); // expected-warning{{parentheses were disambiguated as a function declarator}} + typename N::A::type f(typename N::A::type(a)); // expected-warning{{parentheses were disambiguated as a function declarator}} \ + // expected-warning 2{{'typename' refers to a non-dependent type name}} int five = f(5); using namespace N; - for (typename A::type i = 0; i < 10; ++i) + for (typename A::type i = 0; i < 10; ++i) // expected-warning{{'typename' refers to a non-dependent type name}} five += 1; - const typename N::A::type f2(d); + const typename N::A::type f2(d); // expected-warning{{'typename' refers to a non-dependent type name}} } namespace N { |