Index: include/clang/AST/DeclTemplate.h =================================================================== --- include/clang/AST/DeclTemplate.h +++ include/clang/AST/DeclTemplate.h @@ -2946,16 +2946,6 @@ return P.get(); } -inline TemplateDecl *getAsTypeTemplateDecl(Decl *D) { - auto *TD = dyn_cast(D); - return TD && (isa(TD) || - isa(TD) || - isa(TD) || - isa(TD)) - ? TD - : nullptr; -} - } /* end of namespace clang */ #endif Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -1884,11 +1884,6 @@ "|in conversion function type|here|in lambda parameter" "|in type allocated by 'new'|in K&R-style function parameter" "|in template parameter|in friend declaration}1">; -def err_dependent_deduced_tst : Error< - "typename specifier refers to " - "%select{class template|function template|variable template|alias template|" - "template template parameter|template}0 member in %1; " - "argument deduction not allowed here">; def err_auto_not_allowed_var_inst : Error< "'auto' variable template instantiation is not allowed">; def err_auto_var_requires_init : Error< Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -7359,8 +7359,7 @@ TypeSourceInfo *SubstType(TypeSourceInfo *T, const MultiLevelTemplateArgumentList &TemplateArgs, - SourceLocation Loc, DeclarationName Entity, - bool AllowDeducedTST = false); + SourceLocation Loc, DeclarationName Entity); QualType SubstType(QualType T, const MultiLevelTemplateArgumentList &TemplateArgs, Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -60,6 +60,11 @@ return DeclGroupPtrTy::make(DeclGroupRef(Ptr)); } +static bool isTypeTemplate(NamedDecl *ND) { + return isa(ND) || isa(ND) || + isa(ND); +} + namespace { class TypeNameValidatorCCC : public CorrectionCandidateCallback { @@ -76,7 +81,7 @@ bool ValidateCandidate(const TypoCorrection &candidate) override { if (NamedDecl *ND = candidate.getCorrectionDecl()) { bool IsType = isa(ND) || isa(ND); - bool AllowedTemplate = AllowTemplates && getAsTypeTemplateDecl(ND); + bool AllowedTemplate = AllowTemplates && isTypeTemplate(ND); return (IsType || AllowedTemplate) && (AllowInvalidDecl || !ND->isInvalidDecl()); } @@ -400,7 +405,7 @@ for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end(); Res != ResEnd; ++Res) { if (isa(*Res) || isa(*Res) || - (AllowDeducedTemplate && getAsTypeTemplateDecl(*Res))) { + (AllowDeducedTemplate && isTypeTemplate(*Res))) { if (!IIDecl || (*Res)->getLocation().getRawEncoding() < IIDecl->getLocation().getRawEncoding()) @@ -453,10 +458,9 @@ (void)DiagnoseUseOfDecl(IDecl, NameLoc); if (!HasTrailingDot) T = Context.getObjCInterfaceType(IDecl); - } else if (AllowDeducedTemplate) { - if (auto *TD = getAsTypeTemplateDecl(IIDecl)) - T = Context.getDeducedTemplateSpecializationType(TemplateName(TD), - QualType(), false); + } else if (AllowDeducedTemplate && isTypeTemplate(IIDecl)) { + T = Context.getDeducedTemplateSpecializationType( + TemplateName(cast(IIDecl)), QualType(), false); } if (T.isNull()) { Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -8792,18 +8792,8 @@ Context.getTypeDeclType(Type)); } - // C++ [dcl.type.simple]p2: - // A type-specifier of the form - // typename[opt] nested-name-specifier[opt] template-name - // is a placeholder for a deduced class type [...]. - if (getLangOpts().CPlusPlus1z) { - if (auto *TD = getAsTypeTemplateDecl(Result.getFoundDecl())) { - return Context.getElaboratedType( - Keyword, QualifierLoc.getNestedNameSpecifier(), - Context.getDeducedTemplateSpecializationType(TemplateName(TD), - QualType(), false)); - } - } + // FIXME: Form a deduced template specialization type if we get a template + // declaration here. DiagID = diag::err_typename_nested_not_type; Referenced = Result.getFoundDecl(); Index: lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiate.cpp +++ lib/Sema/SemaTemplateInstantiate.cpp @@ -1490,16 +1490,12 @@ /// a cast expression) or that the entity has no name (e.g., an /// unnamed function parameter). /// -/// \param AllowDeducedTST Whether a DeducedTemplateSpecializationType is -/// acceptable as the top level type of the result. -/// /// \returns If the instantiation succeeds, the instantiated /// type. Otherwise, produces diagnostics and returns a NULL type. TypeSourceInfo *Sema::SubstType(TypeSourceInfo *T, const MultiLevelTemplateArgumentList &Args, SourceLocation Loc, - DeclarationName Entity, - bool AllowDeducedTST) { + DeclarationName Entity) { assert(!ActiveTemplateInstantiations.empty() && "Cannot perform an instantiation without some context on the " "instantiation stack"); @@ -1509,8 +1505,7 @@ return T; TemplateInstantiator Instantiator(*this, Args, Loc, Entity); - return AllowDeducedTST ? Instantiator.TransformTypeWithDeducedTST(T) - : Instantiator.TransformType(T); + return Instantiator.TransformType(T); } TypeSourceInfo *Sema::SubstType(TypeLoc TL, Index: lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -657,9 +657,10 @@ ArrayRef *Bindings) { // Do substitution on the type of the declaration - TypeSourceInfo *DI = SemaRef.SubstType( - D->getTypeSourceInfo(), TemplateArgs, D->getTypeSpecStartLoc(), - D->getDeclName(), /*AllowDeducedTST*/true); + TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(), + TemplateArgs, + D->getTypeSpecStartLoc(), + D->getDeclName()); if (!DI) return nullptr; Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -307,17 +307,6 @@ /// QualType TransformType(TypeLocBuilder &TLB, TypeLoc TL); - /// \brief Transform a type that is permitted to produce a - /// DeducedTemplateSpecializationType. - /// - /// This is used in the (relatively rare) contexts where it is acceptable - /// for transformation to produce a class template type with deduced - /// template arguments. - /// @{ - QualType TransformTypeWithDeducedTST(QualType T); - TypeSourceInfo *TransformTypeWithDeducedTST(TypeSourceInfo *DI); - /// @} - /// \brief Transform the given statement. /// /// By default, this routine transforms a statement by delegating to the @@ -909,7 +898,7 @@ /// By default, builds a new ParenType type from the inner type. /// Subclasses may override this routine to provide different behavior. QualType RebuildParenType(QualType InnerType) { - return SemaRef.BuildParenType(InnerType); + return SemaRef.Context.getParenType(InnerType); } /// \brief Build a new qualified name type. @@ -979,8 +968,7 @@ SourceLocation KeywordLoc, NestedNameSpecifierLoc QualifierLoc, const IdentifierInfo *Id, - SourceLocation IdLoc, - bool DeducedTSTContext) { + SourceLocation IdLoc) { CXXScopeSpec SS; SS.Adopt(QualifierLoc); @@ -992,25 +980,9 @@ Id); } - if (Keyword == ETK_None || Keyword == ETK_Typename) { - QualType T = SemaRef.CheckTypenameType(Keyword, KeywordLoc, QualifierLoc, - *Id, IdLoc); - // If a dependent name resolves to a deduced template specialization type, - // check that we're in one of the syntactic contexts permitting it. - if (!DeducedTSTContext) { - if (auto *Deduced = dyn_cast_or_null( - T.isNull() ? nullptr : T->getContainedDeducedType())) { - SemaRef.Diag(IdLoc, diag::err_dependent_deduced_tst) - << (int)SemaRef.getTemplateNameKindForDiagnostics( - Deduced->getTemplateName()) - << QualType(QualifierLoc.getNestedNameSpecifier()->getAsType(), 0); - if (auto *TD = Deduced->getTemplateName().getAsTemplateDecl()) - SemaRef.Diag(TD->getLocation(), diag::note_template_decl_here); - return QualType(); - } - } - return T; - } + if (Keyword == ETK_None || Keyword == ETK_Typename) + return SemaRef.CheckTypenameType(Keyword, KeywordLoc, QualifierLoc, + *Id, IdLoc); TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword); @@ -3185,10 +3157,6 @@ TypeSourceInfo *TransformTSIInObjectScope(TypeLoc TL, QualType ObjectType, NamedDecl *FirstQualifierInScope, CXXScopeSpec &SS); - - QualType TransformDependentNameType(TypeLocBuilder &TLB, - DependentNameTypeLoc TL, - bool DeducibleTSTContext); }; template @@ -4080,52 +4048,6 @@ llvm_unreachable("unhandled type loc!"); } -template -QualType TreeTransform::TransformTypeWithDeducedTST(QualType T) { - if (!isa(T)) - return TransformType(T); - - if (getDerived().AlreadyTransformed(T)) - return T; - TypeSourceInfo *DI = getSema().Context.getTrivialTypeSourceInfo(T, - getDerived().getBaseLocation()); - TypeSourceInfo *NewDI = getDerived().TransformTypeWithDeducedTST(DI); - return NewDI ? NewDI->getType() : QualType(); -} - -template -TypeSourceInfo * -TreeTransform::TransformTypeWithDeducedTST(TypeSourceInfo *DI) { - if (!isa(DI->getType())) - return TransformType(DI); - - // Refine the base location to the type's location. - TemporaryBase Rebase(*this, DI->getTypeLoc().getBeginLoc(), - getDerived().getBaseEntity()); - if (getDerived().AlreadyTransformed(DI->getType())) - return DI; - - TypeLocBuilder TLB; - - TypeLoc TL = DI->getTypeLoc(); - TLB.reserve(TL.getFullDataSize()); - - Qualifiers Quals; - if (auto QTL = TL.getAs()) { - Quals = QTL.getType().getLocalQualifiers(); - TL = QTL.getUnqualifiedLoc(); - } - - auto DNTL = TL.castAs(); - - QualType Result = getDerived().TransformDependentNameType( - TLB, DNTL, /*DeducedTSTContext*/true); - if (Result.isNull()) - return nullptr; - - return TLB.getTypeSourceInfo(SemaRef.Context, Result); -} - /// FIXME: By default, this routine adds type qualifiers only to types /// that can have qualifiers, and silently suppresses those qualifiers /// that are not permitted (e.g., qualifiers on reference or function @@ -5932,14 +5854,8 @@ } template -QualType TreeTransform::TransformDependentNameType( - TypeLocBuilder &TLB, DependentNameTypeLoc TL) { - return TransformDependentNameType(TLB, TL, false); -} - -template -QualType TreeTransform::TransformDependentNameType( - TypeLocBuilder &TLB, DependentNameTypeLoc TL, bool DeducedTSTContext) { +QualType TreeTransform::TransformDependentNameType(TypeLocBuilder &TLB, + DependentNameTypeLoc TL) { const DependentNameType *T = TL.getTypePtr(); NestedNameSpecifierLoc QualifierLoc @@ -5952,8 +5868,7 @@ TL.getElaboratedKeywordLoc(), QualifierLoc, T->getIdentifier(), - TL.getNameLoc(), - DeducedTSTContext); + TL.getNameLoc()); if (Result.isNull()) return QualType(); @@ -9559,8 +9474,7 @@ ExprResult TreeTransform::TransformCXXFunctionalCastExpr( CXXFunctionalCastExpr *E) { - TypeSourceInfo *Type = - getDerived().TransformTypeWithDeducedTST(E->getTypeInfoAsWritten()); + TypeSourceInfo *Type = getDerived().TransformType(E->getTypeInfoAsWritten()); if (!Type) return ExprError(); @@ -9749,8 +9663,8 @@ ExprResult TreeTransform::TransformCXXNewExpr(CXXNewExpr *E) { // Transform the type that we're allocating - TypeSourceInfo *AllocTypeInfo = - getDerived().TransformTypeWithDeducedTST(E->getAllocatedTypeSourceInfo()); + TypeSourceInfo *AllocTypeInfo + = getDerived().TransformType(E->getAllocatedTypeSourceInfo()); if (!AllocTypeInfo) return ExprError(); @@ -10461,8 +10375,7 @@ ExprResult TreeTransform::TransformCXXTemporaryObjectExpr( CXXTemporaryObjectExpr *E) { - TypeSourceInfo *T = - getDerived().TransformTypeWithDeducedTST(E->getTypeSourceInfo()); + TypeSourceInfo *T = getDerived().TransformType(E->getTypeSourceInfo()); if (!T) return ExprError(); @@ -10759,8 +10672,7 @@ ExprResult TreeTransform::TransformCXXUnresolvedConstructExpr( CXXUnresolvedConstructExpr *E) { - TypeSourceInfo *T = - getDerived().TransformTypeWithDeducedTST(E->getTypeSourceInfo()); + TypeSourceInfo *T = getDerived().TransformType(E->getTypeSourceInfo()); if (!T) return ExprError(); Index: test/Parser/cxx1z-class-template-argument-deduction.cpp =================================================================== --- test/Parser/cxx1z-class-template-argument-deduction.cpp +++ test/Parser/cxx1z-class-template-argument-deduction.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -verify %s -template struct A {}; // expected-note 35{{declared here}} +template struct A {}; // expected-note 31{{declared here}} // Make sure we still correctly parse cases where a template can appear without arguments. namespace template_template_arg { @@ -101,8 +101,6 @@ (void)reinterpret_cast(&n); // expected-error{{requires template arguments; argument deduction not allowed here}} (void)const_cast(n); // expected-error{{requires template arguments; argument deduction not allowed here}} (void)*(A*)(&n); // expected-error{{requires template arguments; argument deduction not allowed here}} - (void)(A)(n); // expected-error{{requires template arguments; argument deduction not allowed here}} - (void)(A){n}; // expected-error{{requires template arguments; argument deduction not allowed here}} (void)A(n); // expected-error {{not yet supported}} (void)A{n}; // expected-error {{not yet supported}} @@ -123,7 +121,6 @@ A a; // expected-error {{requires an initializer}} A b = 0; // expected-error {{not yet supported}} - const A c = 0; // expected-error {{not yet supported}} A (parens) = 0; // expected-error {{cannot use parentheses when declaring variable with deduced class template specialization type}} A *p = 0; // expected-error {{cannot form pointer to deduced class template specialization type}} A &r = *p; // expected-error {{cannot form reference to deduced class template specialization type}} @@ -132,57 +129,3 @@ A (*fp)() = 0; // expected-error {{cannot form function returning deduced class template specialization type}} A [x, y] = 0; // expected-error {{cannot be declared with type 'A'}} expected-error {{not yet supported}} } - -namespace typename_specifier { - struct F {}; - - void e() { - (void) typename ::A(0); // expected-error {{not yet supported}} - (void) typename ::A{0}; // expected-error {{not yet supported}} - new typename ::A(0); // expected-error {{not yet supported}} - new typename ::A{0}; // expected-error {{not yet supported}} - typename ::A a = 0; // expected-error {{not yet supported}} - const typename ::A b = 0; // expected-error {{not yet supported}} - if (typename ::A a = 0) {} // expected-error {{not yet supported}} - for (typename ::A a = 0; typename ::A b = 0; /**/) {} // expected-error 2{{not yet supported}} - - (void)(typename ::A)(0); // expected-error{{requires template arguments; argument deduction not allowed here}} - (void)(typename ::A){0}; // expected-error{{requires template arguments; argument deduction not allowed here}} - } - typename ::A a = 0; // expected-error {{not yet supported}} - const typename ::A b = 0; // expected-error {{not yet supported}} - typename ::A (parens) = 0; // expected-error {{cannot use parentheses when declaring variable with deduced class template specialization type}} - typename ::A *p = 0; // expected-error {{cannot form pointer to deduced class template specialization type}} - typename ::A &r = *p; // expected-error {{cannot form reference to deduced class template specialization type}} - typename ::A arr[3] = 0; // expected-error {{cannot form array of deduced class template specialization type}} - typename ::A F::*pm = 0; // expected-error {{cannot form pointer to deduced class template specialization type}} - typename ::A (*fp)() = 0; // expected-error {{cannot form function returning deduced class template specialization type}} - typename ::A [x, y] = 0; // expected-error {{cannot be declared with type 'typename ::A'}} expected-error {{not yet supported}} - - struct X { template struct A {}; }; // expected-note 8{{template}} - - template void f() { - (void) typename T::A(0); // expected-error {{not yet supported}} - (void) typename T::A{0}; // expected-error {{not yet supported}} - new typename T::A(0); // expected-error {{not yet supported}} - new typename T::A{0}; // expected-error {{not yet supported}} - typename T::A a = 0; // expected-error {{not yet supported}} - const typename T::A b = 0; // expected-error {{not yet supported}} - if (typename T::A a = 0) {} // expected-error {{not yet supported}} - for (typename T::A a = 0; typename T::A b = 0; /**/) {} // expected-error 2{{not yet supported}} - - {(void)(typename T::A)(0);} // expected-error{{refers to class template member}} - {(void)(typename T::A){0};} // expected-error{{refers to class template member}} - {typename T::A (parens) = 0;} // expected-error {{refers to class template member in 'typename_specifier::X'; argument deduction not allowed here}} - {typename T::A *p = 0;} // expected-error {{refers to class template member}} - {typename T::A &r = *p;} // expected-error {{refers to class template member}} - {typename T::A arr[3] = 0;} // expected-error {{refers to class template member}} - {typename T::A F::*pm = 0;} // expected-error {{refers to class template member}} - {typename T::A (*fp)() = 0;} // expected-error {{refers to class template member}} - {typename T::A [x, y] = 0;} // expected-error {{cannot be declared with type 'typename T::A'}} expected-error {{not yet supported}} - } - template void f(); // expected-note {{instantiation of}} - - template void g(typename T::A = 0); // expected-note {{refers to class template member}} - void h() { g(); } // expected-error {{no matching function}} -} Index: test/SemaCXX/cxx0x-class.cpp =================================================================== --- test/SemaCXX/cxx0x-class.cpp +++ test/SemaCXX/cxx0x-class.cpp @@ -45,3 +45,12 @@ DefaultMemberTemplate t = {}; int *p = &t.n; }; + +namespace composed_templates { + // Regression test -- obtaining the type from composed templates should not + // require out-of-line definition. + template struct Foo { static constexpr bool value = true; }; + template struct Bar { using type = char; }; + template struct Baz { static const typename Bar::value>::type value = 0; }; + template struct Baz<0>; +}