|
|
|
@ -3332,6 +3332,26 @@ QualType ASTContext::getAdjustedType(QualType Orig, QualType New) const {
|
|
|
|
|
return QualType(AT, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QualType ASTContext::getDecayedType(QualType Orig, QualType Decayed) const {
|
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
|
AdjustedType::Profile(ID, Orig, Decayed);
|
|
|
|
|
void *InsertPos = nullptr;
|
|
|
|
|
AdjustedType *AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
|
if (AT)
|
|
|
|
|
return QualType(AT, 0);
|
|
|
|
|
|
|
|
|
|
QualType Canonical = getCanonicalType(Decayed);
|
|
|
|
|
|
|
|
|
|
// Get the new insert position for the node we care about.
|
|
|
|
|
AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
|
assert(!AT && "Shouldn't be in the map!");
|
|
|
|
|
|
|
|
|
|
AT = new (*this, TypeAlignment) DecayedType(Orig, Decayed, Canonical);
|
|
|
|
|
Types.push_back(AT);
|
|
|
|
|
AdjustedTypes.InsertNode(AT, InsertPos);
|
|
|
|
|
return QualType(AT, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QualType ASTContext::getDecayedType(QualType T) const {
|
|
|
|
|
assert((T->isArrayType() || T->isFunctionType()) && "T does not decay");
|
|
|
|
|
|
|
|
|
@ -3352,23 +3372,7 @@ QualType ASTContext::getDecayedType(QualType T) const {
|
|
|
|
|
if (T->isFunctionType())
|
|
|
|
|
Decayed = getPointerType(T);
|
|
|
|
|
|
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
|
AdjustedType::Profile(ID, T, Decayed);
|
|
|
|
|
void *InsertPos = nullptr;
|
|
|
|
|
AdjustedType *AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
|
if (AT)
|
|
|
|
|
return QualType(AT, 0);
|
|
|
|
|
|
|
|
|
|
QualType Canonical = getCanonicalType(Decayed);
|
|
|
|
|
|
|
|
|
|
// Get the new insert position for the node we care about.
|
|
|
|
|
AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
|
assert(!AT && "Shouldn't be in the map!");
|
|
|
|
|
|
|
|
|
|
AT = new (*this, TypeAlignment) DecayedType(T, Decayed, Canonical);
|
|
|
|
|
Types.push_back(AT);
|
|
|
|
|
AdjustedTypes.InsertNode(AT, InsertPos);
|
|
|
|
|
return QualType(AT, 0);
|
|
|
|
|
return getDecayedType(T, Decayed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// getBlockPointerType - Return the uniqued reference to the type for
|
|
|
|
@ -12195,11 +12199,19 @@ static TemplateName getCommonTemplateName(ASTContext &Ctx, TemplateName X,
|
|
|
|
|
// with more sugar. For example one could be a SubstTemplateTemplate*
|
|
|
|
|
// replacing the other.
|
|
|
|
|
TemplateName CX = Ctx.getCanonicalTemplateName(X);
|
|
|
|
|
assert(CX.getAsVoidPointer() ==
|
|
|
|
|
Ctx.getCanonicalTemplateName(Y).getAsVoidPointer());
|
|
|
|
|
if (CX.getAsVoidPointer() !=
|
|
|
|
|
Ctx.getCanonicalTemplateName(Y).getAsVoidPointer())
|
|
|
|
|
return TemplateName();
|
|
|
|
|
return CX;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static TemplateName
|
|
|
|
|
getCommonTemplateNameChecked(ASTContext &Ctx, TemplateName X, TemplateName Y) {
|
|
|
|
|
TemplateName R = getCommonTemplateName(Ctx, X, Y);
|
|
|
|
|
assert(R.getAsVoidPointer() != nullptr);
|
|
|
|
|
return R;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static auto getCommonTypes(ASTContext &Ctx, ArrayRef<QualType> Xs,
|
|
|
|
|
ArrayRef<QualType> Ys, bool Unqualified = false) {
|
|
|
|
|
assert(Xs.size() == Ys.size());
|
|
|
|
@ -12218,27 +12230,71 @@ static SourceLocation getCommonAttrLoc(const T *X, const T *Y) {
|
|
|
|
|
static TemplateArgument getCommonTemplateArgument(ASTContext &Ctx,
|
|
|
|
|
const TemplateArgument &X,
|
|
|
|
|
const TemplateArgument &Y) {
|
|
|
|
|
assert(X.getKind() == Y.getKind());
|
|
|
|
|
if (X.getKind() != Y.getKind())
|
|
|
|
|
return TemplateArgument();
|
|
|
|
|
|
|
|
|
|
switch (X.getKind()) {
|
|
|
|
|
case TemplateArgument::ArgKind::Type:
|
|
|
|
|
if (!Ctx.hasSameType(X.getAsType(), Y.getAsType()))
|
|
|
|
|
return TemplateArgument();
|
|
|
|
|
return TemplateArgument(
|
|
|
|
|
Ctx.getCommonSugaredType(X.getAsType(), Y.getAsType()));
|
|
|
|
|
case TemplateArgument::ArgKind::NullPtr:
|
|
|
|
|
if (!Ctx.hasSameType(X.getNullPtrType(), Y.getNullPtrType()))
|
|
|
|
|
return TemplateArgument();
|
|
|
|
|
return TemplateArgument(
|
|
|
|
|
Ctx.getCommonSugaredType(X.getNullPtrType(), Y.getNullPtrType()),
|
|
|
|
|
/*Unqualified=*/true);
|
|
|
|
|
case TemplateArgument::ArgKind::Expression:
|
|
|
|
|
if (!Ctx.hasSameType(X.getAsExpr()->getType(), Y.getAsExpr()->getType()))
|
|
|
|
|
return TemplateArgument();
|
|
|
|
|
// FIXME: Try to keep the common sugar.
|
|
|
|
|
return X;
|
|
|
|
|
case TemplateArgument::ArgKind::Template: {
|
|
|
|
|
TemplateName TX = X.getAsTemplate(), TY = Y.getAsTemplate();
|
|
|
|
|
TemplateName CTN = ::getCommonTemplateName(Ctx, TX, TY);
|
|
|
|
|
if (!CTN.getAsVoidPointer())
|
|
|
|
|
return TemplateArgument();
|
|
|
|
|
return TemplateArgument(CTN);
|
|
|
|
|
}
|
|
|
|
|
case TemplateArgument::ArgKind::TemplateExpansion: {
|
|
|
|
|
TemplateName TX = X.getAsTemplateOrTemplatePattern(),
|
|
|
|
|
TY = Y.getAsTemplateOrTemplatePattern();
|
|
|
|
|
TemplateName CTN = ::getCommonTemplateName(Ctx, TX, TY);
|
|
|
|
|
if (!CTN.getAsVoidPointer())
|
|
|
|
|
return TemplateName();
|
|
|
|
|
auto NExpX = X.getNumTemplateExpansions();
|
|
|
|
|
assert(NExpX == Y.getNumTemplateExpansions());
|
|
|
|
|
return TemplateArgument(CTN, NExpX);
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
// FIXME: Handle the other argument kinds.
|
|
|
|
|
return X;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool getCommonTemplateArguments(ASTContext &Ctx,
|
|
|
|
|
SmallVectorImpl<TemplateArgument> &R,
|
|
|
|
|
ArrayRef<TemplateArgument> Xs,
|
|
|
|
|
ArrayRef<TemplateArgument> Ys) {
|
|
|
|
|
if (Xs.size() != Ys.size())
|
|
|
|
|
return true;
|
|
|
|
|
R.resize(Xs.size());
|
|
|
|
|
for (size_t I = 0; I < R.size(); ++I) {
|
|
|
|
|
R[I] = getCommonTemplateArgument(Ctx, Xs[I], Ys[I]);
|
|
|
|
|
if (R[I].isNull())
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static auto getCommonTemplateArguments(ASTContext &Ctx,
|
|
|
|
|
ArrayRef<TemplateArgument> X,
|
|
|
|
|
ArrayRef<TemplateArgument> Y) {
|
|
|
|
|
SmallVector<TemplateArgument, 8> R(X.size());
|
|
|
|
|
for (size_t I = 0; I < R.size(); ++I)
|
|
|
|
|
R[I] = getCommonTemplateArgument(Ctx, X[I], Y[I]);
|
|
|
|
|
ArrayRef<TemplateArgument> Xs,
|
|
|
|
|
ArrayRef<TemplateArgument> Ys) {
|
|
|
|
|
SmallVector<TemplateArgument, 8> R;
|
|
|
|
|
bool Different = getCommonTemplateArguments(Ctx, R, Xs, Ys);
|
|
|
|
|
assert(!Different);
|
|
|
|
|
(void)Different;
|
|
|
|
|
return R;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -12384,10 +12440,11 @@ ASTContext::mergeExceptionSpecs(FunctionProtoType::ExceptionSpecInfo ESI1,
|
|
|
|
|
llvm_unreachable("invalid ExceptionSpecificationType");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static QualType getCommonType(ASTContext &Ctx, SplitQualType &X,
|
|
|
|
|
SplitQualType &Y) {
|
|
|
|
|
Type::TypeClass TC = X.Ty->getTypeClass();
|
|
|
|
|
assert(TC == Y.Ty->getTypeClass());
|
|
|
|
|
static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X,
|
|
|
|
|
Qualifiers &QX, const Type *Y,
|
|
|
|
|
Qualifiers &QY) {
|
|
|
|
|
Type::TypeClass TC = X->getTypeClass();
|
|
|
|
|
assert(TC == Y->getTypeClass());
|
|
|
|
|
switch (TC) {
|
|
|
|
|
#define UNEXPECTED_TYPE(Class, Kind) \
|
|
|
|
|
case Type::Class: \
|
|
|
|
@ -12419,7 +12476,7 @@ static QualType getCommonType(ASTContext &Ctx, SplitQualType &X,
|
|
|
|
|
#undef UNEXPECTED_TYPE
|
|
|
|
|
|
|
|
|
|
case Type::Auto: {
|
|
|
|
|
const auto *AX = cast<AutoType>(X.Ty), *AY = cast<AutoType>(Y.Ty);
|
|
|
|
|
const auto *AX = cast<AutoType>(X), *AY = cast<AutoType>(Y);
|
|
|
|
|
assert(AX->getDeducedType().isNull());
|
|
|
|
|
assert(AY->getDeducedType().isNull());
|
|
|
|
|
assert(AX->getKeyword() == AY->getKeyword());
|
|
|
|
@ -12430,22 +12487,22 @@ static QualType getCommonType(ASTContext &Ctx, SplitQualType &X,
|
|
|
|
|
return Ctx.getAutoType(QualType(), AX->getKeyword(),
|
|
|
|
|
AX->isInstantiationDependentType(),
|
|
|
|
|
AX->containsUnexpandedParameterPack(),
|
|
|
|
|
getCommonDecl(AX->getTypeConstraintConcept(),
|
|
|
|
|
getCommonDeclChecked(AX->getTypeConstraintConcept(),
|
|
|
|
|
AY->getTypeConstraintConcept()),
|
|
|
|
|
As);
|
|
|
|
|
}
|
|
|
|
|
case Type::IncompleteArray: {
|
|
|
|
|
const auto *AX = cast<IncompleteArrayType>(X.Ty),
|
|
|
|
|
*AY = cast<IncompleteArrayType>(Y.Ty);
|
|
|
|
|
const auto *AX = cast<IncompleteArrayType>(X),
|
|
|
|
|
*AY = cast<IncompleteArrayType>(Y);
|
|
|
|
|
return Ctx.getIncompleteArrayType(
|
|
|
|
|
getCommonArrayElementType(Ctx, AX, X.Quals, AY, Y.Quals),
|
|
|
|
|
getCommonArrayElementType(Ctx, AX, QX, AY, QY),
|
|
|
|
|
getCommonSizeModifier(AX, AY), getCommonIndexTypeCVRQualifiers(AX, AY));
|
|
|
|
|
}
|
|
|
|
|
case Type::DependentSizedArray: {
|
|
|
|
|
const auto *AX = cast<DependentSizedArrayType>(X.Ty),
|
|
|
|
|
*AY = cast<DependentSizedArrayType>(Y.Ty);
|
|
|
|
|
const auto *AX = cast<DependentSizedArrayType>(X),
|
|
|
|
|
*AY = cast<DependentSizedArrayType>(Y);
|
|
|
|
|
return Ctx.getDependentSizedArrayType(
|
|
|
|
|
getCommonArrayElementType(Ctx, AX, X.Quals, AY, Y.Quals),
|
|
|
|
|
getCommonArrayElementType(Ctx, AX, QX, AY, QY),
|
|
|
|
|
getCommonSizeExpr(Ctx, AX, AY), getCommonSizeModifier(AX, AY),
|
|
|
|
|
getCommonIndexTypeCVRQualifiers(AX, AY),
|
|
|
|
|
AX->getBracketsRange() == AY->getBracketsRange()
|
|
|
|
@ -12453,44 +12510,41 @@ static QualType getCommonType(ASTContext &Ctx, SplitQualType &X,
|
|
|
|
|
: SourceRange());
|
|
|
|
|
}
|
|
|
|
|
case Type::ConstantArray: {
|
|
|
|
|
const auto *AX = cast<ConstantArrayType>(X.Ty),
|
|
|
|
|
*AY = cast<ConstantArrayType>(Y.Ty);
|
|
|
|
|
const auto *AX = cast<ConstantArrayType>(X),
|
|
|
|
|
*AY = cast<ConstantArrayType>(Y);
|
|
|
|
|
assert(AX->getSize() == AY->getSize());
|
|
|
|
|
const Expr *SizeExpr = Ctx.hasSameExpr(AX->getSizeExpr(), AY->getSizeExpr())
|
|
|
|
|
? AX->getSizeExpr()
|
|
|
|
|
: nullptr;
|
|
|
|
|
return Ctx.getConstantArrayType(
|
|
|
|
|
getCommonArrayElementType(Ctx, AX, X.Quals, AY, Y.Quals), AX->getSize(),
|
|
|
|
|
SizeExpr, getCommonSizeModifier(AX, AY),
|
|
|
|
|
getCommonIndexTypeCVRQualifiers(AX, AY));
|
|
|
|
|
getCommonArrayElementType(Ctx, AX, QX, AY, QY), AX->getSize(), SizeExpr,
|
|
|
|
|
getCommonSizeModifier(AX, AY), getCommonIndexTypeCVRQualifiers(AX, AY));
|
|
|
|
|
}
|
|
|
|
|
case Type::Atomic: {
|
|
|
|
|
const auto *AX = cast<AtomicType>(X.Ty), *AY = cast<AtomicType>(Y.Ty);
|
|
|
|
|
const auto *AX = cast<AtomicType>(X), *AY = cast<AtomicType>(Y);
|
|
|
|
|
return Ctx.getAtomicType(
|
|
|
|
|
Ctx.getCommonSugaredType(AX->getValueType(), AY->getValueType()));
|
|
|
|
|
}
|
|
|
|
|
case Type::Complex: {
|
|
|
|
|
const auto *CX = cast<ComplexType>(X.Ty), *CY = cast<ComplexType>(Y.Ty);
|
|
|
|
|
return Ctx.getComplexType(
|
|
|
|
|
getCommonArrayElementType(Ctx, CX, X.Quals, CY, Y.Quals));
|
|
|
|
|
const auto *CX = cast<ComplexType>(X), *CY = cast<ComplexType>(Y);
|
|
|
|
|
return Ctx.getComplexType(getCommonArrayElementType(Ctx, CX, QX, CY, QY));
|
|
|
|
|
}
|
|
|
|
|
case Type::Pointer: {
|
|
|
|
|
const auto *PX = cast<PointerType>(X.Ty), *PY = cast<PointerType>(Y.Ty);
|
|
|
|
|
const auto *PX = cast<PointerType>(X), *PY = cast<PointerType>(Y);
|
|
|
|
|
return Ctx.getPointerType(getCommonPointeeType(Ctx, PX, PY));
|
|
|
|
|
}
|
|
|
|
|
case Type::BlockPointer: {
|
|
|
|
|
const auto *PX = cast<BlockPointerType>(X.Ty),
|
|
|
|
|
*PY = cast<BlockPointerType>(Y.Ty);
|
|
|
|
|
const auto *PX = cast<BlockPointerType>(X), *PY = cast<BlockPointerType>(Y);
|
|
|
|
|
return Ctx.getBlockPointerType(getCommonPointeeType(Ctx, PX, PY));
|
|
|
|
|
}
|
|
|
|
|
case Type::ObjCObjectPointer: {
|
|
|
|
|
const auto *PX = cast<ObjCObjectPointerType>(X.Ty),
|
|
|
|
|
*PY = cast<ObjCObjectPointerType>(Y.Ty);
|
|
|
|
|
const auto *PX = cast<ObjCObjectPointerType>(X),
|
|
|
|
|
*PY = cast<ObjCObjectPointerType>(Y);
|
|
|
|
|
return Ctx.getObjCObjectPointerType(getCommonPointeeType(Ctx, PX, PY));
|
|
|
|
|
}
|
|
|
|
|
case Type::MemberPointer: {
|
|
|
|
|
const auto *PX = cast<MemberPointerType>(X.Ty),
|
|
|
|
|
*PY = cast<MemberPointerType>(Y.Ty);
|
|
|
|
|
const auto *PX = cast<MemberPointerType>(X),
|
|
|
|
|
*PY = cast<MemberPointerType>(Y);
|
|
|
|
|
return Ctx.getMemberPointerType(
|
|
|
|
|
getCommonPointeeType(Ctx, PX, PY),
|
|
|
|
|
Ctx.getCommonSugaredType(QualType(PX->getClass(), 0),
|
|
|
|
@ -12498,38 +12552,38 @@ static QualType getCommonType(ASTContext &Ctx, SplitQualType &X,
|
|
|
|
|
.getTypePtr());
|
|
|
|
|
}
|
|
|
|
|
case Type::LValueReference: {
|
|
|
|
|
const auto *PX = cast<LValueReferenceType>(X.Ty),
|
|
|
|
|
*PY = cast<LValueReferenceType>(Y.Ty);
|
|
|
|
|
const auto *PX = cast<LValueReferenceType>(X),
|
|
|
|
|
*PY = cast<LValueReferenceType>(Y);
|
|
|
|
|
// FIXME: Preserve PointeeTypeAsWritten.
|
|
|
|
|
return Ctx.getLValueReferenceType(getCommonPointeeType(Ctx, PX, PY),
|
|
|
|
|
PX->isSpelledAsLValue() ||
|
|
|
|
|
PY->isSpelledAsLValue());
|
|
|
|
|
}
|
|
|
|
|
case Type::RValueReference: {
|
|
|
|
|
const auto *PX = cast<RValueReferenceType>(X.Ty),
|
|
|
|
|
*PY = cast<RValueReferenceType>(Y.Ty);
|
|
|
|
|
const auto *PX = cast<RValueReferenceType>(X),
|
|
|
|
|
*PY = cast<RValueReferenceType>(Y);
|
|
|
|
|
// FIXME: Preserve PointeeTypeAsWritten.
|
|
|
|
|
return Ctx.getRValueReferenceType(getCommonPointeeType(Ctx, PX, PY));
|
|
|
|
|
}
|
|
|
|
|
case Type::DependentAddressSpace: {
|
|
|
|
|
const auto *PX = cast<DependentAddressSpaceType>(X.Ty),
|
|
|
|
|
*PY = cast<DependentAddressSpaceType>(Y.Ty);
|
|
|
|
|
const auto *PX = cast<DependentAddressSpaceType>(X),
|
|
|
|
|
*PY = cast<DependentAddressSpaceType>(Y);
|
|
|
|
|
assert(Ctx.hasSameExpr(PX->getAddrSpaceExpr(), PY->getAddrSpaceExpr()));
|
|
|
|
|
return Ctx.getDependentAddressSpaceType(getCommonPointeeType(Ctx, PX, PY),
|
|
|
|
|
PX->getAddrSpaceExpr(),
|
|
|
|
|
getCommonAttrLoc(PX, PY));
|
|
|
|
|
}
|
|
|
|
|
case Type::FunctionNoProto: {
|
|
|
|
|
const auto *FX = cast<FunctionNoProtoType>(X.Ty),
|
|
|
|
|
*FY = cast<FunctionNoProtoType>(Y.Ty);
|
|
|
|
|
const auto *FX = cast<FunctionNoProtoType>(X),
|
|
|
|
|
*FY = cast<FunctionNoProtoType>(Y);
|
|
|
|
|
assert(FX->getExtInfo() == FY->getExtInfo());
|
|
|
|
|
return Ctx.getFunctionNoProtoType(
|
|
|
|
|
Ctx.getCommonSugaredType(FX->getReturnType(), FY->getReturnType()),
|
|
|
|
|
FX->getExtInfo());
|
|
|
|
|
}
|
|
|
|
|
case Type::FunctionProto: {
|
|
|
|
|
const auto *FX = cast<FunctionProtoType>(X.Ty),
|
|
|
|
|
*FY = cast<FunctionProtoType>(Y.Ty);
|
|
|
|
|
const auto *FX = cast<FunctionProtoType>(X),
|
|
|
|
|
*FY = cast<FunctionProtoType>(Y);
|
|
|
|
|
FunctionProtoType::ExtProtoInfo EPIX = FX->getExtProtoInfo(),
|
|
|
|
|
EPIY = FY->getExtProtoInfo();
|
|
|
|
|
assert(EPIX.ExtInfo == EPIY.ExtInfo);
|
|
|
|
@ -12554,8 +12608,7 @@ static QualType getCommonType(ASTContext &Ctx, SplitQualType &X,
|
|
|
|
|
return Ctx.getFunctionType(R, P, EPIX);
|
|
|
|
|
}
|
|
|
|
|
case Type::ObjCObject: {
|
|
|
|
|
const auto *OX = cast<ObjCObjectType>(X.Ty),
|
|
|
|
|
*OY = cast<ObjCObjectType>(Y.Ty);
|
|
|
|
|
const auto *OX = cast<ObjCObjectType>(X), *OY = cast<ObjCObjectType>(Y);
|
|
|
|
|
assert(llvm::equal(OX->getProtocols(), OY->getProtocols()));
|
|
|
|
|
auto TAs = getCommonTypes(Ctx, OX->getTypeArgsAsWritten(),
|
|
|
|
|
OY->getTypeArgsAsWritten());
|
|
|
|
@ -12565,16 +12618,16 @@ static QualType getCommonType(ASTContext &Ctx, SplitQualType &X,
|
|
|
|
|
OX->isKindOfTypeAsWritten() && OY->isKindOfTypeAsWritten());
|
|
|
|
|
}
|
|
|
|
|
case Type::ConstantMatrix: {
|
|
|
|
|
const auto *MX = cast<ConstantMatrixType>(X.Ty),
|
|
|
|
|
*MY = cast<ConstantMatrixType>(Y.Ty);
|
|
|
|
|
const auto *MX = cast<ConstantMatrixType>(X),
|
|
|
|
|
*MY = cast<ConstantMatrixType>(Y);
|
|
|
|
|
assert(MX->getNumRows() == MY->getNumRows());
|
|
|
|
|
assert(MX->getNumColumns() == MY->getNumColumns());
|
|
|
|
|
return Ctx.getConstantMatrixType(getCommonElementType(Ctx, MX, MY),
|
|
|
|
|
MX->getNumRows(), MX->getNumColumns());
|
|
|
|
|
}
|
|
|
|
|
case Type::DependentSizedMatrix: {
|
|
|
|
|
const auto *MX = cast<DependentSizedMatrixType>(X.Ty),
|
|
|
|
|
*MY = cast<DependentSizedMatrixType>(Y.Ty);
|
|
|
|
|
const auto *MX = cast<DependentSizedMatrixType>(X),
|
|
|
|
|
*MY = cast<DependentSizedMatrixType>(Y);
|
|
|
|
|
assert(Ctx.hasSameExpr(MX->getRowExpr(), MY->getRowExpr()));
|
|
|
|
|
assert(Ctx.hasSameExpr(MX->getColumnExpr(), MY->getColumnExpr()));
|
|
|
|
|
return Ctx.getDependentSizedMatrixType(
|
|
|
|
@ -12582,62 +12635,62 @@ static QualType getCommonType(ASTContext &Ctx, SplitQualType &X,
|
|
|
|
|
MX->getColumnExpr(), getCommonAttrLoc(MX, MY));
|
|
|
|
|
}
|
|
|
|
|
case Type::Vector: {
|
|
|
|
|
const auto *VX = cast<VectorType>(X.Ty), *VY = cast<VectorType>(Y.Ty);
|
|
|
|
|
const auto *VX = cast<VectorType>(X), *VY = cast<VectorType>(Y);
|
|
|
|
|
assert(VX->getNumElements() == VY->getNumElements());
|
|
|
|
|
assert(VX->getVectorKind() == VY->getVectorKind());
|
|
|
|
|
return Ctx.getVectorType(getCommonElementType(Ctx, VX, VY),
|
|
|
|
|
VX->getNumElements(), VX->getVectorKind());
|
|
|
|
|
}
|
|
|
|
|
case Type::ExtVector: {
|
|
|
|
|
const auto *VX = cast<ExtVectorType>(X.Ty), *VY = cast<ExtVectorType>(Y.Ty);
|
|
|
|
|
const auto *VX = cast<ExtVectorType>(X), *VY = cast<ExtVectorType>(Y);
|
|
|
|
|
assert(VX->getNumElements() == VY->getNumElements());
|
|
|
|
|
return Ctx.getExtVectorType(getCommonElementType(Ctx, VX, VY),
|
|
|
|
|
VX->getNumElements());
|
|
|
|
|
}
|
|
|
|
|
case Type::DependentSizedExtVector: {
|
|
|
|
|
const auto *VX = cast<DependentSizedExtVectorType>(X.Ty),
|
|
|
|
|
*VY = cast<DependentSizedExtVectorType>(Y.Ty);
|
|
|
|
|
const auto *VX = cast<DependentSizedExtVectorType>(X),
|
|
|
|
|
*VY = cast<DependentSizedExtVectorType>(Y);
|
|
|
|
|
return Ctx.getDependentSizedExtVectorType(getCommonElementType(Ctx, VX, VY),
|
|
|
|
|
getCommonSizeExpr(Ctx, VX, VY),
|
|
|
|
|
getCommonAttrLoc(VX, VY));
|
|
|
|
|
}
|
|
|
|
|
case Type::DependentVector: {
|
|
|
|
|
const auto *VX = cast<DependentVectorType>(X.Ty),
|
|
|
|
|
*VY = cast<DependentVectorType>(Y.Ty);
|
|
|
|
|
const auto *VX = cast<DependentVectorType>(X),
|
|
|
|
|
*VY = cast<DependentVectorType>(Y);
|
|
|
|
|
assert(VX->getVectorKind() == VY->getVectorKind());
|
|
|
|
|
return Ctx.getDependentVectorType(
|
|
|
|
|
getCommonElementType(Ctx, VX, VY), getCommonSizeExpr(Ctx, VX, VY),
|
|
|
|
|
getCommonAttrLoc(VX, VY), VX->getVectorKind());
|
|
|
|
|
}
|
|
|
|
|
case Type::InjectedClassName: {
|
|
|
|
|
const auto *IX = cast<InjectedClassNameType>(X.Ty),
|
|
|
|
|
*IY = cast<InjectedClassNameType>(Y.Ty);
|
|
|
|
|
const auto *IX = cast<InjectedClassNameType>(X),
|
|
|
|
|
*IY = cast<InjectedClassNameType>(Y);
|
|
|
|
|
return Ctx.getInjectedClassNameType(
|
|
|
|
|
getCommonDeclChecked(IX->getDecl(), IY->getDecl()),
|
|
|
|
|
Ctx.getCommonSugaredType(IX->getInjectedSpecializationType(),
|
|
|
|
|
IY->getInjectedSpecializationType()));
|
|
|
|
|
}
|
|
|
|
|
case Type::TemplateSpecialization: {
|
|
|
|
|
const auto *TX = cast<TemplateSpecializationType>(X.Ty),
|
|
|
|
|
*TY = cast<TemplateSpecializationType>(Y.Ty);
|
|
|
|
|
const auto *TX = cast<TemplateSpecializationType>(X),
|
|
|
|
|
*TY = cast<TemplateSpecializationType>(Y);
|
|
|
|
|
auto As = getCommonTemplateArguments(Ctx, TX->template_arguments(),
|
|
|
|
|
TY->template_arguments());
|
|
|
|
|
return Ctx.getTemplateSpecializationType(
|
|
|
|
|
::getCommonTemplateName(Ctx, TX->getTemplateName(),
|
|
|
|
|
::getCommonTemplateNameChecked(Ctx, TX->getTemplateName(),
|
|
|
|
|
TY->getTemplateName()),
|
|
|
|
|
As, TX->getCanonicalTypeInternal());
|
|
|
|
|
As, X->getCanonicalTypeInternal());
|
|
|
|
|
}
|
|
|
|
|
case Type::DependentName: {
|
|
|
|
|
const auto *NX = cast<DependentNameType>(X.Ty),
|
|
|
|
|
*NY = cast<DependentNameType>(Y.Ty);
|
|
|
|
|
const auto *NX = cast<DependentNameType>(X),
|
|
|
|
|
*NY = cast<DependentNameType>(Y);
|
|
|
|
|
assert(NX->getIdentifier() == NY->getIdentifier());
|
|
|
|
|
return Ctx.getDependentNameType(
|
|
|
|
|
getCommonTypeKeyword(NX, NY), getCommonNNS(Ctx, NX, NY),
|
|
|
|
|
NX->getIdentifier(), NX->getCanonicalTypeInternal());
|
|
|
|
|
}
|
|
|
|
|
case Type::DependentTemplateSpecialization: {
|
|
|
|
|
const auto *TX = cast<DependentTemplateSpecializationType>(X.Ty),
|
|
|
|
|
*TY = cast<DependentTemplateSpecializationType>(Y.Ty);
|
|
|
|
|
const auto *TX = cast<DependentTemplateSpecializationType>(X),
|
|
|
|
|
*TY = cast<DependentTemplateSpecializationType>(Y);
|
|
|
|
|
assert(TX->getIdentifier() == TY->getIdentifier());
|
|
|
|
|
auto As = getCommonTemplateArguments(Ctx, TX->template_arguments(),
|
|
|
|
|
TY->template_arguments());
|
|
|
|
@ -12646,8 +12699,8 @@ static QualType getCommonType(ASTContext &Ctx, SplitQualType &X,
|
|
|
|
|
TX->getIdentifier(), As);
|
|
|
|
|
}
|
|
|
|
|
case Type::UnaryTransform: {
|
|
|
|
|
const auto *TX = cast<UnaryTransformType>(X.Ty),
|
|
|
|
|
*TY = cast<UnaryTransformType>(Y.Ty);
|
|
|
|
|
const auto *TX = cast<UnaryTransformType>(X),
|
|
|
|
|
*TY = cast<UnaryTransformType>(Y);
|
|
|
|
|
assert(TX->getUTTKind() == TY->getUTTKind());
|
|
|
|
|
return Ctx.getUnaryTransformType(
|
|
|
|
|
Ctx.getCommonSugaredType(TX->getBaseType(), TY->getBaseType()),
|
|
|
|
@ -12656,23 +12709,23 @@ static QualType getCommonType(ASTContext &Ctx, SplitQualType &X,
|
|
|
|
|
TX->getUTTKind());
|
|
|
|
|
}
|
|
|
|
|
case Type::PackExpansion: {
|
|
|
|
|
const auto *PX = cast<PackExpansionType>(X.Ty),
|
|
|
|
|
*PY = cast<PackExpansionType>(Y.Ty);
|
|
|
|
|
const auto *PX = cast<PackExpansionType>(X),
|
|
|
|
|
*PY = cast<PackExpansionType>(Y);
|
|
|
|
|
assert(PX->getNumExpansions() == PY->getNumExpansions());
|
|
|
|
|
return Ctx.getPackExpansionType(
|
|
|
|
|
Ctx.getCommonSugaredType(PX->getPattern(), PY->getPattern()),
|
|
|
|
|
PX->getNumExpansions(), false);
|
|
|
|
|
}
|
|
|
|
|
case Type::Pipe: {
|
|
|
|
|
const auto *PX = cast<PipeType>(X.Ty), *PY = cast<PipeType>(Y.Ty);
|
|
|
|
|
const auto *PX = cast<PipeType>(X), *PY = cast<PipeType>(Y);
|
|
|
|
|
assert(PX->isReadOnly() == PY->isReadOnly());
|
|
|
|
|
auto MP = PX->isReadOnly() ? &ASTContext::getReadPipeType
|
|
|
|
|
: &ASTContext::getWritePipeType;
|
|
|
|
|
return (Ctx.*MP)(getCommonElementType(Ctx, PX, PY));
|
|
|
|
|
}
|
|
|
|
|
case Type::TemplateTypeParm: {
|
|
|
|
|
const auto *TX = cast<TemplateTypeParmType>(X.Ty),
|
|
|
|
|
*TY = cast<TemplateTypeParmType>(Y.Ty);
|
|
|
|
|
const auto *TX = cast<TemplateTypeParmType>(X),
|
|
|
|
|
*TY = cast<TemplateTypeParmType>(Y);
|
|
|
|
|
assert(TX->getDepth() == TY->getDepth());
|
|
|
|
|
assert(TX->getIndex() == TY->getIndex());
|
|
|
|
|
assert(TX->isParameterPack() == TY->isParameterPack());
|
|
|
|
@ -12684,31 +12737,208 @@ static QualType getCommonType(ASTContext &Ctx, SplitQualType &X,
|
|
|
|
|
llvm_unreachable("Unknown Type Class");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static auto unwrapSugar(SplitQualType &T) {
|
|
|
|
|
static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
|
|
|
|
|
const Type *Y,
|
|
|
|
|
SplitQualType Underlying) {
|
|
|
|
|
Type::TypeClass TC = X->getTypeClass();
|
|
|
|
|
if (TC != Y->getTypeClass())
|
|
|
|
|
return QualType();
|
|
|
|
|
switch (TC) {
|
|
|
|
|
#define UNEXPECTED_TYPE(Class, Kind) \
|
|
|
|
|
case Type::Class: \
|
|
|
|
|
llvm_unreachable("Unexpected " Kind ": " #Class);
|
|
|
|
|
#define TYPE(Class, Base)
|
|
|
|
|
#define DEPENDENT_TYPE(Class, Base) UNEXPECTED_TYPE(Class, "dependent")
|
|
|
|
|
#include "clang/AST/TypeNodes.inc"
|
|
|
|
|
|
|
|
|
|
#define CANONICAL_TYPE(Class) UNEXPECTED_TYPE(Class, "canonical")
|
|
|
|
|
CANONICAL_TYPE(Atomic)
|
|
|
|
|
CANONICAL_TYPE(BitInt)
|
|
|
|
|
CANONICAL_TYPE(BlockPointer)
|
|
|
|
|
CANONICAL_TYPE(Builtin)
|
|
|
|
|
CANONICAL_TYPE(Complex)
|
|
|
|
|
CANONICAL_TYPE(ConstantArray)
|
|
|
|
|
CANONICAL_TYPE(ConstantMatrix)
|
|
|
|
|
CANONICAL_TYPE(Enum)
|
|
|
|
|
CANONICAL_TYPE(ExtVector)
|
|
|
|
|
CANONICAL_TYPE(FunctionNoProto)
|
|
|
|
|
CANONICAL_TYPE(FunctionProto)
|
|
|
|
|
CANONICAL_TYPE(IncompleteArray)
|
|
|
|
|
CANONICAL_TYPE(LValueReference)
|
|
|
|
|
CANONICAL_TYPE(MemberPointer)
|
|
|
|
|
CANONICAL_TYPE(ObjCInterface)
|
|
|
|
|
CANONICAL_TYPE(ObjCObject)
|
|
|
|
|
CANONICAL_TYPE(ObjCObjectPointer)
|
|
|
|
|
CANONICAL_TYPE(Pipe)
|
|
|
|
|
CANONICAL_TYPE(Pointer)
|
|
|
|
|
CANONICAL_TYPE(Record)
|
|
|
|
|
CANONICAL_TYPE(RValueReference)
|
|
|
|
|
CANONICAL_TYPE(VariableArray)
|
|
|
|
|
CANONICAL_TYPE(Vector)
|
|
|
|
|
#undef CANONICAL_TYPE
|
|
|
|
|
|
|
|
|
|
#undef UNEXPECTED_TYPE
|
|
|
|
|
|
|
|
|
|
case Type::Adjusted: {
|
|
|
|
|
const auto *AX = cast<AdjustedType>(X), *AY = cast<AdjustedType>(Y);
|
|
|
|
|
QualType OX = AX->getOriginalType(), OY = AY->getOriginalType();
|
|
|
|
|
if (!Ctx.hasSameType(OX, OY))
|
|
|
|
|
return QualType();
|
|
|
|
|
// FIXME: It's inefficient to have to unify the original types.
|
|
|
|
|
return Ctx.getAdjustedType(Ctx.getCommonSugaredType(OX, OY),
|
|
|
|
|
Ctx.getQualifiedType(Underlying));
|
|
|
|
|
}
|
|
|
|
|
case Type::Decayed: {
|
|
|
|
|
const auto *DX = cast<DecayedType>(X), *DY = cast<DecayedType>(Y);
|
|
|
|
|
QualType OX = DX->getOriginalType(), OY = DY->getOriginalType();
|
|
|
|
|
if (!Ctx.hasSameType(OX, OY))
|
|
|
|
|
return QualType();
|
|
|
|
|
// FIXME: It's inefficient to have to unify the original types.
|
|
|
|
|
return Ctx.getDecayedType(Ctx.getCommonSugaredType(OX, OY),
|
|
|
|
|
Ctx.getQualifiedType(Underlying));
|
|
|
|
|
}
|
|
|
|
|
case Type::Attributed: {
|
|
|
|
|
const auto *AX = cast<AttributedType>(X), *AY = cast<AttributedType>(Y);
|
|
|
|
|
AttributedType::Kind Kind = AX->getAttrKind();
|
|
|
|
|
if (Kind != AY->getAttrKind())
|
|
|
|
|
return QualType();
|
|
|
|
|
QualType MX = AX->getModifiedType(), MY = AY->getModifiedType();
|
|
|
|
|
if (!Ctx.hasSameType(MX, MY))
|
|
|
|
|
return QualType();
|
|
|
|
|
// FIXME: It's inefficient to have to unify the modified types.
|
|
|
|
|
return Ctx.getAttributedType(Kind, Ctx.getCommonSugaredType(MX, MY),
|
|
|
|
|
Ctx.getQualifiedType(Underlying));
|
|
|
|
|
}
|
|
|
|
|
case Type::BTFTagAttributed: {
|
|
|
|
|
const auto *BX = cast<BTFTagAttributedType>(X);
|
|
|
|
|
const BTFTypeTagAttr *AX = BX->getAttr();
|
|
|
|
|
// The attribute is not uniqued, so just compare the tag.
|
|
|
|
|
if (AX->getBTFTypeTag() !=
|
|
|
|
|
cast<BTFTagAttributedType>(Y)->getAttr()->getBTFTypeTag())
|
|
|
|
|
return QualType();
|
|
|
|
|
return Ctx.getBTFTagAttributedType(AX, Ctx.getQualifiedType(Underlying));
|
|
|
|
|
}
|
|
|
|
|
case Type::Auto: {
|
|
|
|
|
const auto *AX = cast<AutoType>(X), *AY = cast<AutoType>(Y);
|
|
|
|
|
|
|
|
|
|
AutoTypeKeyword KW = AX->getKeyword();
|
|
|
|
|
if (KW != AY->getKeyword())
|
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
|
|
ConceptDecl *CD = ::getCommonDecl(AX->getTypeConstraintConcept(),
|
|
|
|
|
AY->getTypeConstraintConcept());
|
|
|
|
|
SmallVector<TemplateArgument, 8> As;
|
|
|
|
|
if (CD &&
|
|
|
|
|
getCommonTemplateArguments(Ctx, As, AX->getTypeConstraintArguments(),
|
|
|
|
|
AY->getTypeConstraintArguments()))
|
|
|
|
|
CD = nullptr; // The arguments differ, so make it unconstrained.
|
|
|
|
|
|
|
|
|
|
// Both auto types can't be dependent, otherwise they wouldn't have been
|
|
|
|
|
// sugar. This implies they can't contain unexpanded packs either.
|
|
|
|
|
return Ctx.getAutoType(Ctx.getQualifiedType(Underlying), AX->getKeyword(),
|
|
|
|
|
/*IsDependent=*/false, /*IsPack=*/false, CD, As);
|
|
|
|
|
}
|
|
|
|
|
case Type::Decltype:
|
|
|
|
|
return QualType();
|
|
|
|
|
case Type::DeducedTemplateSpecialization:
|
|
|
|
|
// FIXME: Try to merge these.
|
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
|
|
case Type::Elaborated: {
|
|
|
|
|
const auto *EX = cast<ElaboratedType>(X), *EY = cast<ElaboratedType>(Y);
|
|
|
|
|
return Ctx.getElaboratedType(
|
|
|
|
|
::getCommonTypeKeyword(EX, EY), ::getCommonNNS(Ctx, EX, EY),
|
|
|
|
|
Ctx.getQualifiedType(Underlying),
|
|
|
|
|
::getCommonDecl(EX->getOwnedTagDecl(), EY->getOwnedTagDecl()));
|
|
|
|
|
}
|
|
|
|
|
case Type::MacroQualified: {
|
|
|
|
|
const auto *MX = cast<MacroQualifiedType>(X),
|
|
|
|
|
*MY = cast<MacroQualifiedType>(Y);
|
|
|
|
|
const IdentifierInfo *IX = MX->getMacroIdentifier();
|
|
|
|
|
if (IX != MY->getMacroIdentifier())
|
|
|
|
|
return QualType();
|
|
|
|
|
return Ctx.getMacroQualifiedType(Ctx.getQualifiedType(Underlying), IX);
|
|
|
|
|
}
|
|
|
|
|
case Type::SubstTemplateTypeParm: {
|
|
|
|
|
const auto *SX = cast<SubstTemplateTypeParmType>(X),
|
|
|
|
|
*SY = cast<SubstTemplateTypeParmType>(Y);
|
|
|
|
|
const TemplateTypeParmType *PX = SX->getReplacedParameter();
|
|
|
|
|
if (PX != SY->getReplacedParameter())
|
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
|
|
return Ctx.getSubstTemplateTypeParmType(PX,
|
|
|
|
|
Ctx.getQualifiedType(Underlying));
|
|
|
|
|
}
|
|
|
|
|
case Type::ObjCTypeParam:
|
|
|
|
|
// FIXME: Try to merge these.
|
|
|
|
|
return QualType();
|
|
|
|
|
case Type::Paren:
|
|
|
|
|
return Ctx.getParenType(Ctx.getQualifiedType(Underlying));
|
|
|
|
|
|
|
|
|
|
case Type::TemplateSpecialization: {
|
|
|
|
|
const auto *TX = cast<TemplateSpecializationType>(X),
|
|
|
|
|
*TY = cast<TemplateSpecializationType>(Y);
|
|
|
|
|
TemplateName CTN = ::getCommonTemplateName(Ctx, TX->getTemplateName(),
|
|
|
|
|
TY->getTemplateName());
|
|
|
|
|
if (!CTN.getAsVoidPointer())
|
|
|
|
|
return QualType();
|
|
|
|
|
SmallVector<TemplateArgument, 8> Args;
|
|
|
|
|
if (getCommonTemplateArguments(Ctx, Args, TX->template_arguments(),
|
|
|
|
|
TY->template_arguments()))
|
|
|
|
|
return QualType();
|
|
|
|
|
return Ctx.getTemplateSpecializationType(CTN, Args,
|
|
|
|
|
Ctx.getQualifiedType(Underlying));
|
|
|
|
|
}
|
|
|
|
|
case Type::Typedef: {
|
|
|
|
|
const auto *TX = cast<TypedefType>(X), *TY = cast<TypedefType>(Y);
|
|
|
|
|
const TypedefNameDecl *CD = ::getCommonDecl(TX->getDecl(), TY->getDecl());
|
|
|
|
|
if (!CD)
|
|
|
|
|
return QualType();
|
|
|
|
|
return Ctx.getTypedefType(CD, Ctx.getQualifiedType(Underlying));
|
|
|
|
|
}
|
|
|
|
|
case Type::TypeOf:
|
|
|
|
|
return Ctx.getTypeOfType(Ctx.getQualifiedType(Underlying));
|
|
|
|
|
case Type::TypeOfExpr:
|
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
|
|
case Type::UnaryTransform: {
|
|
|
|
|
const auto *UX = cast<UnaryTransformType>(X),
|
|
|
|
|
*UY = cast<UnaryTransformType>(Y);
|
|
|
|
|
UnaryTransformType::UTTKind KX = UX->getUTTKind();
|
|
|
|
|
if (KX != UY->getUTTKind())
|
|
|
|
|
return QualType();
|
|
|
|
|
QualType BX = UX->getBaseType(), BY = UY->getBaseType();
|
|
|
|
|
if (!Ctx.hasSameType(BX, BY))
|
|
|
|
|
return QualType();
|
|
|
|
|
// FIXME: It's inefficient to have to unify the base types.
|
|
|
|
|
return Ctx.getUnaryTransformType(Ctx.getCommonSugaredType(BX, BY),
|
|
|
|
|
Ctx.getQualifiedType(Underlying), KX);
|
|
|
|
|
}
|
|
|
|
|
case Type::Using: {
|
|
|
|
|
const auto *UX = cast<UsingType>(X), *UY = cast<UsingType>(Y);
|
|
|
|
|
const UsingShadowDecl *CD =
|
|
|
|
|
::getCommonDecl(UX->getFoundDecl(), UY->getFoundDecl());
|
|
|
|
|
if (!CD)
|
|
|
|
|
return QualType();
|
|
|
|
|
return Ctx.getUsingType(CD, Ctx.getQualifiedType(Underlying));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
llvm_unreachable("Unhandled Type Class");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static auto unwrapSugar(SplitQualType &T, Qualifiers &QTotal) {
|
|
|
|
|
SmallVector<SplitQualType, 8> R;
|
|
|
|
|
while (true) {
|
|
|
|
|
QTotal += T.Quals;
|
|
|
|
|
QualType NT = T.Ty->getLocallyUnqualifiedSingleStepDesugaredType();
|
|
|
|
|
if (NT == QualType(T.Ty, 0))
|
|
|
|
|
break;
|
|
|
|
|
SplitQualType SplitNT = NT.split();
|
|
|
|
|
SplitNT.Quals += T.Quals;
|
|
|
|
|
R.push_back(T);
|
|
|
|
|
T = SplitNT;
|
|
|
|
|
T = NT.split();
|
|
|
|
|
}
|
|
|
|
|
return R;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool removeDifferentTopLevelSugar(SplitQualType &SX, SplitQualType &SY) {
|
|
|
|
|
auto Xs = ::unwrapSugar(SX), Ys = ::unwrapSugar(SY);
|
|
|
|
|
if (SX.Ty != SY.Ty)
|
|
|
|
|
return true;
|
|
|
|
|
while (!Xs.empty() && !Ys.empty() && Xs.back().Ty == Ys.back().Ty) {
|
|
|
|
|
SX = Xs.pop_back_val();
|
|
|
|
|
SY = Ys.pop_back_val();
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QualType ASTContext::getCommonSugaredType(QualType X, QualType Y,
|
|
|
|
|
bool Unqualified) {
|
|
|
|
|
assert(Unqualified ? hasSameUnqualifiedType(X, Y) : hasSameType(X, Y));
|
|
|
|
@ -12722,15 +12952,52 @@ QualType ASTContext::getCommonSugaredType(QualType X, QualType Y,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SplitQualType SX = X.split(), SY = Y.split();
|
|
|
|
|
if (::removeDifferentTopLevelSugar(SX, SY))
|
|
|
|
|
SX.Ty = ::getCommonType(*this, SX, SY).getTypePtr();
|
|
|
|
|
|
|
|
|
|
Qualifiers QX, QY;
|
|
|
|
|
// Desugar SX and SY, setting the sugar and qualifiers aside into Xs and Ys,
|
|
|
|
|
// until we reach their underlying "canonical nodes". Note these are not
|
|
|
|
|
// necessarily canonical types, as they may still have sugared properties.
|
|
|
|
|
// QX and QY will store the sum of all qualifiers in Xs and Ys respectively.
|
|
|
|
|
auto Xs = ::unwrapSugar(SX, QX), Ys = ::unwrapSugar(SY, QY);
|
|
|
|
|
if (SX.Ty != SY.Ty) {
|
|
|
|
|
// The canonical nodes differ. Build a common canonical node out of the two,
|
|
|
|
|
// unifying their sugar. This may recurse back here.
|
|
|
|
|
SX.Ty =
|
|
|
|
|
::getCommonNonSugarTypeNode(*this, SX.Ty, QX, SY.Ty, QY).getTypePtr();
|
|
|
|
|
} else {
|
|
|
|
|
// The canonical nodes were identical: We may have desugared too much.
|
|
|
|
|
// Add any common sugar back in.
|
|
|
|
|
while (!Xs.empty() && !Ys.empty() && Xs.back().Ty == Ys.back().Ty) {
|
|
|
|
|
QX -= SX.Quals;
|
|
|
|
|
QY -= SY.Quals;
|
|
|
|
|
SX = Xs.pop_back_val();
|
|
|
|
|
SY = Ys.pop_back_val();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (Unqualified)
|
|
|
|
|
SX.Quals = Qualifiers::removeCommonQualifiers(SX.Quals, SY.Quals);
|
|
|
|
|
QX = Qualifiers::removeCommonQualifiers(QX, QY);
|
|
|
|
|
else
|
|
|
|
|
assert(SX.Quals == SY.Quals);
|
|
|
|
|
assert(QX == QY);
|
|
|
|
|
|
|
|
|
|
QualType R = getQualifiedType(SX);
|
|
|
|
|
// Even though the remaining sugar nodes in Xs and Ys differ, some may be
|
|
|
|
|
// related. Walk up these nodes, unifying them and adding the result.
|
|
|
|
|
while (!Xs.empty() && !Ys.empty()) {
|
|
|
|
|
auto Underlying = SplitQualType(
|
|
|
|
|
SX.Ty, Qualifiers::removeCommonQualifiers(SX.Quals, SY.Quals));
|
|
|
|
|
SX = Xs.pop_back_val();
|
|
|
|
|
SY = Ys.pop_back_val();
|
|
|
|
|
SX.Ty = ::getCommonSugarTypeNode(*this, SX.Ty, SY.Ty, Underlying)
|
|
|
|
|
.getTypePtrOrNull();
|
|
|
|
|
// Stop at the first pair which is unrelated.
|
|
|
|
|
if (!SX.Ty) {
|
|
|
|
|
SX.Ty = Underlying.Ty;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
QX -= Underlying.Quals;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Add back the missing accumulated qualifiers, which were stripped off
|
|
|
|
|
// with the sugar nodes we could not unify.
|
|
|
|
|
QualType R = getQualifiedType(SX.Ty, QX);
|
|
|
|
|
assert(Unqualified ? hasSameUnqualifiedType(R, X) : hasSameType(R, X));
|
|
|
|
|
return R;
|
|
|
|
|
}
|
|
|
|
|