From: Douglas Gregor Date: Sat, 13 Feb 2010 05:23:25 +0000 (+0000) Subject: Permit the use of typedefs of class template specializations in X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fe3310697028d8d3d35a11b0877bb2bc47e55b8d;p=clang Permit the use of typedefs of class template specializations in qualified declarator-ids. This patch is actually due to Cornelius; fixes PR6179. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96082 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 0eb694cb91..19b242e86b 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1108,9 +1108,6 @@ def err_template_tag_noparams : Error< def err_template_decl_ref : Error< "cannot refer to class template %0 without a template argument list">; -def err_typedef_in_def_scope : Error< - "cannot use typedef %0 in scope specifier for out-of-line declaration">; - // C++ Template Argument Lists def err_template_arg_list_different_arity : Error< "%select{too few|too many}0 template arguments for " diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index c2f0fbc641..10e411f582 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1235,18 +1235,14 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, // such a member, the member declaration shall be preceded by a // template<> for each enclosing class template that is // explicitly specialized. - // We interpret this as forbidding typedefs of template - // specializations in the scope specifiers of out-of-line decls. - if (const TypedefType *TT = dyn_cast(T)) { - const Type *UnderlyingT = TT->LookThroughTypedefs().getTypePtr(); - if (isa(UnderlyingT)) - // FIXME: better source location information. - Diag(DeclStartLoc, diag::err_typedef_in_def_scope) << QualType(T,0); - T = UnderlyingT; - } + // + // Following the existing practice of GNU and EDG, we allow a typedef of a + // template specialization type. + if (const TypedefType *TT = dyn_cast(T)) + T = TT->LookThroughTypedefs().getTypePtr(); if (const TemplateSpecializationType *SpecType - = dyn_cast(T)) { + = dyn_cast(T)) { TemplateDecl *Template = SpecType->getTemplateName().getAsTemplateDecl(); if (!Template) continue; // FIXME: should this be an error? probably... diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp index 3b5b5afa8e..88cfc5d7c3 100644 --- a/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp @@ -18,7 +18,18 @@ namespace test1 { }; typedef A AA; - template <> int AA::foo = 0; // expected-error {{cannot use typedef}} - int AA::bar = 1; // expected-error {{cannot use typedef}} expected-error {{template specialization requires 'template<>'}} + template <> int AA::foo = 0; + int AA::bar = 1; // expected-error {{template specialization requires 'template<>'}} int A::bar = 2; // expected-error {{template specialization requires 'template<>'}} + + template <> class A { + public: + static int foo; // expected-note{{attempt to specialize}} + static int bar; + }; + + typedef A AB; + template <> int AB::foo = 0; // expected-error{{extraneous 'template<>'}} \ + // expected-error{{does not specialize}} + int AB::bar = 1; }