================ @@ -13461,13 +13486,112 @@ static ElaboratedTypeKeyword getCommonTypeKeyword(const T *X, const T *Y) { : ElaboratedTypeKeyword::None; } +static NestedNameSpecifier *getCommonNNS(ASTContext &Ctx, + NestedNameSpecifier *X, + NestedNameSpecifier *Y, bool Sugar) { + if (X == Y) + return X; + + NestedNameSpecifier *Canon = Ctx.getCanonicalNestedNameSpecifier(X); + if (Canon != Ctx.getCanonicalNestedNameSpecifier(Y)) { + if (Sugar) + return nullptr; + llvm_unreachable("Should be the same NestedNameSpecifier"); + } + + NestedNameSpecifier *R; + switch (auto KX = X->getKind(), KY = Y->getKind(); KX) { + case NestedNameSpecifier::SpecifierKind::Identifier: { + assert(KY == NestedNameSpecifier::SpecifierKind::Identifier); + IdentifierInfo *II = X->getAsIdentifier(); + assert(II == Y->getAsIdentifier()); + NestedNameSpecifier *P = + ::getCommonNNS(Ctx, X->getPrefix(), Y->getPrefix(), /*Sugar=*/false); + R = NestedNameSpecifier::Create(Ctx, P, II); + break; + } + case NestedNameSpecifier::SpecifierKind::Namespace: + case NestedNameSpecifier::SpecifierKind::NamespaceAlias: { + assert(KY == NestedNameSpecifier::SpecifierKind::Namespace || + KY == NestedNameSpecifier::SpecifierKind::NamespaceAlias); + NestedNameSpecifier *P = ::getCommonNNS(Ctx, X->getPrefix(), Y->getPrefix(), + /*Sugar=*/true); + NamespaceAliasDecl *AX = X->getAsNamespaceAlias(), + *AY = Y->getAsNamespaceAlias(); + if (declaresSameEntity(AX, AY)) { + R = NestedNameSpecifier::Create(Ctx, P, ::getCommonDeclChecked(AX, AY)); + break; + } + NamespaceDecl *NX = AX ? AX->getNamespace() : X->getAsNamespace(), + *NY = AY ? AY->getNamespace() : Y->getAsNamespace(); + R = NestedNameSpecifier::Create(Ctx, P, ::getCommonDeclChecked(NX, NY)); + break; + } + case NestedNameSpecifier::SpecifierKind::TypeSpec: + case NestedNameSpecifier::SpecifierKind::TypeSpecWithTemplate: { + assert(KY == NestedNameSpecifier::SpecifierKind::TypeSpec || + KY == NestedNameSpecifier::SpecifierKind::TypeSpecWithTemplate); + bool Template = + KX == NestedNameSpecifier::SpecifierKind::TypeSpecWithTemplate && + KY == NestedNameSpecifier::SpecifierKind::TypeSpecWithTemplate; + + const Type *TX = X->getAsType(), *TY = Y->getAsType(); + if (TX == TY) { + NestedNameSpecifier *P = + ::getCommonNNS(Ctx, X->getPrefix(), Y->getPrefix(), + /*Sugar=*/true); + R = NestedNameSpecifier::Create(Ctx, P, Template, TX); + break; + } + // TODO: Try to salvage the original prefix. + // If getCommonSugaredType removed any top level sugar, the original prefix + // is not applicable anymore. + NestedNameSpecifier *P = nullptr; + const Type *T = Ctx.getCommonSugaredType(QualType(X->getAsType(), 0), + QualType(Y->getAsType(), 0), + /*Unqualified=*/true) + .getTypePtr(); + switch (T->getTypeClass()) { + case Type::Elaborated: { + auto *ET = cast<ElaboratedType>(T); + R = NestedNameSpecifier::Create(Ctx, ET->getQualifier(), Template, + ET->getNamedType().getTypePtr()); + break; + } + case Type::DependentName: { + auto *DN = cast<DependentNameType>(T); + R = NestedNameSpecifier::Create(Ctx, DN->getQualifier(), + DN->getIdentifier()); + break; + } + case Type::DependentTemplateSpecialization: { + auto *DTST = cast<DependentTemplateSpecializationType>(T); + T = Ctx.getDependentTemplateSpecializationType( + DTST->getKeyword(), /*NNS=*/nullptr, DTST->getIdentifier(), + DTST->template_arguments()) + .getTypePtr(); + P = DTST->getQualifier(); + R = NestedNameSpecifier::Create(Ctx, DTST->getQualifier(), Template, T); + break; + } + default: + R = NestedNameSpecifier::Create(Ctx, P, Template, T); + break; + } + break; + } + case NestedNameSpecifier::SpecifierKind::Global: + case NestedNameSpecifier::SpecifierKind::Super: + return X; ---------------- erichkeane wrote:
A sanity check to assert on 'y''s type also seems valuable here. https://github.com/llvm/llvm-project/pull/130537 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits