QualType Wrapped);
QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced,
- QualType Replacement,
- Optional<unsigned> PackIndex) const;
+ QualType Replacement) const;
QualType getSubstTemplateTypeParmPackType(
const TemplateTypeParmType *Replaced,
const TemplateArgument &ArgPack);
void VisitUnaryTransformType(const UnaryTransformType *UTT);
void VisitTagType(const TagType *TT);
void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT);
- void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *STTPT);
void VisitAutoType(const AutoType *AT);
void VisitTemplateSpecializationType(const TemplateSpecializationType *TST);
void VisitInjectedClassNameType(const InjectedClassNameType *ICNT);
void VisitUnaryTransformType(const UnaryTransformType *T);
void VisitTagType(const TagType *T);
void VisitTemplateTypeParmType(const TemplateTypeParmType *T);
- void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T);
void VisitAutoType(const AutoType *T);
void VisitDeducedTemplateSpecializationType(
const DeducedTemplateSpecializationType *T);
unsigned NumArgs;
};
- class SubstTemplateTypeParmTypeBitfields {
- friend class SubstTemplateTypeParmType;
-
- unsigned : NumTypeBits;
-
- /// Represents the index within a pack if this represents a substitution
- /// from a pack expansion.
- /// Positive non-zero number represents the index + 1.
- /// Zero means this is not substituted from an expansion.
- unsigned PackIndex;
- };
-
class SubstTemplateTypeParmPackTypeBitfields {
friend class SubstTemplateTypeParmPackType;
ElaboratedTypeBitfields ElaboratedTypeBits;
VectorTypeBitfields VectorTypeBits;
SubstTemplateTypeParmPackTypeBitfields SubstTemplateTypeParmPackTypeBits;
- SubstTemplateTypeParmTypeBitfields SubstTemplateTypeParmTypeBits;
TemplateSpecializationTypeBitfields TemplateSpecializationTypeBits;
DependentTemplateSpecializationTypeBitfields
DependentTemplateSpecializationTypeBits;
// The original type parameter.
const TemplateTypeParmType *Replaced;
- SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon,
- Optional<unsigned> PackIndex)
+ SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon)
: Type(SubstTemplateTypeParm, Canon, Canon->getDependence()),
- Replaced(Param) {
- SubstTemplateTypeParmTypeBits.PackIndex = PackIndex ? *PackIndex + 1 : 0;
- }
+ Replaced(Param) {}
public:
/// Gets the template parameter that was substituted for.
return getCanonicalTypeInternal();
}
- Optional<unsigned> getPackIndex() const {
- if (SubstTemplateTypeParmTypeBits.PackIndex == 0)
- return None;
- return SubstTemplateTypeParmTypeBits.PackIndex - 1;
- }
-
bool isSugared() const { return true; }
QualType desugar() const { return getReplacementType(); }
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getReplacedParameter(), getReplacementType(), getPackIndex());
+ Profile(ID, getReplacedParameter(), getReplacementType());
}
static void Profile(llvm::FoldingSetNodeID &ID,
const TemplateTypeParmType *Replaced,
- QualType Replacement, Optional<unsigned> PackIndex) {
+ QualType Replacement) {
ID.AddPointer(Replaced);
ID.AddPointer(Replacement.getAsOpaquePtr());
- ID.AddInteger(PackIndex ? *PackIndex - 1 : 0);
}
static bool classof(const Type *T) {
def : Property<"replacementType", QualType> {
let Read = [{ node->getReplacementType() }];
}
- def : Property<"PackIndex", Optional<UInt32>> {
- let Read = [{ node->getPackIndex() }];
- }
def : Creator<[{
// The call to getCanonicalType here existed in ASTReader.cpp, too.
return ctx.getSubstTemplateTypeParmType(
cast<TemplateTypeParmType>(replacedParameter),
- ctx.getCanonicalType(replacementType), PackIndex);
+ ctx.getCanonicalType(replacementType));
}]>;
}
/// Retrieve a substitution-result type.
QualType
ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm,
- QualType Replacement,
- Optional<unsigned> PackIndex) const {
+ QualType Replacement) const {
assert(Replacement.isCanonical()
&& "replacement types must always be canonical");
llvm::FoldingSetNodeID ID;
- SubstTemplateTypeParmType::Profile(ID, Parm, Replacement, PackIndex);
+ SubstTemplateTypeParmType::Profile(ID, Parm, Replacement);
void *InsertPos = nullptr;
SubstTemplateTypeParmType *SubstParm
= SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
if (!SubstParm) {
SubstParm = new (*this, TypeAlignment)
- SubstTemplateTypeParmType(Parm, Replacement, PackIndex);
+ SubstTemplateTypeParmType(Parm, Replacement);
Types.push_back(SubstParm);
SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos);
}
return ToReplacementTypeOrErr.takeError();
return Importer.getToContext().getSubstTemplateTypeParmType(
- *ReplacedOrErr, ToReplacementTypeOrErr->getCanonicalType(),
- T->getPackIndex());
+ *ReplacedOrErr, ToReplacementTypeOrErr->getCanonicalType());
}
ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType(
if (!IsStructurallyEquivalent(Context, Subst1->getReplacementType(),
Subst2->getReplacementType()))
return false;
- if (Subst1->getPackIndex() != Subst2->getPackIndex())
- return false;
break;
}
JOS.attribute("decl", createBareDeclRef(TTPT->getDecl()));
}
-void JSONNodeDumper::VisitSubstTemplateTypeParmType(
- const SubstTemplateTypeParmType *STTPT) {
- if (auto PackIndex = STTPT->getPackIndex())
- JOS.attribute("pack_index", *PackIndex);
-}
-
void JSONNodeDumper::VisitAutoType(const AutoType *AT) {
JOS.attribute("undeduced", !AT->isDeduced());
switch (AT->getKeyword()) {
dumpDeclRef(T->getDecl());
}
-void TextNodeDumper::VisitSubstTemplateTypeParmType(
- const SubstTemplateTypeParmType *T) {
- if (auto PackIndex = T->getPackIndex())
- OS << " pack_index " << *PackIndex;
-}
-
void TextNodeDumper::VisitAutoType(const AutoType *T) {
if (T->isDecltypeAuto())
OS << " decltype(auto)";
return QualType(T, 0);
return Ctx.getSubstTemplateTypeParmType(T->getReplacedParameter(),
- replacementType, T->getPackIndex());
+ replacementType);
}
// FIXME: Non-trivial to implement, but important for C++
return NewT;
}
- Optional<unsigned> PackIndex;
if (T->isParameterPack()) {
assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack");
}
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
- PackIndex = getSema().ArgumentPackSubstitutionIndex;
}
assert(Arg.getKind() == TemplateArgument::Type &&
QualType Replacement = Arg.getAsType();
// TODO: only do this uniquing once, at the start of instantiation.
- QualType Result = getSema().Context.getSubstTemplateTypeParmType(
- T, Replacement, PackIndex);
+ QualType Result
+ = getSema().Context.getSubstTemplateTypeParmType(T, Replacement);
SubstTemplateTypeParmTypeLoc NewTL
= TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
TemplateArgument Arg = TL.getTypePtr()->getArgumentPack();
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ QualType Result = Arg.getAsType();
- QualType Result = getSema().Context.getSubstTemplateTypeParmType(
- TL.getTypePtr()->getReplacedParameter(), Arg.getAsType(),
- getSema().ArgumentPackSubstitutionIndex);
+ Result = getSema().Context.getSubstTemplateTypeParmType(
+ TL.getTypePtr()->getReplacedParameter(),
+ Result);
SubstTemplateTypeParmTypeLoc NewTL
= TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
Replacement = SemaRef.Context.getQualifiedType(
Replacement.getUnqualifiedType(), Qs);
T = SemaRef.Context.getSubstTemplateTypeParmType(
- SubstTypeParam->getReplacedParameter(), Replacement,
- SubstTypeParam->getPackIndex());
+ SubstTypeParam->getReplacedParameter(), Replacement);
} else if ((AutoTy = dyn_cast<AutoType>(T)) && AutoTy->isDeduced()) {
// 'auto' types behave the same way as template parameters.
QualType Deduced = AutoTy->getDeducedType();
// Always canonicalize the replacement type.
Replacement = SemaRef.Context.getCanonicalType(Replacement);
- QualType Result = SemaRef.Context.getSubstTemplateTypeParmType(
- T->getReplacedParameter(), Replacement, T->getPackIndex());
+ QualType Result
+ = SemaRef.Context.getSubstTemplateTypeParmType(T->getReplacedParameter(),
+ Replacement);
// Propagate type-source information.
SubstTemplateTypeParmTypeLoc NewTL
};
using t1 = foo<int, short>::bind<char, float>;
// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'Y<char, float, int, short>' sugar Y
-// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar pack_index 0
+// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack
-// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar pack_index 1
+// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack
-// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar pack_index 2
+// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack
-// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar pack_index 3
+// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack
template <typename... T> struct D {
// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'B<int, short>' sugar alias B
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (int (*)(float, int), int (*)(char, short))' cdecl
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (float, int)' cdecl
-// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar pack_index 0
+// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'T' dependent contains_unexpanded_pack depth 0 index 0 pack
-// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar pack_index 0
+// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'U' dependent contains_unexpanded_pack depth 0 index 0 pack
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (char, short)' cdecl
-// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar pack_index 1
+// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'T' dependent contains_unexpanded_pack depth 0 index 0 pack
-// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar pack_index 1
+// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar
// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'U' dependent contains_unexpanded_pack depth 0 index 0 pack
} // namespace PR56099
ToD2->getDeclContext(), ToD2->getTemplateParameters()->getParam(0)));
}
-TEST_P(ASTImporterOptionSpecificTestBase, ImportSubstTemplateTypeParmType) {
- constexpr auto Code = R"(
- template <class A1, class... A2> struct A {
- using B = A1(A2...);
- };
- template struct A<void, char, float, int, short>;
- )";
- Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input.cpp");
- auto *FromClass = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- FromTU, classTemplateSpecializationDecl());
-
- auto testType = [&](ASTContext &Ctx, const char *Name,
- llvm::Optional<unsigned> PackIndex) {
- const auto *Subst = selectFirst<SubstTemplateTypeParmType>(
- "sttp", match(substTemplateTypeParmType(
- hasReplacementType(hasCanonicalType(asString(Name))))
- .bind("sttp"),
- Ctx));
- const char *ExpectedTemplateParamName = PackIndex ? "A2" : "A1";
- ASSERT_TRUE(Subst);
- ASSERT_EQ(Subst->getReplacedParameter()->getIdentifier()->getName(),
- ExpectedTemplateParamName);
- ASSERT_EQ(Subst->getPackIndex(), PackIndex);
- };
- auto tests = [&](ASTContext &Ctx) {
- testType(Ctx, "void", None);
- testType(Ctx, "char", 0);
- testType(Ctx, "float", 1);
- testType(Ctx, "int", 2);
- testType(Ctx, "short", 3);
- };
-
- tests(FromTU->getASTContext());
-
- ClassTemplateSpecializationDecl *ToClass = Import(FromClass, Lang_CXX11);
- tests(ToClass->getASTContext());
-}
-
const AstTypeMatcher<SubstTemplateTypeParmPackType>
substTemplateTypeParmPackType;