r293207 - PR0091R3: Implement parsing support for using templates as types.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 27 13:40:19 PST 2017
Fixed in r293333.
On 27 January 2017 at 13:27, Richard Smith <richard at metafoo.co.uk> wrote:
> It's a pre-existing bug with some PS4-specific TLS handling ("thread_local
> auto a;" is sufficient to trigger the assert). A fix is on the way.
>
> On 27 January 2017 at 11:00, Galina Kistanova via cfe-commits <
> cfe-commits at lists.llvm.org> wrote:
>
>> Hello Richard,
>>
>> This commit broke test on few our builders:
>>
>> Failing Tests (1):
>> Clang :: Parser/cxx1z-class-template-argument-deduction.cpp
>>
>> http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-
>> scei-ps4-ubuntu-fast
>> http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-
>> scei-ps4-windows10pro-fast
>>
>> Please have a look at this?
>>
>> Thanks
>>
>> Galina
>>
>>
>>
>> On Thu, Jan 26, 2017 at 12:40 PM, Richard Smith via cfe-commits <
>> cfe-commits at lists.llvm.org> wrote:
>>
>>> Author: rsmith
>>> Date: Thu Jan 26 14:40:47 2017
>>> New Revision: 293207
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=293207&view=rev
>>> Log:
>>> PR0091R3: Implement parsing support for using templates as types.
>>>
>>> This change adds a new type node, DeducedTemplateSpecializationType, to
>>> represent a type template name that has been used as a type. This is
>>> modeled
>>> around AutoType, and shares a common base class for representing a
>>> deduced
>>> placeholder type.
>>>
>>> We allow deduced class template types in a few more places than the
>>> standard
>>> does: in conditions and for-range-declarators, and in new-type-ids. This
>>> is
>>> consistent with GCC and with discussion on the core reflector. This patch
>>> does not yet support deduced class template types being named in typename
>>> specifiers.
>>>
>>> Added:
>>> cfe/trunk/test/Parser/cxx1z-class-template-argument-deduction.cpp
>>> Modified:
>>> cfe/trunk/include/clang/AST/ASTContext.h
>>> cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
>>> cfe/trunk/include/clang/AST/Type.h
>>> cfe/trunk/include/clang/AST/TypeLoc.h
>>> cfe/trunk/include/clang/AST/TypeNodes.def
>>> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>>> cfe/trunk/include/clang/Parse/Parser.h
>>> cfe/trunk/include/clang/Sema/DeclSpec.h
>>> cfe/trunk/include/clang/Sema/Sema.h
>>> cfe/trunk/include/clang/Serialization/ASTBitCodes.h
>>> cfe/trunk/lib/AST/ASTContext.cpp
>>> cfe/trunk/lib/AST/ASTImporter.cpp
>>> cfe/trunk/lib/AST/ExprConstant.cpp
>>> cfe/trunk/lib/AST/ItaniumMangle.cpp
>>> cfe/trunk/lib/AST/MicrosoftMangle.cpp
>>> cfe/trunk/lib/AST/Type.cpp
>>> cfe/trunk/lib/AST/TypePrinter.cpp
>>> cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
>>> cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
>>> cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
>>> cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
>>> cfe/trunk/lib/Parse/ParseDecl.cpp
>>> cfe/trunk/lib/Parse/ParseDeclCXX.cpp
>>> cfe/trunk/lib/Parse/ParseExprCXX.cpp
>>> cfe/trunk/lib/Parse/Parser.cpp
>>> cfe/trunk/lib/Sema/SemaDecl.cpp
>>> cfe/trunk/lib/Sema/SemaExpr.cpp
>>> cfe/trunk/lib/Sema/SemaExprCXX.cpp
>>> cfe/trunk/lib/Sema/SemaLookup.cpp
>>> cfe/trunk/lib/Sema/SemaTemplate.cpp
>>> cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
>>> cfe/trunk/lib/Sema/SemaType.cpp
>>> cfe/trunk/lib/Sema/TreeTransform.h
>>> cfe/trunk/lib/Serialization/ASTReader.cpp
>>> cfe/trunk/lib/Serialization/ASTWriter.cpp
>>> cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
>>> cfe/trunk/test/CXX/drs/dr5xx.cpp
>>> cfe/trunk/test/Parser/backtrack-off-by-one.cpp
>>> cfe/trunk/test/SemaTemplate/temp_arg.cpp
>>> cfe/trunk/test/SemaTemplate/typename-specifier-3.cpp
>>> cfe/trunk/tools/libclang/CIndex.cpp
>>> cfe/trunk/tools/libclang/CXType.cpp
>>>
>>> Modified: cfe/trunk/include/clang/AST/ASTContext.h
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/
>>> AST/ASTContext.h?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/include/clang/AST/ASTContext.h (original)
>>> +++ cfe/trunk/include/clang/AST/ASTContext.h Thu Jan 26 14:40:47 2017
>>> @@ -167,6 +167,8 @@ class ASTContext : public RefCountedBase
>>> mutable llvm::FoldingSet<DependentUnaryTransformType>
>>> DependentUnaryTransformTypes;
>>> mutable llvm::FoldingSet<AutoType> AutoTypes;
>>> + mutable llvm::FoldingSet<DeducedTemplateSpecializationType>
>>> + DeducedTemplateSpecializationTypes;
>>> mutable llvm::FoldingSet<AtomicType> AtomicTypes;
>>> llvm::FoldingSet<AttributedType> AttributedTypes;
>>> mutable llvm::FoldingSet<PipeType> PipeTypes;
>>> @@ -1412,6 +1414,11 @@ public:
>>> /// \brief C++11 deduction pattern for 'auto &&' type.
>>> QualType getAutoRRefDeductType() const;
>>>
>>> + /// \brief C++1z deduced class template specialization type.
>>> + QualType getDeducedTemplateSpecializationType(TemplateName Template,
>>> + QualType DeducedType,
>>> + bool IsDependent) const;
>>> +
>>> /// \brief Return the unique reference to the type for the specified
>>> TagDecl
>>> /// (struct/union/class/enum) decl.
>>> QualType getTagDeclType(const TagDecl *Decl) const;
>>>
>>> Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/
>>> AST/RecursiveASTVisitor.h?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
>>> +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Thu Jan 26
>>> 14:40:47 2017
>>> @@ -1008,6 +1008,10 @@ DEF_TRAVERSE_TYPE(UnaryTransformType, {
>>> })
>>>
>>> DEF_TRAVERSE_TYPE(AutoType, { TRY_TO(TraverseType(T->getDeducedType()));
>>> })
>>> +DEF_TRAVERSE_TYPE(DeducedTemplateSpecializationType, {
>>> + TRY_TO(TraverseTemplateName(T->getTemplateName()));
>>> + TRY_TO(TraverseType(T->getDeducedType()));
>>> +})
>>>
>>> DEF_TRAVERSE_TYPE(RecordType, {})
>>> DEF_TRAVERSE_TYPE(EnumType, {})
>>> @@ -1232,6 +1236,11 @@ DEF_TRAVERSE_TYPELOC(AutoType, {
>>> TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
>>> })
>>>
>>> +DEF_TRAVERSE_TYPELOC(DeducedTemplateSpecializationType, {
>>> + TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName()));
>>> + TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
>>> +})
>>> +
>>> DEF_TRAVERSE_TYPELOC(RecordType, {})
>>> DEF_TRAVERSE_TYPELOC(EnumType, {})
>>> DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {})
>>>
>>> Modified: cfe/trunk/include/clang/AST/Type.h
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/
>>> AST/Type.h?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/include/clang/AST/Type.h (original)
>>> +++ cfe/trunk/include/clang/AST/Type.h Thu Jan 26 14:40:47 2017
>>> @@ -1785,7 +1785,8 @@ public:
>>> }
>>>
>>> /// \brief Determine whether this type is an undeduced type, meaning
>>> that
>>> - /// it somehow involves a C++11 'auto' type which has not yet been
>>> deduced.
>>> + /// it somehow involves a C++11 'auto' type or similar which has not
>>> yet been
>>> + /// deduced.
>>> bool isUndeducedType() const;
>>>
>>> /// \brief Whether this type is a variably-modified type (C99 6.7.5).
>>> @@ -1862,10 +1863,17 @@ public:
>>> /// not refer to a CXXRecordDecl, returns NULL.
>>> const CXXRecordDecl *getPointeeCXXRecordDecl() const;
>>>
>>> + /// Get the DeducedType whose type will be deduced for a variable with
>>> + /// an initializer of this type. This looks through declarators like
>>> pointer
>>> + /// types, but not through decltype or typedefs.
>>> + DeducedType *getContainedDeducedType() const;
>>> +
>>> /// Get the AutoType whose type will be deduced for a variable with
>>> /// an initializer of this type. This looks through declarators like
>>> pointer
>>> /// types, but not through decltype or typedefs.
>>> - AutoType *getContainedAutoType() const;
>>> + AutoType *getContainedAutoType() const {
>>> + return dyn_cast_or_null<AutoType>(getContainedDeducedType());
>>> + }
>>>
>>> /// Determine whether this type was written with a leading 'auto'
>>> /// corresponding to a trailing return type (possibly for a nested
>>> @@ -4094,43 +4102,38 @@ public:
>>> }
>>> };
>>>
>>> -/// \brief Represents a C++11 auto or C++14 decltype(auto) type.
>>> +/// \brief Common base class for placeholders for types that get
>>> replaced by
>>> +/// placeholder type deduction: C++11 auto, C++14 decltype(auto), C++17
>>> deduced
>>> +/// class template types, and (eventually) constrained type names from
>>> the C++
>>> +/// Concepts TS.
>>> ///
>>> /// These types are usually a placeholder for a deduced type. However,
>>> before
>>> /// the initializer is attached, or (usually) if the initializer is
>>> -/// type-dependent, there is no deduced type and an auto type is
>>> canonical. In
>>> +/// type-dependent, there is no deduced type and the type is canonical.
>>> In
>>> /// the latter case, it is also a dependent type.
>>> -class AutoType : public Type, public llvm::FoldingSetNode {
>>> - AutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool
>>> IsDependent)
>>> - : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
>>> - /*Dependent=*/IsDependent, /*InstantiationDependent=*/IsD
>>> ependent,
>>> - /*VariablyModified=*/false, /*ContainsParameterPack=*/false)
>>> {
>>> - if (!DeducedType.isNull()) {
>>> - if (DeducedType->isDependentType())
>>> +class DeducedType : public Type {
>>> +protected:
>>> + DeducedType(TypeClass TC, QualType DeducedAsType, bool IsDependent,
>>> + bool IsInstantiationDependent, bool ContainsParameterPack)
>>> + : Type(TC, DeducedAsType.isNull() ? QualType(this, 0) :
>>> DeducedAsType,
>>> + IsDependent, IsInstantiationDependent,
>>> + /*VariablyModified=*/false, ContainsParameterPack) {
>>> + if (!DeducedAsType.isNull()) {
>>> + if (DeducedAsType->isDependentType())
>>> setDependent();
>>> - if (DeducedType->isInstantiationDependentType())
>>> + if (DeducedAsType->isInstantiationDependentType())
>>> setInstantiationDependent();
>>> - if (DeducedType->containsUnexpandedParameterPack())
>>> + if (DeducedAsType->containsUnexpandedParameterPack())
>>> setContainsUnexpandedParameterPack();
>>> }
>>> - AutoTypeBits.Keyword = (unsigned)Keyword;
>>> }
>>>
>>> - friend class ASTContext; // ASTContext creates these
>>> -
>>> public:
>>> - bool isDecltypeAuto() const {
>>> - return getKeyword() == AutoTypeKeyword::DecltypeAuto;
>>> - }
>>> - AutoTypeKeyword getKeyword() const {
>>> - return (AutoTypeKeyword)AutoTypeBits.Keyword;
>>> - }
>>> -
>>> bool isSugared() const { return !isCanonicalUnqualified(); }
>>> QualType desugar() const { return getCanonicalTypeInternal(); }
>>>
>>> - /// \brief Get the type deduced for this auto type, or null if it's
>>> either
>>> - /// not been deduced or was deduced to a dependent type.
>>> + /// \brief Get the type deduced for this placeholder type, or null if
>>> it's
>>> + /// either not been deduced or was deduced to a dependent type.
>>> QualType getDeducedType() const {
>>> return !isCanonicalUnqualified() ? getCanonicalTypeInternal() :
>>> QualType();
>>> }
>>> @@ -4138,6 +4141,31 @@ public:
>>> return !isCanonicalUnqualified() || isDependentType();
>>> }
>>>
>>> + static bool classof(const Type *T) {
>>> + return T->getTypeClass() == Auto ||
>>> + T->getTypeClass() == DeducedTemplateSpecialization;
>>> + }
>>> +};
>>> +
>>> +/// \brief Represents a C++11 auto or C++14 decltype(auto) type.
>>> +class AutoType : public DeducedType, public llvm::FoldingSetNode {
>>> + AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword,
>>> + bool IsDeducedAsDependent)
>>> + : DeducedType(Auto, DeducedAsType, IsDeducedAsDependent,
>>> + IsDeducedAsDependent, /*ContainsPack=*/false) {
>>> + AutoTypeBits.Keyword = (unsigned)Keyword;
>>> + }
>>> +
>>> + friend class ASTContext; // ASTContext creates these
>>> +
>>> +public:
>>> + bool isDecltypeAuto() const {
>>> + return getKeyword() == AutoTypeKeyword::DecltypeAuto;
>>> + }
>>> + AutoTypeKeyword getKeyword() const {
>>> + return (AutoTypeKeyword)AutoTypeBits.Keyword;
>>> + }
>>> +
>>> void Profile(llvm::FoldingSetNodeID &ID) {
>>> Profile(ID, getDeducedType(), getKeyword(), isDependentType());
>>> }
>>> @@ -4154,6 +4182,43 @@ public:
>>> }
>>> };
>>>
>>> +/// \brief Represents a C++17 deduced template specialization type.
>>> +class DeducedTemplateSpecializationType : public DeducedType,
>>> + public llvm::FoldingSetNode {
>>> + /// The name of the template whose arguments will be deduced.
>>> + TemplateName Template;
>>> +
>>> + DeducedTemplateSpecializationType(TemplateName Template,
>>> + QualType DeducedAsType,
>>> + bool IsDeducedAsDependent)
>>> + : DeducedType(DeducedTemplateSpecialization, DeducedAsType,
>>> + IsDeducedAsDependent || Template.isDependent(),
>>> + IsDeducedAsDependent ||
>>> Template.isInstantiationDependent(),
>>> + Template.containsUnexpandedParameterPack()),
>>> + Template(Template) {}
>>> +
>>> + friend class ASTContext; // ASTContext creates these
>>> +
>>> +public:
>>> + /// Retrieve the name of the template that we are deducing.
>>> + TemplateName getTemplateName() const { return Template;}
>>> +
>>> + void Profile(llvm::FoldingSetNodeID &ID) {
>>> + Profile(ID, getTemplateName(), getDeducedType(), isDependentType());
>>> + }
>>> +
>>> + static void Profile(llvm::FoldingSetNodeID &ID, TemplateName Template,
>>> + QualType Deduced, bool IsDependent) {
>>> + Template.Profile(ID);
>>> + ID.AddPointer(Deduced.getAsOpaquePtr());
>>> + ID.AddBoolean(IsDependent);
>>> + }
>>> +
>>> + static bool classof(const Type *T) {
>>> + return T->getTypeClass() == DeducedTemplateSpecialization;
>>> + }
>>> +};
>>> +
>>> /// \brief Represents a type template specialization; the template
>>> /// must be a class template, a type alias template, or a template
>>> /// template parameter. A template which cannot be resolved to one of
>>> @@ -5857,8 +5922,8 @@ inline bool Type::isBooleanType() const
>>> }
>>>
>>> inline bool Type::isUndeducedType() const {
>>> - const AutoType *AT = getContainedAutoType();
>>> - return AT && !AT->isDeduced();
>>> + auto *DT = getContainedDeducedType();
>>> + return DT && !DT->isDeduced();
>>> }
>>>
>>> /// \brief Determines whether this is a type for which one can define
>>>
>>> Modified: cfe/trunk/include/clang/AST/TypeLoc.h
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/
>>> AST/TypeLoc.h?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/include/clang/AST/TypeLoc.h (original)
>>> +++ cfe/trunk/include/clang/AST/TypeLoc.h Thu Jan 26 14:40:47 2017
>>> @@ -1827,9 +1827,25 @@ public:
>>> }
>>> };
>>>
>>> -class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
>>> - AutoTypeLoc,
>>> - AutoType> {
>>> +class DeducedTypeLoc
>>> + : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DeducedTypeLoc,
>>> + DeducedType> {};
>>> +
>>> +class AutoTypeLoc
>>> + : public InheritingConcreteTypeLoc<DeducedTypeLoc, AutoTypeLoc,
>>> AutoType> {
>>> +};
>>> +
>>> +class DeducedTemplateSpecializationTypeLoc
>>> + : public InheritingConcreteTypeLoc<DeducedTypeLoc,
>>> + DeducedTemplateSpecialization
>>> TypeLoc,
>>> + DeducedTemplateSpecializationType>
>>> {
>>> +public:
>>> + SourceLocation getTemplateNameLoc() const {
>>> + return getNameLoc();
>>> + }
>>> + void setTemplateNameLoc(SourceLocation Loc) {
>>> + setNameLoc(Loc);
>>> + }
>>> };
>>>
>>> struct ElaboratedLocInfo {
>>>
>>> Modified: cfe/trunk/include/clang/AST/TypeNodes.def
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/
>>> AST/TypeNodes.def?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/include/clang/AST/TypeNodes.def (original)
>>> +++ cfe/trunk/include/clang/AST/TypeNodes.def Thu Jan 26 14:40:47 2017
>>> @@ -96,7 +96,9 @@ DEPENDENT_TYPE(TemplateTypeParm, Type)
>>> NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
>>> DEPENDENT_TYPE(SubstTemplateTypeParmPack, Type)
>>> NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type)
>>> -TYPE(Auto, Type)
>>> +ABSTRACT_TYPE(Deduced, Type)
>>> +TYPE(Auto, DeducedType)
>>> +TYPE(DeducedTemplateSpecialization, DeducedType)
>>> DEPENDENT_TYPE(InjectedClassName, Type)
>>> DEPENDENT_TYPE(DependentName, Type)
>>> DEPENDENT_TYPE(DependentTemplateSpecialization, Type)
>>>
>>> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/
>>> Basic/DiagnosticSemaKinds.td?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
>>> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Jan 26
>>> 14:40:47 2017
>>> @@ -1870,16 +1870,20 @@ def err_illegal_decl_array_of_auto : Err
>>> def err_new_array_of_auto : Error<
>>> "cannot allocate array of 'auto'">;
>>> def err_auto_not_allowed : Error<
>>> - "%select{'auto'|'decltype(auto)'|'__auto_type'}0 not allowed "
>>> + "%select{'auto'|'decltype(auto)'|'__auto_type'|"
>>> + "use of "
>>> + "%select{class template|function template|variable template|alias
>>> template|"
>>> + "template template parameter|template}2 %3 requires template
>>> arguments; "
>>> + "argument deduction}0 not allowed "
>>> "%select{in function prototype"
>>> "|in non-static struct member|in struct member"
>>> "|in non-static union member|in union member"
>>> "|in non-static class member|in interface member"
>>> - "|in exception declaration|in template parameter|in block literal"
>>> + "|in exception declaration|in template parameter until C++1z|in block
>>> literal"
>>> "|in template argument|in typedef|in type alias|in function return
>>> type"
>>> "|in conversion function type|here|in lambda parameter"
>>> - "|in type allocated by 'new'|in K&R-style function parameter}1"
>>> - "%select{|||||||| until C++1z||||||||||}1">;
>>> + "|in type allocated by 'new'|in K&R-style function parameter"
>>> + "|in template parameter|in friend declaration}1">;
>>> def err_auto_not_allowed_var_inst : Error<
>>> "'auto' variable template instantiation is not allowed">;
>>> def err_auto_var_requires_init : Error<
>>> @@ -1944,6 +1948,14 @@ def err_decltype_auto_compound_type : Er
>>> def err_decltype_auto_initializer_list : Error<
>>> "cannot deduce 'decltype(auto)' from initializer list">;
>>>
>>> +// C++1z deduced class template specialization types
>>> +def err_deduced_class_template_compound_type : Error<
>>> + "cannot %select{form pointer to|form reference to|form array of|"
>>> + "form function returning|use parentheses when declaring variable
>>> with}0 "
>>> + "deduced class template specialization type">;
>>> +def err_deduced_class_template_not_supported : Error<
>>> + "deduction of template arguments for class templates is not yet
>>> supported">;
>>> +
>>> // C++1y deduced return types
>>> def err_auto_fn_deduction_failure : Error<
>>> "cannot deduce return type %0 from returned value of type %1">;
>>>
>>> Modified: cfe/trunk/include/clang/Parse/Parser.h
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/
>>> Parse/Parser.h?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/include/clang/Parse/Parser.h (original)
>>> +++ cfe/trunk/include/clang/Parse/Parser.h Thu Jan 26 14:40:47 2017
>>> @@ -1834,6 +1834,26 @@ private:
>>> llvm_unreachable("Missing DeclSpecContext case");
>>> }
>>>
>>> + /// Is this a context in which we can perform class template argument
>>> + /// deduction?
>>> + static bool isClassTemplateDeductionContext(DeclSpecContext DSC) {
>>> + switch (DSC) {
>>> + case DSC_normal:
>>> + case DSC_class:
>>> + case DSC_top_level:
>>> + case DSC_condition:
>>> + case DSC_type_specifier:
>>> + return true;
>>> +
>>> + case DSC_objc_method_result:
>>> + case DSC_template_type_arg:
>>> + case DSC_trailing:
>>> + case DSC_alias_declaration:
>>> + return false;
>>> + }
>>> + llvm_unreachable("Missing DeclSpecContext case");
>>> + }
>>> +
>>> /// Information on a C++0x for-range-initializer found while parsing a
>>> /// declaration which turns out to be a for-range-declaration.
>>> struct ForRangeInit {
>>>
>>> Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/
>>> Sema/DeclSpec.h?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
>>> +++ cfe/trunk/include/clang/Sema/DeclSpec.h Thu Jan 26 14:40:47 2017
>>> @@ -1709,6 +1709,7 @@ public:
>>> ObjCParameterContext,// An ObjC method parameter type.
>>> KNRTypeListContext, // K&R type definition list for formals.
>>> TypeNameContext, // Abstract declarator for types.
>>> + FunctionalCastContext, // Type in a C++ functional cast expression.
>>> MemberContext, // Struct/Union field.
>>> BlockContext, // Declaration within a block in a function.
>>> ForContext, // Declaration within first part of a for loop.
>>> @@ -1911,6 +1912,7 @@ public:
>>> return false;
>>>
>>> case TypeNameContext:
>>> + case FunctionalCastContext:
>>> case AliasDeclContext:
>>> case AliasTemplateContext:
>>> case PrototypeContext:
>>> @@ -1951,6 +1953,7 @@ public:
>>> return true;
>>>
>>> case TypeNameContext:
>>> + case FunctionalCastContext:
>>> case CXXNewContext:
>>> case AliasDeclContext:
>>> case AliasTemplateContext:
>>> @@ -1983,6 +1986,7 @@ public:
>>> case CXXCatchContext:
>>> case ObjCCatchContext:
>>> case TypeNameContext:
>>> + case FunctionalCastContext:
>>> case ConversionIdContext:
>>> case ObjCParameterContext:
>>> case ObjCResultContext:
>>> @@ -2021,6 +2025,7 @@ public:
>>> // These contexts don't allow any kind of non-abstract declarator.
>>> case KNRTypeListContext:
>>> case TypeNameContext:
>>> + case FunctionalCastContext:
>>> case AliasDeclContext:
>>> case AliasTemplateContext:
>>> case LambdaExprParameterContext:
>>> @@ -2078,6 +2083,7 @@ public:
>>> case CXXCatchContext:
>>> case ObjCCatchContext:
>>> case TypeNameContext:
>>> + case FunctionalCastContext: // FIXME
>>> case CXXNewContext:
>>> case AliasDeclContext:
>>> case AliasTemplateContext:
>>> @@ -2279,6 +2285,7 @@ public:
>>> case ConditionContext:
>>> case KNRTypeListContext:
>>> case TypeNameContext:
>>> + case FunctionalCastContext:
>>> case AliasDeclContext:
>>> case AliasTemplateContext:
>>> case PrototypeContext:
>>>
>>> Modified: cfe/trunk/include/clang/Sema/Sema.h
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/
>>> Sema/Sema.h?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/include/clang/Sema/Sema.h (original)
>>> +++ cfe/trunk/include/clang/Sema/Sema.h Thu Jan 26 14:40:47 2017
>>> @@ -1548,6 +1548,7 @@ public:
>>> ParsedType ObjectType = nullptr,
>>> bool IsCtorOrDtorName = false,
>>> bool WantNontrivialTypeSourceInfo = false,
>>> + bool IsClassTemplateDeductionContext = true,
>>> IdentifierInfo **CorrectedII = nullptr);
>>> TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S);
>>> bool isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S);
>>>
>>> Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/
>>> Serialization/ASTBitCodes.h?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
>>> +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Thu Jan 26
>>> 14:40:47 2017
>>> @@ -914,7 +914,9 @@ namespace clang {
>>> /// \brief A PipeType record.
>>> TYPE_PIPE = 43,
>>> /// \brief An ObjCTypeParamType record.
>>> - TYPE_OBJC_TYPE_PARAM = 44
>>> + TYPE_OBJC_TYPE_PARAM = 44,
>>> + /// \brief A DeducedTemplateSpecializationType record.
>>> + TYPE_DEDUCED_TEMPLATE_SPECIALIZATION = 45
>>> };
>>>
>>> /// \brief The type IDs for special types constructed by semantic
>>>
>>> Modified: cfe/trunk/lib/AST/ASTContext.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTCon
>>> text.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/ASTImp
>>> orter.cpp?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/lib/AST/ASTImporter.cpp (original)
>>> +++ cfe/trunk/lib/AST/ASTImporter.cpp Thu Jan 26 14:40:47 2017
>>> @@ -883,6 +883,20 @@ static bool IsStructurallyEquivalent(Str
>>> return false;
>>> break;
>>>
>>> + case Type::DeducedTemplateSpecialization: {
>>> + auto *DT1 = cast<DeducedTemplateSpecializationType>(T1);
>>> + auto *DT2 = cast<DeducedTemplateSpecializationType>(T2);
>>> + if (!IsStructurallyEquivalent(Context,
>>> + DT1->getTemplateName(),
>>> + DT2->getTemplateName()))
>>> + return false;
>>> + if (!IsStructurallyEquivalent(Context,
>>> + DT1->getDeducedType(),
>>> + DT2->getDeducedType()))
>>> + return false;
>>> + break;
>>> + }
>>> +
>>> case Type::Record:
>>> case Type::Enum:
>>> if (!IsStructurallyEquivalent(Context,
>>>
>>> Modified: cfe/trunk/lib/AST/ExprConstant.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCo
>>> nstant.cpp?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
>>> +++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Jan 26 14:40:47 2017
>>> @@ -7004,6 +7004,7 @@ static int EvaluateBuiltinClassifyType(c
>>> case Type::Vector:
>>> case Type::ExtVector:
>>> case Type::Auto:
>>> + case Type::DeducedTemplateSpecialization:
>>> case Type::ObjCObject:
>>> case Type::ObjCInterface:
>>> case Type::ObjCObjectPointer:
>>>
>>> Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Itaniu
>>> mMangle.cpp?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
>>> +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Thu Jan 26 14:40:47 2017
>>> @@ -1870,6 +1870,7 @@ bool CXXNameMangler::mangleUnresolvedTyp
>>> case Type::Paren:
>>> case Type::Attributed:
>>> case Type::Auto:
>>> + case Type::DeducedTemplateSpecialization:
>>> case Type::PackExpansion:
>>> case Type::ObjCObject:
>>> case Type::ObjCInterface:
>>> @@ -3145,6 +3146,16 @@ void CXXNameMangler::mangleType(const Au
>>> mangleType(D);
>>> }
>>>
>>> +void CXXNameMangler::mangleType(const DeducedTemplateSpecializationType
>>> *T) {
>>> + // FIXME: This is not the right mangling. We also need to include a
>>> scope
>>> + // here in some cases.
>>> + QualType D = T->getDeducedType();
>>> + if (D.isNull())
>>> + mangleUnscopedTemplateName(T->getTemplateName(), nullptr);
>>> + else
>>> + mangleType(D);
>>> +}
>>> +
>>> void CXXNameMangler::mangleType(const AtomicType *T) {
>>> // <type> ::= U <source-name> <type> # vendor extended type qualifier
>>> // (Until there's a standardized mangling...)
>>>
>>> Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Micros
>>> oftMangle.cpp?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
>>> +++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Thu Jan 26 14:40:47 2017
>>> @@ -2474,6 +2474,17 @@ void MicrosoftCXXNameMangler::mangleType
>>> << Range;
>>> }
>>>
>>> +void MicrosoftCXXNameMangler::mangleType(
>>> + const DeducedTemplateSpecializationType *T, Qualifiers,
>>> SourceRange Range) {
>>> + assert(T->getDeducedType().isNull() && "expecting a dependent
>>> type!");
>>> +
>>> + DiagnosticsEngine &Diags = Context.getDiags();
>>> + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
>>> + "cannot mangle this deduced class template specialization type
>>> yet");
>>> + Diags.Report(Range.getBegin(), DiagID)
>>> + << Range;
>>> +}
>>> +
>>> void MicrosoftCXXNameMangler::mangleType(const AtomicType *T,
>>> Qualifiers,
>>> SourceRange Range) {
>>> QualType ValueType = T->getValueType();
>>>
>>> Modified: cfe/trunk/lib/AST/Type.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.c
>>> pp?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/TypePr
>>> inter.cpp?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/lib/AST/TypePrinter.cpp (original)
>>> +++ cfe/trunk/lib/AST/TypePrinter.cpp Thu Jan 26 14:40:47 2017
>>> @@ -189,6 +189,7 @@ bool TypePrinter::canPrefixQualifiers(co
>>> case Type::Elaborated:
>>> case Type::TemplateTypeParm:
>>> case Type::SubstTemplateTypeParmPack:
>>> + case Type::DeducedTemplateSpecialization:
>>> case Type::TemplateSpecialization:
>>> case Type::InjectedClassName:
>>> case Type::DependentName:
>>> @@ -887,6 +888,24 @@ void TypePrinter::printAutoAfter(const A
>>> if (!T->getDeducedType().isNull())
>>> printAfter(T->getDeducedType(), OS);
>>> }
>>> +
>>> +void TypePrinter::printDeducedTemplateSpecializationBefore(
>>> + const DeducedTemplateSpecializationType *T, raw_ostream &OS) {
>>> + // If the type has been deduced, print the deduced type.
>>> + if (!T->getDeducedType().isNull()) {
>>> + printBefore(T->getDeducedType(), OS);
>>> + } else {
>>> + IncludeStrongLifetimeRAII Strong(Policy);
>>> + T->getTemplateName().print(OS, Policy);
>>> + spaceBeforePlaceHolder(OS);
>>> + }
>>> +}
>>> +void TypePrinter::printDeducedTemplateSpecializationAfter(
>>> + const DeducedTemplateSpecializationType *T, raw_ostream &OS) {
>>> + // If the type has been deduced, print the deduced type.
>>> + if (!T->getDeducedType().isNull())
>>> + printAfter(T->getDeducedType(), OS);
>>> +}
>>>
>>> void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream
>>> &OS) {
>>> IncludeStrongLifetimeRAII Strong(Policy);
>>>
>>> Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CG
>>> DebugInfo.cpp?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
>>> +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Thu Jan 26 14:40:47 2017
>>> @@ -2618,6 +2618,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNod
>>> case Type::Attributed:
>>> case Type::Adjusted:
>>> case Type::Decayed:
>>> + case Type::DeducedTemplateSpecialization:
>>> case Type::Elaborated:
>>> case Type::Paren:
>>> case Type::SubstTemplateTypeParm:
>>>
>>> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/Co
>>> deGenFunction.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/Co
>>> deGenTypes.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/It
>>> aniumCXXABI.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/Pars
>>> eDecl.cpp?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
>>> +++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Jan 26 14:40:47 2017
>>> @@ -2884,7 +2884,8 @@ void Parser::ParseDeclarationSpecifiers(
>>> Actions.getTypeName(*Next.getIdentifierInfo(),
>>> Next.getLocation(),
>>> getCurScope(), &SS, false, false, nullptr,
>>> /*IsCtorOrDtorName=*/false,
>>> - /*NonTrivialSourceInfo=*/true);
>>> + /*WantNonTrivialSourceInfo=*/true,
>>> + isClassTemplateDeductionContex
>>> t(DSContext));
>>>
>>> // If the referenced identifier is not a type, then this declspec
>>> is
>>> // erroneous: We already checked about that it has no type
>>> specifier, and
>>> @@ -2998,9 +2999,10 @@ void Parser::ParseDeclarationSpecifiers(
>>> continue;
>>> }
>>>
>>> - ParsedType TypeRep =
>>> - Actions.getTypeName(*Tok.getIdentifierInfo(),
>>> - Tok.getLocation(), getCurScope());
>>> + ParsedType TypeRep = Actions.getTypeName(
>>> + *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(),
>>> nullptr,
>>> + false, false, nullptr, false, false,
>>> + isClassTemplateDeductionContext(DSContext));
>>>
>>> // If this is not a typedef name, don't parse it as part of the
>>> declspec,
>>> // it must be an implicit int or an error.
>>>
>>> Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Pars
>>> eDeclCXX.cpp?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
>>> +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Thu Jan 26 14:40:47 2017
>>> @@ -1144,10 +1144,11 @@ TypeResult Parser::ParseBaseTypeSpecifie
>>>
>>> // We have an identifier; check whether it is actually a type.
>>> IdentifierInfo *CorrectedII = nullptr;
>>> - ParsedType Type =
>>> - Actions.getTypeName(*Id, IdLoc, getCurScope(), &SS, true, false,
>>> nullptr,
>>> - /*IsCtorOrDtorName=*/false,
>>> - /*NonTrivialTypeSourceInfo=*/true,
>>> &CorrectedII);
>>> + ParsedType Type = Actions.getTypeName(
>>> + *Id, IdLoc, getCurScope(), &SS, true, false, nullptr,
>>> + /*IsCtorOrDtorName=*/false,
>>> + /*NonTrivialTypeSourceInfo=*/true,
>>> + /*IsClassTemplateDeductionContext*/ false, &CorrectedII);
>>> if (!Type) {
>>> Diag(IdLoc, diag::err_expected_class_name);
>>> return true;
>>>
>>> Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Pars
>>> eExprCXX.cpp?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
>>> +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Thu Jan 26 14:40:47 2017
>>> @@ -1639,9 +1639,10 @@ ExprResult Parser::ParseCXXThis() {
>>> /// typename-specifier '(' expression-list[opt] ')'
>>> /// [C++0x] typename-specifier braced-init-list
>>> ///
>>> +/// In C++1z onwards, the type specifier can also be a template-name.
>>> ExprResult
>>> Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
>>> - Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
>>> + Declarator DeclaratorInfo(DS, Declarator::FunctionalCastContext);
>>> ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(),
>>> DeclaratorInfo).get();
>>>
>>> assert((Tok.is(tok::l_paren) ||
>>>
>>> Modified: cfe/trunk/lib/Parse/Parser.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Pars
>>> er.cpp?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/lib/Parse/Parser.cpp (original)
>>> +++ cfe/trunk/lib/Parse/Parser.cpp Thu Jan 26 14:40:47 2017
>>> @@ -1743,7 +1743,8 @@ bool Parser::TryAnnotateTypeOrScopeToken
>>> *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(),
>>> &SS,
>>> false, NextToken().is(tok::period), nullptr,
>>> /*IsCtorOrDtorName=*/false,
>>> - /*NonTrivialTypeSourceInfo*/ true)) {
>>> + /*NonTrivialTypeSourceInfo*/ true,
>>> + /*IsClassTemplateDeductionContext*/GreaterThanIsOperator))
>>> {
>>> SourceLocation BeginLoc = Tok.getLocation();
>>> if (SS.isNotEmpty()) // it was a C++ qualified type name.
>>> BeginLoc = SS.getBeginLoc();
>>>
>>> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaD
>>> ecl.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.getCorrectionAsIden
>>> tifierInfo();
>>> 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_o
>>> r_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_templa
>>> te_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/SemaE
>>> xpr.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/SemaE
>>> xprCXX.cpp?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
>>> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Jan 26 14:40:47 2017
>>> @@ -1255,9 +1255,19 @@ Sema::BuildCXXTypeConstructExpr(TypeSour
>>> RParenLoc);
>>> }
>>>
>>> + // C++1z [expr.type.conv]p1:
>>> + // If the type is a placeholder for a deduced class type,
>>> [...perform class
>>> + // template argument deduction...]
>>> + DeducedType *Deduced = Ty->getContainedDeducedType();
>>> + if (Deduced && isa<DeducedTemplateSpecializationType>(Deduced)) {
>>> + Diag(TyBeginLoc, diag::err_deduced_class_template_not_supported);
>>> + return ExprError();
>>> + }
>>> +
>>> bool ListInitialization = LParenLoc.isInvalid();
>>> - assert((!ListInitialization || (Exprs.size() == 1 &&
>>> isa<InitListExpr>(Exprs[0])))
>>> - && "List initialization must have initializer list as
>>> expression.");
>>> + assert((!ListInitialization ||
>>> + (Exprs.size() == 1 && isa<InitListExpr>(Exprs[0]))) &&
>>> + "List initialization must have initializer list as
>>> expression.");
>>> SourceRange FullRange = SourceRange(TyBeginLoc,
>>> ListInitialization ? Exprs[0]->getSourceRange().getEnd() :
>>> RParenLoc);
>>>
>>> @@ -1646,6 +1656,11 @@ Sema::BuildCXXNew(SourceRange Range, boo
>>>
>>> // C++11 [dcl.spec.auto]p6. Deduce the type which 'auto' stands in
>>> for.
>>> if (AllocType->isUndeducedType()) {
>>> + if (isa<DeducedTemplateSpecializationType>(
>>> + AllocType->getContainedDeducedType()))
>>> + return ExprError(Diag(TypeRange.getBegin(),
>>> + diag::err_deduced_class_templa
>>> te_not_supported));
>>> +
>>> if (initStyle == CXXNewExpr::NoInit || NumInits == 0)
>>> return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ct
>>> or_arg)
>>> << AllocType << TypeRange);
>>>
>>> Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaL
>>> ookup.cpp?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
>>> +++ cfe/trunk/lib/Sema/SemaLookup.cpp Thu Jan 26 14:40:47 2017
>>> @@ -2694,6 +2694,7 @@ addAssociatedClassesAndNamespaces(Associ
>>>
>>> // Non-deduced auto types only get here for error cases.
>>> case Type::Auto:
>>> + case Type::DeducedTemplateSpecialization:
>>> break;
>>>
>>> // If T is an Objective-C object or interface type, or a pointer to
>>> an
>>>
>>> Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaT
>>> emplate.cpp?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
>>> +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Jan 26 14:40:47 2017
>>> @@ -4439,6 +4439,11 @@ bool UnnamedLocalNoLinkageFinder::VisitA
>>> return Visit(T->getDeducedType());
>>> }
>>>
>>> +bool UnnamedLocalNoLinkageFinder::VisitDeducedTemplateSpecializat
>>> ionType(
>>> + 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/SemaT
>>> emplateDeduction.cpp?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
>>> +++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Thu Jan 26 14:40:47
>>> 2017
>>> @@ -1723,6 +1723,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema
>>> case Type::Decltype:
>>> case Type::UnaryTransform:
>>> case Type::Auto:
>>> + case Type::DeducedTemplateSpecialization:
>>> case Type::DependentTemplateSpecialization:
>>> case Type::PackExpansion:
>>> case Type::Pipe:
>>> @@ -5152,8 +5153,9 @@ MarkUsedTemplateParameters(ASTContext &C
>>> break;
>>>
>>> case Type::Auto:
>>> + case Type::DeducedTemplateSpecialization:
>>> MarkUsedTemplateParameters(Ctx,
>>> - cast<AutoType>(T)->getDeducedType(),
>>> + cast<DeducedType>(T)->getDeducedType(),
>>> OnlyDeduced, Depth, Used);
>>>
>>> // None of these types have any template parameters in them.
>>>
>>> Modified: cfe/trunk/lib/Sema/SemaType.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaT
>>> ype.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<DeducedTemplateSpecializa
>>> tionType>(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<DeducedTemplateSpecia
>>> lizationType>(Deduced);
>>> + TemplateName TN = DTST ? DTST->getTemplateName() : TemplateName();
>>> +
>>> SemaRef.Diag(AutoRange.getBegin(), diag::err_auto_not_allowed)
>>> - << Keyword << Error << AutoRange;
>>> + << Kind << Error << (int)SemaRef.getTemplateNameKi
>>> ndForDiagnostics(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<DeducedTemplateSpecializat
>>> ionType>(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_templa
>>> te_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/TreeT
>>> ransform.h?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/lib/Sema/TreeTransform.h (original)
>>> +++ cfe/trunk/lib/Sema/TreeTransform.h Thu Jan 26 14:40:47 2017
>>> @@ -876,6 +876,14 @@ public:
>>> /*IsDependent*/ false);
>>> }
>>>
>>> + /// By default, builds a new DeducedTemplateSpecializationType with
>>> the given
>>> + /// deduced type.
>>> + QualType RebuildDeducedTemplateSpecializationType(TemplateName
>>> Template,
>>> + QualType Deduced) {
>>> + return SemaRef.Context.getDeducedTemplateSpecializationType(
>>> + Template, Deduced, /*IsDependent*/ false);
>>> + }
>>> +
>>> /// \brief Build a new template specialization type.
>>> ///
>>> /// By default, performs semantic analysis when building the template
>>> @@ -5344,6 +5352,37 @@ QualType TreeTransform<Derived>::Transfo
>>>
>>> return Result;
>>> }
>>> +
>>> +template<typename Derived>
>>> +QualType TreeTransform<Derived>::TransformDeducedTemplateSpecializati
>>> onType(
>>> + 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().RebuildDeducedTem
>>> plateSpecializationType(
>>> + 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/Serializat
>>> ion/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/Serializat
>>> ion/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/p
>>> 5.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.d
>>> cl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp?rev=293207&r1=2932
>>> 06&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/d
>>> r5xx.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/ba
>>> cktrack-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/cx
>>> x1z-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/SemaTempl
>>> ate/temp_arg.cpp?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/test/SemaTemplate/temp_arg.cpp (original)
>>> +++ cfe/trunk/test/SemaTemplate/temp_arg.cpp Thu Jan 26 14:40:47 2017
>>> @@ -10,7 +10,7 @@ A<int, 0, X> * a1;
>>>
>>> A<float, 1, X, double> *a2; // expected-error{{too many template
>>> arguments for class template 'A'}}
>>> A<float, 1> *a3; // expected-error{{too few template arguments for
>>> class template 'A'}}
>>> -A a3; // expected-error{{use of class template 'A' requires template
>>> arguments}}
>>> +A a4; // expected-error{{use of class template 'A' requires template
>>> arguments}}
>>>
>>> namespace test0 {
>>> template <class t> class foo {};
>>>
>>> Modified: cfe/trunk/test/SemaTemplate/typename-specifier-3.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTempl
>>> ate/typename-specifier-3.cpp?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/test/SemaTemplate/typename-specifier-3.cpp (original)
>>> +++ cfe/trunk/test/SemaTemplate/typename-specifier-3.cpp Thu Jan 26
>>> 14:40:47 2017
>>> @@ -1,7 +1,7 @@
>>> // RUN: %clang_cc1 -fsyntax-only -verify %s
>>>
>>> // PR4364
>>> -template<class T> struct a {
>>> +template<class T> struct a { // expected-note {{here}}
>>> T b() {
>>> return typename T::x();
>>> }
>>> @@ -17,3 +17,4 @@ B c() {
>>> // Some extra tests for invalid cases
>>> template<class T> struct test2 { T b() { return typename T::a; } }; //
>>> expected-error{{expected '(' for function-style cast or type construction}}
>>> template<class T> struct test3 { T b() { return typename a; } }; //
>>> expected-error{{expected a qualified name after 'typename'}}
>>> +template<class T> struct test4 { T b() { return typename ::a; } }; //
>>> expected-error{{refers to non-type member}} expected-error{{expected '('
>>> for function-style cast or type construction}}
>>>
>>> Modified: cfe/trunk/tools/libclang/CIndex.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang
>>> /CIndex.cpp?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/tools/libclang/CIndex.cpp (original)
>>> +++ cfe/trunk/tools/libclang/CIndex.cpp Thu Jan 26 14:40:47 2017
>>> @@ -1640,6 +1640,15 @@ bool CursorVisitor::VisitAdjustedTypeLoc
>>> return Visit(TL.getOriginalLoc());
>>> }
>>>
>>> +bool CursorVisitor::VisitDeducedTemplateSpecializationTypeLoc(
>>> + DeducedTemplateSpecializationTypeLoc TL) {
>>> + if (VisitTemplateName(TL.getTypePtr()->getTemplateName(),
>>> + TL.getTemplateNameLoc()))
>>> + return true;
>>> +
>>> + return false;
>>> +}
>>> +
>>> bool CursorVisitor::VisitTemplateSpecializationTypeLoc(
>>>
>>> TemplateSpecializationTypeLoc TL) {
>>> // Visit the template name.
>>>
>>> Modified: cfe/trunk/tools/libclang/CXType.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang
>>> /CXType.cpp?rev=293207&r1=293206&r2=293207&view=diff
>>> ============================================================
>>> ==================
>>> --- cfe/trunk/tools/libclang/CXType.cpp (original)
>>> +++ cfe/trunk/tools/libclang/CXType.cpp Thu Jan 26 14:40:47 2017
>>> @@ -452,7 +452,8 @@ try_again:
>>> break;
>>>
>>> case Type::Auto:
>>> - TP = cast<AutoType>(TP)->getDeducedType().getTypePtrOrNull();
>>> + case Type::DeducedTemplateSpecialization:
>>> + TP = cast<DeducedType>(TP)->getDeducedType().getTypePtrOrNull();
>>> if (TP)
>>> goto try_again;
>>> break;
>>>
>>>
>>> _______________________________________________
>>> cfe-commits mailing list
>>> cfe-commits at lists.llvm.org
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>>
>>
>>
>> _______________________________________________
>> 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/111f7b59/attachment-0001.html>
More information about the cfe-commits
mailing list