[clang] [clang-tools-extra] [clang] improve class type sugar preservation in pointers to members (PR #130537)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 10 08:02:31 PDT 2025
================
@@ -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
More information about the cfe-commits
mailing list