Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ Bug Fixes to C++ Support
- Fixed an incorrect template argument deduction when matching packs of template
template parameters when one of its parameters is also a pack. (#GH181166)
- Fixed a crash when a default argument is passed to an explicit object parameter. (#GH176639)
- Fixed an alias template CTAD crash.
- Fixed a crash when diagnosing an invalid static member function with an explicit object parameter (#GH177741)
- Fixed a crash when pack expansions are used as arguments for non-pack parameters of built-in templates. (#GH180307)
- Fixed a bug where captured variables in non-mutable lambdas were incorrectly treated as mutable
Expand Down
23 changes: 5 additions & 18 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1839,12 +1839,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType getFunctionTypeInternal(QualType ResultTy, ArrayRef<QualType> Args,
const FunctionProtoType::ExtProtoInfo &EPI,
bool OnlyWantCanonical) const;
QualType
getAutoTypeInternal(QualType DeducedType, AutoTypeKeyword Keyword,
bool IsDependent, bool IsPack = false,
TemplateDecl *TypeConstraintConcept = nullptr,
ArrayRef<TemplateArgument> TypeConstraintArgs = {},
bool IsCanon = false) const;

public:
QualType getTypeDeclType(ElaboratedTypeKeyword Keyword,
Expand Down Expand Up @@ -2084,8 +2078,7 @@ class ASTContext : public RefCountedBase<ASTContext> {

/// C++11 deduced auto type.
QualType
getAutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent,
bool IsPack = false,
getAutoType(DeducedKind DK, QualType DeducedAsType, AutoTypeKeyword Keyword,
TemplateDecl *TypeConstraintConcept = nullptr,
ArrayRef<TemplateArgument> TypeConstraintArgs = {}) const;

Expand All @@ -2100,17 +2093,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType getUnconstrainedType(QualType T) const;

/// C++17 deduced class template specialization type.
QualType getDeducedTemplateSpecializationType(ElaboratedTypeKeyword Keyword,
TemplateName Template,
QualType DeducedType,
bool IsDependent) const;

private:
QualType getDeducedTemplateSpecializationTypeInternal(
ElaboratedTypeKeyword Keyword, TemplateName Template,
QualType DeducedType, bool IsDependent, QualType Canon) const;
QualType getDeducedTemplateSpecializationType(DeducedKind DK,
QualType DeducedAsType,
ElaboratedTypeKeyword Keyword,
TemplateName Template) const;

public:
/// Return the unique type for "size_t" (C99 7.17), defined in
/// <stddef.h>.
///
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/PropertiesBase.td
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def APValueKind : EnumPropertyType<"APValue::ValueKind">;
def ArraySizeModifier : EnumPropertyType<"ArraySizeModifier">;
def AttrKind : EnumPropertyType<"attr::Kind">;
def Attr : PropertyType<"const Attr *">;
def DeducedKind : EnumPropertyType;
def AutoTypeKeyword : EnumPropertyType;
def Bool : PropertyType<"bool">;
def BuiltinTypeKind : EnumPropertyType<"BuiltinType::Kind">;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/TextNodeDumper.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ class TextNodeDumper
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T);
void
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T);
void VisitDeducedType(const DeducedType *T);
void VisitAutoType(const AutoType *T);
void VisitDeducedTemplateSpecializationType(
const DeducedTemplateSpecializationType *T);
Expand Down
119 changes: 81 additions & 38 deletions clang/include/clang/AST/TypeBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -1794,6 +1794,33 @@ enum RefQualifierKind {
RQ_RValue
};

// The kind of type deduction represented by a DeducedType (ie AutoType).
enum class DeducedKind {
/// Not deduced yet. This is for example an 'auto' which was just parsed.
Undeduced,

/// The normal deduced case. For example, an 'auto' which has been deduced to
/// 'int' will be of this kind, with 'int' as the deduced-as type. This is the
/// only case where the node is sugar.
Deduced,

/// This is a special case where the initializer is dependent, so we can't
/// deduce a type yet. For example, 'auto x = V' where 'V' is a
/// value-dependent expression.
/// Formally we can't deduce an initializer which is dependent, because for
/// one reason it might be non-instantiable (ie it can contain a placeholder
/// dependent type such as DependentTy, which cannot be instantiated).
/// In general TreeTransform will turn these back to 'Undeduced' so we can try
/// to deduce them again.
DeducedAsDependent,

/// Same as above, but additionally this represents a case where the deduced
/// entity itself is a pack.
/// This currently only happens for a lambda init-capture pack, which always
/// uses AutoType.
DeducedAsPack,
};

/// Which keyword(s) were used to create an AutoType.
enum class AutoTypeKeyword {
/// auto
Expand Down Expand Up @@ -2108,11 +2135,25 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
unsigned AttrKind : 32 - NumTypeBits;
};

class DeducedTypeBitfields {
friend class DeducedType;

// One of the base classes uses the KeywordWrapper, so reserve those bits.
LLVM_PREFERRED_TYPE(KeywordWrapperBitfields)
unsigned : NumTypeWithKeywordBits;

/// The kind of deduction this type represents, ie 'undeduced' or otherwise.
LLVM_PREFERRED_TYPE(DeducedKind)
unsigned Kind : 2;
};

static constexpr int NumDeducedTypeBits = NumTypeBits + 2;

class AutoTypeBitfields {
friend class AutoType;

LLVM_PREFERRED_TYPE(TypeBitfields)
unsigned : NumTypeBits;
LLVM_PREFERRED_TYPE(DeducedTypeBitfields)
unsigned : NumDeducedTypeBits;

/// Was this placeholder type spelled as 'auto', 'decltype(auto)',
/// or '__auto_type'? AutoTypeKeyword value.
Expand Down Expand Up @@ -2320,6 +2361,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
ArrayTypeBitfields ArrayTypeBits;
ConstantArrayTypeBitfields ConstantArrayTypeBits;
AttributedTypeBitfields AttributedTypeBits;
DeducedTypeBitfields DeducedTypeBits;
AutoTypeBitfields AutoTypeBits;
TypeOfBitfields TypeOfBits;
TypedefBitfields TypedefBits;
Expand Down Expand Up @@ -7232,27 +7274,28 @@ class DeducedType : public Type {
QualType DeducedAsType;

protected:
DeducedType(TypeClass TC, QualType DeducedAsType,
TypeDependence ExtraDependence, QualType Canon)
: Type(TC, Canon,
ExtraDependence | (DeducedAsType.isNull()
? TypeDependence::None
: DeducedAsType->getDependence() &
~TypeDependence::VariablyModified)),
DeducedAsType(DeducedAsType) {}
DeducedType(TypeClass TC, DeducedKind DK, QualType DeducedAsTypeOrCanon);

static void Profile(llvm::FoldingSetNodeID &ID, DeducedKind DK,
QualType Deduced) {
ID.AddInteger(llvm::to_underlying(DK));
Deduced.Profile(ID);
}

public:
bool isSugared() const { return !DeducedAsType.isNull(); }
DeducedKind getDeducedKind() const {
return static_cast<DeducedKind>(DeducedTypeBits.Kind);
}

bool isSugared() const { return getDeducedKind() == DeducedKind::Deduced; }
QualType desugar() const {
return isSugared() ? DeducedAsType : QualType(this, 0);
}

/// Get the type deduced for this placeholder type, or null if it
/// has not been deduced.
QualType getDeducedType() const { return DeducedAsType; }
bool isDeduced() const {
return !DeducedAsType.isNull() || isDependentType();
}
bool isDeduced() const { return getDeducedKind() != DeducedKind::Undeduced; }

static bool classof(const Type *T) {
return T->getTypeClass() == Auto ||
Expand All @@ -7262,13 +7305,13 @@ class DeducedType : public Type {

/// Represents a C++11 auto or C++14 decltype(auto) type, possibly constrained
/// by a type-constraint.
class AutoType : public DeducedType {
class AutoType : public DeducedType, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these

TemplateDecl *TypeConstraintConcept;

AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword,
TypeDependence ExtraDependence, QualType Canon, TemplateDecl *CD,
AutoType(DeducedKind DK, QualType DeducedAsTypeOrCanon,
AutoTypeKeyword Keyword, TemplateDecl *TypeConstraintConcept,
ArrayRef<TemplateArgument> TypeConstraintArgs);

public:
Expand Down Expand Up @@ -7299,9 +7342,8 @@ class AutoType : public DeducedType {

void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context);
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
QualType Deduced, AutoTypeKeyword Keyword,
bool IsDependent, TemplateDecl *CD,
ArrayRef<TemplateArgument> Arguments);
DeducedKind DK, QualType Deduced, AutoTypeKeyword Keyword,
TemplateDecl *CD, ArrayRef<TemplateArgument> Arguments);

static bool classof(const Type *T) {
return T->getTypeClass() == Auto;
Expand All @@ -7316,34 +7358,35 @@ class DeducedTemplateSpecializationType : public KeywordWrapper<DeducedType>,
/// The name of the template whose arguments will be deduced.
TemplateName Template;

DeducedTemplateSpecializationType(ElaboratedTypeKeyword Keyword,
TemplateName Template,
QualType DeducedAsType,
bool IsDeducedAsDependent, QualType Canon)
: KeywordWrapper(Keyword, DeducedTemplateSpecialization, DeducedAsType,
toTypeDependence(Template.getDependence()) |
(IsDeducedAsDependent
? TypeDependence::DependentInstantiation
: TypeDependence::None),
Canon),
Template(Template) {}
DeducedTemplateSpecializationType(DeducedKind DK,
QualType DeducedAsTypeOrCanon,
ElaboratedTypeKeyword Keyword,
TemplateName Template)
: KeywordWrapper(Keyword, DeducedTemplateSpecialization, DK,
DeducedAsTypeOrCanon),
Template(Template) {
auto Dep = toTypeDependence(Template.getDependence());
// A deduced AutoType only syntactically depends on its template name.
if (DK == DeducedKind::Deduced)
Dep = toSyntacticDependence(Dep);
addDependence(Dep);
}

public:
/// Retrieve the name of the template that we are deducing.
TemplateName getTemplateName() const { return Template; }

void Profile(llvm::FoldingSetNodeID &ID) const {
Profile(ID, getKeyword(), getTemplateName(), getDeducedType(),
isDependentType());
Profile(ID, getDeducedKind(), getDeducedType(), getKeyword(),
getTemplateName());
}

static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword,
TemplateName Template, QualType Deduced,
bool IsDependent) {
static void Profile(llvm::FoldingSetNodeID &ID, DeducedKind DK,
QualType Deduced, ElaboratedTypeKeyword Keyword,
TemplateName Template) {
DeducedType::Profile(ID, DK, Deduced);
ID.AddInteger(llvm::to_underlying(Keyword));
Template.Profile(ID);
Deduced.Profile(ID);
ID.AddBoolean(IsDependent || Template.isDependent());
}

static bool classof(const Type *T) {
Expand Down
27 changes: 9 additions & 18 deletions clang/include/clang/AST/TypeProperties.td
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,9 @@ let Class = UnaryTransformType in {
}

let Class = AutoType in {
def : Property<"deducedKind", DeducedKind> {
let Read = [{ node->getDeducedKind() }];
}
def : Property<"deducedType", Optional<QualType>> {
let Read = [{ makeOptionalFromNullable(node->getDeducedType()) }];
}
Expand All @@ -526,18 +529,9 @@ let Class = AutoType in {
def : Property<"typeConstraintArguments", Array<TemplateArgument>> {
let Read = [{ node->getTypeConstraintArguments() }];
}
// FIXME: better enumerated value
// Only really required when the deduced type is null
def : Property<"dependence", UInt32> {
let Read = [{ !node->getDeducedType().isNull() ? 0 :
node->containsUnexpandedParameterPack() ? 2 :
node->isDependentType() ? 1 : 0 }];
}

def : Creator<[{
return ctx.getAutoType(makeNullableFromOptional(deducedType), keyword,
/*isDependentWithoutDeducedType*/ dependence > 0,
/*isPackWithoutDeducedType*/ dependence > 1,
return ctx.getAutoType(deducedKind, makeNullableFromOptional(deducedType), keyword,
makePointerFromOptional(typeConstraintConcept),
typeConstraintArguments);
}]>;
Expand All @@ -550,19 +544,16 @@ let Class = DeducedTemplateSpecializationType in {
def : Property<"templateName", Optional<TemplateName>> {
let Read = [{ makeOptionalFromNullable(node->getTemplateName()) }];
}
def : Property<"deducedKind", DeducedKind> {
let Read = [{ node->getDeducedKind() }];
}
def : Property<"deducedType", QualType> {
let Read = [{ node->getDeducedType() }];
}
// Only really required when the deduced type is null
def : Property<"dependent", Bool> {
let Read = [{ !node->getDeducedType().isNull()
? false : node->isDependentType() }];
}

def : Creator<[{
return ctx.getDeducedTemplateSpecializationType(keyword,
makeNullableFromOptional(templateName),
deducedType, dependent);
return ctx.getDeducedTemplateSpecializationType(deducedKind, deducedType, keyword,
makeNullableFromOptional(templateName));
}]>;
}

Expand Down
Loading