https://github.com/qiongsiwu updated https://github.com/llvm/llvm-project/pull/200961
>From b2ffa916c4b4f43183fb90a47548f08e2986882b Mon Sep 17 00:00:00 2001 From: Qiongsi Wu <[email protected]> Date: Mon, 1 Jun 2026 14:54:21 -0700 Subject: [PATCH 1/2] Fixing attributed type deduplication. --- clang/include/clang/AST/Attr.h | 12 ++++++++++++ clang/include/clang/AST/TypeBase.h | 8 +------- clang/include/clang/Basic/Attr.td | 5 +++++ clang/lib/AST/Type.cpp | 11 +++++++++++ .../AST/attributed-type-dedup-nullability.m | 18 ++++++++++++++++++ .../AST/attributed-type-dedup-swift-attr.m | 15 +++++++++++++++ 6 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 clang/test/AST/attributed-type-dedup-nullability.m create mode 100644 clang/test/AST/attributed-type-dedup-swift-attr.m diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h index 0f9fc01391c30..df2da85cf6402 100644 --- a/clang/include/clang/AST/Attr.h +++ b/clang/include/clang/AST/Attr.h @@ -81,6 +81,8 @@ class Attr : public AttributeCommonInfo { return ::operator delete(Ptr, C, Alignment); } + virtual ~Attr() = default; + protected: Attr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, attr::Kind AK, bool IsLateParsed) @@ -120,6 +122,16 @@ class Attr : public AttributeCommonInfo { void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const; static StringRef getDocumentation(attr::Kind); + + // Contribute Attr-specific content to a FoldingSetNodeID for callers like + // AttributedType::Profile that dedupe nodes by Attr identity. The default + // is empty: AttributedType::Profile already hashes attrKind (and + // asserts attr->getKind() == attrKind), so a no-op default makes stateless + // Attrs (nullability, ARC ownership, calling conventions, ...) dedupe by + // (kind, modified, equivalent) — pointer identity of the Attr is ignored. + // Override this in subclasses whose arguments meaningfully distinguish + // the wrapped type (e.g. SwiftAttrAttr hashes its string payload). + virtual void Profile(llvm::FoldingSetNodeID &ID) const {} }; class TypeAttr : public Attr { diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h index c64eee11fd91e..cce7af88181cd 100644 --- a/clang/include/clang/AST/TypeBase.h +++ b/clang/include/clang/AST/TypeBase.h @@ -6746,13 +6746,7 @@ class AttributedType : public Type, public llvm::FoldingSetNode { } static void Profile(llvm::FoldingSetNodeID &ID, Kind attrKind, - QualType modified, QualType equivalent, - const Attr *attr) { - ID.AddInteger(attrKind); - ID.AddPointer(modified.getAsOpaquePtr()); - ID.AddPointer(equivalent.getAsOpaquePtr()); - ID.AddPointer(attr); - } + QualType modified, QualType equivalent, const Attr *attr); static bool classof(const Type *T) { return T->getTypeClass() == Attributed; diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 32f72e8da960e..533f13d2ca879 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3196,6 +3196,11 @@ def SwiftAttr : DeclOrTypeAttr { let Args = [StringArgument<"Attribute">]; let Documentation = [SwiftAttrDocs]; let PragmaAttributeSupport = 1; + let AdditionalMembers = [{ + void Profile(llvm::FoldingSetNodeID &ID) const override { + ID.AddString(getAttribute()); + } + }]; } def SwiftBridge : InheritableAttr { diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 96a398aa21dad..711b216d81de7 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -5338,6 +5338,17 @@ NullabilityKindOrNone AttributedType::stripOuterNullability(QualType &T) { return std::nullopt; } +void AttributedType::Profile(llvm::FoldingSetNodeID &ID, Kind attrKind, + QualType modified, QualType equivalent, + const Attr *attr) { + + ID.AddInteger(attrKind); + ID.AddPointer(modified.getAsOpaquePtr()); + ID.AddPointer(equivalent.getAsOpaquePtr()); + if (attr) + attr->Profile(ID); +} + bool Type::isSignableIntegerType(const ASTContext &Ctx) const { if (!isIntegralType(Ctx) || isEnumeralType()) return false; diff --git a/clang/test/AST/attributed-type-dedup-nullability.m b/clang/test/AST/attributed-type-dedup-nullability.m new file mode 100644 index 0000000000000..9904ec00913d0 --- /dev/null +++ b/clang/test/AST/attributed-type-dedup-nullability.m @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fobjc-arc -emit-pch -o %t.pch %s +// RUN: llvm-bcanalyzer --dump --disable-histogram %t.pch | FileCheck %s + +// All three non-null types below should share a single AttributedType node and +// serialize as exactly one TYPE_ATTRIBUTED record. + +@class NSString; + +#pragma clang assume_nonnull begin +@interface T +- (NSString *)a; +- (NSString *)b; +- (NSString *)c; +@end +#pragma clang assume_nonnull end + +// CHECK-COUNT-1: <TYPE_ATTRIBUTED +// CHECK-NOT: <TYPE_ATTRIBUTED diff --git a/clang/test/AST/attributed-type-dedup-swift-attr.m b/clang/test/AST/attributed-type-dedup-swift-attr.m new file mode 100644 index 0000000000000..d39778572eda5 --- /dev/null +++ b/clang/test/AST/attributed-type-dedup-swift-attr.m @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fobjc-arc -emit-pch -o %t.pch %s +// RUN: llvm-bcanalyzer --dump --disable-histogram %t.pch | FileCheck %s + +// Checks that swift_attr deduplication works correctly. +// The following test should generate two attributed types, not three. + +#define ATTR_A __attribute__((swift_attr("@A"))) +#define ATTR_B __attribute__((swift_attr("@B"))) + +void f1(int * ATTR_A p); +void f2(int * ATTR_A p); +void f3(int * ATTR_B p); + +// CHECK-COUNT-2: <TYPE_ATTRIBUTED +// CHECK-NOT: <TYPE_ATTRIBUTED >From 90f72abfe49e55b1c93eaa93640e9ba05ebd00f6 Mon Sep 17 00:00:00 2001 From: Qiongsi Wu <[email protected]> Date: Tue, 2 Jun 2026 10:52:23 -0700 Subject: [PATCH 2/2] Revise to make the fix more focused. Removed the virtual method Profile from the base Attr class. --- clang/include/clang/AST/Attr.h | 12 ------------ clang/include/clang/Basic/Attr.td | 2 +- clang/lib/AST/Type.cpp | 6 +++--- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h index df2da85cf6402..0f9fc01391c30 100644 --- a/clang/include/clang/AST/Attr.h +++ b/clang/include/clang/AST/Attr.h @@ -81,8 +81,6 @@ class Attr : public AttributeCommonInfo { return ::operator delete(Ptr, C, Alignment); } - virtual ~Attr() = default; - protected: Attr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, attr::Kind AK, bool IsLateParsed) @@ -122,16 +120,6 @@ class Attr : public AttributeCommonInfo { void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const; static StringRef getDocumentation(attr::Kind); - - // Contribute Attr-specific content to a FoldingSetNodeID for callers like - // AttributedType::Profile that dedupe nodes by Attr identity. The default - // is empty: AttributedType::Profile already hashes attrKind (and - // asserts attr->getKind() == attrKind), so a no-op default makes stateless - // Attrs (nullability, ARC ownership, calling conventions, ...) dedupe by - // (kind, modified, equivalent) — pointer identity of the Attr is ignored. - // Override this in subclasses whose arguments meaningfully distinguish - // the wrapped type (e.g. SwiftAttrAttr hashes its string payload). - virtual void Profile(llvm::FoldingSetNodeID &ID) const {} }; class TypeAttr : public Attr { diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 533f13d2ca879..44f8ea6d16532 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3197,7 +3197,7 @@ def SwiftAttr : DeclOrTypeAttr { let Documentation = [SwiftAttrDocs]; let PragmaAttributeSupport = 1; let AdditionalMembers = [{ - void Profile(llvm::FoldingSetNodeID &ID) const override { + void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddString(getAttribute()); } }]; diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 711b216d81de7..c9d038ec308ef 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -14,6 +14,7 @@ #include "Linkage.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" +#include "clang/AST/Attrs.inc" #include "clang/AST/CharUnits.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" @@ -5341,12 +5342,11 @@ NullabilityKindOrNone AttributedType::stripOuterNullability(QualType &T) { void AttributedType::Profile(llvm::FoldingSetNodeID &ID, Kind attrKind, QualType modified, QualType equivalent, const Attr *attr) { - ID.AddInteger(attrKind); ID.AddPointer(modified.getAsOpaquePtr()); ID.AddPointer(equivalent.getAsOpaquePtr()); - if (attr) - attr->Profile(ID); + if (const auto *A = dyn_cast_or_null<SwiftAttrAttr>(attr)) + A->Profile(ID); } bool Type::isSignableIntegerType(const ASTContext &Ctx) const { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
