Hi Richard, I've filed this issue as PR31783.

Douglas Yung

> -----Original Message-----
> From: cfe-commits [mailto:cfe-commits-boun...@lists.llvm.org] On Behalf
> Of Yung, Douglas via cfe-commits
> Sent: Thursday, January 26, 2017 15:36
> To: Richard Smith
> Cc: cfe-commits@lists.llvm.org
> Subject: RE: r293207 - PR0091R3: Implement parsing support for using
> templates as types.
> 
> Hi Richard,
> 
> I don't know if you have noticed, but the test you added in this commit
> is failing on both the Linux and Windows PS4 bots. The test is failing
> with an assertion failure:
> 
> Assertion failed: !A->getDeducedType().isNull() && "cannot request the
> size of an undeduced or dependent auto type", file
> C:\Buildbot\Slave\llvm-clang-lld-x86_64-scei-ps4-windows10pro-
> fast\llvm.src\tools\clang\lib\AST\ASTContext.cpp, line 1884
> 
> Can you take a look?
> 
> Windows PS4 bot failure: http://lab.llvm.org:8011/builders/llvm-clang-
> lld-x86_64-scei-ps4-windows10pro-fast/builds/4531
> Linux PS4 bot failure: http://lab.llvm.org:8011/builders/llvm-clang-
> lld-x86_64-scei-ps4-ubuntu-fast/builds/5093
> 
> Douglas Yung
> 
> > -----Original Message-----
> > From: cfe-commits [mailto:cfe-commits-boun...@lists.llvm.org] On
> Behalf
> > Of Richard Smith via cfe-commits
> > Sent: Thursday, January 26, 2017 12:41
> > To: cfe-commits@lists.llvm.org
> > Subject: r293207 - PR0091R3: Implement parsing support for using
> > templates as types.
> >
> > 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&r
> > 2=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=2932
> > 07&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=2
> > 93207&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,
> > +
> > DeducedTemplateSpecializationTypeLoc,
> > +
> > 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=293
> > 207&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=29320
> > 7&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=2932
> > 07&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=293
> > 207&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=2
> > 93207&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=29320
> > 7&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=2
> > 93207&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=29320
> > 7&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,
> > +
> > isClassTemplateDeductionContext(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=29
> > 3207&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=29
> > 3207&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&v
> > iew=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=2932
> > 07&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=29320
> > 7&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=293
> > 207&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=2932
> > 06&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<DeducedTemplateSpecializationType>(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.getTemplateNameKindForDiagnostics(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<DeducedTemplateSpecializationType>(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=2932
> > 07&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>::TransformDeducedTemplateSpecializationType(
> > +    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().RebuildDeducedTemplateSpecializationType(
> > +      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.c
> > pp?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@-2 {{requires a type specifier}} expected-
> > error@-2 {{can only be classes or functions}}
> > +#else
> > +    // expected-error@-4 {{use of class template 'T' requires
> template
> > arguments; argument deduction not allowed in friend declaration}}
> > +    // expected-note@-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@-2 {{requires a type specifier}} expected-
> > error@-2 {{can only be classes or functions}}
> > +#else
> > +    // expected-error@-4 {{use of template template parameter 'T'
> > requires template arguments; argument deduction not allowed in friend
> > declaration}}
> > +    // expected-note@-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@+1 {{expected '{' after base class list}}
> >  template <typename T> class B : T // not ',' or '{'
> >  #if __cplusplus < 201103L
> > -// expected-error@+4 {{expected ';' after top level declarator}}
> > +// expected-error@+8 {{expected ';' after top level declarator}}
> > +#endif
> > +#if __cplusplus <= 201402L
> > +// expected-error@+5 {{C++ requires a type specifier for all
> > declarations}}
> > +#else
> > +// expected-error@+3 {{expected unqualified-id}}
> >  #endif
> > -// expected-error@+2 {{C++ requires a type specifier for all
> > declarations}}
> >  // expected-error@+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&r
> > 2=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=293
> > 207&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=293
> > 207&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@lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
> _______________________________________________
> cfe-commits mailing list
> cfe-commits@lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to