[clang] [TBAA] Don't emit pointer tbaa for unnamed structs or unions. (PR #116596)

Florian Hahn via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 21 13:14:33 PST 2024


https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/116596

>From df9460221a937f9a705f6ddf7c080ca9b7fa4e3f Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Sun, 17 Nov 2024 20:07:57 +0000
Subject: [PATCH 1/3] [TBAA] Don't emit pointer tbaa for unnamed structs or
 unions.

For unnamed structs or unions, C's compatible types rule applies.
Two compatible types in different compilation units can have different
mangled names, meaning the metadata emitted below would incorrectly mark
them as no-alias. Use AnyPtr for such types in both C and C++, as C and
C++ types may be visible when doing LTO.
---
 clang/lib/CodeGen/CodeGenTBAA.cpp  | 9 +++++++++
 clang/test/CodeGen/tbaa-pointers.c | 5 +----
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp
index 4bcb541156bd23..9064cff2f8b8b4 100644
--- a/clang/lib/CodeGen/CodeGenTBAA.cpp
+++ b/clang/lib/CodeGen/CodeGenTBAA.cpp
@@ -249,6 +249,15 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
       if (!Ty->isRecordType())
         return AnyPtr;
 
+      // For unnamed structs or unions C's compatible types rule applies. Two
+      // compatible types in different compilation units can have different
+      // mangled names, meaning the metadata emitted below would incorrectly
+      // mark them as no-alias. Use AnyPtr for such types in both C and C++, as
+      // C and C++ types may be visible when doing LTO.
+      const auto *RT = Ty->getAs<RecordType>();
+      if (RT && !RT->getDecl()->getDeclName())
+        return AnyPtr;
+
       // For non-builtin types use the mangled name of the canonical type.
       llvm::raw_svector_ostream TyOut(TyName);
       MangleCtx->mangleCanonicalTypeName(QualType(Ty, 0), TyOut);
diff --git a/clang/test/CodeGen/tbaa-pointers.c b/clang/test/CodeGen/tbaa-pointers.c
index 9417a0e2f09e8c..068459f4dce118 100644
--- a/clang/test/CodeGen/tbaa-pointers.c
+++ b/clang/test/CodeGen/tbaa-pointers.c
@@ -190,8 +190,6 @@ typedef struct {
   int i1;
 } TypedefS;
 
-// FIXME: The !tbaa tag for unnamed structs doesn't account for compatible
-// types in C.
 void unamed_struct_typedef(TypedefS *ptr) {
 // COMMON-LABEL: define void @unamed_struct_typedef(
 // COMMON-SAME: ptr noundef [[PTRA:%.+]])
@@ -238,5 +236,4 @@ void unamed_struct_typedef(TypedefS *ptr) {
 // DEFAULT: [[S2_TY]]  = !{!"S2", [[ANY_POINTER]], i64 0}
 // COMMON:  [[INT_TAG]] = !{[[INT_TY:!.+]], [[INT_TY]], i64 0}
 // COMMON:  [[INT_TY]] = !{!"int", [[CHAR]], i64 0}
-// ENABLED: [[P1TYPEDEF]] = !{[[P1TYPEDEF_TY:!.+]],  [[P1TYPEDEF_TY]], i64 0}
-// ENABLED: [[P1TYPEDEF_TY]] = !{!"p1 _ZTS8TypedefS", [[ANY_POINTER]], i64 0}
+// ENABLED: [[P1TYPEDEF]] = !{[[ANY_POINTER]],  [[ANY_POINTER]], i64 0}

>From fe01d7e9339196ae6b5642ec78ddd082265ec417 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Wed, 20 Nov 2024 19:11:37 +0000
Subject: [PATCH 2/3] !fixup add clarifying note as suggested, thanks!

---
 clang/lib/CodeGen/CodeGenTBAA.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp
index 9064cff2f8b8b4..d94bb3f3d79ba6 100644
--- a/clang/lib/CodeGen/CodeGenTBAA.cpp
+++ b/clang/lib/CodeGen/CodeGenTBAA.cpp
@@ -254,6 +254,12 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
       // mangled names, meaning the metadata emitted below would incorrectly
       // mark them as no-alias. Use AnyPtr for such types in both C and C++, as
       // C and C++ types may be visible when doing LTO.
+      //
+      // Note that using AnyPtr is overly conservative. We could summarize the
+      // members of the type, as per the C compatibility rule in the future.
+      // This also covers anonymous structs and unions, which have a different
+      // compatibility rule, but it doesn't matter because you can never have a
+      // pointer to an anonymous struct or union.
       const auto *RT = Ty->getAs<RecordType>();
       if (RT && !RT->getDecl()->getDeclName())
         return AnyPtr;

>From 796ccf850495d9946d6e92d33233e770dc26fade Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Thu, 21 Nov 2024 21:13:42 +0000
Subject: [PATCH 3/3] !fixup Move up getAs<>() as suggested

---
 clang/lib/CodeGen/CodeGenTBAA.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp
index d94bb3f3d79ba6..6eed8e1d2b671a 100644
--- a/clang/lib/CodeGen/CodeGenTBAA.cpp
+++ b/clang/lib/CodeGen/CodeGenTBAA.cpp
@@ -246,7 +246,8 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
       // Be conservative if the type isn't a RecordType. We are specifically
       // required to do this for member pointers until we implement the
       // similar-types rule.
-      if (!Ty->isRecordType())
+      const auto *RT = Ty->getAs<RecordType>();
+      if (!RT)
         return AnyPtr;
 
       // For unnamed structs or unions C's compatible types rule applies. Two
@@ -260,8 +261,7 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
       // This also covers anonymous structs and unions, which have a different
       // compatibility rule, but it doesn't matter because you can never have a
       // pointer to an anonymous struct or union.
-      const auto *RT = Ty->getAs<RecordType>();
-      if (RT && !RT->getDecl()->getDeclName())
+      if (!RT->getDecl()->getDeclName())
         return AnyPtr;
 
       // For non-builtin types use the mangled name of the canonical type.



More information about the cfe-commits mailing list