r293207 - PR0091R3: Implement parsing support for using templates as types.
Galina Kistanova via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 27 11:00:22 PST 2017
Hello Richard,
This commit broke test on few our builders:
Failing Tests (1):
Clang :: Parser/cxx1z-class-template-argument-deduction.cpp
http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast
http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast
Please have a look at this?
Thanks
Galina
On Thu, Jan 26, 2017 at 12:40 PM, Richard Smith via cfe-commits <
cfe-commits at lists.llvm.org> wrote:
> Author: rsmith
> Date: Thu Jan 26 14:40:47 2017
> New Revision: 293207
>
> URL: http://llvm.org/viewvc/llvm-project?rev=293207&view=rev
> Log:
> PR0091R3: Implement parsing support for using templates as types.
>
> This change adds a new type node, DeducedTemplateSpecializationType, to
> represent a type template name that has been used as a type. This is
> modeled
> around AutoType, and shares a common base class for representing a deduced
> placeholder type.
>
> We allow deduced class template types in a few more places than the
> standard
> does: in conditions and for-range-declarators, and in new-type-ids. This is
> consistent with GCC and with discussion on the core reflector. This patch
> does not yet support deduced class template types being named in typename
> specifiers.
>
> Added:
> cfe/trunk/test/Parser/cxx1z-class-template-argument-deduction.cpp
> Modified:
> cfe/trunk/include/clang/AST/ASTContext.h
> cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
> cfe/trunk/include/clang/AST/Type.h
> cfe/trunk/include/clang/AST/TypeLoc.h
> cfe/trunk/include/clang/AST/TypeNodes.def
> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> cfe/trunk/include/clang/Parse/Parser.h
> cfe/trunk/include/clang/Sema/DeclSpec.h
> cfe/trunk/include/clang/Sema/Sema.h
> cfe/trunk/include/clang/Serialization/ASTBitCodes.h
> cfe/trunk/lib/AST/ASTContext.cpp
> cfe/trunk/lib/AST/ASTImporter.cpp
> cfe/trunk/lib/AST/ExprConstant.cpp
> cfe/trunk/lib/AST/ItaniumMangle.cpp
> cfe/trunk/lib/AST/MicrosoftMangle.cpp
> cfe/trunk/lib/AST/Type.cpp
> cfe/trunk/lib/AST/TypePrinter.cpp
> cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
> cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
> cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
> cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
> cfe/trunk/lib/Parse/ParseDecl.cpp
> cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> cfe/trunk/lib/Parse/ParseExprCXX.cpp
> cfe/trunk/lib/Parse/Parser.cpp
> cfe/trunk/lib/Sema/SemaDecl.cpp
> cfe/trunk/lib/Sema/SemaExpr.cpp
> cfe/trunk/lib/Sema/SemaExprCXX.cpp
> cfe/trunk/lib/Sema/SemaLookup.cpp
> cfe/trunk/lib/Sema/SemaTemplate.cpp
> cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
> cfe/trunk/lib/Sema/SemaType.cpp
> cfe/trunk/lib/Sema/TreeTransform.h
> cfe/trunk/lib/Serialization/ASTReader.cpp
> cfe/trunk/lib/Serialization/ASTWriter.cpp
> cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
> cfe/trunk/test/CXX/drs/dr5xx.cpp
> cfe/trunk/test/Parser/backtrack-off-by-one.cpp
> cfe/trunk/test/SemaTemplate/temp_arg.cpp
> cfe/trunk/test/SemaTemplate/typename-specifier-3.cpp
> cfe/trunk/tools/libclang/CIndex.cpp
> cfe/trunk/tools/libclang/CXType.cpp
>
> Modified: cfe/trunk/include/clang/AST/ASTContext.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/AST/ASTContext.h?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/AST/ASTContext.h (original)
> +++ cfe/trunk/include/clang/AST/ASTContext.h Thu Jan 26 14:40:47 2017
> @@ -167,6 +167,8 @@ class ASTContext : public RefCountedBase
> mutable llvm::FoldingSet<DependentUnaryTransformType>
> DependentUnaryTransformTypes;
> mutable llvm::FoldingSet<AutoType> AutoTypes;
> + mutable llvm::FoldingSet<DeducedTemplateSpecializationType>
> + DeducedTemplateSpecializationTypes;
> mutable llvm::FoldingSet<AtomicType> AtomicTypes;
> llvm::FoldingSet<AttributedType> AttributedTypes;
> mutable llvm::FoldingSet<PipeType> PipeTypes;
> @@ -1412,6 +1414,11 @@ public:
> /// \brief C++11 deduction pattern for 'auto &&' type.
> QualType getAutoRRefDeductType() const;
>
> + /// \brief C++1z deduced class template specialization type.
> + QualType getDeducedTemplateSpecializationType(TemplateName Template,
> + QualType DeducedType,
> + bool IsDependent) const;
> +
> /// \brief Return the unique reference to the type for the specified
> TagDecl
> /// (struct/union/class/enum) decl.
> QualType getTagDeclType(const TagDecl *Decl) const;
>
> Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/AST/RecursiveASTVisitor.h?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
> +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Thu Jan 26 14:40:47
> 2017
> @@ -1008,6 +1008,10 @@ DEF_TRAVERSE_TYPE(UnaryTransformType, {
> })
>
> DEF_TRAVERSE_TYPE(AutoType, { TRY_TO(TraverseType(T->getDeducedType()));
> })
> +DEF_TRAVERSE_TYPE(DeducedTemplateSpecializationType, {
> + TRY_TO(TraverseTemplateName(T->getTemplateName()));
> + TRY_TO(TraverseType(T->getDeducedType()));
> +})
>
> DEF_TRAVERSE_TYPE(RecordType, {})
> DEF_TRAVERSE_TYPE(EnumType, {})
> @@ -1232,6 +1236,11 @@ DEF_TRAVERSE_TYPELOC(AutoType, {
> TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
> })
>
> +DEF_TRAVERSE_TYPELOC(DeducedTemplateSpecializationType, {
> + TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName()));
> + TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
> +})
> +
> DEF_TRAVERSE_TYPELOC(RecordType, {})
> DEF_TRAVERSE_TYPELOC(EnumType, {})
> DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {})
>
> Modified: cfe/trunk/include/clang/AST/Type.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/AST/Type.h?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/AST/Type.h (original)
> +++ cfe/trunk/include/clang/AST/Type.h Thu Jan 26 14:40:47 2017
> @@ -1785,7 +1785,8 @@ public:
> }
>
> /// \brief Determine whether this type is an undeduced type, meaning
> that
> - /// it somehow involves a C++11 'auto' type which has not yet been
> deduced.
> + /// it somehow involves a C++11 'auto' type or similar which has not
> yet been
> + /// deduced.
> bool isUndeducedType() const;
>
> /// \brief Whether this type is a variably-modified type (C99 6.7.5).
> @@ -1862,10 +1863,17 @@ public:
> /// not refer to a CXXRecordDecl, returns NULL.
> const CXXRecordDecl *getPointeeCXXRecordDecl() const;
>
> + /// Get the DeducedType whose type will be deduced for a variable with
> + /// an initializer of this type. This looks through declarators like
> pointer
> + /// types, but not through decltype or typedefs.
> + DeducedType *getContainedDeducedType() const;
> +
> /// Get the AutoType whose type will be deduced for a variable with
> /// an initializer of this type. This looks through declarators like
> pointer
> /// types, but not through decltype or typedefs.
> - AutoType *getContainedAutoType() const;
> + AutoType *getContainedAutoType() const {
> + return dyn_cast_or_null<AutoType>(getContainedDeducedType());
> + }
>
> /// Determine whether this type was written with a leading 'auto'
> /// corresponding to a trailing return type (possibly for a nested
> @@ -4094,43 +4102,38 @@ public:
> }
> };
>
> -/// \brief Represents a C++11 auto or C++14 decltype(auto) type.
> +/// \brief Common base class for placeholders for types that get replaced
> by
> +/// placeholder type deduction: C++11 auto, C++14 decltype(auto), C++17
> deduced
> +/// class template types, and (eventually) constrained type names from
> the C++
> +/// Concepts TS.
> ///
> /// These types are usually a placeholder for a deduced type. However,
> before
> /// the initializer is attached, or (usually) if the initializer is
> -/// type-dependent, there is no deduced type and an auto type is
> canonical. In
> +/// type-dependent, there is no deduced type and the type is canonical. In
> /// the latter case, it is also a dependent type.
> -class AutoType : public Type, public llvm::FoldingSetNode {
> - AutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool
> IsDependent)
> - : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
> - /*Dependent=*/IsDependent, /*InstantiationDependent=*/
> IsDependent,
> - /*VariablyModified=*/false, /*ContainsParameterPack=*/false) {
> - if (!DeducedType.isNull()) {
> - if (DeducedType->isDependentType())
> +class DeducedType : public Type {
> +protected:
> + DeducedType(TypeClass TC, QualType DeducedAsType, bool IsDependent,
> + bool IsInstantiationDependent, bool ContainsParameterPack)
> + : Type(TC, DeducedAsType.isNull() ? QualType(this, 0) :
> DeducedAsType,
> + IsDependent, IsInstantiationDependent,
> + /*VariablyModified=*/false, ContainsParameterPack) {
> + if (!DeducedAsType.isNull()) {
> + if (DeducedAsType->isDependentType())
> setDependent();
> - if (DeducedType->isInstantiationDependentType())
> + if (DeducedAsType->isInstantiationDependentType())
> setInstantiationDependent();
> - if (DeducedType->containsUnexpandedParameterPack())
> + if (DeducedAsType->containsUnexpandedParameterPack())
> setContainsUnexpandedParameterPack();
> }
> - AutoTypeBits.Keyword = (unsigned)Keyword;
> }
>
> - friend class ASTContext; // ASTContext creates these
> -
> public:
> - bool isDecltypeAuto() const {
> - return getKeyword() == AutoTypeKeyword::DecltypeAuto;
> - }
> - AutoTypeKeyword getKeyword() const {
> - return (AutoTypeKeyword)AutoTypeBits.Keyword;
> - }
> -
> bool isSugared() const { return !isCanonicalUnqualified(); }
> QualType desugar() const { return getCanonicalTypeInternal(); }
>
> - /// \brief Get the type deduced for this auto type, or null if it's
> either
> - /// not been deduced or was deduced to a dependent type.
> + /// \brief Get the type deduced for this placeholder type, or null if
> it's
> + /// either not been deduced or was deduced to a dependent type.
> QualType getDeducedType() const {
> return !isCanonicalUnqualified() ? getCanonicalTypeInternal() :
> QualType();
> }
> @@ -4138,6 +4141,31 @@ public:
> return !isCanonicalUnqualified() || isDependentType();
> }
>
> + static bool classof(const Type *T) {
> + return T->getTypeClass() == Auto ||
> + T->getTypeClass() == DeducedTemplateSpecialization;
> + }
> +};
> +
> +/// \brief Represents a C++11 auto or C++14 decltype(auto) type.
> +class AutoType : public DeducedType, public llvm::FoldingSetNode {
> + AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword,
> + bool IsDeducedAsDependent)
> + : DeducedType(Auto, DeducedAsType, IsDeducedAsDependent,
> + IsDeducedAsDependent, /*ContainsPack=*/false) {
> + AutoTypeBits.Keyword = (unsigned)Keyword;
> + }
> +
> + friend class ASTContext; // ASTContext creates these
> +
> +public:
> + bool isDecltypeAuto() const {
> + return getKeyword() == AutoTypeKeyword::DecltypeAuto;
> + }
> + AutoTypeKeyword getKeyword() const {
> + return (AutoTypeKeyword)AutoTypeBits.Keyword;
> + }
> +
> void Profile(llvm::FoldingSetNodeID &ID) {
> Profile(ID, getDeducedType(), getKeyword(), isDependentType());
> }
> @@ -4154,6 +4182,43 @@ public:
> }
> };
>
> +/// \brief Represents a C++17 deduced template specialization type.
> +class DeducedTemplateSpecializationType : public DeducedType,
> + public llvm::FoldingSetNode {
> + /// The name of the template whose arguments will be deduced.
> + TemplateName Template;
> +
> + DeducedTemplateSpecializationType(TemplateName Template,
> + QualType DeducedAsType,
> + bool IsDeducedAsDependent)
> + : DeducedType(DeducedTemplateSpecialization, DeducedAsType,
> + IsDeducedAsDependent || Template.isDependent(),
> + IsDeducedAsDependent || Template.
> isInstantiationDependent(),
> + Template.containsUnexpandedParameterPack()),
> + Template(Template) {}
> +
> + friend class ASTContext; // ASTContext creates these
> +
> +public:
> + /// Retrieve the name of the template that we are deducing.
> + TemplateName getTemplateName() const { return Template;}
> +
> + void Profile(llvm::FoldingSetNodeID &ID) {
> + Profile(ID, getTemplateName(), getDeducedType(), isDependentType());
> + }
> +
> + static void Profile(llvm::FoldingSetNodeID &ID, TemplateName Template,
> + QualType Deduced, bool IsDependent) {
> + Template.Profile(ID);
> + ID.AddPointer(Deduced.getAsOpaquePtr());
> + ID.AddBoolean(IsDependent);
> + }
> +
> + static bool classof(const Type *T) {
> + return T->getTypeClass() == DeducedTemplateSpecialization;
> + }
> +};
> +
> /// \brief Represents a type template specialization; the template
> /// must be a class template, a type alias template, or a template
> /// template parameter. A template which cannot be resolved to one of
> @@ -5857,8 +5922,8 @@ inline bool Type::isBooleanType() const
> }
>
> inline bool Type::isUndeducedType() const {
> - const AutoType *AT = getContainedAutoType();
> - return AT && !AT->isDeduced();
> + auto *DT = getContainedDeducedType();
> + return DT && !DT->isDeduced();
> }
>
> /// \brief Determines whether this is a type for which one can define
>
> Modified: cfe/trunk/include/clang/AST/TypeLoc.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/AST/TypeLoc.h?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/AST/TypeLoc.h (original)
> +++ cfe/trunk/include/clang/AST/TypeLoc.h Thu Jan 26 14:40:47 2017
> @@ -1827,9 +1827,25 @@ public:
> }
> };
>
> -class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
> - AutoTypeLoc,
> - AutoType> {
> +class DeducedTypeLoc
> + : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DeducedTypeLoc,
> + DeducedType> {};
> +
> +class AutoTypeLoc
> + : public InheritingConcreteTypeLoc<DeducedTypeLoc, AutoTypeLoc,
> AutoType> {
> +};
> +
> +class DeducedTemplateSpecializationTypeLoc
> + : public InheritingConcreteTypeLoc<DeducedTypeLoc,
> + DeducedTemplateSpecializationT
> ypeLoc,
> + DeducedTemplateSpecializationType>
> {
> +public:
> + SourceLocation getTemplateNameLoc() const {
> + return getNameLoc();
> + }
> + void setTemplateNameLoc(SourceLocation Loc) {
> + setNameLoc(Loc);
> + }
> };
>
> struct ElaboratedLocInfo {
>
> Modified: cfe/trunk/include/clang/AST/TypeNodes.def
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/AST/TypeNodes.def?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/AST/TypeNodes.def (original)
> +++ cfe/trunk/include/clang/AST/TypeNodes.def Thu Jan 26 14:40:47 2017
> @@ -96,7 +96,9 @@ DEPENDENT_TYPE(TemplateTypeParm, Type)
> NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
> DEPENDENT_TYPE(SubstTemplateTypeParmPack, Type)
> NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type)
> -TYPE(Auto, Type)
> +ABSTRACT_TYPE(Deduced, Type)
> +TYPE(Auto, DeducedType)
> +TYPE(DeducedTemplateSpecialization, DeducedType)
> DEPENDENT_TYPE(InjectedClassName, Type)
> DEPENDENT_TYPE(DependentName, Type)
> DEPENDENT_TYPE(DependentTemplateSpecialization, Type)
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/
> DiagnosticSemaKinds.td?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Jan 26
> 14:40:47 2017
> @@ -1870,16 +1870,20 @@ def err_illegal_decl_array_of_auto : Err
> def err_new_array_of_auto : Error<
> "cannot allocate array of 'auto'">;
> def err_auto_not_allowed : Error<
> - "%select{'auto'|'decltype(auto)'|'__auto_type'}0 not allowed "
> + "%select{'auto'|'decltype(auto)'|'__auto_type'|"
> + "use of "
> + "%select{class template|function template|variable template|alias
> template|"
> + "template template parameter|template}2 %3 requires template arguments;
> "
> + "argument deduction}0 not allowed "
> "%select{in function prototype"
> "|in non-static struct member|in struct member"
> "|in non-static union member|in union member"
> "|in non-static class member|in interface member"
> - "|in exception declaration|in template parameter|in block literal"
> + "|in exception declaration|in template parameter until C++1z|in block
> literal"
> "|in template argument|in typedef|in type alias|in function return type"
> "|in conversion function type|here|in lambda parameter"
> - "|in type allocated by 'new'|in K&R-style function parameter}1"
> - "%select{|||||||| until C++1z||||||||||}1">;
> + "|in type allocated by 'new'|in K&R-style function parameter"
> + "|in template parameter|in friend declaration}1">;
> def err_auto_not_allowed_var_inst : Error<
> "'auto' variable template instantiation is not allowed">;
> def err_auto_var_requires_init : Error<
> @@ -1944,6 +1948,14 @@ def err_decltype_auto_compound_type : Er
> def err_decltype_auto_initializer_list : Error<
> "cannot deduce 'decltype(auto)' from initializer list">;
>
> +// C++1z deduced class template specialization types
> +def err_deduced_class_template_compound_type : Error<
> + "cannot %select{form pointer to|form reference to|form array of|"
> + "form function returning|use parentheses when declaring variable with}0
> "
> + "deduced class template specialization type">;
> +def err_deduced_class_template_not_supported : Error<
> + "deduction of template arguments for class templates is not yet
> supported">;
> +
> // C++1y deduced return types
> def err_auto_fn_deduction_failure : Error<
> "cannot deduce return type %0 from returned value of type %1">;
>
> Modified: cfe/trunk/include/clang/Parse/Parser.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Parse/Parser.h?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Parse/Parser.h (original)
> +++ cfe/trunk/include/clang/Parse/Parser.h Thu Jan 26 14:40:47 2017
> @@ -1834,6 +1834,26 @@ private:
> llvm_unreachable("Missing DeclSpecContext case");
> }
>
> + /// Is this a context in which we can perform class template argument
> + /// deduction?
> + static bool isClassTemplateDeductionContext(DeclSpecContext DSC) {
> + switch (DSC) {
> + case DSC_normal:
> + case DSC_class:
> + case DSC_top_level:
> + case DSC_condition:
> + case DSC_type_specifier:
> + return true;
> +
> + case DSC_objc_method_result:
> + case DSC_template_type_arg:
> + case DSC_trailing:
> + case DSC_alias_declaration:
> + return false;
> + }
> + llvm_unreachable("Missing DeclSpecContext case");
> + }
> +
> /// Information on a C++0x for-range-initializer found while parsing a
> /// declaration which turns out to be a for-range-declaration.
> struct ForRangeInit {
>
> Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Sema/DeclSpec.h?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
> +++ cfe/trunk/include/clang/Sema/DeclSpec.h Thu Jan 26 14:40:47 2017
> @@ -1709,6 +1709,7 @@ public:
> ObjCParameterContext,// An ObjC method parameter type.
> KNRTypeListContext, // K&R type definition list for formals.
> TypeNameContext, // Abstract declarator for types.
> + FunctionalCastContext, // Type in a C++ functional cast expression.
> MemberContext, // Struct/Union field.
> BlockContext, // Declaration within a block in a function.
> ForContext, // Declaration within first part of a for loop.
> @@ -1911,6 +1912,7 @@ public:
> return false;
>
> case TypeNameContext:
> + case FunctionalCastContext:
> case AliasDeclContext:
> case AliasTemplateContext:
> case PrototypeContext:
> @@ -1951,6 +1953,7 @@ public:
> return true;
>
> case TypeNameContext:
> + case FunctionalCastContext:
> case CXXNewContext:
> case AliasDeclContext:
> case AliasTemplateContext:
> @@ -1983,6 +1986,7 @@ public:
> case CXXCatchContext:
> case ObjCCatchContext:
> case TypeNameContext:
> + case FunctionalCastContext:
> case ConversionIdContext:
> case ObjCParameterContext:
> case ObjCResultContext:
> @@ -2021,6 +2025,7 @@ public:
> // These contexts don't allow any kind of non-abstract declarator.
> case KNRTypeListContext:
> case TypeNameContext:
> + case FunctionalCastContext:
> case AliasDeclContext:
> case AliasTemplateContext:
> case LambdaExprParameterContext:
> @@ -2078,6 +2083,7 @@ public:
> case CXXCatchContext:
> case ObjCCatchContext:
> case TypeNameContext:
> + case FunctionalCastContext: // FIXME
> case CXXNewContext:
> case AliasDeclContext:
> case AliasTemplateContext:
> @@ -2279,6 +2285,7 @@ public:
> case ConditionContext:
> case KNRTypeListContext:
> case TypeNameContext:
> + case FunctionalCastContext:
> case AliasDeclContext:
> case AliasTemplateContext:
> case PrototypeContext:
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Sema/Sema.h?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Thu Jan 26 14:40:47 2017
> @@ -1548,6 +1548,7 @@ public:
> ParsedType ObjectType = nullptr,
> bool IsCtorOrDtorName = false,
> bool WantNontrivialTypeSourceInfo = false,
> + bool IsClassTemplateDeductionContext = true,
> IdentifierInfo **CorrectedII = nullptr);
> TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S);
> bool isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S);
>
> Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Serialization/ASTBitCodes.h?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
> +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Thu Jan 26
> 14:40:47 2017
> @@ -914,7 +914,9 @@ namespace clang {
> /// \brief A PipeType record.
> TYPE_PIPE = 43,
> /// \brief An ObjCTypeParamType record.
> - TYPE_OBJC_TYPE_PARAM = 44
> + TYPE_OBJC_TYPE_PARAM = 44,
> + /// \brief A DeducedTemplateSpecializationType record.
> + TYPE_DEDUCED_TEMPLATE_SPECIALIZATION = 45
> };
>
> /// \brief The type IDs for special types constructed by semantic
>
> Modified: cfe/trunk/lib/AST/ASTContext.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> ASTContext.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/ASTContext.cpp (original)
> +++ cfe/trunk/lib/AST/ASTContext.cpp Thu Jan 26 14:40:47 2017
> @@ -1877,8 +1877,9 @@ TypeInfo ASTContext::getTypeInfoImpl(con
> return getTypeInfo(cast<SubstTemplateTypeParmType>(T)->
> getReplacementType().getTypePtr());
>
> - case Type::Auto: {
> - const AutoType *A = cast<AutoType>(T);
> + case Type::Auto:
> + case Type::DeducedTemplateSpecialization: {
> + const DeducedType *A = cast<DeducedType>(T);
> assert(!A->getDeducedType().isNull() &&
> "cannot request the size of an undeduced or dependent auto
> type");
> return getTypeInfo(A->getDeducedType().getTypePtr());
> @@ -2765,6 +2766,7 @@ QualType ASTContext::getVariableArrayDec
> case Type::TemplateTypeParm:
> case Type::SubstTemplateTypeParmPack:
> case Type::Auto:
> + case Type::DeducedTemplateSpecialization:
> case Type::PackExpansion:
> llvm_unreachable("type should never be variably-modified");
>
> @@ -4435,6 +4437,28 @@ QualType ASTContext::getAutoType(QualTyp
> return QualType(AT, 0);
> }
>
> +/// Return the uniqued reference to the deduced template specialization
> type
> +/// which has been deduced to the given type, or to the canonical
> undeduced
> +/// such type, or the canonical deduced-but-dependent such type.
> +QualType ASTContext::getDeducedTemplateSpecializationType(
> + TemplateName Template, QualType DeducedType, bool IsDependent) const {
> + // Look in the folding set for an existing type.
> + void *InsertPos = nullptr;
> + llvm::FoldingSetNodeID ID;
> + DeducedTemplateSpecializationType::Profile(ID, Template, DeducedType,
> + IsDependent);
> + if (DeducedTemplateSpecializationType *DTST =
> + DeducedTemplateSpecializationTypes.FindNodeOrInsertPos(ID,
> InsertPos))
> + return QualType(DTST, 0);
> +
> + DeducedTemplateSpecializationType *DTST = new (*this, TypeAlignment)
> + DeducedTemplateSpecializationType(Template, DeducedType,
> IsDependent);
> + Types.push_back(DTST);
> + if (InsertPos)
> + DeducedTemplateSpecializationTypes.InsertNode(DTST, InsertPos);
> + return QualType(DTST, 0);
> +}
> +
> /// getAtomicType - Return the uniqued reference to the atomic type for
> /// the given value type.
> QualType ASTContext::getAtomicType(QualType T) const {
> @@ -6333,6 +6357,7 @@ void ASTContext::getObjCEncodingForTypeI
> // We could see an undeduced auto type here during error recovery.
> // Just ignore it.
> case Type::Auto:
> + case Type::DeducedTemplateSpecialization:
> return;
>
> case Type::Pipe:
> @@ -8132,6 +8157,7 @@ QualType ASTContext::mergeTypes(QualType
> llvm_unreachable("Non-canonical and dependent types shouldn't get
> here");
>
> case Type::Auto:
> + case Type::DeducedTemplateSpecialization:
> case Type::LValueReference:
> case Type::RValueReference:
> case Type::MemberPointer:
>
> Modified: cfe/trunk/lib/AST/ASTImporter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> ASTImporter.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/ASTImporter.cpp (original)
> +++ cfe/trunk/lib/AST/ASTImporter.cpp Thu Jan 26 14:40:47 2017
> @@ -883,6 +883,20 @@ static bool IsStructurallyEquivalent(Str
> return false;
> break;
>
> + case Type::DeducedTemplateSpecialization: {
> + auto *DT1 = cast<DeducedTemplateSpecializationType>(T1);
> + auto *DT2 = cast<DeducedTemplateSpecializationType>(T2);
> + if (!IsStructurallyEquivalent(Context,
> + DT1->getTemplateName(),
> + DT2->getTemplateName()))
> + return false;
> + if (!IsStructurallyEquivalent(Context,
> + DT1->getDeducedType(),
> + DT2->getDeducedType()))
> + return false;
> + break;
> + }
> +
> case Type::Record:
> case Type::Enum:
> if (!IsStructurallyEquivalent(Context,
>
> Modified: cfe/trunk/lib/AST/ExprConstant.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> ExprConstant.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
> +++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Jan 26 14:40:47 2017
> @@ -7004,6 +7004,7 @@ static int EvaluateBuiltinClassifyType(c
> case Type::Vector:
> case Type::ExtVector:
> case Type::Auto:
> + case Type::DeducedTemplateSpecialization:
> case Type::ObjCObject:
> case Type::ObjCInterface:
> case Type::ObjCObjectPointer:
>
> Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> ItaniumMangle.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
> +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Thu Jan 26 14:40:47 2017
> @@ -1870,6 +1870,7 @@ bool CXXNameMangler::mangleUnresolvedTyp
> case Type::Paren:
> case Type::Attributed:
> case Type::Auto:
> + case Type::DeducedTemplateSpecialization:
> case Type::PackExpansion:
> case Type::ObjCObject:
> case Type::ObjCInterface:
> @@ -3145,6 +3146,16 @@ void CXXNameMangler::mangleType(const Au
> mangleType(D);
> }
>
> +void CXXNameMangler::mangleType(const DeducedTemplateSpecializationType
> *T) {
> + // FIXME: This is not the right mangling. We also need to include a
> scope
> + // here in some cases.
> + QualType D = T->getDeducedType();
> + if (D.isNull())
> + mangleUnscopedTemplateName(T->getTemplateName(), nullptr);
> + else
> + mangleType(D);
> +}
> +
> void CXXNameMangler::mangleType(const AtomicType *T) {
> // <type> ::= U <source-name> <type> # vendor extended type qualifier
> // (Until there's a standardized mangling...)
>
> Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> MicrosoftMangle.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
> +++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Thu Jan 26 14:40:47 2017
> @@ -2474,6 +2474,17 @@ void MicrosoftCXXNameMangler::mangleType
> << Range;
> }
>
> +void MicrosoftCXXNameMangler::mangleType(
> + const DeducedTemplateSpecializationType *T, Qualifiers, SourceRange
> Range) {
> + assert(T->getDeducedType().isNull() && "expecting a dependent type!");
> +
> + DiagnosticsEngine &Diags = Context.getDiags();
> + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
> + "cannot mangle this deduced class template specialization type yet");
> + Diags.Report(Range.getBegin(), DiagID)
> + << Range;
> +}
> +
> void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, Qualifiers,
> SourceRange Range) {
> QualType ValueType = T->getValueType();
>
> Modified: cfe/trunk/lib/AST/Type.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> Type.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/Type.cpp (original)
> +++ cfe/trunk/lib/AST/Type.cpp Thu Jan 26 14:40:47 2017
> @@ -1559,25 +1559,29 @@ TagDecl *Type::getAsTagDecl() const {
> }
>
> namespace {
> - class GetContainedAutoVisitor :
> - public TypeVisitor<GetContainedAutoVisitor, Type*> {
> + class GetContainedDeducedTypeVisitor :
> + public TypeVisitor<GetContainedDeducedTypeVisitor, Type*> {
> bool Syntactic;
> public:
> - GetContainedAutoVisitor(bool Syntactic = false) :
> Syntactic(Syntactic) {}
> + GetContainedDeducedTypeVisitor(bool Syntactic = false)
> + : Syntactic(Syntactic) {}
>
> - using TypeVisitor<GetContainedAutoVisitor, Type*>::Visit;
> + using TypeVisitor<GetContainedDeducedTypeVisitor, Type*>::Visit;
> Type *Visit(QualType T) {
> if (T.isNull())
> return nullptr;
> return Visit(T.getTypePtr());
> }
>
> - // The 'auto' type itself.
> - Type *VisitAutoType(const AutoType *AT) {
> - return const_cast<AutoType*>(AT);
> + // The deduced type itself.
> + Type *VisitDeducedType(const DeducedType *AT) {
> + return const_cast<DeducedType*>(AT);
> }
>
> // Only these types can contain the desired 'auto' type.
> + Type *VisitElaboratedType(const ElaboratedType *T) {
> + return Visit(T->getNamedType());
> + }
> Type *VisitPointerType(const PointerType *T) {
> return Visit(T->getPointeeType());
> }
> @@ -1620,13 +1624,14 @@ namespace {
> };
> }
>
> -AutoType *Type::getContainedAutoType() const {
> - return cast_or_null<AutoType>(GetContainedAutoVisitor().Visit(this));
> +DeducedType *Type::getContainedDeducedType() const {
> + return cast_or_null<DeducedType>(
> + GetContainedDeducedTypeVisitor().Visit(this));
> }
>
> bool Type::hasAutoForTrailingReturnType() const {
> return dyn_cast_or_null<FunctionType>(
> - GetContainedAutoVisitor(true).Visit(this));
> + GetContainedDeducedTypeVisitor(true).Visit(this));
> }
>
> bool Type::hasIntegerRepresentation() const {
> @@ -3378,6 +3383,7 @@ static CachedProperties computeCachedPro
> return CachedProperties(ExternalLinkage, false);
>
> case Type::Auto:
> + case Type::DeducedTemplateSpecialization:
> // Give non-deduced 'auto' types external linkage. We should only see
> them
> // here in error recovery.
> return CachedProperties(ExternalLinkage, false);
> @@ -3485,6 +3491,7 @@ static LinkageInfo computeLinkageInfo(co
> return LinkageInfo::external();
>
> case Type::Auto:
> + case Type::DeducedTemplateSpecialization:
> return LinkageInfo::external();
>
> case Type::Record:
> @@ -3621,7 +3628,8 @@ bool Type::canHaveNullability() const {
>
> // auto is considered dependent when it isn't deduced.
> case Type::Auto:
> - return !cast<AutoType>(type.getTypePtr())->isDeduced();
> + case Type::DeducedTemplateSpecialization:
> + return !cast<DeducedType>(type.getTypePtr())->isDeduced();
>
> case Type::Builtin:
> switch (cast<BuiltinType>(type.getTypePtr())->getKind()) {
>
> Modified: cfe/trunk/lib/AST/TypePrinter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> TypePrinter.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/TypePrinter.cpp (original)
> +++ cfe/trunk/lib/AST/TypePrinter.cpp Thu Jan 26 14:40:47 2017
> @@ -189,6 +189,7 @@ bool TypePrinter::canPrefixQualifiers(co
> case Type::Elaborated:
> case Type::TemplateTypeParm:
> case Type::SubstTemplateTypeParmPack:
> + case Type::DeducedTemplateSpecialization:
> case Type::TemplateSpecialization:
> case Type::InjectedClassName:
> case Type::DependentName:
> @@ -887,6 +888,24 @@ void TypePrinter::printAutoAfter(const A
> if (!T->getDeducedType().isNull())
> printAfter(T->getDeducedType(), OS);
> }
> +
> +void TypePrinter::printDeducedTemplateSpecializationBefore(
> + const DeducedTemplateSpecializationType *T, raw_ostream &OS) {
> + // If the type has been deduced, print the deduced type.
> + if (!T->getDeducedType().isNull()) {
> + printBefore(T->getDeducedType(), OS);
> + } else {
> + IncludeStrongLifetimeRAII Strong(Policy);
> + T->getTemplateName().print(OS, Policy);
> + spaceBeforePlaceHolder(OS);
> + }
> +}
> +void TypePrinter::printDeducedTemplateSpecializationAfter(
> + const DeducedTemplateSpecializationType *T, raw_ostream &OS) {
> + // If the type has been deduced, print the deduced type.
> + if (!T->getDeducedType().isNull())
> + printAfter(T->getDeducedType(), OS);
> +}
>
> void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream
> &OS) {
> IncludeStrongLifetimeRAII Strong(Policy);
>
> Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/
> CGDebugInfo.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Thu Jan 26 14:40:47 2017
> @@ -2618,6 +2618,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNod
> case Type::Attributed:
> case Type::Adjusted:
> case Type::Decayed:
> + case Type::DeducedTemplateSpecialization:
> case Type::Elaborated:
> case Type::Paren:
> case Type::SubstTemplateTypeParm:
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/
> CodeGenFunction.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Thu Jan 26 14:40:47 2017
> @@ -200,7 +200,8 @@ TypeEvaluationKind CodeGenFunction::getE
> llvm_unreachable("non-canonical or dependent type in
> IR-generation");
>
> case Type::Auto:
> - llvm_unreachable("undeduced auto type in IR-generation");
> + case Type::DeducedTemplateSpecialization:
> + llvm_unreachable("undeduced type in IR-generation");
>
> // Various scalar types.
> case Type::Builtin:
> @@ -1899,6 +1900,7 @@ void CodeGenFunction::EmitVariablyModifi
> case Type::Typedef:
> case Type::Decltype:
> case Type::Auto:
> + case Type::DeducedTemplateSpecialization:
> // Stop walking: nothing to do.
> return;
>
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/
> CodeGenTypes.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Thu Jan 26 14:40:47 2017
> @@ -487,7 +487,8 @@ llvm::Type *CodeGenTypes::ConvertType(Qu
> break;
> }
> case Type::Auto:
> - llvm_unreachable("Unexpected undeduced auto type!");
> + case Type::DeducedTemplateSpecialization:
> + llvm_unreachable("Unexpected undeduced type!");
> case Type::Complex: {
> llvm::Type *EltTy = ConvertType(cast<ComplexType>(
> Ty)->getElementType());
> ResultType = llvm::StructType::get(EltTy, EltTy, nullptr);
>
> Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/
> ItaniumCXXABI.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
> +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Thu Jan 26 14:40:47 2017
> @@ -2815,7 +2815,8 @@ void ItaniumRTTIBuilder::BuildVTablePoin
> llvm_unreachable("References shouldn't get here");
>
> case Type::Auto:
> - llvm_unreachable("Undeduced auto type shouldn't get here");
> + case Type::DeducedTemplateSpecialization:
> + llvm_unreachable("Undeduced type shouldn't get here");
>
> case Type::Pipe:
> llvm_unreachable("Pipe types shouldn't get here");
> @@ -3045,7 +3046,8 @@ llvm::Constant *ItaniumRTTIBuilder::Buil
> llvm_unreachable("References shouldn't get here");
>
> case Type::Auto:
> - llvm_unreachable("Undeduced auto type shouldn't get here");
> + case Type::DeducedTemplateSpecialization:
> + llvm_unreachable("Undeduced type shouldn't get here");
>
> case Type::Pipe:
> llvm_unreachable("Pipe type shouldn't get here");
>
> Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/
> ParseDecl.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Jan 26 14:40:47 2017
> @@ -2884,7 +2884,8 @@ void Parser::ParseDeclarationSpecifiers(
> Actions.getTypeName(*Next.getIdentifierInfo(),
> Next.getLocation(),
> getCurScope(), &SS, false, false, nullptr,
> /*IsCtorOrDtorName=*/false,
> - /*NonTrivialSourceInfo=*/true);
> + /*WantNonTrivialSourceInfo=*/true,
> + isClassTemplateDeductionContex
> t(DSContext));
>
> // If the referenced identifier is not a type, then this declspec is
> // erroneous: We already checked about that it has no type
> specifier, and
> @@ -2998,9 +2999,10 @@ void Parser::ParseDeclarationSpecifiers(
> continue;
> }
>
> - ParsedType TypeRep =
> - Actions.getTypeName(*Tok.getIdentifierInfo(),
> - Tok.getLocation(), getCurScope());
> + ParsedType TypeRep = Actions.getTypeName(
> + *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(),
> nullptr,
> + false, false, nullptr, false, false,
> + isClassTemplateDeductionContext(DSContext));
>
> // If this is not a typedef name, don't parse it as part of the
> declspec,
> // it must be an implicit int or an error.
>
> Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/
> ParseDeclCXX.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Thu Jan 26 14:40:47 2017
> @@ -1144,10 +1144,11 @@ TypeResult Parser::ParseBaseTypeSpecifie
>
> // We have an identifier; check whether it is actually a type.
> IdentifierInfo *CorrectedII = nullptr;
> - ParsedType Type =
> - Actions.getTypeName(*Id, IdLoc, getCurScope(), &SS, true, false,
> nullptr,
> - /*IsCtorOrDtorName=*/false,
> - /*NonTrivialTypeSourceInfo=*/true,
> &CorrectedII);
> + ParsedType Type = Actions.getTypeName(
> + *Id, IdLoc, getCurScope(), &SS, true, false, nullptr,
> + /*IsCtorOrDtorName=*/false,
> + /*NonTrivialTypeSourceInfo=*/true,
> + /*IsClassTemplateDeductionContext*/ false, &CorrectedII);
> if (!Type) {
> Diag(IdLoc, diag::err_expected_class_name);
> return true;
>
> Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/
> ParseExprCXX.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Thu Jan 26 14:40:47 2017
> @@ -1639,9 +1639,10 @@ ExprResult Parser::ParseCXXThis() {
> /// typename-specifier '(' expression-list[opt] ')'
> /// [C++0x] typename-specifier braced-init-list
> ///
> +/// In C++1z onwards, the type specifier can also be a template-name.
> ExprResult
> Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
> - Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
> + Declarator DeclaratorInfo(DS, Declarator::FunctionalCastContext);
> ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(),
> DeclaratorInfo).get();
>
> assert((Tok.is(tok::l_paren) ||
>
> Modified: cfe/trunk/lib/Parse/Parser.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/
> Parser.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Parse/Parser.cpp (original)
> +++ cfe/trunk/lib/Parse/Parser.cpp Thu Jan 26 14:40:47 2017
> @@ -1743,7 +1743,8 @@ bool Parser::TryAnnotateTypeOrScopeToken
> *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(),
> &SS,
> false, NextToken().is(tok::period), nullptr,
> /*IsCtorOrDtorName=*/false,
> - /*NonTrivialTypeSourceInfo*/ true)) {
> + /*NonTrivialTypeSourceInfo*/ true,
> + /*IsClassTemplateDeductionContext*/GreaterThanIsOperator)) {
> SourceLocation BeginLoc = Tok.getLocation();
> if (SS.isNotEmpty()) // it was a C++ qualified type name.
> BeginLoc = SS.getBeginLoc();
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaDecl.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Jan 26 14:40:47 2017
> @@ -60,6 +60,11 @@ Sema::DeclGroupPtrTy Sema::ConvertDeclTo
> return DeclGroupPtrTy::make(DeclGroupRef(Ptr));
> }
>
> +static bool isTypeTemplate(NamedDecl *ND) {
> + return isa<ClassTemplateDecl>(ND) || isa<TypeAliasTemplateDecl>(ND) ||
> + isa<TemplateTemplateParmDecl>(ND);
> +}
> +
> namespace {
>
> class TypeNameValidatorCCC : public CorrectionCandidateCallback {
> @@ -67,7 +72,7 @@ class TypeNameValidatorCCC : public Corr
> TypeNameValidatorCCC(bool AllowInvalid, bool WantClass=false,
> bool AllowTemplates=false)
> : AllowInvalidDecl(AllowInvalid), WantClassName(WantClass),
> - AllowClassTemplates(AllowTemplates) {
> + AllowTemplates(AllowTemplates) {
> WantExpressionKeywords = false;
> WantCXXNamedCasts = false;
> WantRemainingKeywords = false;
> @@ -76,7 +81,7 @@ class TypeNameValidatorCCC : public Corr
> bool ValidateCandidate(const TypoCorrection &candidate) override {
> if (NamedDecl *ND = candidate.getCorrectionDecl()) {
> bool IsType = isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
> - bool AllowedTemplate = AllowClassTemplates &&
> isa<ClassTemplateDecl>(ND);
> + bool AllowedTemplate = AllowTemplates && isTypeTemplate(ND);
> return (IsType || AllowedTemplate) &&
> (AllowInvalidDecl || !ND->isInvalidDecl());
> }
> @@ -86,7 +91,7 @@ class TypeNameValidatorCCC : public Corr
> private:
> bool AllowInvalidDecl;
> bool WantClassName;
> - bool AllowClassTemplates;
> + bool AllowTemplates;
> };
>
> } // end anonymous namespace
> @@ -252,7 +257,13 @@ ParsedType Sema::getTypeName(const Ident
> ParsedType ObjectTypePtr,
> bool IsCtorOrDtorName,
> bool WantNontrivialTypeSourceInfo,
> + bool IsClassTemplateDeductionContext,
> IdentifierInfo **CorrectedII) {
> + // FIXME: Consider allowing this outside C++1z mode as an extension.
> + bool AllowDeducedTemplate = IsClassTemplateDeductionContext &&
> + getLangOpts().CPlusPlus1z &&
> !IsCtorOrDtorName &&
> + !isClassName && !HasTrailingDot;
> +
> // Determine where we will perform name lookup.
> DeclContext *LookupCtx = nullptr;
> if (ObjectTypePtr) {
> @@ -334,10 +345,11 @@ ParsedType Sema::getTypeName(const Ident
> case LookupResult::NotFound:
> case LookupResult::NotFoundInCurrentInstantiation:
> if (CorrectedII) {
> - TypoCorrection Correction = CorrectTypo(
> - Result.getLookupNameInfo(), Kind, S, SS,
> - llvm::make_unique<TypeNameValidatorCCC>(true, isClassName),
> - CTK_ErrorRecovery);
> + TypoCorrection Correction =
> + CorrectTypo(Result.getLookupNameInfo(), Kind, S, SS,
> + llvm::make_unique<TypeNameValidatorCCC>(
> + true, isClassName, AllowDeducedTemplate),
> + CTK_ErrorRecovery);
> IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo();
> TemplateTy Template;
> bool MemberOfUnknownSpecialization;
> @@ -359,7 +371,8 @@ ParsedType Sema::getTypeName(const Ident
> ParsedType Ty = getTypeName(*NewII, NameLoc, S, NewSSPtr,
> isClassName, HasTrailingDot,
> ObjectTypePtr,
> IsCtorOrDtorName,
> - WantNontrivialTypeSourceInfo);
> + WantNontrivialTypeSourceInfo,
> + IsClassTemplateDeductionContext);
> if (Ty) {
> diagnoseTypo(Correction,
> PDiag(diag::err_unknown_type_
> or_class_name_suggest)
> @@ -391,7 +404,8 @@ ParsedType Sema::getTypeName(const Ident
> // Look to see if we have a type anywhere in the list of results.
> for (LookupResult::iterator Res = Result.begin(), ResEnd =
> Result.end();
> Res != ResEnd; ++Res) {
> - if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res)) {
> + if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res) ||
> + (AllowDeducedTemplate && isTypeTemplate(*Res))) {
> if (!IIDecl ||
> (*Res)->getLocation().getRawEncoding() <
> IIDecl->getLocation().getRawEncoding())
> @@ -440,29 +454,13 @@ ParsedType Sema::getTypeName(const Ident
>
> T = Context.getTypeDeclType(TD);
> MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
> -
> - // NOTE: avoid constructing an ElaboratedType(Loc) if this is a
> - // constructor or destructor name (in such a case, the scope specifier
> - // will be attached to the enclosing Expr or Decl node).
> - if (SS && SS->isNotEmpty() && !IsCtorOrDtorName) {
> - if (WantNontrivialTypeSourceInfo) {
> - // Construct a type with type-source information.
> - TypeLocBuilder Builder;
> - Builder.pushTypeSpec(T).setNameLoc(NameLoc);
> -
> - T = getElaboratedType(ETK_None, *SS, T);
> - ElaboratedTypeLoc ElabTL = Builder.push<ElaboratedTypeLoc>(T);
> - ElabTL.setElaboratedKeywordLoc(SourceLocation());
> - ElabTL.setQualifierLoc(SS->getWithLocInContext(Context));
> - return CreateParsedType(T, Builder.getTypeSourceInfo(Context,
> T));
> - } else {
> - T = getElaboratedType(ETK_None, *SS, T);
> - }
> - }
> } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl))
> {
> (void)DiagnoseUseOfDecl(IDecl, NameLoc);
> if (!HasTrailingDot)
> T = Context.getObjCInterfaceType(IDecl);
> + } else if (AllowDeducedTemplate && isTypeTemplate(IIDecl)) {
> + T = Context.getDeducedTemplateSpecializationType(
> + TemplateName(cast<TemplateDecl>(IIDecl)), QualType(), false);
> }
>
> if (T.isNull()) {
> @@ -470,6 +468,27 @@ ParsedType Sema::getTypeName(const Ident
> Result.suppressDiagnostics();
> return nullptr;
> }
> +
> + // NOTE: avoid constructing an ElaboratedType(Loc) if this is a
> + // constructor or destructor name (in such a case, the scope specifier
> + // will be attached to the enclosing Expr or Decl node).
> + if (SS && SS->isNotEmpty() && !IsCtorOrDtorName &&
> + !isa<ObjCInterfaceDecl>(IIDecl)) {
> + if (WantNontrivialTypeSourceInfo) {
> + // Construct a type with type-source information.
> + TypeLocBuilder Builder;
> + Builder.pushTypeSpec(T).setNameLoc(NameLoc);
> +
> + T = getElaboratedType(ETK_None, *SS, T);
> + ElaboratedTypeLoc ElabTL = Builder.push<ElaboratedTypeLoc>(T);
> + ElabTL.setElaboratedKeywordLoc(SourceLocation());
> + ElabTL.setQualifierLoc(SS->getWithLocInContext(Context));
> + return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
> + } else {
> + T = getElaboratedType(ETK_None, *SS, T);
> + }
> + }
> +
> return ParsedType::make(T);
> }
>
> @@ -647,6 +666,7 @@ void Sema::DiagnoseUnknownTypeName(Ident
> if (Corrected.getCorrectionSpecifier())
> tmpSS.MakeTrivial(Context, Corrected.getCorrectionSpecifier(),
> SourceRange(IILoc));
> + // FIXME: Support class template argument deduction here.
> SuggestedType =
> getTypeName(*Corrected.getCorrectionAsIdentifierInfo(), IILoc,
> S,
> tmpSS.isSet() ? &tmpSS : SS, false, false, nullptr,
> @@ -9740,6 +9760,14 @@ QualType Sema::deduceVarTypeFromInitiali
>
> VarDeclOrName VN{VDecl, Name};
>
> + DeducedType *Deduced = Type->getContainedDeducedType();
> + assert(Deduced && "deduceVarTypeFromInitializer for non-deduced type");
> +
> + if (isa<DeducedTemplateSpecializationType>(Deduced)) {
> + Diag(Init->getLocStart(), diag::err_deduced_class_
> template_not_supported);
> + return QualType();
> + }
> +
> ArrayRef<Expr *> DeduceInits = Init;
> if (DirectInit) {
> if (auto *PL = dyn_cast<ParenListExpr>(Init))
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaExpr.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Jan 26 14:40:47 2017
> @@ -3976,7 +3976,8 @@ static void captureVariablyModifiedType(
> T = cast<DecltypeType>(Ty)->desugar();
> break;
> case Type::Auto:
> - T = cast<AutoType>(Ty)->getDeducedType();
> + case Type::DeducedTemplateSpecialization:
> + T = cast<DeducedType>(Ty)->getDeducedType();
> break;
> case Type::TypeOfExpr:
> T = cast<TypeOfExprType>(Ty)->getUnderlyingExpr()->getType();
>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaExprCXX.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Jan 26 14:40:47 2017
> @@ -1255,9 +1255,19 @@ Sema::BuildCXXTypeConstructExpr(TypeSour
> RParenLoc);
> }
>
> + // C++1z [expr.type.conv]p1:
> + // If the type is a placeholder for a deduced class type, [...perform
> class
> + // template argument deduction...]
> + DeducedType *Deduced = Ty->getContainedDeducedType();
> + if (Deduced && isa<DeducedTemplateSpecializationType>(Deduced)) {
> + Diag(TyBeginLoc, diag::err_deduced_class_template_not_supported);
> + return ExprError();
> + }
> +
> bool ListInitialization = LParenLoc.isInvalid();
> - assert((!ListInitialization || (Exprs.size() == 1 &&
> isa<InitListExpr>(Exprs[0])))
> - && "List initialization must have initializer list as
> expression.");
> + assert((!ListInitialization ||
> + (Exprs.size() == 1 && isa<InitListExpr>(Exprs[0]))) &&
> + "List initialization must have initializer list as expression.");
> SourceRange FullRange = SourceRange(TyBeginLoc,
> ListInitialization ? Exprs[0]->getSourceRange().getEnd() :
> RParenLoc);
>
> @@ -1646,6 +1656,11 @@ Sema::BuildCXXNew(SourceRange Range, boo
>
> // C++11 [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for.
> if (AllocType->isUndeducedType()) {
> + if (isa<DeducedTemplateSpecializationType>(
> + AllocType->getContainedDeducedType()))
> + return ExprError(Diag(TypeRange.getBegin(),
> + diag::err_deduced_class_
> template_not_supported));
> +
> if (initStyle == CXXNewExpr::NoInit || NumInits == 0)
> return ExprError(Diag(StartLoc, diag::err_auto_new_requires_
> ctor_arg)
> << AllocType << TypeRange);
>
> Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaLookup.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaLookup.cpp Thu Jan 26 14:40:47 2017
> @@ -2694,6 +2694,7 @@ addAssociatedClassesAndNamespaces(Associ
>
> // Non-deduced auto types only get here for error cases.
> case Type::Auto:
> + case Type::DeducedTemplateSpecialization:
> break;
>
> // If T is an Objective-C object or interface type, or a pointer to an
>
> Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaTemplate.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Jan 26 14:40:47 2017
> @@ -4439,6 +4439,11 @@ bool UnnamedLocalNoLinkageFinder::VisitA
> return Visit(T->getDeducedType());
> }
>
> +bool UnnamedLocalNoLinkageFinder::VisitDeducedTemplateSpecializationType(
> + const DeducedTemplateSpecializationType *T) {
> + return Visit(T->getDeducedType());
> +}
> +
> bool UnnamedLocalNoLinkageFinder::VisitRecordType(const RecordType* T) {
> return VisitTagDecl(T->getDecl());
> }
> @@ -8786,6 +8791,9 @@ Sema::CheckTypenameType(ElaboratedTypeKe
> Context.getTypeDeclType(Type));
> }
>
> + // FIXME: Form a deduced template specialization type if we get a
> template
> + // declaration here.
> +
> DiagID = diag::err_typename_nested_not_type;
> Referenced = Result.getFoundDecl();
> break;
>
> Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaTemplateDeduction.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Thu Jan 26 14:40:47 2017
> @@ -1723,6 +1723,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema
> case Type::Decltype:
> case Type::UnaryTransform:
> case Type::Auto:
> + case Type::DeducedTemplateSpecialization:
> case Type::DependentTemplateSpecialization:
> case Type::PackExpansion:
> case Type::Pipe:
> @@ -5152,8 +5153,9 @@ MarkUsedTemplateParameters(ASTContext &C
> break;
>
> case Type::Auto:
> + case Type::DeducedTemplateSpecialization:
> MarkUsedTemplateParameters(Ctx,
> - cast<AutoType>(T)->getDeducedType(),
> + cast<DeducedType>(T)->getDeducedType(),
> OnlyDeduced, Depth, Used);
>
> // None of these types have any template parameters in them.
>
> Modified: cfe/trunk/lib/Sema/SemaType.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaType.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaType.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaType.cpp Thu Jan 26 14:40:47 2017
> @@ -2778,12 +2778,20 @@ static QualType GetDeclSpecTypeForDeclar
> distributeTypeAttrsFromDeclarator(state, T);
>
> // C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed
> context.
> - if (D.getDeclSpec().containsPlaceholderType()) {
> + if (DeducedType *Deduced = T->getContainedDeducedType()) {
> + AutoType *Auto = dyn_cast<AutoType>(Deduced);
> int Error = -1;
>
> + // Is this a 'auto' or 'decltype(auto)' type (as opposed to
> __auto_type or
> + // class template argument deduction)?
> + bool IsCXXAutoType =
> + (Auto && Auto->getKeyword() != AutoTypeKeyword::GNUAutoType);
> +
> switch (D.getContext()) {
> case Declarator::LambdaExprContext:
> - llvm_unreachable("Can't specify a type specifier in lambda
> grammar");
> + // Declared return type of a lambda-declarator is implicit and is
> always
> + // 'auto'.
> + break;
> case Declarator::ObjCParameterContext:
> case Declarator::ObjCResultContext:
> case Declarator::PrototypeContext:
> @@ -2791,8 +2799,8 @@ static QualType GetDeclSpecTypeForDeclar
> break;
> case Declarator::LambdaExprParameterContext:
> // In C++14, generic lambdas allow 'auto' in their parameters.
> - if (!(SemaRef.getLangOpts().CPlusPlus14
> - && D.getDeclSpec().getTypeSpecType() ==
> DeclSpec::TST_auto))
> + if (!SemaRef.getLangOpts().CPlusPlus14 ||
> + !Auto || Auto->getKeyword() != AutoTypeKeyword::Auto)
> Error = 16;
> break;
> case Declarator::MemberContext: {
> @@ -2807,6 +2815,8 @@ static QualType GetDeclSpecTypeForDeclar
> case TTK_Class: Error = 5; /* Class member */ break;
> case TTK_Interface: Error = 6; /* Interface member */ break;
> }
> + if (D.getDeclSpec().isFriendSpecified())
> + Error = 20; // Friend type
> break;
> }
> case Declarator::CXXCatchContext:
> @@ -2814,8 +2824,10 @@ static QualType GetDeclSpecTypeForDeclar
> Error = 7; // Exception declaration
> break;
> case Declarator::TemplateParamContext:
> - if (!SemaRef.getLangOpts().CPlusPlus1z)
> - Error = 8; // Template parameter
> + if (isa<DeducedTemplateSpecializationType>(Deduced))
> + Error = 19; // Template parameter
> + else if (!SemaRef.getLangOpts().CPlusPlus1z)
> + Error = 8; // Template parameter (until C++1z)
> break;
> case Declarator::BlockLiteralContext:
> Error = 9; // Block literal
> @@ -2828,15 +2840,17 @@ static QualType GetDeclSpecTypeForDeclar
> Error = 12; // Type alias
> break;
> case Declarator::TrailingReturnContext:
> - if (!SemaRef.getLangOpts().CPlusPlus14 ||
> - D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type)
> + if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
> Error = 13; // Function return type
> break;
> case Declarator::ConversionIdContext:
> - if (!SemaRef.getLangOpts().CPlusPlus14 ||
> - D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type)
> + if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
> Error = 14; // conversion-type-id
> break;
> + case Declarator::FunctionalCastContext:
> + if (isa<DeducedTemplateSpecializationType>(Deduced))
> + break;
> + LLVM_FALLTHROUGH;
> case Declarator::TypeNameContext:
> Error = 15; // Generic
> break;
> @@ -2845,9 +2859,14 @@ static QualType GetDeclSpecTypeForDeclar
> case Declarator::ForContext:
> case Declarator::InitStmtContext:
> case Declarator::ConditionContext:
> + // FIXME: P0091R3 (erroneously) does not permit class template
> argument
> + // deduction in conditions, for-init-statements, and other
> declarations
> + // that are not simple-declarations.
> break;
> case Declarator::CXXNewContext:
> - if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type)
> + // FIXME: P0091R3 does not permit class template argument deduction
> here,
> + // but we follow GCC and allow it anyway.
> + if (!IsCXXAutoType && !isa<DeducedTemplateSpecializationT
> ype>(Deduced))
> Error = 17; // 'new' type
> break;
> case Declarator::KNRTypeListContext:
> @@ -2861,8 +2880,7 @@ static QualType GetDeclSpecTypeForDeclar
> // In Objective-C it is an error to use 'auto' on a function
> declarator
> // (and everywhere for '__auto_type').
> if (D.isFunctionDeclarator() &&
> - (!SemaRef.getLangOpts().CPlusPlus11 ||
> - D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type))
> + (!SemaRef.getLangOpts().CPlusPlus11 || !IsCXXAutoType))
> Error = 13;
>
> bool HaveTrailing = false;
> @@ -2872,8 +2890,8 @@ static QualType GetDeclSpecTypeForDeclar
> // level. Check all declarator chunks (outermost first) anyway, to
> give
> // better diagnostics.
> // We don't support '__auto_type' with trailing return types.
> - if (SemaRef.getLangOpts().CPlusPlus11 &&
> - D.getDeclSpec().getTypeSpecType() != DeclSpec::TST_auto_type) {
> + // FIXME: Should we only do this for 'auto' and not 'decltype(auto)'?
> + if (SemaRef.getLangOpts().CPlusPlus11 && IsCXXAutoType) {
> for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
> unsigned chunkIndex = e - i - 1;
> state.setCurrentChunkIndex(chunkIndex);
> @@ -2894,15 +2912,28 @@ static QualType GetDeclSpecTypeForDeclar
> AutoRange = D.getName().getSourceRange();
>
> if (Error != -1) {
> - unsigned Keyword;
> - switch (D.getDeclSpec().getTypeSpecType()) {
> - case DeclSpec::TST_auto: Keyword = 0; break;
> - case DeclSpec::TST_decltype_auto: Keyword = 1; break;
> - case DeclSpec::TST_auto_type: Keyword = 2; break;
> - default: llvm_unreachable("unknown auto TypeSpecType");
> + unsigned Kind;
> + if (Auto) {
> + switch (Auto->getKeyword()) {
> + case AutoTypeKeyword::Auto: Kind = 0; break;
> + case AutoTypeKeyword::DecltypeAuto: Kind = 1; break;
> + case AutoTypeKeyword::GNUAutoType: Kind = 2; break;
> + }
> + } else {
> + assert(isa<DeducedTemplateSpecializationType>(Deduced) &&
> + "unknown auto type");
> + Kind = 3;
> }
> +
> + auto *DTST = dyn_cast<DeducedTemplateSpecializationType>(Deduced);
> + TemplateName TN = DTST ? DTST->getTemplateName() : TemplateName();
> +
> SemaRef.Diag(AutoRange.getBegin(), diag::err_auto_not_allowed)
> - << Keyword << Error << AutoRange;
> + << Kind << Error << (int)SemaRef.getTemplateNameKindForDiagnost
> ics(TN)
> + << QualType(Deduced, 0) << AutoRange;
> + if (auto *TD = TN.getAsTemplateDecl())
> + SemaRef.Diag(TD->getLocation(), diag::note_template_decl_here);
> +
> T = SemaRef.Context.IntTy;
> D.setInvalidType(true);
> } else if (!HaveTrailing) {
> @@ -2942,6 +2973,7 @@ static QualType GetDeclSpecTypeForDeclar
> DiagID = diag::err_type_defined_in_alias_template;
> break;
> case Declarator::TypeNameContext:
> + case Declarator::FunctionalCastContext:
> case Declarator::ConversionIdContext:
> case Declarator::TemplateParamContext:
> case Declarator::CXXNewContext:
> @@ -3623,17 +3655,32 @@ static TypeSourceInfo *GetFullTypeForDec
>
> // If T is 'decltype(auto)', the only declarators we can have are parens
> // and at most one function declarator if this is a function
> declaration.
> - if (const AutoType *AT = T->getAs<AutoType>()) {
> - if (AT->isDecltypeAuto()) {
> + // If T is a deduced class template specialization type, we can have no
> + // declarator chunks at all.
> + if (auto *DT = T->getAs<DeducedType>()) {
> + const AutoType *AT = T->getAs<AutoType>();
> + bool IsClassTemplateDeduction = isa<DeducedTemplateSpecializationT
> ype>(DT);
> + if ((AT && AT->isDecltypeAuto()) || IsClassTemplateDeduction) {
> for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) {
> unsigned Index = E - I - 1;
> DeclaratorChunk &DeclChunk = D.getTypeObject(Index);
> - unsigned DiagId = diag::err_decltype_auto_compound_type;
> + unsigned DiagId = IsClassTemplateDeduction
> + ? diag::err_deduced_class_
> template_compound_type
> + : diag::err_decltype_auto_compound_type;
> unsigned DiagKind = 0;
> switch (DeclChunk.Kind) {
> case DeclaratorChunk::Paren:
> + // FIXME: Rejecting this is a little silly.
> + if (IsClassTemplateDeduction) {
> + DiagKind = 4;
> + break;
> + }
> continue;
> case DeclaratorChunk::Function: {
> + if (IsClassTemplateDeduction) {
> + DiagKind = 3;
> + break;
> + }
> unsigned FnIndex;
> if (D.isFunctionDeclarationContext() &&
> D.isFunctionDeclarator(FnIndex) && FnIndex == Index)
> @@ -3834,6 +3881,7 @@ static TypeSourceInfo *GetFullTypeForDec
> case Declarator::TemplateParamContext:
> case Declarator::TemplateTypeArgContext:
> case Declarator::TypeNameContext:
> + case Declarator::FunctionalCastContext:
> // Don't infer in these contexts.
> break;
> }
> @@ -4713,6 +4761,7 @@ static TypeSourceInfo *GetFullTypeForDec
> case Declarator::ObjCParameterContext: // FIXME: special diagnostic
> here?
> case Declarator::ObjCResultContext: // FIXME: special diagnostic
> here?
> case Declarator::TypeNameContext:
> + case Declarator::FunctionalCastContext:
> case Declarator::CXXNewContext:
> case Declarator::AliasDeclContext:
> case Declarator::AliasTemplateContext:
>
> Modified: cfe/trunk/lib/Sema/TreeTransform.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> TreeTransform.h?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/TreeTransform.h (original)
> +++ cfe/trunk/lib/Sema/TreeTransform.h Thu Jan 26 14:40:47 2017
> @@ -876,6 +876,14 @@ public:
> /*IsDependent*/ false);
> }
>
> + /// By default, builds a new DeducedTemplateSpecializationType with
> the given
> + /// deduced type.
> + QualType RebuildDeducedTemplateSpecializationType(TemplateName
> Template,
> + QualType Deduced) {
> + return SemaRef.Context.getDeducedTemplateSpecializationType(
> + Template, Deduced, /*IsDependent*/ false);
> + }
> +
> /// \brief Build a new template specialization type.
> ///
> /// By default, performs semantic analysis when building the template
> @@ -5344,6 +5352,37 @@ QualType TreeTransform<Derived>::Transfo
>
> return Result;
> }
> +
> +template<typename Derived>
> +QualType TreeTransform<Derived>::TransformDeducedTemplateSpecia
> lizationType(
> + TypeLocBuilder &TLB, DeducedTemplateSpecializationTypeLoc TL) {
> + const DeducedTemplateSpecializationType *T = TL.getTypePtr();
> +
> + CXXScopeSpec SS;
> + TemplateName TemplateName = getDerived().TransformTemplateName(
> + SS, T->getTemplateName(), TL.getTemplateNameLoc());
> + if (TemplateName.isNull())
> + return QualType();
> +
> + QualType OldDeduced = T->getDeducedType();
> + QualType NewDeduced;
> + if (!OldDeduced.isNull()) {
> + NewDeduced = getDerived().TransformType(OldDeduced);
> + if (NewDeduced.isNull())
> + return QualType();
> + }
> +
> + QualType Result = getDerived().RebuildDeducedTemplateSpeciali
> zationType(
> + TemplateName, NewDeduced);
> + if (Result.isNull())
> + return QualType();
> +
> + DeducedTemplateSpecializationTypeLoc NewTL =
> + TLB.push<DeducedTemplateSpecializationTypeLoc>(Result);
> + NewTL.setTemplateNameLoc(TL.getTemplateNameLoc());
> +
> + return Result;
> +}
>
> template<typename Derived>
> QualType TreeTransform<Derived>::TransformRecordType(TypeLocBuilder &TLB,
>
> Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/
> Serialization/ASTReader.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReader.cpp Thu Jan 26 14:40:47 2017
> @@ -5651,6 +5651,14 @@ QualType ASTReader::readTypeRecord(unsig
> return Context.getAutoType(Deduced, Keyword, IsDependent);
> }
>
> + case TYPE_DEDUCED_TEMPLATE_SPECIALIZATION: {
> + TemplateName Name = ReadTemplateName(*Loc.F, Record, Idx);
> + QualType Deduced = readType(*Loc.F, Record, Idx);
> + bool IsDependent = Deduced.isNull() ? Record[Idx++] : false;
> + return Context.getDeducedTemplateSpecializationType(Name, Deduced,
> + IsDependent);
> + }
> +
> case TYPE_RECORD: {
> if (Record.size() != 2) {
> Error("incorrect encoding of record type");
> @@ -6082,6 +6090,11 @@ void TypeLocReader::VisitAutoTypeLoc(Aut
> TL.setNameLoc(ReadSourceLocation());
> }
>
> +void TypeLocReader::VisitDeducedTemplateSpecializationTypeLoc(
> + DeducedTemplateSpecializationTypeLoc TL) {
> + TL.setTemplateNameLoc(ReadSourceLocation());
> +}
> +
> void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
> TL.setNameLoc(ReadSourceLocation());
> }
>
> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/
> Serialization/ASTWriter.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Thu Jan 26 14:40:47 2017
> @@ -349,6 +349,15 @@ void ASTTypeWriter::VisitAutoType(const
> Code = TYPE_AUTO;
> }
>
> +void ASTTypeWriter::VisitDeducedTemplateSpecializationType(
> + const DeducedTemplateSpecializationType *T) {
> + Record.AddTemplateName(T->getTemplateName());
> + Record.AddTypeRef(T->getDeducedType());
> + if (T->getDeducedType().isNull())
> + Record.push_back(T->isDependentType());
> + Code = TYPE_DEDUCED_TEMPLATE_SPECIALIZATION;
> +}
> +
> void ASTTypeWriter::VisitTagType(const TagType *T) {
> Record.push_back(T->isDependentType());
> Record.AddDeclRef(T->getDecl()->getCanonicalDecl());
> @@ -683,6 +692,11 @@ void TypeLocWriter::VisitAutoTypeLoc(Aut
> Record.AddSourceLocation(TL.getNameLoc());
> }
>
> +void TypeLocWriter::VisitDeducedTemplateSpecializationTypeLoc(
> + DeducedTemplateSpecializationTypeLoc TL) {
> + Record.AddSourceLocation(TL.getTemplateNameLoc());
> +}
> +
> void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {
> Record.AddSourceLocation(TL.getNameLoc());
> }
>
> Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.
> auto/p5.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp?rev=293207&
> r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
> (original)
> +++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp Thu
> Jan 26 14:40:47 2017
> @@ -9,7 +9,7 @@ struct S {
>
> void f() throw (auto); // expected-error{{'auto' not allowed here}}
>
> - friend auto; // expected-error{{'auto' not allowed in non-static struct
> member}}
> + friend auto; // expected-error{{'auto' not allowed in friend
> declaration}}
>
> operator auto(); // expected-error{{'auto' not allowed in conversion
> function type}}
> };
>
> Modified: cfe/trunk/test/CXX/drs/dr5xx.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/
> drs/dr5xx.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/drs/dr5xx.cpp (original)
> +++ cfe/trunk/test/CXX/drs/dr5xx.cpp Thu Jan 26 14:40:47 2017
> @@ -877,13 +877,25 @@ namespace dr583 { // dr583: 4
> namespace dr585 { // dr585: yes
> template<typename> struct T;
> struct A {
> - friend T; // expected-error {{requires a type specifier}}
> expected-error {{can only be classes or functions}}
> + friend T;
> +#if __cplusplus <= 201402L
> + // expected-error at -2 {{requires a type specifier}} expected-error at -2
> {{can only be classes or functions}}
> +#else
> + // expected-error at -4 {{use of class template 'T' requires template
> arguments; argument deduction not allowed in friend declaration}}
> + // expected-note at -7 {{here}}
> +#endif
> // FIXME: It's not clear whether the standard allows this or what it
> means,
> // but the DR585 writeup suggests it as an alternative.
> template<typename U> friend T<U>; // expected-error {{must use an
> elaborated type}}
> };
> template<template<typename> class T> struct B {
> - friend T; // expected-error {{requires a type specifier}}
> expected-error {{can only be classes or functions}}
> + friend T;
> +#if __cplusplus <= 201402L
> + // expected-error at -2 {{requires a type specifier}} expected-error at -2
> {{can only be classes or functions}}
> +#else
> + // expected-error at -4 {{use of template template parameter 'T'
> requires template arguments; argument deduction not allowed in friend
> declaration}}
> + // expected-note at -6 {{here}}
> +#endif
> template<typename U> friend T<U>; // expected-error {{must use an
> elaborated type}}
> };
> }
>
> Modified: cfe/trunk/test/Parser/backtrack-off-by-one.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/
> backtrack-off-by-one.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/Parser/backtrack-off-by-one.cpp (original)
> +++ cfe/trunk/test/Parser/backtrack-off-by-one.cpp Thu Jan 26 14:40:47
> 2017
> @@ -1,6 +1,7 @@
> // RUN: %clang_cc1 -verify %s
> // RUN: %clang_cc1 -verify %s -std=c++98
> // RUN: %clang_cc1 -verify %s -std=c++11
> +// RUN: %clang_cc1 -verify %s -std=c++1z
>
> // PR25946
> // We had an off-by-one error in an assertion when annotating A<int>
> below. Our
> @@ -13,9 +14,13 @@ template <typename T> class A {};
> // expected-error at +1 {{expected '{' after base class list}}
> template <typename T> class B : T // not ',' or '{'
> #if __cplusplus < 201103L
> -// expected-error at +4 {{expected ';' after top level declarator}}
> +// expected-error at +8 {{expected ';' after top level declarator}}
> +#endif
> +#if __cplusplus <= 201402L
> +// expected-error at +5 {{C++ requires a type specifier for all
> declarations}}
> +#else
> +// expected-error at +3 {{expected unqualified-id}}
> #endif
> -// expected-error at +2 {{C++ requires a type specifier for all
> declarations}}
> // expected-error at +1 {{expected ';' after class}}
> A<int> {
> };
>
> Added: cfe/trunk/test/Parser/cxx1z-class-template-argument-deduction.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/
> cxx1z-class-template-argument-deduction.cpp?rev=293207&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/Parser/cxx1z-class-template-argument-deduction.cpp
> (added)
> +++ cfe/trunk/test/Parser/cxx1z-class-template-argument-deduction.cpp Thu
> Jan 26 14:40:47 2017
> @@ -0,0 +1,131 @@
> +// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -verify %s
> +
> +template<typename T> 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 {
> + template<template<typename> typename> struct X {};
> + template<typename> struct Y {};
> +
> + X<A> xa;
> + Y<A> ya; // expected-error {{requires template arguments}}
> + X<::A> xcca;
> + Y<::A> ycca; // expected-error {{requires template arguments}}
> +
> + template<template<typename> typename = A> struct XD {};
> + template<typename = A> struct YD {}; // expected-error {{requires
> template arguments}}
> + template<template<typename> typename = ::A> struct XCCD {};
> + template<typename = ::A> struct YCCD {}; // expected-error {{requires
> template arguments}}
> +
> + // FIXME: replacing the invalid type with 'int' here is horrible
> + template <A a = A<int>()> class C { }; // expected-error {{requires
> template arguments}} expected-error {{not implicitly convertible to 'int'}}
> + template<typename T = A> struct G { }; // expected-error {{requires
> template arguments}}
> +}
> +
> +namespace injected_class_name {
> + template<typename T> struct A {
> + A(T);
> + void f(int) {
> + A a = 1;
> + injected_class_name::A b = 1; // expected-error {{not yet
> supported}}
> + }
> + void f(T);
> + };
> + A<short> ai = 1;
> + A<double>::A b(1); // expected-error {{constructor name}}
> +}
> +
> +struct member {
> + A a; // expected-error {{requires template arguments}}
> + A *b; // expected-error {{requires template arguments}}
> + const A c; // expected-error {{requires template arguments}}
> +
> + void f() throw (A); // expected-error {{requires template arguments}}
> +
> + friend A; // expected-error {{requires template arguments; argument
> deduction not allowed in friend declaration}}
> +
> + operator A(); // expected-error {{requires template arguments; argument
> deduction not allowed in conversion function type}}
> +
> + static A x; // expected-error {{requires an initializer}}
> + static A y = 0; // expected-error {{not yet supported}}
> +};
> +
> +namespace in_typedef {
> + typedef A *AutoPtr; // expected-error {{requires template arguments;
> argument deduction not allowed in typedef}}
> + typedef A (*PFun)(int a); // expected-error{{requires template
> arguments; argument deduction not allowed in typedef}}
> + typedef A Fun(int a) -> decltype(a + a); // expected-error{{requires
> template arguments; argument deduction not allowed in function return type}}
> +}
> +
> +namespace stmt {
> + void g(A a) { // expected-error{{requires template arguments; argument
> deduction not allowed in function prototype}}
> + try { }
> + catch (A &a) { } // expected-error{{requires template arguments;
> argument deduction not allowed in exception declaration}}
> + catch (const A a) { } // expected-error{{requires template arguments;
> argument deduction not allowed in exception declaration}}
> + try { } catch (A a) { } // expected-error{{requires template
> arguments; argument deduction not allowed in exception declaration}}
> +
> + // FIXME: The standard only permits class template argument deduction
> in a
> + // simple-declaration or cast. We also permit it in conditions,
> + // for-range-declarations, member-declarations for static data
> members, and
> + // new-expressions, because not doing so would be bizarre.
> + A local = 0; // expected-error {{not yet supported}}
> + static A local_static = 0; // expected-error {{not yet supported}}
> + static thread_local A thread_local_static = 0; // expected-error
> {{not yet supported}}
> + if (A a = 0) {} // expected-error {{not yet supported}}
> + if (A a = 0; a) {} // expected-error {{not yet supported}}
> + switch (A a = 0) {} // expected-error {{not yet supported}}
> + switch (A a = 0; a) {} // expected-error {{not yet supported}}
> + for (A a = 0; a; /**/) {} // expected-error {{not yet supported}}
> + for (/**/; A a = 0; /**/) {} // expected-error {{not yet supported}}
> + while (A a = 0) {} // expected-error {{not yet supported}}
> + int arr[3];
> + for (A a : arr) {} // expected-error {{not yet supported}}
> + }
> +
> + namespace std {
> + class type_info;
> + }
> +}
> +
> +namespace expr {
> + template<typename T> struct U {};
> + void j() {
> + (void)typeid(A); // expected-error{{requires template arguments;
> argument deduction not allowed here}}
> + (void)sizeof(A); // expected-error{{requires template arguments;
> argument deduction not allowed here}}
> + (void)__alignof(A); // expected-error{{requires template arguments;
> argument deduction not allowed here}}
> +
> + U<A> v; // expected-error {{requires template arguments}}
> +
> + int n;
> + (void)dynamic_cast<A&>(n); // expected-error{{requires template
> arguments; argument deduction not allowed here}}
> + (void)static_cast<A*>(&n); // expected-error{{requires template
> arguments; argument deduction not allowed here}}
> + (void)reinterpret_cast<A*>(&n); // expected-error{{requires template
> arguments; argument deduction not allowed here}}
> + (void)const_cast<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}}
> + (void)new A(n); // expected-error {{not yet supported}}
> + (void)new A{n}; // expected-error {{not yet supported}}
> + // FIXME: We should diagnose the lack of an initializer here.
> + (void)new A; // expected-error {{not yet supported}}
> + }
> +}
> +
> +namespace decl {
> + enum E : A {}; // expected-error{{requires template arguments; argument
> deduction not allowed here}}
> + struct F : A {}; // expected-error{{expected class name}}
> +
> + using B = A; // expected-error{{requires template arguments}}
> +
> + auto k() -> A; // expected-error{{requires template arguments}}
> +
> + A a; // expected-error {{requires an initializer}}
> + A b = 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}}
> + A arr[3] = 0; // expected-error {{cannot form array of deduced class
> template specialization type}}
> + A F::*pm = 0; // expected-error {{cannot form pointer to deduced class
> template specialization type}}
> + 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}}
> +}
>
> Modified: cfe/trunk/test/SemaTemplate/temp_arg.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> SemaTemplate/temp_arg.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/SemaTemplate/temp_arg.cpp (original)
> +++ cfe/trunk/test/SemaTemplate/temp_arg.cpp Thu Jan 26 14:40:47 2017
> @@ -10,7 +10,7 @@ A<int, 0, X> * a1;
>
> A<float, 1, X, double> *a2; // expected-error{{too many template
> arguments for class template 'A'}}
> A<float, 1> *a3; // expected-error{{too few template arguments for class
> template 'A'}}
> -A a3; // expected-error{{use of class template 'A' requires template
> arguments}}
> +A a4; // expected-error{{use of class template 'A' requires template
> arguments}}
>
> namespace test0 {
> template <class t> class foo {};
>
> Modified: cfe/trunk/test/SemaTemplate/typename-specifier-3.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> SemaTemplate/typename-specifier-3.cpp?rev=293207&r1=
> 293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/SemaTemplate/typename-specifier-3.cpp (original)
> +++ cfe/trunk/test/SemaTemplate/typename-specifier-3.cpp Thu Jan 26
> 14:40:47 2017
> @@ -1,7 +1,7 @@
> // RUN: %clang_cc1 -fsyntax-only -verify %s
>
> // PR4364
> -template<class T> struct a {
> +template<class T> struct a { // expected-note {{here}}
> T b() {
> return typename T::x();
> }
> @@ -17,3 +17,4 @@ B c() {
> // Some extra tests for invalid cases
> template<class T> struct test2 { T b() { return typename T::a; } }; //
> expected-error{{expected '(' for function-style cast or type construction}}
> template<class T> struct test3 { T b() { return typename a; } }; //
> expected-error{{expected a qualified name after 'typename'}}
> +template<class T> struct test4 { T b() { return typename ::a; } }; //
> expected-error{{refers to non-type member}} expected-error{{expected '('
> for function-style cast or type construction}}
>
> Modified: cfe/trunk/tools/libclang/CIndex.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/
> libclang/CIndex.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/tools/libclang/CIndex.cpp (original)
> +++ cfe/trunk/tools/libclang/CIndex.cpp Thu Jan 26 14:40:47 2017
> @@ -1640,6 +1640,15 @@ bool CursorVisitor::VisitAdjustedTypeLoc
> return Visit(TL.getOriginalLoc());
> }
>
> +bool CursorVisitor::VisitDeducedTemplateSpecializationTypeLoc(
> + DeducedTemplateSpecializationTypeLoc TL) {
> + if (VisitTemplateName(TL.getTypePtr()->getTemplateName(),
> + TL.getTemplateNameLoc()))
> + return true;
> +
> + return false;
> +}
> +
> bool CursorVisitor::VisitTemplateSpecializationTypeLoc(
>
> TemplateSpecializationTypeLoc TL) {
> // Visit the template name.
>
> Modified: cfe/trunk/tools/libclang/CXType.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/
> libclang/CXType.cpp?rev=293207&r1=293206&r2=293207&view=diff
> ============================================================
> ==================
> --- cfe/trunk/tools/libclang/CXType.cpp (original)
> +++ cfe/trunk/tools/libclang/CXType.cpp Thu Jan 26 14:40:47 2017
> @@ -452,7 +452,8 @@ try_again:
> break;
>
> case Type::Auto:
> - TP = cast<AutoType>(TP)->getDeducedType().getTypePtrOrNull();
> + case Type::DeducedTemplateSpecialization:
> + TP = cast<DeducedType>(TP)->getDeducedType().getTypePtrOrNull();
> if (TP)
> goto try_again;
> break;
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170127/f3d09290/attachment-0001.html>
More information about the cfe-commits
mailing list