diff options
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 18 | ||||
-rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp | 8 | ||||
-rw-r--r-- | clang/test/SemaCXX/PR9908.cpp | 32 | ||||
-rw-r--r-- | clang/test/SemaTemplate/alias-templates.cpp | 70 |
5 files changed, 120 insertions, 10 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 58c12d4c754..c31ed017377 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/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/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index c45d02a56c6..e007f062356 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4504,14 +4504,16 @@ TreeTransform<Derived>::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<TemplateSpecializationType>()) { - TemplateName Template = TST->getTemplateName(); - if (TypeAliasTemplateDecl *TAT = - dyn_cast_or_null<TypeAliasTemplateDecl>(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<TemplateSpecializationType>()) { + TemplateName Template = TST->getTemplateName(); + if (TypeAliasTemplateDecl *TAT = + dyn_cast_or_null<TypeAliasTemplateDecl>(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/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp index 5fc0fe0411c..81204d89a69 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp +++ b/clang/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<typename T> using X = A; // expected-note {{declared here}} struct X<int>* p2; // expected-error {{elaborated type refers to a type alias template}} @@ -9,5 +9,11 @@ template<typename T> using Id = T; // expected-note {{declared here}} template<template<typename> class F> struct Y { struct F<int> i; // expected-error {{elaborated type refers to a type alias template}} + typename F<A>::type j; // ok + + // FIXME: don't produce the diagnostic both for the definition and the instantiation. + template<typename T> using U = F<char>; // expected-note 2{{declared here}} + struct Y<F>::template U<char> k; // expected-error 2{{elaborated type refers to a type alias template}} + typename Y<F>::template U<char> l; // ok }; template struct Y<Id>; // expected-note {{requested here}} diff --git a/clang/test/SemaCXX/PR9908.cpp b/clang/test/SemaCXX/PR9908.cpp new file mode 100644 index 00000000000..3b98b724dd8 --- /dev/null +++ b/clang/test/SemaCXX/PR9908.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +template <class _Tp, class _Up> +struct __allocator_traits_rebind +{ + typedef typename _Tp::template rebind<_Up>::other type; +}; + +template <class Alloc> +struct allocator_traits +{ + typedef Alloc allocator_type; + template <class T> using rebind_alloc = typename +__allocator_traits_rebind<allocator_type, T>::type; + template <class T> using rebind_traits = allocator_traits<rebind_alloc<T>>; +}; + +template <class T> +struct ReboundA {}; + +template <class T> +struct A +{ + typedef T value_type; + + template <class U> struct rebind {typedef ReboundA<U> other;}; +}; + +int main() +{ + allocator_traits<A<char> >::rebind_traits<double> a; +} diff --git a/clang/test/SemaTemplate/alias-templates.cpp b/clang/test/SemaTemplate/alias-templates.cpp new file mode 100644 index 00000000000..f4c917c5ebc --- /dev/null +++ b/clang/test/SemaTemplate/alias-templates.cpp @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +template<typename S> +struct A { + typedef S B; + template<typename T> using C = typename T::B; + template<typename T> struct D { + template<typename U> using E = typename A<U>::template C<A<T>>; + template<typename U> using F = A<E<U>>; + template<typename U> using G = C<F<U>>; + G<T> g; + }; + typedef decltype(D<B>().g) H; + D<H> h; + template<typename T> using I = A<decltype(h.g)>; + template<typename T> using J = typename A<decltype(h.g)>::template C<I<T>>; +}; + +A<int> a; +A<char>::D<double> b; + +template<typename T> T make(); + +namespace X { + template<typename T> struct traits { + typedef T thing; + typedef decltype(val(make<thing>())) inner_ptr; + + template<typename U> using rebind_thing = typename thing::template rebind<U>; + template<typename U> using rebind = traits<rebind_thing<U>>; + + inner_ptr &&alloc(); + void free(inner_ptr&&); + }; + + template<typename T> struct ptr_traits { + typedef T *type; + }; + template<typename T> using ptr = typename ptr_traits<T>::type; + + template<typename T> struct thing { + typedef T inner; + typedef ptr<inner> inner_ptr; + typedef traits<thing<inner>> traits_type; + + template<typename U> using rebind = thing<U>; + + thing(traits_type &traits) : traits(traits), val(traits.alloc()) {} + ~thing() { traits.free(static_cast<inner_ptr&&>(val)); } + + traits_type &traits; + inner_ptr val; + + friend inner_ptr val(const thing &t) { return t.val; } + }; + + template<> struct ptr_traits<bool> { + typedef bool &type; + }; + template<> bool &traits<thing<bool>>::alloc() { static bool b; return b; } + template<> void traits<thing<bool>>::free(bool&) {} +} + +typedef X::traits<X::thing<int>> itt; + +itt::thing::traits_type itr; +itt::thing ith(itr); + +itt::rebind<bool> btr; +itt::rebind_thing<bool> btt(btr); |