Fix clang assertion when compiling the devel/onetbb port

Merge commit 740a164de from llvm git (by Richard Smith):

  PR46377: Fix dependence calculation for function types and typedef
  types.

  We previously did not treat a function type as dependent if it had a
  parameter pack with a non-dependent type -- such a function type depends
  on the arity of the pack so is dependent even though none of the
  parameter types is dependent. In order to properly handle this, we now
  treat pack expansion types as always being dependent types (depending on
  at least the pack arity), and always canonically being pack expansion
  types, even in the unusual case when the pattern is not a dependent
  type. This does mean that we can have canonical types that are pack
  expansions that contain no unexpanded packs, which is unfortunate but
  not inaccurate.

  We also previously did not treat a typedef type as
  instantiation-dependent if its canonical type was not
  instantiation-dependent. That's wrong because instantiation-dependence
  is a property of the type sugar, not of the type; an
  instantiation-dependent type can have a non-instantiation-dependent
  canonical type.

Merge commit 9cf98d26e from llvm git (by Richard Smith):

  PR46637: Fix handling of placeholder types in trailing-return-types.

  Only permit a placeholder type in a trailing-return-type if it would
  also have been permitted in the decl-specifier sequence of a
  corresponding declaration with no trailing-return-type. The standard
  doesn't actually say this, but this is the only thing that makes sense.

  Also fix handling of an 'auto' in a trailing-return-type in a parameter
  of a generic lambda. We used to crash if we saw such a thing.

Merge commit 234f51a65 from llvm git (by Richard Smith):

  Don't crash if we deserialize a pack expansion type whose pattern
  contains no packs.

  Fixes a regression from 740a164dec483225cbd02ab6c82199e2747ffacb.

PR:		252892
Reported by:	thierry
MFC after:	3 days
This commit is contained in:
Dimitry Andric 2021-01-26 14:07:47 +01:00
parent cfd6422a52
commit e63539f305
16 changed files with 120 additions and 98 deletions

View File

@ -1475,8 +1475,16 @@ class ASTContext : public RefCountedBase<ASTContext> {
void getInjectedTemplateArgs(const TemplateParameterList *Params,
SmallVectorImpl<TemplateArgument> &Args);
/// Form a pack expansion type with the given pattern.
/// \param NumExpansions The number of expansions for the pack, if known.
/// \param ExpectPackInType If \c false, we should not expect \p Pattern to
/// contain an unexpanded pack. This only makes sense if the pack
/// expansion is used in a context where the arity is inferred from
/// elsewhere, such as if the pattern contains a placeholder type or
/// if this is the canonical type of another pack expansion type.
QualType getPackExpansionType(QualType Pattern,
Optional<unsigned> NumExpansions);
Optional<unsigned> NumExpansions,
bool ExpectPackInType = true);
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
ObjCInterfaceDecl *PrevDecl = nullptr) const;

View File

@ -4375,11 +4375,7 @@ class TypedefType : public Type {
protected:
friend class ASTContext; // ASTContext creates these.
TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can)
: Type(tc, can, can->getDependence() & ~TypeDependence::UnexpandedPack),
Decl(const_cast<TypedefNameDecl *>(D)) {
assert(!isa<TypedefType>(can) && "Invalid canonical type");
}
TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can);
public:
TypedefNameDecl *getDecl() const { return Decl; }
@ -5616,7 +5612,8 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
PackExpansionType(QualType Pattern, QualType Canon,
Optional<unsigned> NumExpansions)
: Type(PackExpansion, Canon,
(Pattern->getDependence() | TypeDependence::Instantiation) &
(Pattern->getDependence() | TypeDependence::Dependent |
TypeDependence::Instantiation) &
~TypeDependence::UnexpandedPack),
Pattern(Pattern) {
PackExpansionTypeBits.NumExpansions =
@ -5637,8 +5634,8 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
return None;
}
bool isSugared() const { return !Pattern->isDependentType(); }
QualType desugar() const { return isSugared() ? Pattern : QualType(this, 0); }
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getPattern(), getNumExpansions());

View File

@ -722,7 +722,8 @@ let Class = PackExpansionType in {
}
def : Creator<[{
return ctx.getPackExpansionType(pattern, numExpansions);
return ctx.getPackExpansionType(pattern, numExpansions,
/*ExpectPackInType*/false);
}]>;
}

View File

@ -100,7 +100,7 @@ def DeducedTemplateSpecializationType : TypeNode<DeducedType>;
def InjectedClassNameType : TypeNode<Type>, AlwaysDependent, LeafType;
def DependentNameType : TypeNode<Type>, AlwaysDependent;
def DependentTemplateSpecializationType : TypeNode<Type>, AlwaysDependent;
def PackExpansionType : TypeNode<Type>, NeverCanonicalUnlessDependent;
def PackExpansionType : TypeNode<Type>, AlwaysDependent;
def ObjCTypeParamType : TypeNode<Type>, NeverCanonical;
def ObjCObjectType : TypeNode<Type>;
def ObjCInterfaceType : TypeNode<ObjCObjectType>, LeafType;

View File

@ -2435,6 +2435,15 @@ class Declarator {
return true;
return false;
}
/// Get the trailing return type appearing (at any level) within this
/// declarator.
ParsedType getTrailingReturnType() const {
for (const auto &Chunk : type_objects())
if (Chunk.Kind == DeclaratorChunk::Function &&
Chunk.Fun.hasTrailingReturnType())
return Chunk.Fun.getTrailingReturnType();
return ParsedType();
}
/// \brief Sets a trailing requires clause for this declarator.
void setTrailingRequiresClause(Expr *TRC) {

View File

@ -8172,6 +8172,8 @@ class Sema final {
/// Completely replace the \c auto in \p TypeWithAuto by
/// \p Replacement. This does not retain any \c auto type sugar.
QualType ReplaceAutoType(QualType TypeWithAuto, QualType Replacement);
TypeSourceInfo *ReplaceAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
QualType Replacement);
/// Result type of DeduceAutoType.
enum DeduceAutoResult {

View File

@ -4868,37 +4868,27 @@ ASTContext::getInjectedTemplateArgs(const TemplateParameterList *Params,
}
QualType ASTContext::getPackExpansionType(QualType Pattern,
Optional<unsigned> NumExpansions) {
Optional<unsigned> NumExpansions,
bool ExpectPackInType) {
assert((!ExpectPackInType || Pattern->containsUnexpandedParameterPack()) &&
"Pack expansions must expand one or more parameter packs");
llvm::FoldingSetNodeID ID;
PackExpansionType::Profile(ID, Pattern, NumExpansions);
// A deduced type can deduce to a pack, eg
// auto ...x = some_pack;
// That declaration isn't (yet) valid, but is created as part of building an
// init-capture pack:
// [...x = some_pack] {}
assert((Pattern->containsUnexpandedParameterPack() ||
Pattern->getContainedDeducedType()) &&
"Pack expansions must expand one or more parameter packs");
void *InsertPos = nullptr;
PackExpansionType *T
= PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos);
PackExpansionType *T = PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos);
if (T)
return QualType(T, 0);
QualType Canon;
if (!Pattern.isCanonical()) {
Canon = getCanonicalType(Pattern);
// The canonical type might not contain an unexpanded parameter pack, if it
// contains an alias template specialization which ignores one of its
// parameters.
if (Canon->containsUnexpandedParameterPack()) {
Canon = getPackExpansionType(Canon, NumExpansions);
Canon = getPackExpansionType(getCanonicalType(Pattern), NumExpansions,
/*ExpectPackInType=*/false);
// Find the insert position again, in case we inserted an element into
// PackExpansionTypes and invalidated our insert position.
PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos);
}
// Find the insert position again, in case we inserted an element into
// PackExpansionTypes and invalidated our insert position.
PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos);
}
T = new (*this, TypeAlignment)

View File

@ -1498,7 +1498,8 @@ ASTNodeImporter::VisitPackExpansionType(const PackExpansionType *T) {
return ToPatternOrErr.takeError();
return Importer.getToContext().getPackExpansionType(*ToPatternOrErr,
T->getNumExpansions());
T->getNumExpansions(),
/*ExpactPack=*/false);
}
ExpectedType ASTNodeImporter::VisitDependentTemplateSpecializationType(

View File

@ -1187,9 +1187,6 @@ struct SimpleTransformVisitor : public TypeVisitor<Derived, QualType> {
T->getTypeConstraintArguments());
}
// FIXME: Non-trivial to implement, but important for C++
SUGARED_TYPE_CLASS(PackExpansion)
QualType VisitObjCObjectType(const ObjCObjectType *T) {
QualType baseType = recurse(T->getBaseType());
if (baseType.isNull())
@ -3317,6 +3314,12 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID,
getExtProtoInfo(), Ctx, isCanonicalUnqualified());
}
TypedefType::TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can)
: Type(tc, can, D->getUnderlyingType()->getDependence()),
Decl(const_cast<TypedefNameDecl *>(D)) {
assert(!isa<TypedefType>(can) && "Invalid canonical type");
}
QualType TypedefType::desugar() const {
return getDecl()->getUnderlyingType();
}

View File

@ -3268,7 +3268,6 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
case Type::TypeOf:
case Type::Decltype:
case Type::UnaryTransform:
case Type::PackExpansion:
break;
}

View File

@ -2075,7 +2075,6 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
case Type::UnaryTransform:
case Type::Attributed:
case Type::SubstTemplateTypeParm:
case Type::PackExpansion:
case Type::MacroQualified:
// Keep walking after single level desugaring.
type = type.getSingleStepDesugaredType(getContext());

View File

@ -4345,7 +4345,6 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T,
case Type::UnaryTransform:
case Type::Attributed:
case Type::SubstTemplateTypeParm:
case Type::PackExpansion:
case Type::MacroQualified:
// Keep walking after single level desugaring.
T = T.getSingleStepDesugaredType(Context);

View File

@ -803,7 +803,8 @@ QualType Sema::buildLambdaInitCaptureInitialization(
Diag(EllipsisLoc, getLangOpts().CPlusPlus20
? diag::warn_cxx17_compat_init_capture_pack
: diag::ext_init_capture_pack);
DeductType = Context.getPackExpansionType(DeductType, NumExpansions);
DeductType = Context.getPackExpansionType(DeductType, NumExpansions,
/*ExpectPackInType=*/false);
TLB.push<PackExpansionTypeLoc>(DeductType).setEllipsisLoc(EllipsisLoc);
} else {
// Just ignore the ellipsis for now and form a non-pack variable. We'll

View File

@ -4894,6 +4894,13 @@ QualType Sema::ReplaceAutoType(QualType TypeWithAuto,
.TransformType(TypeWithAuto);
}
TypeSourceInfo *Sema::ReplaceAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
QualType TypeToReplaceAuto) {
return SubstituteDeducedTypeTransform(*this, TypeToReplaceAuto,
/*UseTypeSugar*/ false)
.TransformType(TypeWithAuto);
}
void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
if (isa<InitListExpr>(Init))
Diag(VDecl->getLocation(),

View File

@ -614,7 +614,8 @@ QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange PatternRange,
return QualType();
}
return Context.getPackExpansionType(Pattern, NumExpansions);
return Context.getPackExpansionType(Pattern, NumExpansions,
/*ExpectPackInType=*/false);
}
ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) {

View File

@ -3101,24 +3101,10 @@ static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy,
D.getDeclSpec().getUnalignedSpecLoc());
}
static void CopyTypeConstraintFromAutoType(Sema &SemaRef, const AutoType *Auto,
AutoTypeLoc AutoLoc,
TemplateTypeParmDecl *TP,
SourceLocation EllipsisLoc) {
TemplateArgumentListInfo TAL(AutoLoc.getLAngleLoc(), AutoLoc.getRAngleLoc());
for (unsigned Idx = 0; Idx < AutoLoc.getNumArgs(); ++Idx)
TAL.addArgument(AutoLoc.getArgLoc(Idx));
SemaRef.AttachTypeConstraint(
AutoLoc.getNestedNameSpecifierLoc(), AutoLoc.getConceptNameInfo(),
AutoLoc.getNamedConcept(),
AutoLoc.hasExplicitTemplateArgs() ? &TAL : nullptr, TP, EllipsisLoc);
}
static QualType InventTemplateParameter(
TypeProcessingState &state, QualType T, TypeSourceInfo *TSI, AutoType *Auto,
InventedTemplateParameterInfo &Info) {
static std::pair<QualType, TypeSourceInfo *>
InventTemplateParameter(TypeProcessingState &state, QualType T,
TypeSourceInfo *TrailingTSI, AutoType *Auto,
InventedTemplateParameterInfo &Info) {
Sema &S = state.getSema();
Declarator &D = state.getDeclarator();
@ -3143,13 +3129,25 @@ static QualType InventTemplateParameter(
IsParameterPack, /*HasTypeConstraint=*/Auto->isConstrained());
InventedTemplateParam->setImplicit();
Info.TemplateParams.push_back(InventedTemplateParam);
// Attach type constraints
// Attach type constraints to the new parameter.
if (Auto->isConstrained()) {
if (TSI) {
CopyTypeConstraintFromAutoType(
S, Auto, TSI->getTypeLoc().getContainedAutoTypeLoc(),
InventedTemplateParam, D.getEllipsisLoc());
if (TrailingTSI) {
// The 'auto' appears in a trailing return type we've already built;
// extract its type constraints to attach to the template parameter.
AutoTypeLoc AutoLoc = TrailingTSI->getTypeLoc().getContainedAutoTypeLoc();
TemplateArgumentListInfo TAL(AutoLoc.getLAngleLoc(), AutoLoc.getRAngleLoc());
for (unsigned Idx = 0; Idx < AutoLoc.getNumArgs(); ++Idx)
TAL.addArgument(AutoLoc.getArgLoc(Idx));
S.AttachTypeConstraint(AutoLoc.getNestedNameSpecifierLoc(),
AutoLoc.getConceptNameInfo(),
AutoLoc.getNamedConcept(),
AutoLoc.hasExplicitTemplateArgs() ? &TAL : nullptr,
InventedTemplateParam, D.getEllipsisLoc());
} else {
// The 'auto' appears in the decl-specifiers; we've not finished forming
// TypeSourceInfo for it yet.
TemplateIdAnnotation *TemplateId = D.getDeclSpec().getRepAsTemplateId();
TemplateArgumentListInfo TemplateArgsInfo;
if (TemplateId->LAngleLoc.isValid()) {
@ -3167,15 +3165,16 @@ static QualType InventTemplateParameter(
}
}
// If TSI is nullptr, this is a constrained declspec auto and the type
// constraint will be attached later in TypeSpecLocFiller
// Replace the 'auto' in the function parameter with this invented
// template type parameter.
// FIXME: Retain some type sugar to indicate that this was written
// as 'auto'?
return state.ReplaceAutoType(
T, QualType(InventedTemplateParam->getTypeForDecl(), 0));
QualType Replacement(InventedTemplateParam->getTypeForDecl(), 0);
QualType NewT = state.ReplaceAutoType(T, Replacement);
TypeSourceInfo *NewTSI =
TrailingTSI ? S.ReplaceAutoTypeSourceInfo(TrailingTSI, Replacement)
: nullptr;
return {NewT, NewTSI};
}
static TypeSourceInfo *
@ -3234,8 +3233,19 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
if (!D.getAttributes().empty())
distributeTypeAttrsFromDeclarator(state, T);
// Find the deduced type in this type. Look in the trailing return type if we
// have one, otherwise in the DeclSpec type.
// FIXME: The standard wording doesn't currently describe this.
DeducedType *Deduced = T->getContainedDeducedType();
bool DeducedIsTrailingReturnType = false;
if (Deduced && isa<AutoType>(Deduced) && D.hasTrailingReturnType()) {
QualType T = SemaRef.GetTypeFromParser(D.getTrailingReturnType());
Deduced = T.isNull() ? nullptr : T->getContainedDeducedType();
DeducedIsTrailingReturnType = true;
}
// C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context.
if (DeducedType *Deduced = T->getContainedDeducedType()) {
if (Deduced) {
AutoType *Auto = dyn_cast<AutoType>(Deduced);
int Error = -1;
@ -3269,10 +3279,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
} else if (!SemaRef.getCurScope()->isFunctionDeclarationScope()) {
Error = 21;
break;
} else if (D.hasTrailingReturnType()) {
// This might be OK, but we'll need to convert the trailing return
// type later.
break;
}
Info = &SemaRef.InventedParameterInfos.back();
@ -3286,7 +3292,12 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
Info = SemaRef.getCurLambda();
assert(Info && "No LambdaScopeInfo on the stack!");
}
T = InventTemplateParameter(state, T, nullptr, Auto, *Info);
// We'll deal with inventing template parameters for 'auto' in trailing
// return types when we pick up the trailing return type when processing
// the function chunk.
if (!DeducedIsTrailingReturnType)
T = InventTemplateParameter(state, T, nullptr, Auto, *Info).first;
break;
}
case DeclaratorContext::MemberContext: {
@ -3384,20 +3395,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
(!SemaRef.getLangOpts().CPlusPlus11 || !IsCXXAutoType))
Error = 13;
bool HaveTrailing = false;
// C++11 [dcl.spec.auto]p2: 'auto' is always fine if the declarator
// contains a trailing return type. That is only legal at the outermost
// level. Check all declarator chunks (outermost first) anyway, to give
// better diagnostics.
// We don't support '__auto_type' with trailing return types.
// FIXME: Should we only do this for 'auto' and not 'decltype(auto)'?
if (SemaRef.getLangOpts().CPlusPlus11 && IsCXXAutoType &&
D.hasTrailingReturnType()) {
HaveTrailing = true;
Error = -1;
}
SourceRange AutoRange = D.getDeclSpec().getTypeSpecTypeLoc();
if (D.getName().getKind() == UnqualifiedIdKind::IK_ConversionFunctionId)
AutoRange = D.getName().getSourceRange();
@ -3427,8 +3424,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
T = SemaRef.Context.IntTy;
D.setInvalidType(true);
} else if (Auto && !HaveTrailing &&
D.getContext() != DeclaratorContext::LambdaExprContext) {
} else if (Auto && D.getContext() != DeclaratorContext::LambdaExprContext) {
// If there was a trailing return type, we already got
// warn_cxx98_compat_trailing_return_type in the parser.
SemaRef.Diag(AutoRange.getBegin(),
@ -4881,12 +4877,21 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// An error occurred parsing the trailing return type.
T = Context.IntTy;
D.setInvalidType(true);
} else if (S.getLangOpts().CPlusPlus20)
// Handle cases like: `auto f() -> auto` or `auto f() -> C auto`.
if (AutoType *Auto = T->getContainedAutoType())
if (S.getCurScope()->isFunctionDeclarationScope())
T = InventTemplateParameter(state, T, TInfo, Auto,
S.InventedParameterInfos.back());
} else if (AutoType *Auto = T->getContainedAutoType()) {
// If the trailing return type contains an `auto`, we may need to
// invent a template parameter for it, for cases like
// `auto f() -> C auto` or `[](auto (*p) -> auto) {}`.
InventedTemplateParameterInfo *InventedParamInfo = nullptr;
if (D.getContext() == DeclaratorContext::PrototypeContext)
InventedParamInfo = &S.InventedParameterInfos.back();
else if (D.getContext() ==
DeclaratorContext::LambdaExprParameterContext)
InventedParamInfo = S.getCurLambda();
if (InventedParamInfo) {
std::tie(T, TInfo) = InventTemplateParameter(
state, T, TInfo, Auto, *InventedParamInfo);
}
}
} else {
// This function type is not the type of the entity being declared,
// so checking the 'auto' is not the responsibility of this chunk.
@ -5518,7 +5523,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
<< T << D.getSourceRange();
D.setEllipsisLoc(SourceLocation());
} else {
T = Context.getPackExpansionType(T, None);
T = Context.getPackExpansionType(T, None, /*ExpectPackInType=*/false);
}
break;
case DeclaratorContext::TemplateParamContext: