forked from OSchip/llvm-project
[clang] AST: SubstTemplateTypeParmType support for non-canonical underlying type
This change allows us to represent in the AST some specific circumstances where we substitute a template parameter type which is part of the underlying type of a previous substitution. This presently happens in some circumstances dealing with substitution of defaulted parameters of template template parameters, and in some other cases during concepts substitution. The main motivation for this change is for the future use in the implementation of template specialization resugaring, as this will allow us to represent a substitution with sugared types. Signed-off-by: Matheus Izvekov <mizvekov@gmail.com> Differential Revision: https://reviews.llvm.org/D132816
This commit is contained in:
parent
54d81e49e3
commit
ef4bbfe338
|
@ -1798,6 +1798,8 @@ protected:
|
|||
|
||||
unsigned : NumTypeBits;
|
||||
|
||||
unsigned HasNonCanonicalUnderlyingType : 1;
|
||||
|
||||
/// Represents the index within a pack if this represents a substitution
|
||||
/// from a pack expansion. This index starts at the end of the pack and
|
||||
/// increments towards the beginning.
|
||||
|
@ -4985,8 +4987,12 @@ public:
|
|||
/// been replaced with these. They are used solely to record that a
|
||||
/// type was originally written as a template type parameter;
|
||||
/// therefore they are never canonical.
|
||||
class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode {
|
||||
class SubstTemplateTypeParmType final
|
||||
: public Type,
|
||||
public llvm::FoldingSetNode,
|
||||
private llvm::TrailingObjects<SubstTemplateTypeParmType, QualType> {
|
||||
friend class ASTContext;
|
||||
friend class llvm::TrailingObjects<SubstTemplateTypeParmType, QualType>;
|
||||
|
||||
// The original type parameter.
|
||||
const TemplateTypeParmType *Replaced;
|
||||
|
@ -5003,7 +5009,9 @@ public:
|
|||
/// Gets the type that was substituted for the template
|
||||
/// parameter.
|
||||
QualType getReplacementType() const {
|
||||
return getCanonicalTypeInternal();
|
||||
return SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType
|
||||
? *getTrailingObjects<QualType>()
|
||||
: getCanonicalTypeInternal();
|
||||
}
|
||||
|
||||
Optional<unsigned> getPackIndex() const {
|
||||
|
@ -5023,7 +5031,7 @@ public:
|
|||
const TemplateTypeParmType *Replaced,
|
||||
QualType Replacement, Optional<unsigned> PackIndex) {
|
||||
ID.AddPointer(Replaced);
|
||||
ID.AddPointer(Replacement.getAsOpaquePtr());
|
||||
Replacement.Profile(ID);
|
||||
ID.AddInteger(PackIndex ? *PackIndex - 1 : 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -739,10 +739,9 @@ let Class = SubstTemplateTypeParmType in {
|
|||
}
|
||||
|
||||
def : Creator<[{
|
||||
// The call to getCanonicalType here existed in ASTReader.cpp, too.
|
||||
return ctx.getSubstTemplateTypeParmType(
|
||||
cast<TemplateTypeParmType>(replacedParameter),
|
||||
ctx.getCanonicalType(replacementType), PackIndex);
|
||||
replacementType, PackIndex);
|
||||
}]>;
|
||||
}
|
||||
|
||||
|
|
|
@ -4764,9 +4764,6 @@ QualType
|
|||
ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm,
|
||||
QualType Replacement,
|
||||
Optional<unsigned> PackIndex) const {
|
||||
assert(Replacement.isCanonical()
|
||||
&& "replacement types must always be canonical");
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
SubstTemplateTypeParmType::Profile(ID, Parm, Replacement, PackIndex);
|
||||
void *InsertPos = nullptr;
|
||||
|
@ -4774,8 +4771,11 @@ ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm,
|
|||
= SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
|
||||
if (!SubstParm) {
|
||||
SubstParm = new (*this, TypeAlignment)
|
||||
SubstTemplateTypeParmType(Parm, Replacement, PackIndex);
|
||||
void *Mem = Allocate(SubstTemplateTypeParmType::totalSizeToAlloc<QualType>(
|
||||
!Replacement.isCanonical()),
|
||||
TypeAlignment);
|
||||
SubstParm =
|
||||
new (Mem) SubstTemplateTypeParmType(Parm, Replacement, PackIndex);
|
||||
Types.push_back(SubstParm);
|
||||
SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos);
|
||||
}
|
||||
|
|
|
@ -1530,8 +1530,7 @@ ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType(
|
|||
return ToReplacementTypeOrErr.takeError();
|
||||
|
||||
return Importer.getToContext().getSubstTemplateTypeParmType(
|
||||
*ReplacedOrErr, ToReplacementTypeOrErr->getCanonicalType(),
|
||||
T->getPackIndex());
|
||||
*ReplacedOrErr, *ToReplacementTypeOrErr, T->getPackIndex());
|
||||
}
|
||||
|
||||
ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType(
|
||||
|
|
|
@ -3650,10 +3650,16 @@ IdentifierInfo *TemplateTypeParmType::getIdentifier() const {
|
|||
}
|
||||
|
||||
SubstTemplateTypeParmType::SubstTemplateTypeParmType(
|
||||
const TemplateTypeParmType *Param, QualType Canon,
|
||||
const TemplateTypeParmType *Param, QualType Replacement,
|
||||
Optional<unsigned> PackIndex)
|
||||
: Type(SubstTemplateTypeParm, Canon, Canon->getDependence()),
|
||||
: Type(SubstTemplateTypeParm, Replacement.getCanonicalType(),
|
||||
Replacement->getDependence()),
|
||||
Replaced(Param) {
|
||||
SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType =
|
||||
Replacement != getCanonicalTypeInternal();
|
||||
if (SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType)
|
||||
*getTrailingObjects<QualType>() = Replacement;
|
||||
|
||||
SubstTemplateTypeParmTypeBits.PackIndex = PackIndex ? *PackIndex + 1 : 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -3513,8 +3513,7 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
|
|||
0, IndexReplaced, false,
|
||||
cast<TemplateTypeParmDecl>(TPL->getParam(IndexReplaced)));
|
||||
return SemaRef.Context.getSubstTemplateTypeParmType(
|
||||
cast<TemplateTypeParmType>(TTP), Replacement.getCanonicalType(),
|
||||
PackIndexReplaced);
|
||||
cast<TemplateTypeParmType>(TTP), Replacement, PackIndexReplaced);
|
||||
};
|
||||
|
||||
switch (BTD->getBuiltinTemplateKind()) {
|
||||
|
|
|
@ -6408,8 +6408,6 @@ QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
|
|||
if (Replacement.isNull())
|
||||
return QualType();
|
||||
|
||||
// Always canonicalize the replacement type.
|
||||
Replacement = SemaRef.Context.getCanonicalType(Replacement);
|
||||
QualType Result = SemaRef.Context.getSubstTemplateTypeParmType(
|
||||
T->getReplacedParameter(), Replacement, T->getPackIndex());
|
||||
|
||||
|
|
|
@ -162,3 +162,22 @@ using t2 = D<float, char>::B<int, short>;
|
|||
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar pack_index 0
|
||||
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'U' dependent contains_unexpanded_pack depth 0 index 0 pack
|
||||
} // namespace PR56099
|
||||
|
||||
namespace subst_default_argument {
|
||||
template<class A1> class A {};
|
||||
template<template<class C1, class C2 = A<C1>> class D1, class D2> using D = D1<D2>;
|
||||
|
||||
template<class E1, class E2> class E {};
|
||||
using test1 = D<E, int>;
|
||||
// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[1-9]+}}:1, col:23> col:7 test1 'D<subst_default_argument::E, int>':'subst_default_argument::E<int, subst_default_argument::A<int>>'
|
||||
// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'A<int>' sugar A
|
||||
// CHECK-NEXT: |-TemplateArgument type 'int':'int'
|
||||
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar
|
||||
// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[^ ]*}} 'C1' dependent depth 1 index 0
|
||||
// CHECK-NEXT: | | `-TemplateTypeParm 0x{{[^ ]*}} 'C1'
|
||||
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar
|
||||
// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[^ ]*}} 'type-parameter-0-1' dependent depth 0 index 1
|
||||
// CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'int'
|
||||
// CHECK-NEXT: `-RecordType 0x{{[^ ]*}} 'subst_default_argument::A<int>'
|
||||
// CHECK-NEXT: `-ClassTemplateSpecialization 0x{{[^ ]*}} 'A'
|
||||
} // namespace subst_default_argument
|
||||
|
|
Loading…
Reference in New Issue