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