diff options
-rw-r--r-- | lib/AST/Type.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 18 | ||||
-rw-r--r-- | test/SemaTemplate/typename-specifier-4.cpp | 56 |
3 files changed, 68 insertions, 8 deletions
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index bf506415ac..c6ea357fbd 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -530,7 +530,7 @@ const TemplateSpecializationType * Type::getAsTemplateSpecializationType() const { // There is no sugar for class template specialization types, so // just return the canonical type pointer if it is the right class. - return dyn_cast<TemplateSpecializationType>(CanonicalType); + return this->getAs<TemplateSpecializationType>(); } bool Type::isIntegerType() const { diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 3985c1c0e0..8566789ccd 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1137,9 +1137,7 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, NestedNameSpecifier *Qualifier = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); - // FIXME: member of the current instantiation - - if (!Qualifier->isDependent()) { + if (computeDeclContext(SS, false)) { // C++0x [temp.names]p5: // If a name prefixed by the keyword template is not the name of // a template, the program is ill-formed. [Note: the keyword @@ -3010,10 +3008,16 @@ Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, = T->getAsTemplateSpecializationType(); assert(TemplateId && "Expected a template specialization type"); - if (NNS->isDependent()) - return Context.getTypenameType(NNS, TemplateId).getAsOpaquePtr(); - - return Context.getQualifiedNameType(NNS, T).getAsOpaquePtr(); + if (computeDeclContext(SS, false)) { + // If we can compute a declaration context, then the "typename" + // keyword was superfluous. Just build a QualifiedNameType to keep + // track of the nested-name-specifier. + + // FIXME: Note that the QualifiedNameType had the "typename" keyword! + return Context.getQualifiedNameType(NNS, T).getAsOpaquePtr(); + } + + return Context.getTypenameType(NNS, TemplateId).getAsOpaquePtr(); } /// \brief Build the type that describes a C++ typename specifier, diff --git a/test/SemaTemplate/typename-specifier-4.cpp b/test/SemaTemplate/typename-specifier-4.cpp new file mode 100644 index 0000000000..2b1517e40c --- /dev/null +++ b/test/SemaTemplate/typename-specifier-4.cpp @@ -0,0 +1,56 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +template<typename MetaFun, typename T1, typename T2> +struct metafun_apply2 { + typedef typename MetaFun::template apply<T1, T2> inner; + typedef typename inner::type type; +}; + +template<typename T, typename U> struct pair; + +struct make_pair { + template<typename T1, typename T2> + struct apply { + typedef pair<T1, T2> type; + }; +}; + +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>, + make_pair::apply<int, float> + >::value? 1 : -1]; + +template<typename MetaFun> +struct swap_and_apply2 { + template<typename T1, typename T2> + struct apply { + typedef typename MetaFun::template apply<T2, T1> new_metafun; + typedef typename new_metafun::type type; + }; +}; + +int a2[is_same<swap_and_apply2<make_pair>::apply<int, float>::type, + pair<float, int> >::value? 1 : -1]; + +template<typename T> +struct X0 { + template<typename U, typename V> + struct Inner; + + void f0(X0<T>::Inner<T*, T&>); // expected-note{{here}} + void f0(typename X0<T>::Inner<T*, T&>); // expected-error{{redecl}} + + void f1(X0<T>::Inner<T*, T&>); // expected-note{{here}} + void f1(typename X0<T>::template Inner<T*, T&>); // expected-error{{redecl}} +}; |