r293207 - PR0091R3: Implement parsing support for using templates as types.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 27 00:30:29 PST 2017


On 26 Jan 2017 3:36 pm, "Yung, Douglas via cfe-commits" <
cfe-commits at lists.llvm.org> wrote:

Hi Richard,

I don't know if you have noticed, but the test you added in this commit is
failing on both the Linux and Windows PS4 bots. The test is failing with an
assertion failure:


Thanks for letting me know, I didn't get any mail from the bots about this
(maybe due to the llvm.org downtime?). I'll look at this tomorrow; please
feel free to revert in the meantime, of course.

Assertion failed: !A->getDeducedType().isNull() && "cannot request the size
of an undeduced or dependent auto type", file C:\Buildbot\Slave\llvm-clang-
lld-x86_64-scei-ps4-windows10pro-fast\llvm.src\tools\clang\lib\AST\ASTContext.cpp,
line 1884

Can you take a look?

Windows PS4 bot failure: http://lab.llvm.org:8011/
builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/4531
Linux PS4 bot failure: http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_
64-scei-ps4-ubuntu-fast/builds/5093

Douglas Yung

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


More information about the cfe-commits mailing list