Skip to content

Commit 740a164

Browse files
committed
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.
1 parent b46176b commit 740a164

File tree

12 files changed

+62
-41
lines changed

12 files changed

+62
-41
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1459,8 +1459,16 @@ class ASTContext : public RefCountedBase<ASTContext> {
14591459
void getInjectedTemplateArgs(const TemplateParameterList *Params,
14601460
SmallVectorImpl<TemplateArgument> &Args);
14611461

1462+
/// Form a pack expansion type with the given pattern.
1463+
/// \param NumExpansions The number of expansions for the pack, if known.
1464+
/// \param ExpectPackInType If \c false, we should not expect \p Pattern to
1465+
/// contain an unexpanded pack. This only makes sense if the pack
1466+
/// expansion is used in a context where the arity is inferred from
1467+
/// elsewhere, such as if the pattern contains a placeholder type or
1468+
/// if this is the canonical type of another pack expansion type.
14621469
QualType getPackExpansionType(QualType Pattern,
1463-
Optional<unsigned> NumExpansions);
1470+
Optional<unsigned> NumExpansions,
1471+
bool ExpectPackInType = true);
14641472

14651473
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
14661474
ObjCInterfaceDecl *PrevDecl = nullptr) const;

clang/include/clang/AST/Type.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4383,11 +4383,7 @@ class TypedefType : public Type {
43834383
protected:
43844384
friend class ASTContext; // ASTContext creates these.
43854385

4386-
TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can)
4387-
: Type(tc, can, can->getDependence() & ~TypeDependence::UnexpandedPack),
4388-
Decl(const_cast<TypedefNameDecl *>(D)) {
4389-
assert(!isa<TypedefType>(can) && "Invalid canonical type");
4390-
}
4386+
TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can);
43914387

43924388
public:
43934389
TypedefNameDecl *getDecl() const { return Decl; }
@@ -5624,7 +5620,8 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
56245620
PackExpansionType(QualType Pattern, QualType Canon,
56255621
Optional<unsigned> NumExpansions)
56265622
: Type(PackExpansion, Canon,
5627-
(Pattern->getDependence() | TypeDependence::Instantiation) &
5623+
(Pattern->getDependence() | TypeDependence::Dependent |
5624+
TypeDependence::Instantiation) &
56285625
~TypeDependence::UnexpandedPack),
56295626
Pattern(Pattern) {
56305627
PackExpansionTypeBits.NumExpansions =
@@ -5645,8 +5642,8 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
56455642
return None;
56465643
}
56475644

5648-
bool isSugared() const { return !Pattern->isDependentType(); }
5649-
QualType desugar() const { return isSugared() ? Pattern : QualType(this, 0); }
5645+
bool isSugared() const { return false; }
5646+
QualType desugar() const { return QualType(this, 0); }
56505647

56515648
void Profile(llvm::FoldingSetNodeID &ID) {
56525649
Profile(ID, getPattern(), getNumExpansions());

clang/include/clang/Basic/TypeNodes.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def DeducedTemplateSpecializationType : TypeNode<DeducedType>;
100100
def InjectedClassNameType : TypeNode<Type>, AlwaysDependent, LeafType;
101101
def DependentNameType : TypeNode<Type>, AlwaysDependent;
102102
def DependentTemplateSpecializationType : TypeNode<Type>, AlwaysDependent;
103-
def PackExpansionType : TypeNode<Type>, NeverCanonicalUnlessDependent;
103+
def PackExpansionType : TypeNode<Type>, AlwaysDependent;
104104
def ObjCTypeParamType : TypeNode<Type>, NeverCanonical;
105105
def ObjCObjectType : TypeNode<Type>;
106106
def ObjCInterfaceType : TypeNode<ObjCObjectType>, LeafType;

clang/lib/AST/ASTContext.cpp

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4817,37 +4817,27 @@ ASTContext::getInjectedTemplateArgs(const TemplateParameterList *Params,
48174817
}
48184818

48194819
QualType ASTContext::getPackExpansionType(QualType Pattern,
4820-
Optional<unsigned> NumExpansions) {
4820+
Optional<unsigned> NumExpansions,
4821+
bool ExpectPackInType) {
4822+
assert((!ExpectPackInType || Pattern->containsUnexpandedParameterPack()) &&
4823+
"Pack expansions must expand one or more parameter packs");
4824+
48214825
llvm::FoldingSetNodeID ID;
48224826
PackExpansionType::Profile(ID, Pattern, NumExpansions);
48234827

4824-
// A deduced type can deduce to a pack, eg
4825-
// auto ...x = some_pack;
4826-
// That declaration isn't (yet) valid, but is created as part of building an
4827-
// init-capture pack:
4828-
// [...x = some_pack] {}
4829-
assert((Pattern->containsUnexpandedParameterPack() ||
4830-
Pattern->getContainedDeducedType()) &&
4831-
"Pack expansions must expand one or more parameter packs");
48324828
void *InsertPos = nullptr;
4833-
PackExpansionType *T
4834-
= PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos);
4829+
PackExpansionType *T = PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos);
48354830
if (T)
48364831
return QualType(T, 0);
48374832

48384833
QualType Canon;
48394834
if (!Pattern.isCanonical()) {
4840-
Canon = getCanonicalType(Pattern);
4841-
// The canonical type might not contain an unexpanded parameter pack, if it
4842-
// contains an alias template specialization which ignores one of its
4843-
// parameters.
4844-
if (Canon->containsUnexpandedParameterPack()) {
4845-
Canon = getPackExpansionType(Canon, NumExpansions);
4846-
4847-
// Find the insert position again, in case we inserted an element into
4848-
// PackExpansionTypes and invalidated our insert position.
4849-
PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos);
4850-
}
4835+
Canon = getPackExpansionType(getCanonicalType(Pattern), NumExpansions,
4836+
/*ExpectPackInType=*/false);
4837+
4838+
// Find the insert position again, in case we inserted an element into
4839+
// PackExpansionTypes and invalidated our insert position.
4840+
PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos);
48514841
}
48524842

48534843
T = new (*this, TypeAlignment)

clang/lib/AST/Type.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,9 +1187,6 @@ struct SimpleTransformVisitor : public TypeVisitor<Derived, QualType> {
11871187
T->getTypeConstraintArguments());
11881188
}
11891189

1190-
// FIXME: Non-trivial to implement, but important for C++
1191-
SUGARED_TYPE_CLASS(PackExpansion)
1192-
11931190
QualType VisitObjCObjectType(const ObjCObjectType *T) {
11941191
QualType baseType = recurse(T->getBaseType());
11951192
if (baseType.isNull())
@@ -3348,6 +3345,12 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID,
33483345
getExtProtoInfo(), Ctx, isCanonicalUnqualified());
33493346
}
33503347

3348+
TypedefType::TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can)
3349+
: Type(tc, can, D->getUnderlyingType()->getDependence()),
3350+
Decl(const_cast<TypedefNameDecl *>(D)) {
3351+
assert(!isa<TypedefType>(can) && "Invalid canonical type");
3352+
}
3353+
33513354
QualType TypedefType::desugar() const {
33523355
return getDecl()->getUnderlyingType();
33533356
}

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3252,7 +3252,6 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
32523252
case Type::TypeOf:
32533253
case Type::Decltype:
32543254
case Type::UnaryTransform:
3255-
case Type::PackExpansion:
32563255
break;
32573256
}
32583257

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2075,7 +2075,6 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
20752075
case Type::UnaryTransform:
20762076
case Type::Attributed:
20772077
case Type::SubstTemplateTypeParm:
2078-
case Type::PackExpansion:
20792078
case Type::MacroQualified:
20802079
// Keep walking after single level desugaring.
20812080
type = type.getSingleStepDesugaredType(getContext());

clang/lib/Sema/SemaExpr.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4345,7 +4345,6 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T,
43454345
case Type::UnaryTransform:
43464346
case Type::Attributed:
43474347
case Type::SubstTemplateTypeParm:
4348-
case Type::PackExpansion:
43494348
case Type::MacroQualified:
43504349
// Keep walking after single level desugaring.
43514350
T = T.getSingleStepDesugaredType(Context);

clang/lib/Sema/SemaLambda.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,8 @@ QualType Sema::buildLambdaInitCaptureInitialization(
803803
Diag(EllipsisLoc, getLangOpts().CPlusPlus20
804804
? diag::warn_cxx17_compat_init_capture_pack
805805
: diag::ext_init_capture_pack);
806-
DeductType = Context.getPackExpansionType(DeductType, NumExpansions);
806+
DeductType = Context.getPackExpansionType(DeductType, NumExpansions,
807+
/*ExpectPackInType=*/false);
807808
TLB.push<PackExpansionTypeLoc>(DeductType).setEllipsisLoc(EllipsisLoc);
808809
} else {
809810
// Just ignore the ellipsis for now and form a non-pack variable. We'll

clang/lib/Sema/SemaTemplateVariadic.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,8 @@ QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange PatternRange,
614614
return QualType();
615615
}
616616

617-
return Context.getPackExpansionType(Pattern, NumExpansions);
617+
return Context.getPackExpansionType(Pattern, NumExpansions,
618+
/*ExpectPackInType=*/false);
618619
}
619620

620621
ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) {

clang/lib/Sema/SemaType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5516,7 +5516,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
55165516
<< T << D.getSourceRange();
55175517
D.setEllipsisLoc(SourceLocation());
55185518
} else {
5519-
T = Context.getPackExpansionType(T, None);
5519+
T = Context.getPackExpansionType(T, None, /*ExpectPackInType=*/false);
55205520
}
55215521
break;
55225522
case DeclaratorContext::TemplateParamContext:
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %clang_cc1 -std=c++20 -verify %s
2+
3+
namespace PR46377 {
4+
template<typename> using IntPtr = int*;
5+
template<typename ...T> auto non_dependent_typedef() {
6+
typedef int(*P)(IntPtr<T>...);
7+
return P();
8+
}
9+
template<typename ...T> auto non_dependent_alias() {
10+
using P = int(*)(IntPtr<T>...);
11+
return P();
12+
}
13+
template<typename ...T> auto non_dependent_via_sizeof() {
14+
using P = int(*)(int(...pack)[sizeof(sizeof(T))]); // expected-error {{invalid application of 'sizeof'}}
15+
return P();
16+
}
17+
18+
using a = int (*)(int*, int*);
19+
using a = decltype(non_dependent_typedef<void, void>());
20+
using a = decltype(non_dependent_alias<void, void>());
21+
using a = decltype(non_dependent_via_sizeof<float, float>());
22+
23+
using b = decltype(non_dependent_via_sizeof<float, void>()); // expected-note {{instantiation of}}
24+
}

0 commit comments

Comments
 (0)