Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

vitalybuka
Copy link
Collaborator

@vitalybuka vitalybuka commented Sep 12, 2025

According GCC documentation transparent union
calling convention is the same as the type of the
first member of the union.

C++ ignores attribute.

Note, it does not generalize args of function pointer args.
It's unnecessary with pointer generalization.
It will be fixed in followup patch.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:codegen IR generation bugs: mangling, exceptions, etc. labels Sep 12, 2025
@llvmbot
Copy link
Member

llvmbot commented Sep 12, 2025

@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-clang

Author: Vitaly Buka (vitalybuka)

Changes

According GCC documentation transparent union
calling convention is the same as the type of the
first member of the union.

C++ ignores attribute.


Full diff: https://github.com/llvm/llvm-project/pull/158193.diff

5 Files Affected:

  • (modified) clang/lib/CodeGen/CodeGenModule.cpp (+17-1)
  • (modified) clang/test/CodeGen/cfi-icall-generalize.c (+4-4)
  • (modified) clang/test/CodeGen/cfi-icall-normalize2.c (+2-2)
  • (modified) clang/test/CodeGen/kcfi-generalize.c (+4-4)
  • (modified) clang/test/CodeGen/kcfi-normalize.c (+6-4)
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index c647003ff389d..46dbd85665e5d 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2339,13 +2339,29 @@ llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) {
   return llvm::ConstantInt::get(Int64Ty, llvm::MD5Hash(MDS->getString()));
 }
 
+static QualType GeneralizeTransparentUnion(QualType Ty) {
+  const RecordType *UT = Ty->getAsUnionType();
+  if (!UT)
+    return Ty;
+  const RecordDecl *UD = UT->getOriginalDecl()->getDefinitionOrSelf();
+  if (!UD->hasAttr<TransparentUnionAttr>())
+    return Ty;
+  for (const auto *it : UD->fields()) {
+    return it->getType();
+  }
+  return Ty;
+}
+
+static QualType GeneralizeTransparentUnion(QualType Ty) {
+}
+
 // Generalize pointer types to a void pointer with the qualifiers of the
 // originally pointed-to type, e.g. 'const char *' and 'char * const *'
 // generalize to 'const void *' while 'char *' and 'const char **' generalize to
 // 'void *'.
 static QualType GeneralizeType(ASTContext &Ctx, QualType Ty,
                                bool GeneralizePointers) {
-  // TODO: Add other generalizations.
+  Ty = GeneralizeTransparentUnion(Ty);
 
   if (!GeneralizePointers || !Ty->isPointerType())
     return Ty;
diff --git a/clang/test/CodeGen/cfi-icall-generalize.c b/clang/test/CodeGen/cfi-icall-generalize.c
index 116a99e4e2859..5359134805198 100644
--- a/clang/test/CodeGen/cfi-icall-generalize.c
+++ b/clang/test/CodeGen/cfi-icall-generalize.c
@@ -22,13 +22,13 @@ union Union {
 
 // CHECK: define{{.*}} void @uni({{.*}} !type [[TYPE2:![0-9]+]] !type [[TYPE2_GENERALIZED:![0-9]+]]
 void uni(void (*fn)(union Union), union Union arg1) {
-  // UNGENERALIZED: call i1 @llvm.type.test(ptr {{.*}}, metadata !"_ZTSFv5UnionE")
-  // GENERALIZED: call i1 @llvm.type.test(ptr {{.*}}, metadata !"_ZTSFv5UnionE.generalized")
+  // UNGENERALIZED: call i1 @llvm.type.test(ptr {{.*}}, metadata !"_ZTSFvPcE")
+  // GENERALIZED: call i1 @llvm.type.test(ptr {{.*}}, metadata !"_ZTSFvPvE.generalized")
     fn(arg1);
 }
 
 // CHECK: [[TYPE]] = !{i64 0, !"_ZTSFPPiPKcPS2_E"}
 // CHECK: [[TYPE_GENERALIZED]] = !{i64 0, !"_ZTSFPvPKvS_E.generalized"}
 
-// CHECK: [[TYPE2]] = !{i64 0, !"_ZTSFvPFv5UnionES_E"}
-// CHECK: [[TYPE2_GENERALIZED]] = !{i64 0, !"_ZTSFvPv5UnionE.generalized"}
+// CHECK: [[TYPE2]] = !{i64 0, !"_ZTSFvPFv5UnionEPcE"}
+// CHECK: [[TYPE2_GENERALIZED]] = !{i64 0, !"_ZTSFvPvS_E.generalized"}
diff --git a/clang/test/CodeGen/cfi-icall-normalize2.c b/clang/test/CodeGen/cfi-icall-normalize2.c
index c88ecc9f0c3f7..b9d9af7c8a47b 100644
--- a/clang/test/CodeGen/cfi-icall-normalize2.c
+++ b/clang/test/CodeGen/cfi-icall-normalize2.c
@@ -32,11 +32,11 @@ union Union {
 void uni(void (*fn)(union Union), union Union arg1) {
     // CHECK-LABEL: define{{.*}}uni
     // CHECK-SAME: {{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}}
-    // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFv5UnionE.normalized")
+    // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFvPu2i8E.normalized")
     fn(arg1);
 }
 
 // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvPFvu3i32ES_E.normalized"}
 // CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvPFvu3i32S_ES_S_E.normalized"}
 // CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvPFvu3i32S_S_ES_S_S_E.normalized"}
-// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvPFv5UnionES_E.normalized"}
+// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvPFv5UnionEPu2i8E.normalized"}
diff --git a/clang/test/CodeGen/kcfi-generalize.c b/clang/test/CodeGen/kcfi-generalize.c
index 89b298f3e2faa..24e054549d527 100644
--- a/clang/test/CodeGen/kcfi-generalize.c
+++ b/clang/test/CodeGen/kcfi-generalize.c
@@ -33,8 +33,8 @@ union Union {
 
 // CHECK: define{{.*}} void @uni({{.*}} !kcfi_type [[TYPE2:![0-9]+]]
 void uni(void (*fn)(union Union), union Union arg1) {
-  // UNGENERALIZED: call {{.*}} [ "kcfi"(i32 -1037059548) ]
-  // GENERALIZED: call {{.*}} [ "kcfi"(i32 422130955) ]
+  // UNGENERALIZED: call {{.*}} [ "kcfi"(i32 -587217045) ]
+  // GENERALIZED: call {{.*}} [ "kcfi"(i32 2139530422) ]
     fn(arg1);
 }
 
@@ -44,5 +44,5 @@ void uni(void (*fn)(union Union), union Union arg1) {
 // UNGENERALIZED: [[TYPE3]] = !{i32 874141567}
 // GENERALIZED: [[TYPE3]] = !{i32 954385378}
 
-// UNGENERALIZED: [[TYPE2]] = !{i32 981319178}
-// GENERALIZED: [[TYPE2]] = !{i32 -1599950473}
\ No newline at end of file
+// UNGENERALIZED: [[TYPE2]] = !{i32 -1619636625}
+// GENERALIZED: [[TYPE2]] = !{i32 -125078496}
\ No newline at end of file
diff --git a/clang/test/CodeGen/kcfi-normalize.c b/clang/test/CodeGen/kcfi-normalize.c
index cde784962d11a..08f5249b6d6c3 100644
--- a/clang/test/CodeGen/kcfi-normalize.c
+++ b/clang/test/CodeGen/kcfi-normalize.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi -fsanitize-cfi-icall-experimental-normalize-integers -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi -fsanitize-cfi-icall-experimental-normalize-integers -x c++ -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi -fsanitize-cfi-icall-experimental-normalize-integers -o - %s | FileCheck %s --check-prefixes=CHECK,C
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi -fsanitize-cfi-icall-experimental-normalize-integers -x c++ -o - %s | FileCheck %s --check-prefixes=CHECK,CPP
 #if !__has_feature(kcfi)
 #error Missing kcfi?
 #endif
@@ -36,7 +36,8 @@ union Union {
 void uni(void (*fn)(union Union), union Union arg1) {
     // CHECK-LABEL: define{{.*}}uni
     // CHECK-SAME: {{.*}}!kcfi_type ![[TYPE4:[0-9]+]]
-    // CHECK: call void %0(ptr %1) [ "kcfi"(i32 -1430221633) ]
+    // C: call void %0(ptr %1) [ "kcfi"(i32 1819770848) ]
+    // CPP: call void %0(ptr %1) [ "kcfi"(i32 -1430221633) ]
     fn(arg1);
 }
 
@@ -44,4 +45,5 @@ void uni(void (*fn)(union Union), union Union arg1) {
 // CHECK: ![[TYPE1]] = !{i32 -1143117868}
 // CHECK: ![[TYPE2]] = !{i32 -460921415}
 // CHECK: ![[TYPE3]] = !{i32 -333839615}
-// CHECK: ![[TYPE4]] = !{i32 1766237188}
\ No newline at end of file
+// C: ![[TYPE4]] = !{i32 -650530463}
+// CPP: ![[TYPE4]] = !{i32 1766237188}
\ No newline at end of file

Copy link

github-actions bot commented Sep 12, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Created using spr 1.3.6
Created using spr 1.3.6

[skip ci]
Created using spr 1.3.6
Created using spr 1.3.6

[skip ci]
Created using spr 1.3.6
Created using spr 1.3.6

[skip ci]
Created using spr 1.3.6
Created using spr 1.3.6

[skip ci]
Created using spr 1.3.6
vitalybuka added a commit that referenced this pull request Sep 12, 2025
vitalybuka added a commit that referenced this pull request Sep 13, 2025
Created using spr 1.3.6

[skip ci]
Created using spr 1.3.6
@vitalybuka vitalybuka changed the base branch from users/vitalybuka/spr/main.codegencfi-generalize-transparent-union-parameters to main September 13, 2025 01:51
@vitalybuka vitalybuka enabled auto-merge (squash) September 13, 2025 01:51
@vitalybuka vitalybuka merged commit 004f209 into main Sep 13, 2025
12 of 15 checks passed
@vitalybuka vitalybuka deleted the users/vitalybuka/spr/codegencfi-generalize-transparent-union-parameters branch September 13, 2025 02:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen IR generation bugs: mangling, exceptions, etc. clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants