From: Richard Smith Date: Sat, 14 May 2011 15:04:18 +0000 (+0000) Subject: PR9908: Fix the broken fix for PR9902 to get the template argument lists in the right... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1804174e1591bf59118f317775b48edd0382c3f0;p=clang PR9908: Fix the broken fix for PR9902 to get the template argument lists in the right order. Also, don't reject alias templates in all ElaboratedTypes: some ElaboratedTypes do not correspond to elaborated-type-specifiers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131342 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 58c12d4c75..c31ed01737 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1859,10 +1859,10 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // Only substitute for the innermost template argument list. MultiLevelTemplateArgumentList TemplateArgLists; + TemplateArgLists.addOuterTemplateArguments(&TemplateArgs); unsigned Depth = AliasTemplate->getTemplateParameters()->getDepth(); for (unsigned I = 0; I < Depth; ++I) TemplateArgLists.addOuterTemplateArguments(0, 0); - TemplateArgLists.addOuterTemplateArguments(&TemplateArgs); InstantiatingTemplate Inst(*this, TemplateLoc, Template); CanonType = SubstType(Pattern->getUnderlyingType(), diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index c45d02a56c..e007f06235 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -4504,14 +4504,16 @@ TreeTransform::TransformElaboratedType(TypeLocBuilder &TLB, // If the identifier resolves to a typedef-name or the simple-template-id // resolves to an alias template specialization, the // elaborated-type-specifier is ill-formed. - if (const TemplateSpecializationType *TST = - NamedT->getAs()) { - TemplateName Template = TST->getTemplateName(); - if (TypeAliasTemplateDecl *TAT = - dyn_cast_or_null(Template.getAsTemplateDecl())) { - SemaRef.Diag(TL.getNamedTypeLoc().getBeginLoc(), - diag::err_tag_reference_non_tag) << 4; - SemaRef.Diag(TAT->getLocation(), diag::note_declared_at); + if (T->getKeyword() != ETK_None && T->getKeyword() != ETK_Typename) { + if (const TemplateSpecializationType *TST = + NamedT->getAs()) { + TemplateName Template = TST->getTemplateName(); + if (TypeAliasTemplateDecl *TAT = + dyn_cast_or_null(Template.getAsTemplateDecl())) { + SemaRef.Diag(TL.getNamedTypeLoc().getBeginLoc(), + diag::err_tag_reference_non_tag) << 4; + SemaRef.Diag(TAT->getLocation(), diag::note_declared_at); + } } } diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp index 5fc0fe0411..81204d89a6 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s -struct A { }; +struct A { typedef int type; }; template using X = A; // expected-note {{declared here}} struct X* p2; // expected-error {{elaborated type refers to a type alias template}} @@ -9,5 +9,11 @@ template using Id = T; // expected-note {{declared here}} template class F> struct Y { struct F i; // expected-error {{elaborated type refers to a type alias template}} + typename F::type j; // ok + + // FIXME: don't produce the diagnostic both for the definition and the instantiation. + template using U = F; // expected-note 2{{declared here}} + struct Y::template U k; // expected-error 2{{elaborated type refers to a type alias template}} + typename Y::template U l; // ok }; template struct Y; // expected-note {{requested here}} diff --git a/test/SemaCXX/PR9908.cpp b/test/SemaCXX/PR9908.cpp new file mode 100644 index 0000000000..3b98b724dd --- /dev/null +++ b/test/SemaCXX/PR9908.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +template +struct __allocator_traits_rebind +{ + typedef typename _Tp::template rebind<_Up>::other type; +}; + +template +struct allocator_traits +{ + typedef Alloc allocator_type; + template using rebind_alloc = typename +__allocator_traits_rebind::type; + template using rebind_traits = allocator_traits>; +}; + +template +struct ReboundA {}; + +template +struct A +{ + typedef T value_type; + + template struct rebind {typedef ReboundA other;}; +}; + +int main() +{ + allocator_traits >::rebind_traits a; +} diff --git a/test/SemaTemplate/alias-templates.cpp b/test/SemaTemplate/alias-templates.cpp new file mode 100644 index 0000000000..f4c917c5eb --- /dev/null +++ b/test/SemaTemplate/alias-templates.cpp @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +template +struct A { + typedef S B; + template using C = typename T::B; + template struct D { + template using E = typename A::template C>; + template using F = A>; + template using G = C>; + G g; + }; + typedef decltype(D().g) H; + D h; + template using I = A; + template using J = typename A::template C>; +}; + +A a; +A::D b; + +template T make(); + +namespace X { + template struct traits { + typedef T thing; + typedef decltype(val(make())) inner_ptr; + + template using rebind_thing = typename thing::template rebind; + template using rebind = traits>; + + inner_ptr &&alloc(); + void free(inner_ptr&&); + }; + + template struct ptr_traits { + typedef T *type; + }; + template using ptr = typename ptr_traits::type; + + template struct thing { + typedef T inner; + typedef ptr inner_ptr; + typedef traits> traits_type; + + template using rebind = thing; + + thing(traits_type &traits) : traits(traits), val(traits.alloc()) {} + ~thing() { traits.free(static_cast(val)); } + + traits_type &traits; + inner_ptr val; + + friend inner_ptr val(const thing &t) { return t.val; } + }; + + template<> struct ptr_traits { + typedef bool &type; + }; + template<> bool &traits>::alloc() { static bool b; return b; } + template<> void traits>::free(bool&) {} +} + +typedef X::traits> itt; + +itt::thing::traits_type itr; +itt::thing ith(itr); + +itt::rebind btr; +itt::rebind_thing btt(btr);