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");
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
// 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());
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;
}
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: \
#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());
return Ctx.getAutoType(QualType(), AX->getKeyword(),
AX->isInstantiationDependentType(),
AX->containsUnexpandedParameterPack(),
- getCommonDecl(AX->getTypeConstraintConcept(),
- AY->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()
: 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),
.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);
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());
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(
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(),
- TY->getTemplateName()),
- As, TX->getCanonicalTypeInternal());
+ ::getCommonTemplateNameChecked(Ctx, TX->getTemplateName(),
+ TY->getTemplateName()),
+ 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());
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()),
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());
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));
}
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);
+
+ // 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;
+ };
- QualType R = getQualifiedType(SX);
+ // 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;
}