forked from OSchip/llvm-project
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. llvm-svn: 293207
This commit is contained in:
parent
b26530cd69
commit
600b5261c4
|
@ -167,6 +167,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||||
mutable llvm::FoldingSet<DependentUnaryTransformType>
|
mutable llvm::FoldingSet<DependentUnaryTransformType>
|
||||||
DependentUnaryTransformTypes;
|
DependentUnaryTransformTypes;
|
||||||
mutable llvm::FoldingSet<AutoType> AutoTypes;
|
mutable llvm::FoldingSet<AutoType> AutoTypes;
|
||||||
|
mutable llvm::FoldingSet<DeducedTemplateSpecializationType>
|
||||||
|
DeducedTemplateSpecializationTypes;
|
||||||
mutable llvm::FoldingSet<AtomicType> AtomicTypes;
|
mutable llvm::FoldingSet<AtomicType> AtomicTypes;
|
||||||
llvm::FoldingSet<AttributedType> AttributedTypes;
|
llvm::FoldingSet<AttributedType> AttributedTypes;
|
||||||
mutable llvm::FoldingSet<PipeType> PipeTypes;
|
mutable llvm::FoldingSet<PipeType> PipeTypes;
|
||||||
|
@ -1412,6 +1414,11 @@ public:
|
||||||
/// \brief C++11 deduction pattern for 'auto &&' type.
|
/// \brief C++11 deduction pattern for 'auto &&' type.
|
||||||
QualType getAutoRRefDeductType() const;
|
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
|
/// \brief Return the unique reference to the type for the specified TagDecl
|
||||||
/// (struct/union/class/enum) decl.
|
/// (struct/union/class/enum) decl.
|
||||||
QualType getTagDeclType(const TagDecl *Decl) const;
|
QualType getTagDeclType(const TagDecl *Decl) const;
|
||||||
|
|
|
@ -1008,6 +1008,10 @@ DEF_TRAVERSE_TYPE(UnaryTransformType, {
|
||||||
})
|
})
|
||||||
|
|
||||||
DEF_TRAVERSE_TYPE(AutoType, { TRY_TO(TraverseType(T->getDeducedType())); })
|
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(RecordType, {})
|
||||||
DEF_TRAVERSE_TYPE(EnumType, {})
|
DEF_TRAVERSE_TYPE(EnumType, {})
|
||||||
|
@ -1232,6 +1236,11 @@ DEF_TRAVERSE_TYPELOC(AutoType, {
|
||||||
TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
|
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(RecordType, {})
|
||||||
DEF_TRAVERSE_TYPELOC(EnumType, {})
|
DEF_TRAVERSE_TYPELOC(EnumType, {})
|
||||||
DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {})
|
DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {})
|
||||||
|
|
|
@ -1785,7 +1785,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Determine whether this type is an undeduced type, meaning that
|
/// \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;
|
bool isUndeducedType() const;
|
||||||
|
|
||||||
/// \brief Whether this type is a variably-modified type (C99 6.7.5).
|
/// \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.
|
/// not refer to a CXXRecordDecl, returns NULL.
|
||||||
const CXXRecordDecl *getPointeeCXXRecordDecl() const;
|
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
|
/// Get the AutoType whose type will be deduced for a variable with
|
||||||
/// an initializer of this type. This looks through declarators like pointer
|
/// an initializer of this type. This looks through declarators like pointer
|
||||||
/// types, but not through decltype or typedefs.
|
/// 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'
|
/// Determine whether this type was written with a leading 'auto'
|
||||||
/// corresponding to a trailing return type (possibly for a nested
|
/// corresponding to a trailing return type (possibly for a nested
|
||||||
|
@ -4094,25 +4102,57 @@ 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
|
/// These types are usually a placeholder for a deduced type. However, before
|
||||||
/// the initializer is attached, or (usually) if the initializer is
|
/// 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.
|
/// the latter case, it is also a dependent type.
|
||||||
class AutoType : public Type, public llvm::FoldingSetNode {
|
class DeducedType : public Type {
|
||||||
AutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent)
|
protected:
|
||||||
: Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
|
DeducedType(TypeClass TC, QualType DeducedAsType, bool IsDependent,
|
||||||
/*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent,
|
bool IsInstantiationDependent, bool ContainsParameterPack)
|
||||||
/*VariablyModified=*/false, /*ContainsParameterPack=*/false) {
|
: Type(TC, DeducedAsType.isNull() ? QualType(this, 0) : DeducedAsType,
|
||||||
if (!DeducedType.isNull()) {
|
IsDependent, IsInstantiationDependent,
|
||||||
if (DeducedType->isDependentType())
|
/*VariablyModified=*/false, ContainsParameterPack) {
|
||||||
|
if (!DeducedAsType.isNull()) {
|
||||||
|
if (DeducedAsType->isDependentType())
|
||||||
setDependent();
|
setDependent();
|
||||||
if (DeducedType->isInstantiationDependentType())
|
if (DeducedAsType->isInstantiationDependentType())
|
||||||
setInstantiationDependent();
|
setInstantiationDependent();
|
||||||
if (DeducedType->containsUnexpandedParameterPack())
|
if (DeducedAsType->containsUnexpandedParameterPack())
|
||||||
setContainsUnexpandedParameterPack();
|
setContainsUnexpandedParameterPack();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool isSugared() const { return !isCanonicalUnqualified(); }
|
||||||
|
QualType desugar() const { return getCanonicalTypeInternal(); }
|
||||||
|
|
||||||
|
/// \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();
|
||||||
|
}
|
||||||
|
bool isDeduced() const {
|
||||||
|
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;
|
AutoTypeBits.Keyword = (unsigned)Keyword;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4126,18 +4166,6 @@ public:
|
||||||
return (AutoTypeKeyword)AutoTypeBits.Keyword;
|
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.
|
|
||||||
QualType getDeducedType() const {
|
|
||||||
return !isCanonicalUnqualified() ? getCanonicalTypeInternal() : QualType();
|
|
||||||
}
|
|
||||||
bool isDeduced() const {
|
|
||||||
return !isCanonicalUnqualified() || isDependentType();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||||
Profile(ID, getDeducedType(), getKeyword(), isDependentType());
|
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
|
/// \brief Represents a type template specialization; the template
|
||||||
/// must be a class template, a type alias template, or a template
|
/// must be a class template, a type alias template, or a template
|
||||||
/// template parameter. A template which cannot be resolved to one of
|
/// 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 {
|
inline bool Type::isUndeducedType() const {
|
||||||
const AutoType *AT = getContainedAutoType();
|
auto *DT = getContainedDeducedType();
|
||||||
return AT && !AT->isDeduced();
|
return DT && !DT->isDeduced();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Determines whether this is a type for which one can define
|
/// \brief Determines whether this is a type for which one can define
|
||||||
|
|
|
@ -1827,9 +1827,25 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
class DeducedTypeLoc
|
||||||
AutoTypeLoc,
|
: public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DeducedTypeLoc,
|
||||||
AutoType> {
|
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 {
|
struct ElaboratedLocInfo {
|
||||||
|
|
|
@ -96,7 +96,9 @@ DEPENDENT_TYPE(TemplateTypeParm, Type)
|
||||||
NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
|
NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
|
||||||
DEPENDENT_TYPE(SubstTemplateTypeParmPack, Type)
|
DEPENDENT_TYPE(SubstTemplateTypeParmPack, Type)
|
||||||
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, 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(InjectedClassName, Type)
|
||||||
DEPENDENT_TYPE(DependentName, Type)
|
DEPENDENT_TYPE(DependentName, Type)
|
||||||
DEPENDENT_TYPE(DependentTemplateSpecialization, Type)
|
DEPENDENT_TYPE(DependentTemplateSpecialization, Type)
|
||||||
|
|
|
@ -1870,16 +1870,20 @@ def err_illegal_decl_array_of_auto : Error<
|
||||||
def err_new_array_of_auto : Error<
|
def err_new_array_of_auto : Error<
|
||||||
"cannot allocate array of 'auto'">;
|
"cannot allocate array of 'auto'">;
|
||||||
def err_auto_not_allowed : Error<
|
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"
|
"%select{in function prototype"
|
||||||
"|in non-static struct member|in struct member"
|
"|in non-static struct member|in struct member"
|
||||||
"|in non-static union member|in union member"
|
"|in non-static union member|in union member"
|
||||||
"|in non-static class member|in interface 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 template argument|in typedef|in type alias|in function return type"
|
||||||
"|in conversion function type|here|in lambda parameter"
|
"|in conversion function type|here|in lambda parameter"
|
||||||
"|in type allocated by 'new'|in K&R-style function parameter}1"
|
"|in type allocated by 'new'|in K&R-style function parameter"
|
||||||
"%select{|||||||| until C++1z||||||||||}1">;
|
"|in template parameter|in friend declaration}1">;
|
||||||
def err_auto_not_allowed_var_inst : Error<
|
def err_auto_not_allowed_var_inst : Error<
|
||||||
"'auto' variable template instantiation is not allowed">;
|
"'auto' variable template instantiation is not allowed">;
|
||||||
def err_auto_var_requires_init : Error<
|
def err_auto_var_requires_init : Error<
|
||||||
|
@ -1944,6 +1948,14 @@ def err_decltype_auto_compound_type : Error<
|
||||||
def err_decltype_auto_initializer_list : Error<
|
def err_decltype_auto_initializer_list : Error<
|
||||||
"cannot deduce 'decltype(auto)' from initializer list">;
|
"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
|
// C++1y deduced return types
|
||||||
def err_auto_fn_deduction_failure : Error<
|
def err_auto_fn_deduction_failure : Error<
|
||||||
"cannot deduce return type %0 from returned value of type %1">;
|
"cannot deduce return type %0 from returned value of type %1">;
|
||||||
|
|
|
@ -1834,6 +1834,26 @@ private:
|
||||||
llvm_unreachable("Missing DeclSpecContext case");
|
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
|
/// Information on a C++0x for-range-initializer found while parsing a
|
||||||
/// declaration which turns out to be a for-range-declaration.
|
/// declaration which turns out to be a for-range-declaration.
|
||||||
struct ForRangeInit {
|
struct ForRangeInit {
|
||||||
|
|
|
@ -1709,6 +1709,7 @@ public:
|
||||||
ObjCParameterContext,// An ObjC method parameter type.
|
ObjCParameterContext,// An ObjC method parameter type.
|
||||||
KNRTypeListContext, // K&R type definition list for formals.
|
KNRTypeListContext, // K&R type definition list for formals.
|
||||||
TypeNameContext, // Abstract declarator for types.
|
TypeNameContext, // Abstract declarator for types.
|
||||||
|
FunctionalCastContext, // Type in a C++ functional cast expression.
|
||||||
MemberContext, // Struct/Union field.
|
MemberContext, // Struct/Union field.
|
||||||
BlockContext, // Declaration within a block in a function.
|
BlockContext, // Declaration within a block in a function.
|
||||||
ForContext, // Declaration within first part of a for loop.
|
ForContext, // Declaration within first part of a for loop.
|
||||||
|
@ -1911,6 +1912,7 @@ public:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case TypeNameContext:
|
case TypeNameContext:
|
||||||
|
case FunctionalCastContext:
|
||||||
case AliasDeclContext:
|
case AliasDeclContext:
|
||||||
case AliasTemplateContext:
|
case AliasTemplateContext:
|
||||||
case PrototypeContext:
|
case PrototypeContext:
|
||||||
|
@ -1951,6 +1953,7 @@ public:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case TypeNameContext:
|
case TypeNameContext:
|
||||||
|
case FunctionalCastContext:
|
||||||
case CXXNewContext:
|
case CXXNewContext:
|
||||||
case AliasDeclContext:
|
case AliasDeclContext:
|
||||||
case AliasTemplateContext:
|
case AliasTemplateContext:
|
||||||
|
@ -1983,6 +1986,7 @@ public:
|
||||||
case CXXCatchContext:
|
case CXXCatchContext:
|
||||||
case ObjCCatchContext:
|
case ObjCCatchContext:
|
||||||
case TypeNameContext:
|
case TypeNameContext:
|
||||||
|
case FunctionalCastContext:
|
||||||
case ConversionIdContext:
|
case ConversionIdContext:
|
||||||
case ObjCParameterContext:
|
case ObjCParameterContext:
|
||||||
case ObjCResultContext:
|
case ObjCResultContext:
|
||||||
|
@ -2021,6 +2025,7 @@ public:
|
||||||
// These contexts don't allow any kind of non-abstract declarator.
|
// These contexts don't allow any kind of non-abstract declarator.
|
||||||
case KNRTypeListContext:
|
case KNRTypeListContext:
|
||||||
case TypeNameContext:
|
case TypeNameContext:
|
||||||
|
case FunctionalCastContext:
|
||||||
case AliasDeclContext:
|
case AliasDeclContext:
|
||||||
case AliasTemplateContext:
|
case AliasTemplateContext:
|
||||||
case LambdaExprParameterContext:
|
case LambdaExprParameterContext:
|
||||||
|
@ -2078,6 +2083,7 @@ public:
|
||||||
case CXXCatchContext:
|
case CXXCatchContext:
|
||||||
case ObjCCatchContext:
|
case ObjCCatchContext:
|
||||||
case TypeNameContext:
|
case TypeNameContext:
|
||||||
|
case FunctionalCastContext: // FIXME
|
||||||
case CXXNewContext:
|
case CXXNewContext:
|
||||||
case AliasDeclContext:
|
case AliasDeclContext:
|
||||||
case AliasTemplateContext:
|
case AliasTemplateContext:
|
||||||
|
@ -2279,6 +2285,7 @@ public:
|
||||||
case ConditionContext:
|
case ConditionContext:
|
||||||
case KNRTypeListContext:
|
case KNRTypeListContext:
|
||||||
case TypeNameContext:
|
case TypeNameContext:
|
||||||
|
case FunctionalCastContext:
|
||||||
case AliasDeclContext:
|
case AliasDeclContext:
|
||||||
case AliasTemplateContext:
|
case AliasTemplateContext:
|
||||||
case PrototypeContext:
|
case PrototypeContext:
|
||||||
|
|
|
@ -1548,6 +1548,7 @@ public:
|
||||||
ParsedType ObjectType = nullptr,
|
ParsedType ObjectType = nullptr,
|
||||||
bool IsCtorOrDtorName = false,
|
bool IsCtorOrDtorName = false,
|
||||||
bool WantNontrivialTypeSourceInfo = false,
|
bool WantNontrivialTypeSourceInfo = false,
|
||||||
|
bool IsClassTemplateDeductionContext = true,
|
||||||
IdentifierInfo **CorrectedII = nullptr);
|
IdentifierInfo **CorrectedII = nullptr);
|
||||||
TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S);
|
TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S);
|
||||||
bool isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S);
|
bool isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S);
|
||||||
|
|
|
@ -914,7 +914,9 @@ namespace clang {
|
||||||
/// \brief A PipeType record.
|
/// \brief A PipeType record.
|
||||||
TYPE_PIPE = 43,
|
TYPE_PIPE = 43,
|
||||||
/// \brief An ObjCTypeParamType record.
|
/// \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
|
/// \brief The type IDs for special types constructed by semantic
|
||||||
|
|
|
@ -1877,8 +1877,9 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
|
||||||
return getTypeInfo(cast<SubstTemplateTypeParmType>(T)->
|
return getTypeInfo(cast<SubstTemplateTypeParmType>(T)->
|
||||||
getReplacementType().getTypePtr());
|
getReplacementType().getTypePtr());
|
||||||
|
|
||||||
case Type::Auto: {
|
case Type::Auto:
|
||||||
const AutoType *A = cast<AutoType>(T);
|
case Type::DeducedTemplateSpecialization: {
|
||||||
|
const DeducedType *A = cast<DeducedType>(T);
|
||||||
assert(!A->getDeducedType().isNull() &&
|
assert(!A->getDeducedType().isNull() &&
|
||||||
"cannot request the size of an undeduced or dependent auto type");
|
"cannot request the size of an undeduced or dependent auto type");
|
||||||
return getTypeInfo(A->getDeducedType().getTypePtr());
|
return getTypeInfo(A->getDeducedType().getTypePtr());
|
||||||
|
@ -2765,6 +2766,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
|
||||||
case Type::TemplateTypeParm:
|
case Type::TemplateTypeParm:
|
||||||
case Type::SubstTemplateTypeParmPack:
|
case Type::SubstTemplateTypeParmPack:
|
||||||
case Type::Auto:
|
case Type::Auto:
|
||||||
|
case Type::DeducedTemplateSpecialization:
|
||||||
case Type::PackExpansion:
|
case Type::PackExpansion:
|
||||||
llvm_unreachable("type should never be variably-modified");
|
llvm_unreachable("type should never be variably-modified");
|
||||||
|
|
||||||
|
@ -4435,6 +4437,28 @@ QualType ASTContext::getAutoType(QualType DeducedType, AutoTypeKeyword Keyword,
|
||||||
return QualType(AT, 0);
|
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
|
/// getAtomicType - Return the uniqued reference to the atomic type for
|
||||||
/// the given value type.
|
/// the given value type.
|
||||||
QualType ASTContext::getAtomicType(QualType T) const {
|
QualType ASTContext::getAtomicType(QualType T) const {
|
||||||
|
@ -6333,6 +6357,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||||
// We could see an undeduced auto type here during error recovery.
|
// We could see an undeduced auto type here during error recovery.
|
||||||
// Just ignore it.
|
// Just ignore it.
|
||||||
case Type::Auto:
|
case Type::Auto:
|
||||||
|
case Type::DeducedTemplateSpecialization:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Type::Pipe:
|
case Type::Pipe:
|
||||||
|
@ -8132,6 +8157,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
|
||||||
llvm_unreachable("Non-canonical and dependent types shouldn't get here");
|
llvm_unreachable("Non-canonical and dependent types shouldn't get here");
|
||||||
|
|
||||||
case Type::Auto:
|
case Type::Auto:
|
||||||
|
case Type::DeducedTemplateSpecialization:
|
||||||
case Type::LValueReference:
|
case Type::LValueReference:
|
||||||
case Type::RValueReference:
|
case Type::RValueReference:
|
||||||
case Type::MemberPointer:
|
case Type::MemberPointer:
|
||||||
|
|
|
@ -883,6 +883,20 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
||||||
return false;
|
return false;
|
||||||
break;
|
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::Record:
|
||||||
case Type::Enum:
|
case Type::Enum:
|
||||||
if (!IsStructurallyEquivalent(Context,
|
if (!IsStructurallyEquivalent(Context,
|
||||||
|
|
|
@ -7004,6 +7004,7 @@ static int EvaluateBuiltinClassifyType(const CallExpr *E,
|
||||||
case Type::Vector:
|
case Type::Vector:
|
||||||
case Type::ExtVector:
|
case Type::ExtVector:
|
||||||
case Type::Auto:
|
case Type::Auto:
|
||||||
|
case Type::DeducedTemplateSpecialization:
|
||||||
case Type::ObjCObject:
|
case Type::ObjCObject:
|
||||||
case Type::ObjCInterface:
|
case Type::ObjCInterface:
|
||||||
case Type::ObjCObjectPointer:
|
case Type::ObjCObjectPointer:
|
||||||
|
|
|
@ -1870,6 +1870,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
|
||||||
case Type::Paren:
|
case Type::Paren:
|
||||||
case Type::Attributed:
|
case Type::Attributed:
|
||||||
case Type::Auto:
|
case Type::Auto:
|
||||||
|
case Type::DeducedTemplateSpecialization:
|
||||||
case Type::PackExpansion:
|
case Type::PackExpansion:
|
||||||
case Type::ObjCObject:
|
case Type::ObjCObject:
|
||||||
case Type::ObjCInterface:
|
case Type::ObjCInterface:
|
||||||
|
@ -3145,6 +3146,16 @@ void CXXNameMangler::mangleType(const AutoType *T) {
|
||||||
mangleType(D);
|
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) {
|
void CXXNameMangler::mangleType(const AtomicType *T) {
|
||||||
// <type> ::= U <source-name> <type> # vendor extended type qualifier
|
// <type> ::= U <source-name> <type> # vendor extended type qualifier
|
||||||
// (Until there's a standardized mangling...)
|
// (Until there's a standardized mangling...)
|
||||||
|
|
|
@ -2474,6 +2474,17 @@ void MicrosoftCXXNameMangler::mangleType(const AutoType *T, Qualifiers,
|
||||||
<< Range;
|
<< 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,
|
void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, Qualifiers,
|
||||||
SourceRange Range) {
|
SourceRange Range) {
|
||||||
QualType ValueType = T->getValueType();
|
QualType ValueType = T->getValueType();
|
||||||
|
|
|
@ -1559,25 +1559,29 @@ TagDecl *Type::getAsTagDecl() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class GetContainedAutoVisitor :
|
class GetContainedDeducedTypeVisitor :
|
||||||
public TypeVisitor<GetContainedAutoVisitor, Type*> {
|
public TypeVisitor<GetContainedDeducedTypeVisitor, Type*> {
|
||||||
bool Syntactic;
|
bool Syntactic;
|
||||||
public:
|
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) {
|
Type *Visit(QualType T) {
|
||||||
if (T.isNull())
|
if (T.isNull())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return Visit(T.getTypePtr());
|
return Visit(T.getTypePtr());
|
||||||
}
|
}
|
||||||
|
|
||||||
// The 'auto' type itself.
|
// The deduced type itself.
|
||||||
Type *VisitAutoType(const AutoType *AT) {
|
Type *VisitDeducedType(const DeducedType *AT) {
|
||||||
return const_cast<AutoType*>(AT);
|
return const_cast<DeducedType*>(AT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only these types can contain the desired 'auto' type.
|
// Only these types can contain the desired 'auto' type.
|
||||||
|
Type *VisitElaboratedType(const ElaboratedType *T) {
|
||||||
|
return Visit(T->getNamedType());
|
||||||
|
}
|
||||||
Type *VisitPointerType(const PointerType *T) {
|
Type *VisitPointerType(const PointerType *T) {
|
||||||
return Visit(T->getPointeeType());
|
return Visit(T->getPointeeType());
|
||||||
}
|
}
|
||||||
|
@ -1620,13 +1624,14 @@ namespace {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoType *Type::getContainedAutoType() const {
|
DeducedType *Type::getContainedDeducedType() const {
|
||||||
return cast_or_null<AutoType>(GetContainedAutoVisitor().Visit(this));
|
return cast_or_null<DeducedType>(
|
||||||
|
GetContainedDeducedTypeVisitor().Visit(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type::hasAutoForTrailingReturnType() const {
|
bool Type::hasAutoForTrailingReturnType() const {
|
||||||
return dyn_cast_or_null<FunctionType>(
|
return dyn_cast_or_null<FunctionType>(
|
||||||
GetContainedAutoVisitor(true).Visit(this));
|
GetContainedDeducedTypeVisitor(true).Visit(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type::hasIntegerRepresentation() const {
|
bool Type::hasIntegerRepresentation() const {
|
||||||
|
@ -3378,6 +3383,7 @@ static CachedProperties computeCachedProperties(const Type *T) {
|
||||||
return CachedProperties(ExternalLinkage, false);
|
return CachedProperties(ExternalLinkage, false);
|
||||||
|
|
||||||
case Type::Auto:
|
case Type::Auto:
|
||||||
|
case Type::DeducedTemplateSpecialization:
|
||||||
// Give non-deduced 'auto' types external linkage. We should only see them
|
// Give non-deduced 'auto' types external linkage. We should only see them
|
||||||
// here in error recovery.
|
// here in error recovery.
|
||||||
return CachedProperties(ExternalLinkage, false);
|
return CachedProperties(ExternalLinkage, false);
|
||||||
|
@ -3485,6 +3491,7 @@ static LinkageInfo computeLinkageInfo(const Type *T) {
|
||||||
return LinkageInfo::external();
|
return LinkageInfo::external();
|
||||||
|
|
||||||
case Type::Auto:
|
case Type::Auto:
|
||||||
|
case Type::DeducedTemplateSpecialization:
|
||||||
return LinkageInfo::external();
|
return LinkageInfo::external();
|
||||||
|
|
||||||
case Type::Record:
|
case Type::Record:
|
||||||
|
@ -3621,7 +3628,8 @@ bool Type::canHaveNullability() const {
|
||||||
|
|
||||||
// auto is considered dependent when it isn't deduced.
|
// auto is considered dependent when it isn't deduced.
|
||||||
case Type::Auto:
|
case Type::Auto:
|
||||||
return !cast<AutoType>(type.getTypePtr())->isDeduced();
|
case Type::DeducedTemplateSpecialization:
|
||||||
|
return !cast<DeducedType>(type.getTypePtr())->isDeduced();
|
||||||
|
|
||||||
case Type::Builtin:
|
case Type::Builtin:
|
||||||
switch (cast<BuiltinType>(type.getTypePtr())->getKind()) {
|
switch (cast<BuiltinType>(type.getTypePtr())->getKind()) {
|
||||||
|
|
|
@ -189,6 +189,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
|
||||||
case Type::Elaborated:
|
case Type::Elaborated:
|
||||||
case Type::TemplateTypeParm:
|
case Type::TemplateTypeParm:
|
||||||
case Type::SubstTemplateTypeParmPack:
|
case Type::SubstTemplateTypeParmPack:
|
||||||
|
case Type::DeducedTemplateSpecialization:
|
||||||
case Type::TemplateSpecialization:
|
case Type::TemplateSpecialization:
|
||||||
case Type::InjectedClassName:
|
case Type::InjectedClassName:
|
||||||
case Type::DependentName:
|
case Type::DependentName:
|
||||||
|
@ -888,6 +889,24 @@ void TypePrinter::printAutoAfter(const AutoType *T, raw_ostream &OS) {
|
||||||
printAfter(T->getDeducedType(), OS);
|
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) {
|
void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream &OS) {
|
||||||
IncludeStrongLifetimeRAII Strong(Policy);
|
IncludeStrongLifetimeRAII Strong(Policy);
|
||||||
|
|
||||||
|
|
|
@ -2618,6 +2618,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
|
||||||
case Type::Attributed:
|
case Type::Attributed:
|
||||||
case Type::Adjusted:
|
case Type::Adjusted:
|
||||||
case Type::Decayed:
|
case Type::Decayed:
|
||||||
|
case Type::DeducedTemplateSpecialization:
|
||||||
case Type::Elaborated:
|
case Type::Elaborated:
|
||||||
case Type::Paren:
|
case Type::Paren:
|
||||||
case Type::SubstTemplateTypeParm:
|
case Type::SubstTemplateTypeParm:
|
||||||
|
|
|
@ -200,7 +200,8 @@ TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) {
|
||||||
llvm_unreachable("non-canonical or dependent type in IR-generation");
|
llvm_unreachable("non-canonical or dependent type in IR-generation");
|
||||||
|
|
||||||
case Type::Auto:
|
case Type::Auto:
|
||||||
llvm_unreachable("undeduced auto type in IR-generation");
|
case Type::DeducedTemplateSpecialization:
|
||||||
|
llvm_unreachable("undeduced type in IR-generation");
|
||||||
|
|
||||||
// Various scalar types.
|
// Various scalar types.
|
||||||
case Type::Builtin:
|
case Type::Builtin:
|
||||||
|
@ -1899,6 +1900,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
|
||||||
case Type::Typedef:
|
case Type::Typedef:
|
||||||
case Type::Decltype:
|
case Type::Decltype:
|
||||||
case Type::Auto:
|
case Type::Auto:
|
||||||
|
case Type::DeducedTemplateSpecialization:
|
||||||
// Stop walking: nothing to do.
|
// Stop walking: nothing to do.
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -487,7 +487,8 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Type::Auto:
|
case Type::Auto:
|
||||||
llvm_unreachable("Unexpected undeduced auto type!");
|
case Type::DeducedTemplateSpecialization:
|
||||||
|
llvm_unreachable("Unexpected undeduced type!");
|
||||||
case Type::Complex: {
|
case Type::Complex: {
|
||||||
llvm::Type *EltTy = ConvertType(cast<ComplexType>(Ty)->getElementType());
|
llvm::Type *EltTy = ConvertType(cast<ComplexType>(Ty)->getElementType());
|
||||||
ResultType = llvm::StructType::get(EltTy, EltTy, nullptr);
|
ResultType = llvm::StructType::get(EltTy, EltTy, nullptr);
|
||||||
|
|
|
@ -2815,7 +2815,8 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
|
||||||
llvm_unreachable("References shouldn't get here");
|
llvm_unreachable("References shouldn't get here");
|
||||||
|
|
||||||
case Type::Auto:
|
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:
|
case Type::Pipe:
|
||||||
llvm_unreachable("Pipe types shouldn't get here");
|
llvm_unreachable("Pipe types shouldn't get here");
|
||||||
|
@ -3045,7 +3046,8 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force,
|
||||||
llvm_unreachable("References shouldn't get here");
|
llvm_unreachable("References shouldn't get here");
|
||||||
|
|
||||||
case Type::Auto:
|
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:
|
case Type::Pipe:
|
||||||
llvm_unreachable("Pipe type shouldn't get here");
|
llvm_unreachable("Pipe type shouldn't get here");
|
||||||
|
|
|
@ -2884,7 +2884,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||||
Actions.getTypeName(*Next.getIdentifierInfo(), Next.getLocation(),
|
Actions.getTypeName(*Next.getIdentifierInfo(), Next.getLocation(),
|
||||||
getCurScope(), &SS, false, false, nullptr,
|
getCurScope(), &SS, false, false, nullptr,
|
||||||
/*IsCtorOrDtorName=*/false,
|
/*IsCtorOrDtorName=*/false,
|
||||||
/*NonTrivialSourceInfo=*/true);
|
/*WantNonTrivialSourceInfo=*/true,
|
||||||
|
isClassTemplateDeductionContext(DSContext));
|
||||||
|
|
||||||
// If the referenced identifier is not a type, then this declspec is
|
// If the referenced identifier is not a type, then this declspec is
|
||||||
// erroneous: We already checked about that it has no type specifier, and
|
// erroneous: We already checked about that it has no type specifier, and
|
||||||
|
@ -2998,9 +2999,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParsedType TypeRep =
|
ParsedType TypeRep = Actions.getTypeName(
|
||||||
Actions.getTypeName(*Tok.getIdentifierInfo(),
|
*Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), nullptr,
|
||||||
Tok.getLocation(), getCurScope());
|
false, false, nullptr, false, false,
|
||||||
|
isClassTemplateDeductionContext(DSContext));
|
||||||
|
|
||||||
// If this is not a typedef name, don't parse it as part of the declspec,
|
// 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.
|
// it must be an implicit int or an error.
|
||||||
|
|
|
@ -1144,10 +1144,11 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
|
||||||
|
|
||||||
// We have an identifier; check whether it is actually a type.
|
// We have an identifier; check whether it is actually a type.
|
||||||
IdentifierInfo *CorrectedII = nullptr;
|
IdentifierInfo *CorrectedII = nullptr;
|
||||||
ParsedType Type =
|
ParsedType Type = Actions.getTypeName(
|
||||||
Actions.getTypeName(*Id, IdLoc, getCurScope(), &SS, true, false, nullptr,
|
*Id, IdLoc, getCurScope(), &SS, true, false, nullptr,
|
||||||
/*IsCtorOrDtorName=*/false,
|
/*IsCtorOrDtorName=*/false,
|
||||||
/*NonTrivialTypeSourceInfo=*/true, &CorrectedII);
|
/*NonTrivialTypeSourceInfo=*/true,
|
||||||
|
/*IsClassTemplateDeductionContext*/ false, &CorrectedII);
|
||||||
if (!Type) {
|
if (!Type) {
|
||||||
Diag(IdLoc, diag::err_expected_class_name);
|
Diag(IdLoc, diag::err_expected_class_name);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1639,9 +1639,10 @@ ExprResult Parser::ParseCXXThis() {
|
||||||
/// typename-specifier '(' expression-list[opt] ')'
|
/// typename-specifier '(' expression-list[opt] ')'
|
||||||
/// [C++0x] typename-specifier braced-init-list
|
/// [C++0x] typename-specifier braced-init-list
|
||||||
///
|
///
|
||||||
|
/// In C++1z onwards, the type specifier can also be a template-name.
|
||||||
ExprResult
|
ExprResult
|
||||||
Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
|
Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
|
||||||
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
|
Declarator DeclaratorInfo(DS, Declarator::FunctionalCastContext);
|
||||||
ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
|
ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
|
||||||
|
|
||||||
assert((Tok.is(tok::l_paren) ||
|
assert((Tok.is(tok::l_paren) ||
|
||||||
|
|
|
@ -1743,7 +1743,8 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(CXXScopeSpec &SS,
|
||||||
*Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), &SS,
|
*Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), &SS,
|
||||||
false, NextToken().is(tok::period), nullptr,
|
false, NextToken().is(tok::period), nullptr,
|
||||||
/*IsCtorOrDtorName=*/false,
|
/*IsCtorOrDtorName=*/false,
|
||||||
/*NonTrivialTypeSourceInfo*/ true)) {
|
/*NonTrivialTypeSourceInfo*/ true,
|
||||||
|
/*IsClassTemplateDeductionContext*/GreaterThanIsOperator)) {
|
||||||
SourceLocation BeginLoc = Tok.getLocation();
|
SourceLocation BeginLoc = Tok.getLocation();
|
||||||
if (SS.isNotEmpty()) // it was a C++ qualified type name.
|
if (SS.isNotEmpty()) // it was a C++ qualified type name.
|
||||||
BeginLoc = SS.getBeginLoc();
|
BeginLoc = SS.getBeginLoc();
|
||||||
|
|
|
@ -60,6 +60,11 @@ Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType) {
|
||||||
return DeclGroupPtrTy::make(DeclGroupRef(Ptr));
|
return DeclGroupPtrTy::make(DeclGroupRef(Ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isTypeTemplate(NamedDecl *ND) {
|
||||||
|
return isa<ClassTemplateDecl>(ND) || isa<TypeAliasTemplateDecl>(ND) ||
|
||||||
|
isa<TemplateTemplateParmDecl>(ND);
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class TypeNameValidatorCCC : public CorrectionCandidateCallback {
|
class TypeNameValidatorCCC : public CorrectionCandidateCallback {
|
||||||
|
@ -67,7 +72,7 @@ class TypeNameValidatorCCC : public CorrectionCandidateCallback {
|
||||||
TypeNameValidatorCCC(bool AllowInvalid, bool WantClass=false,
|
TypeNameValidatorCCC(bool AllowInvalid, bool WantClass=false,
|
||||||
bool AllowTemplates=false)
|
bool AllowTemplates=false)
|
||||||
: AllowInvalidDecl(AllowInvalid), WantClassName(WantClass),
|
: AllowInvalidDecl(AllowInvalid), WantClassName(WantClass),
|
||||||
AllowClassTemplates(AllowTemplates) {
|
AllowTemplates(AllowTemplates) {
|
||||||
WantExpressionKeywords = false;
|
WantExpressionKeywords = false;
|
||||||
WantCXXNamedCasts = false;
|
WantCXXNamedCasts = false;
|
||||||
WantRemainingKeywords = false;
|
WantRemainingKeywords = false;
|
||||||
|
@ -76,7 +81,7 @@ class TypeNameValidatorCCC : public CorrectionCandidateCallback {
|
||||||
bool ValidateCandidate(const TypoCorrection &candidate) override {
|
bool ValidateCandidate(const TypoCorrection &candidate) override {
|
||||||
if (NamedDecl *ND = candidate.getCorrectionDecl()) {
|
if (NamedDecl *ND = candidate.getCorrectionDecl()) {
|
||||||
bool IsType = isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
|
bool IsType = isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
|
||||||
bool AllowedTemplate = AllowClassTemplates && isa<ClassTemplateDecl>(ND);
|
bool AllowedTemplate = AllowTemplates && isTypeTemplate(ND);
|
||||||
return (IsType || AllowedTemplate) &&
|
return (IsType || AllowedTemplate) &&
|
||||||
(AllowInvalidDecl || !ND->isInvalidDecl());
|
(AllowInvalidDecl || !ND->isInvalidDecl());
|
||||||
}
|
}
|
||||||
|
@ -86,7 +91,7 @@ class TypeNameValidatorCCC : public CorrectionCandidateCallback {
|
||||||
private:
|
private:
|
||||||
bool AllowInvalidDecl;
|
bool AllowInvalidDecl;
|
||||||
bool WantClassName;
|
bool WantClassName;
|
||||||
bool AllowClassTemplates;
|
bool AllowTemplates;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
@ -252,7 +257,13 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
|
||||||
ParsedType ObjectTypePtr,
|
ParsedType ObjectTypePtr,
|
||||||
bool IsCtorOrDtorName,
|
bool IsCtorOrDtorName,
|
||||||
bool WantNontrivialTypeSourceInfo,
|
bool WantNontrivialTypeSourceInfo,
|
||||||
|
bool IsClassTemplateDeductionContext,
|
||||||
IdentifierInfo **CorrectedII) {
|
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.
|
// Determine where we will perform name lookup.
|
||||||
DeclContext *LookupCtx = nullptr;
|
DeclContext *LookupCtx = nullptr;
|
||||||
if (ObjectTypePtr) {
|
if (ObjectTypePtr) {
|
||||||
|
@ -334,10 +345,11 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
|
||||||
case LookupResult::NotFound:
|
case LookupResult::NotFound:
|
||||||
case LookupResult::NotFoundInCurrentInstantiation:
|
case LookupResult::NotFoundInCurrentInstantiation:
|
||||||
if (CorrectedII) {
|
if (CorrectedII) {
|
||||||
TypoCorrection Correction = CorrectTypo(
|
TypoCorrection Correction =
|
||||||
Result.getLookupNameInfo(), Kind, S, SS,
|
CorrectTypo(Result.getLookupNameInfo(), Kind, S, SS,
|
||||||
llvm::make_unique<TypeNameValidatorCCC>(true, isClassName),
|
llvm::make_unique<TypeNameValidatorCCC>(
|
||||||
CTK_ErrorRecovery);
|
true, isClassName, AllowDeducedTemplate),
|
||||||
|
CTK_ErrorRecovery);
|
||||||
IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo();
|
IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo();
|
||||||
TemplateTy Template;
|
TemplateTy Template;
|
||||||
bool MemberOfUnknownSpecialization;
|
bool MemberOfUnknownSpecialization;
|
||||||
|
@ -359,7 +371,8 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
|
||||||
ParsedType Ty = getTypeName(*NewII, NameLoc, S, NewSSPtr,
|
ParsedType Ty = getTypeName(*NewII, NameLoc, S, NewSSPtr,
|
||||||
isClassName, HasTrailingDot, ObjectTypePtr,
|
isClassName, HasTrailingDot, ObjectTypePtr,
|
||||||
IsCtorOrDtorName,
|
IsCtorOrDtorName,
|
||||||
WantNontrivialTypeSourceInfo);
|
WantNontrivialTypeSourceInfo,
|
||||||
|
IsClassTemplateDeductionContext);
|
||||||
if (Ty) {
|
if (Ty) {
|
||||||
diagnoseTypo(Correction,
|
diagnoseTypo(Correction,
|
||||||
PDiag(diag::err_unknown_type_or_class_name_suggest)
|
PDiag(diag::err_unknown_type_or_class_name_suggest)
|
||||||
|
@ -391,7 +404,8 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
|
||||||
// Look to see if we have a type anywhere in the list of results.
|
// Look to see if we have a type anywhere in the list of results.
|
||||||
for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end();
|
for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end();
|
||||||
Res != ResEnd; ++Res) {
|
Res != ResEnd; ++Res) {
|
||||||
if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res)) {
|
if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res) ||
|
||||||
|
(AllowDeducedTemplate && isTypeTemplate(*Res))) {
|
||||||
if (!IIDecl ||
|
if (!IIDecl ||
|
||||||
(*Res)->getLocation().getRawEncoding() <
|
(*Res)->getLocation().getRawEncoding() <
|
||||||
IIDecl->getLocation().getRawEncoding())
|
IIDecl->getLocation().getRawEncoding())
|
||||||
|
@ -440,29 +454,13 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
|
||||||
|
|
||||||
T = Context.getTypeDeclType(TD);
|
T = Context.getTypeDeclType(TD);
|
||||||
MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
|
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)) {
|
} else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
|
||||||
(void)DiagnoseUseOfDecl(IDecl, NameLoc);
|
(void)DiagnoseUseOfDecl(IDecl, NameLoc);
|
||||||
if (!HasTrailingDot)
|
if (!HasTrailingDot)
|
||||||
T = Context.getObjCInterfaceType(IDecl);
|
T = Context.getObjCInterfaceType(IDecl);
|
||||||
|
} else if (AllowDeducedTemplate && isTypeTemplate(IIDecl)) {
|
||||||
|
T = Context.getDeducedTemplateSpecializationType(
|
||||||
|
TemplateName(cast<TemplateDecl>(IIDecl)), QualType(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (T.isNull()) {
|
if (T.isNull()) {
|
||||||
|
@ -470,6 +468,27 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
|
||||||
Result.suppressDiagnostics();
|
Result.suppressDiagnostics();
|
||||||
return nullptr;
|
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);
|
return ParsedType::make(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -647,6 +666,7 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
|
||||||
if (Corrected.getCorrectionSpecifier())
|
if (Corrected.getCorrectionSpecifier())
|
||||||
tmpSS.MakeTrivial(Context, Corrected.getCorrectionSpecifier(),
|
tmpSS.MakeTrivial(Context, Corrected.getCorrectionSpecifier(),
|
||||||
SourceRange(IILoc));
|
SourceRange(IILoc));
|
||||||
|
// FIXME: Support class template argument deduction here.
|
||||||
SuggestedType =
|
SuggestedType =
|
||||||
getTypeName(*Corrected.getCorrectionAsIdentifierInfo(), IILoc, S,
|
getTypeName(*Corrected.getCorrectionAsIdentifierInfo(), IILoc, S,
|
||||||
tmpSS.isSet() ? &tmpSS : SS, false, false, nullptr,
|
tmpSS.isSet() ? &tmpSS : SS, false, false, nullptr,
|
||||||
|
@ -9740,6 +9760,14 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
|
||||||
|
|
||||||
VarDeclOrName VN{VDecl, Name};
|
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;
|
ArrayRef<Expr *> DeduceInits = Init;
|
||||||
if (DirectInit) {
|
if (DirectInit) {
|
||||||
if (auto *PL = dyn_cast<ParenListExpr>(Init))
|
if (auto *PL = dyn_cast<ParenListExpr>(Init))
|
||||||
|
|
|
@ -3976,7 +3976,8 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T,
|
||||||
T = cast<DecltypeType>(Ty)->desugar();
|
T = cast<DecltypeType>(Ty)->desugar();
|
||||||
break;
|
break;
|
||||||
case Type::Auto:
|
case Type::Auto:
|
||||||
T = cast<AutoType>(Ty)->getDeducedType();
|
case Type::DeducedTemplateSpecialization:
|
||||||
|
T = cast<DeducedType>(Ty)->getDeducedType();
|
||||||
break;
|
break;
|
||||||
case Type::TypeOfExpr:
|
case Type::TypeOfExpr:
|
||||||
T = cast<TypeOfExprType>(Ty)->getUnderlyingExpr()->getType();
|
T = cast<TypeOfExprType>(Ty)->getUnderlyingExpr()->getType();
|
||||||
|
|
|
@ -1255,9 +1255,19 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
|
||||||
RParenLoc);
|
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();
|
bool ListInitialization = LParenLoc.isInvalid();
|
||||||
assert((!ListInitialization || (Exprs.size() == 1 && isa<InitListExpr>(Exprs[0])))
|
assert((!ListInitialization ||
|
||||||
&& "List initialization must have initializer list as expression.");
|
(Exprs.size() == 1 && isa<InitListExpr>(Exprs[0]))) &&
|
||||||
|
"List initialization must have initializer list as expression.");
|
||||||
SourceRange FullRange = SourceRange(TyBeginLoc,
|
SourceRange FullRange = SourceRange(TyBeginLoc,
|
||||||
ListInitialization ? Exprs[0]->getSourceRange().getEnd() : RParenLoc);
|
ListInitialization ? Exprs[0]->getSourceRange().getEnd() : RParenLoc);
|
||||||
|
|
||||||
|
@ -1646,6 +1656,11 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
|
||||||
|
|
||||||
// C++11 [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for.
|
// C++11 [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for.
|
||||||
if (AllocType->isUndeducedType()) {
|
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)
|
if (initStyle == CXXNewExpr::NoInit || NumInits == 0)
|
||||||
return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg)
|
return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg)
|
||||||
<< AllocType << TypeRange);
|
<< AllocType << TypeRange);
|
||||||
|
|
|
@ -2694,6 +2694,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
|
||||||
|
|
||||||
// Non-deduced auto types only get here for error cases.
|
// Non-deduced auto types only get here for error cases.
|
||||||
case Type::Auto:
|
case Type::Auto:
|
||||||
|
case Type::DeducedTemplateSpecialization:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// If T is an Objective-C object or interface type, or a pointer to an
|
// If T is an Objective-C object or interface type, or a pointer to an
|
||||||
|
|
|
@ -4439,6 +4439,11 @@ bool UnnamedLocalNoLinkageFinder::VisitAutoType(const AutoType *T) {
|
||||||
return Visit(T->getDeducedType());
|
return Visit(T->getDeducedType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UnnamedLocalNoLinkageFinder::VisitDeducedTemplateSpecializationType(
|
||||||
|
const DeducedTemplateSpecializationType *T) {
|
||||||
|
return Visit(T->getDeducedType());
|
||||||
|
}
|
||||||
|
|
||||||
bool UnnamedLocalNoLinkageFinder::VisitRecordType(const RecordType* T) {
|
bool UnnamedLocalNoLinkageFinder::VisitRecordType(const RecordType* T) {
|
||||||
return VisitTagDecl(T->getDecl());
|
return VisitTagDecl(T->getDecl());
|
||||||
}
|
}
|
||||||
|
@ -8786,6 +8791,9 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
|
||||||
Context.getTypeDeclType(Type));
|
Context.getTypeDeclType(Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Form a deduced template specialization type if we get a template
|
||||||
|
// declaration here.
|
||||||
|
|
||||||
DiagID = diag::err_typename_nested_not_type;
|
DiagID = diag::err_typename_nested_not_type;
|
||||||
Referenced = Result.getFoundDecl();
|
Referenced = Result.getFoundDecl();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1723,6 +1723,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
|
||||||
case Type::Decltype:
|
case Type::Decltype:
|
||||||
case Type::UnaryTransform:
|
case Type::UnaryTransform:
|
||||||
case Type::Auto:
|
case Type::Auto:
|
||||||
|
case Type::DeducedTemplateSpecialization:
|
||||||
case Type::DependentTemplateSpecialization:
|
case Type::DependentTemplateSpecialization:
|
||||||
case Type::PackExpansion:
|
case Type::PackExpansion:
|
||||||
case Type::Pipe:
|
case Type::Pipe:
|
||||||
|
@ -5152,8 +5153,9 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Type::Auto:
|
case Type::Auto:
|
||||||
|
case Type::DeducedTemplateSpecialization:
|
||||||
MarkUsedTemplateParameters(Ctx,
|
MarkUsedTemplateParameters(Ctx,
|
||||||
cast<AutoType>(T)->getDeducedType(),
|
cast<DeducedType>(T)->getDeducedType(),
|
||||||
OnlyDeduced, Depth, Used);
|
OnlyDeduced, Depth, Used);
|
||||||
|
|
||||||
// None of these types have any template parameters in them.
|
// None of these types have any template parameters in them.
|
||||||
|
|
|
@ -2778,12 +2778,20 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||||
distributeTypeAttrsFromDeclarator(state, T);
|
distributeTypeAttrsFromDeclarator(state, T);
|
||||||
|
|
||||||
// C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context.
|
// 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;
|
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()) {
|
switch (D.getContext()) {
|
||||||
case Declarator::LambdaExprContext:
|
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::ObjCParameterContext:
|
||||||
case Declarator::ObjCResultContext:
|
case Declarator::ObjCResultContext:
|
||||||
case Declarator::PrototypeContext:
|
case Declarator::PrototypeContext:
|
||||||
|
@ -2791,8 +2799,8 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||||
break;
|
break;
|
||||||
case Declarator::LambdaExprParameterContext:
|
case Declarator::LambdaExprParameterContext:
|
||||||
// In C++14, generic lambdas allow 'auto' in their parameters.
|
// In C++14, generic lambdas allow 'auto' in their parameters.
|
||||||
if (!(SemaRef.getLangOpts().CPlusPlus14
|
if (!SemaRef.getLangOpts().CPlusPlus14 ||
|
||||||
&& D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto))
|
!Auto || Auto->getKeyword() != AutoTypeKeyword::Auto)
|
||||||
Error = 16;
|
Error = 16;
|
||||||
break;
|
break;
|
||||||
case Declarator::MemberContext: {
|
case Declarator::MemberContext: {
|
||||||
|
@ -2807,6 +2815,8 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||||
case TTK_Class: Error = 5; /* Class member */ break;
|
case TTK_Class: Error = 5; /* Class member */ break;
|
||||||
case TTK_Interface: Error = 6; /* Interface member */ break;
|
case TTK_Interface: Error = 6; /* Interface member */ break;
|
||||||
}
|
}
|
||||||
|
if (D.getDeclSpec().isFriendSpecified())
|
||||||
|
Error = 20; // Friend type
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Declarator::CXXCatchContext:
|
case Declarator::CXXCatchContext:
|
||||||
|
@ -2814,8 +2824,10 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||||
Error = 7; // Exception declaration
|
Error = 7; // Exception declaration
|
||||||
break;
|
break;
|
||||||
case Declarator::TemplateParamContext:
|
case Declarator::TemplateParamContext:
|
||||||
if (!SemaRef.getLangOpts().CPlusPlus1z)
|
if (isa<DeducedTemplateSpecializationType>(Deduced))
|
||||||
Error = 8; // Template parameter
|
Error = 19; // Template parameter
|
||||||
|
else if (!SemaRef.getLangOpts().CPlusPlus1z)
|
||||||
|
Error = 8; // Template parameter (until C++1z)
|
||||||
break;
|
break;
|
||||||
case Declarator::BlockLiteralContext:
|
case Declarator::BlockLiteralContext:
|
||||||
Error = 9; // Block literal
|
Error = 9; // Block literal
|
||||||
|
@ -2828,15 +2840,17 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||||
Error = 12; // Type alias
|
Error = 12; // Type alias
|
||||||
break;
|
break;
|
||||||
case Declarator::TrailingReturnContext:
|
case Declarator::TrailingReturnContext:
|
||||||
if (!SemaRef.getLangOpts().CPlusPlus14 ||
|
if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
|
||||||
D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type)
|
|
||||||
Error = 13; // Function return type
|
Error = 13; // Function return type
|
||||||
break;
|
break;
|
||||||
case Declarator::ConversionIdContext:
|
case Declarator::ConversionIdContext:
|
||||||
if (!SemaRef.getLangOpts().CPlusPlus14 ||
|
if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
|
||||||
D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type)
|
|
||||||
Error = 14; // conversion-type-id
|
Error = 14; // conversion-type-id
|
||||||
break;
|
break;
|
||||||
|
case Declarator::FunctionalCastContext:
|
||||||
|
if (isa<DeducedTemplateSpecializationType>(Deduced))
|
||||||
|
break;
|
||||||
|
LLVM_FALLTHROUGH;
|
||||||
case Declarator::TypeNameContext:
|
case Declarator::TypeNameContext:
|
||||||
Error = 15; // Generic
|
Error = 15; // Generic
|
||||||
break;
|
break;
|
||||||
|
@ -2845,9 +2859,14 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||||
case Declarator::ForContext:
|
case Declarator::ForContext:
|
||||||
case Declarator::InitStmtContext:
|
case Declarator::InitStmtContext:
|
||||||
case Declarator::ConditionContext:
|
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;
|
break;
|
||||||
case Declarator::CXXNewContext:
|
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
|
Error = 17; // 'new' type
|
||||||
break;
|
break;
|
||||||
case Declarator::KNRTypeListContext:
|
case Declarator::KNRTypeListContext:
|
||||||
|
@ -2861,8 +2880,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||||
// In Objective-C it is an error to use 'auto' on a function declarator
|
// In Objective-C it is an error to use 'auto' on a function declarator
|
||||||
// (and everywhere for '__auto_type').
|
// (and everywhere for '__auto_type').
|
||||||
if (D.isFunctionDeclarator() &&
|
if (D.isFunctionDeclarator() &&
|
||||||
(!SemaRef.getLangOpts().CPlusPlus11 ||
|
(!SemaRef.getLangOpts().CPlusPlus11 || !IsCXXAutoType))
|
||||||
D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type))
|
|
||||||
Error = 13;
|
Error = 13;
|
||||||
|
|
||||||
bool HaveTrailing = false;
|
bool HaveTrailing = false;
|
||||||
|
@ -2872,8 +2890,8 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||||
// level. Check all declarator chunks (outermost first) anyway, to give
|
// level. Check all declarator chunks (outermost first) anyway, to give
|
||||||
// better diagnostics.
|
// better diagnostics.
|
||||||
// We don't support '__auto_type' with trailing return types.
|
// We don't support '__auto_type' with trailing return types.
|
||||||
if (SemaRef.getLangOpts().CPlusPlus11 &&
|
// FIXME: Should we only do this for 'auto' and not 'decltype(auto)'?
|
||||||
D.getDeclSpec().getTypeSpecType() != DeclSpec::TST_auto_type) {
|
if (SemaRef.getLangOpts().CPlusPlus11 && IsCXXAutoType) {
|
||||||
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
|
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
|
||||||
unsigned chunkIndex = e - i - 1;
|
unsigned chunkIndex = e - i - 1;
|
||||||
state.setCurrentChunkIndex(chunkIndex);
|
state.setCurrentChunkIndex(chunkIndex);
|
||||||
|
@ -2894,15 +2912,28 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||||
AutoRange = D.getName().getSourceRange();
|
AutoRange = D.getName().getSourceRange();
|
||||||
|
|
||||||
if (Error != -1) {
|
if (Error != -1) {
|
||||||
unsigned Keyword;
|
unsigned Kind;
|
||||||
switch (D.getDeclSpec().getTypeSpecType()) {
|
if (Auto) {
|
||||||
case DeclSpec::TST_auto: Keyword = 0; break;
|
switch (Auto->getKeyword()) {
|
||||||
case DeclSpec::TST_decltype_auto: Keyword = 1; break;
|
case AutoTypeKeyword::Auto: Kind = 0; break;
|
||||||
case DeclSpec::TST_auto_type: Keyword = 2; break;
|
case AutoTypeKeyword::DecltypeAuto: Kind = 1; break;
|
||||||
default: llvm_unreachable("unknown auto TypeSpecType");
|
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)
|
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;
|
T = SemaRef.Context.IntTy;
|
||||||
D.setInvalidType(true);
|
D.setInvalidType(true);
|
||||||
} else if (!HaveTrailing) {
|
} else if (!HaveTrailing) {
|
||||||
|
@ -2942,6 +2973,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||||
DiagID = diag::err_type_defined_in_alias_template;
|
DiagID = diag::err_type_defined_in_alias_template;
|
||||||
break;
|
break;
|
||||||
case Declarator::TypeNameContext:
|
case Declarator::TypeNameContext:
|
||||||
|
case Declarator::FunctionalCastContext:
|
||||||
case Declarator::ConversionIdContext:
|
case Declarator::ConversionIdContext:
|
||||||
case Declarator::TemplateParamContext:
|
case Declarator::TemplateParamContext:
|
||||||
case Declarator::CXXNewContext:
|
case Declarator::CXXNewContext:
|
||||||
|
@ -3623,17 +3655,32 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||||
|
|
||||||
// If T is 'decltype(auto)', the only declarators we can have are parens
|
// 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.
|
// and at most one function declarator if this is a function declaration.
|
||||||
if (const AutoType *AT = T->getAs<AutoType>()) {
|
// If T is a deduced class template specialization type, we can have no
|
||||||
if (AT->isDecltypeAuto()) {
|
// 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) {
|
for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) {
|
||||||
unsigned Index = E - I - 1;
|
unsigned Index = E - I - 1;
|
||||||
DeclaratorChunk &DeclChunk = D.getTypeObject(Index);
|
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;
|
unsigned DiagKind = 0;
|
||||||
switch (DeclChunk.Kind) {
|
switch (DeclChunk.Kind) {
|
||||||
case DeclaratorChunk::Paren:
|
case DeclaratorChunk::Paren:
|
||||||
|
// FIXME: Rejecting this is a little silly.
|
||||||
|
if (IsClassTemplateDeduction) {
|
||||||
|
DiagKind = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
case DeclaratorChunk::Function: {
|
case DeclaratorChunk::Function: {
|
||||||
|
if (IsClassTemplateDeduction) {
|
||||||
|
DiagKind = 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
unsigned FnIndex;
|
unsigned FnIndex;
|
||||||
if (D.isFunctionDeclarationContext() &&
|
if (D.isFunctionDeclarationContext() &&
|
||||||
D.isFunctionDeclarator(FnIndex) && FnIndex == Index)
|
D.isFunctionDeclarator(FnIndex) && FnIndex == Index)
|
||||||
|
@ -3834,6 +3881,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||||
case Declarator::TemplateParamContext:
|
case Declarator::TemplateParamContext:
|
||||||
case Declarator::TemplateTypeArgContext:
|
case Declarator::TemplateTypeArgContext:
|
||||||
case Declarator::TypeNameContext:
|
case Declarator::TypeNameContext:
|
||||||
|
case Declarator::FunctionalCastContext:
|
||||||
// Don't infer in these contexts.
|
// Don't infer in these contexts.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4713,6 +4761,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||||
case Declarator::ObjCParameterContext: // FIXME: special diagnostic here?
|
case Declarator::ObjCParameterContext: // FIXME: special diagnostic here?
|
||||||
case Declarator::ObjCResultContext: // FIXME: special diagnostic here?
|
case Declarator::ObjCResultContext: // FIXME: special diagnostic here?
|
||||||
case Declarator::TypeNameContext:
|
case Declarator::TypeNameContext:
|
||||||
|
case Declarator::FunctionalCastContext:
|
||||||
case Declarator::CXXNewContext:
|
case Declarator::CXXNewContext:
|
||||||
case Declarator::AliasDeclContext:
|
case Declarator::AliasDeclContext:
|
||||||
case Declarator::AliasTemplateContext:
|
case Declarator::AliasTemplateContext:
|
||||||
|
|
|
@ -876,6 +876,14 @@ public:
|
||||||
/*IsDependent*/ false);
|
/*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.
|
/// \brief Build a new template specialization type.
|
||||||
///
|
///
|
||||||
/// By default, performs semantic analysis when building the template
|
/// By default, performs semantic analysis when building the template
|
||||||
|
@ -5345,6 +5353,37 @@ QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB,
|
||||||
return Result;
|
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>
|
template<typename Derived>
|
||||||
QualType TreeTransform<Derived>::TransformRecordType(TypeLocBuilder &TLB,
|
QualType TreeTransform<Derived>::TransformRecordType(TypeLocBuilder &TLB,
|
||||||
RecordTypeLoc TL) {
|
RecordTypeLoc TL) {
|
||||||
|
|
|
@ -5651,6 +5651,14 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
|
||||||
return Context.getAutoType(Deduced, Keyword, IsDependent);
|
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: {
|
case TYPE_RECORD: {
|
||||||
if (Record.size() != 2) {
|
if (Record.size() != 2) {
|
||||||
Error("incorrect encoding of record type");
|
Error("incorrect encoding of record type");
|
||||||
|
@ -6082,6 +6090,11 @@ void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) {
|
||||||
TL.setNameLoc(ReadSourceLocation());
|
TL.setNameLoc(ReadSourceLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TypeLocReader::VisitDeducedTemplateSpecializationTypeLoc(
|
||||||
|
DeducedTemplateSpecializationTypeLoc TL) {
|
||||||
|
TL.setTemplateNameLoc(ReadSourceLocation());
|
||||||
|
}
|
||||||
|
|
||||||
void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
|
void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
|
||||||
TL.setNameLoc(ReadSourceLocation());
|
TL.setNameLoc(ReadSourceLocation());
|
||||||
}
|
}
|
||||||
|
|
|
@ -349,6 +349,15 @@ void ASTTypeWriter::VisitAutoType(const AutoType *T) {
|
||||||
Code = TYPE_AUTO;
|
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) {
|
void ASTTypeWriter::VisitTagType(const TagType *T) {
|
||||||
Record.push_back(T->isDependentType());
|
Record.push_back(T->isDependentType());
|
||||||
Record.AddDeclRef(T->getDecl()->getCanonicalDecl());
|
Record.AddDeclRef(T->getDecl()->getCanonicalDecl());
|
||||||
|
@ -683,6 +692,11 @@ void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc TL) {
|
||||||
Record.AddSourceLocation(TL.getNameLoc());
|
Record.AddSourceLocation(TL.getNameLoc());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TypeLocWriter::VisitDeducedTemplateSpecializationTypeLoc(
|
||||||
|
DeducedTemplateSpecializationTypeLoc TL) {
|
||||||
|
Record.AddSourceLocation(TL.getTemplateNameLoc());
|
||||||
|
}
|
||||||
|
|
||||||
void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {
|
void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {
|
||||||
Record.AddSourceLocation(TL.getNameLoc());
|
Record.AddSourceLocation(TL.getNameLoc());
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ struct S {
|
||||||
|
|
||||||
void f() throw (auto); // expected-error{{'auto' not allowed here}}
|
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}}
|
operator auto(); // expected-error{{'auto' not allowed in conversion function type}}
|
||||||
};
|
};
|
||||||
|
|
|
@ -877,13 +877,25 @@ namespace dr583 { // dr583: 4
|
||||||
namespace dr585 { // dr585: yes
|
namespace dr585 { // dr585: yes
|
||||||
template<typename> struct T;
|
template<typename> struct T;
|
||||||
struct A {
|
struct A {
|
||||||
friend T; // expected-error {{requires a type specifier}} expected-error {{can only be classes or functions}}
|
friend T;
|
||||||
|
#if __cplusplus <= 201402L
|
||||||
|
// expected-error@-2 {{requires a type specifier}} expected-error@-2 {{can only be classes or functions}}
|
||||||
|
#else
|
||||||
|
// expected-error@-4 {{use of class template 'T' requires template arguments; argument deduction not allowed in friend declaration}}
|
||||||
|
// expected-note@-7 {{here}}
|
||||||
|
#endif
|
||||||
// FIXME: It's not clear whether the standard allows this or what it means,
|
// FIXME: It's not clear whether the standard allows this or what it means,
|
||||||
// but the DR585 writeup suggests it as an alternative.
|
// but the DR585 writeup suggests it as an alternative.
|
||||||
template<typename U> friend T<U>; // expected-error {{must use an elaborated type}}
|
template<typename U> friend T<U>; // expected-error {{must use an elaborated type}}
|
||||||
};
|
};
|
||||||
template<template<typename> class T> struct B {
|
template<template<typename> class T> struct B {
|
||||||
friend T; // expected-error {{requires a type specifier}} expected-error {{can only be classes or functions}}
|
friend T;
|
||||||
|
#if __cplusplus <= 201402L
|
||||||
|
// expected-error@-2 {{requires a type specifier}} expected-error@-2 {{can only be classes or functions}}
|
||||||
|
#else
|
||||||
|
// expected-error@-4 {{use of template template parameter 'T' requires template arguments; argument deduction not allowed in friend declaration}}
|
||||||
|
// expected-note@-6 {{here}}
|
||||||
|
#endif
|
||||||
template<typename U> friend T<U>; // expected-error {{must use an elaborated type}}
|
template<typename U> friend T<U>; // expected-error {{must use an elaborated type}}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// RUN: %clang_cc1 -verify %s
|
// RUN: %clang_cc1 -verify %s
|
||||||
// RUN: %clang_cc1 -verify %s -std=c++98
|
// RUN: %clang_cc1 -verify %s -std=c++98
|
||||||
// RUN: %clang_cc1 -verify %s -std=c++11
|
// RUN: %clang_cc1 -verify %s -std=c++11
|
||||||
|
// RUN: %clang_cc1 -verify %s -std=c++1z
|
||||||
|
|
||||||
// PR25946
|
// PR25946
|
||||||
// We had an off-by-one error in an assertion when annotating A<int> below. Our
|
// We had an off-by-one error in an assertion when annotating A<int> below. Our
|
||||||
|
@ -13,9 +14,13 @@ template <typename T> class A {};
|
||||||
// expected-error@+1 {{expected '{' after base class list}}
|
// expected-error@+1 {{expected '{' after base class list}}
|
||||||
template <typename T> class B : T // not ',' or '{'
|
template <typename T> class B : T // not ',' or '{'
|
||||||
#if __cplusplus < 201103L
|
#if __cplusplus < 201103L
|
||||||
// expected-error@+4 {{expected ';' after top level declarator}}
|
// expected-error@+8 {{expected ';' after top level declarator}}
|
||||||
|
#endif
|
||||||
|
#if __cplusplus <= 201402L
|
||||||
|
// expected-error@+5 {{C++ requires a type specifier for all declarations}}
|
||||||
|
#else
|
||||||
|
// expected-error@+3 {{expected unqualified-id}}
|
||||||
#endif
|
#endif
|
||||||
// expected-error@+2 {{C++ requires a type specifier for all declarations}}
|
|
||||||
// expected-error@+1 {{expected ';' after class}}
|
// expected-error@+1 {{expected ';' after class}}
|
||||||
A<int> {
|
A<int> {
|
||||||
};
|
};
|
||||||
|
|
|
@ -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}}
|
||||||
|
}
|
|
@ -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, 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<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 {
|
namespace test0 {
|
||||||
template <class t> class foo {};
|
template <class t> class foo {};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||||
|
|
||||||
// PR4364
|
// PR4364
|
||||||
template<class T> struct a {
|
template<class T> struct a { // expected-note {{here}}
|
||||||
T b() {
|
T b() {
|
||||||
return typename T::x();
|
return typename T::x();
|
||||||
}
|
}
|
||||||
|
@ -17,3 +17,4 @@ B c() {
|
||||||
// Some extra tests for invalid cases
|
// 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 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 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}}
|
||||||
|
|
|
@ -1640,6 +1640,15 @@ bool CursorVisitor::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
|
||||||
return Visit(TL.getOriginalLoc());
|
return Visit(TL.getOriginalLoc());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CursorVisitor::VisitDeducedTemplateSpecializationTypeLoc(
|
||||||
|
DeducedTemplateSpecializationTypeLoc TL) {
|
||||||
|
if (VisitTemplateName(TL.getTypePtr()->getTemplateName(),
|
||||||
|
TL.getTemplateNameLoc()))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool CursorVisitor::VisitTemplateSpecializationTypeLoc(
|
bool CursorVisitor::VisitTemplateSpecializationTypeLoc(
|
||||||
TemplateSpecializationTypeLoc TL) {
|
TemplateSpecializationTypeLoc TL) {
|
||||||
// Visit the template name.
|
// Visit the template name.
|
||||||
|
|
|
@ -452,7 +452,8 @@ try_again:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Type::Auto:
|
case Type::Auto:
|
||||||
TP = cast<AutoType>(TP)->getDeducedType().getTypePtrOrNull();
|
case Type::DeducedTemplateSpecialization:
|
||||||
|
TP = cast<DeducedType>(TP)->getDeducedType().getTypePtrOrNull();
|
||||||
if (TP)
|
if (TP)
|
||||||
goto try_again;
|
goto try_again;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue