https://github.com/andykaylor created 
https://github.com/llvm/llvm-project/pull/221371

CIR currently has no way to represent atomic types. In most cases this has no 
meaningful effect, but it can lead to incorrect argument and return type 
classification during calling convention lowering. This change adds a 
diagnostic when we are processing function signatures with atomic types.

Assisted-by: Cursor / Grok 4.6

>From a2a85db3aa25f849a4ed3e0d078599a5fd516970 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <[email protected]>
Date: Fri, 4 Sep 2026 15:58:09 -0700
Subject: [PATCH] [CIR] Report errorNYI for function signatures involving
 atomic types

CIR currently has no way to represent atomic types. In most cases this
has no meaningful effect, but it can lead to incorrect argument and
return type classification during calling convention lowering. This
change adds a diagnostic when we are processing function signatures with
atomic types.

Assisted-by: Cursor / Grok 4.6
---
 clang/lib/CIR/CodeGen/CIRGenTypes.cpp  | 31 +++++++++++
 clang/test/CIR/CodeGen/atomic-fn-nyi.c | 74 ++++++++++++++++++++++++++
 2 files changed, 105 insertions(+)
 create mode 100644 clang/test/CIR/CodeGen/atomic-fn-nyi.c

diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp 
b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index f2cb875e908a7..a167e7a8bbf50 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -773,12 +773,43 @@ 
CIRGenTypes::clangCallConvToCIRCallConv(clang::CallingConv cc) {
   }
 }
 
+/// Whether a by-value ABI type is `_Atomic` or contains an `_Atomic` member.
+/// Pointers and references are not walked: `_Atomic(T)*` is just a pointer.
+static bool typeContainsAtomicForABI(QualType ty, ASTContext &ctx) {
+  ty = ty.getCanonicalType().getUnqualifiedType();
+  if (ty->isAtomicType())
+    return true;
+
+  if (const ArrayType *arrayTy = ctx.getAsArrayType(ty))
+    return typeContainsAtomicForABI(arrayTy->getElementType(), ctx);
+
+  const RecordDecl *rd = ty->getAsRecordDecl();
+  if (!rd || !rd->getDefinition())
+    return false;
+
+  if (const CXXRecordDecl *cxxRD = dyn_cast<CXXRecordDecl>(rd)) {
+    for (const CXXBaseSpecifier &base : cxxRD->bases())
+      if (typeContainsAtomicForABI(base.getType(), ctx))
+        return true;
+  }
+
+  for (const FieldDecl *field : rd->fields())
+    if (typeContainsAtomicForABI(field->getType(), ctx))
+      return true;
+  return false;
+}
+
 const CIRGenFunctionInfo &CIRGenTypes::arrangeCIRFunctionInfo(
     CanQualType returnType, bool isInstanceMethod,
     llvm::ArrayRef<CanQualType> argTypes, FunctionType::ExtInfo info,
     RequiredArgs required) {
   assert(llvm::all_of(argTypes,
                       [](CanQualType t) { return t.isCanonicalAsParam(); }));
+  auto containsAtomic = [&](CanQualType t) {
+    return typeContainsAtomicForABI(t, astContext);
+  };
+  if (containsAtomic(returnType) || llvm::any_of(argTypes, containsAtomic))
+    cgm.errorNYI("passing or returning atomic types");
   // Lookup or create unique function info.
   llvm::FoldingSetNodeID id;
   CIRGenFunctionInfo::Profile(id, isInstanceMethod, info, required, returnType,
diff --git a/clang/test/CIR/CodeGen/atomic-fn-nyi.c 
b/clang/test/CIR/CodeGen/atomic-fn-nyi.c
new file mode 100644
index 0000000000000..023c5d645bad5
--- /dev/null
+++ b/clang/test/CIR/CodeGen/atomic-fn-nyi.c
@@ -0,0 +1,74 @@
+// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir \
+// RUN:   -emit-cir -DARG %s -o %t.cir 2>&1 | FileCheck %s --check-prefix=NYI
+// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir \
+// RUN:   -emit-cir -DRET %s -o %t.cir 2>&1 | FileCheck %s --check-prefix=NYI
+// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir \
+// RUN:   -emit-cir -DSTRUCT %s -o %t.cir 2>&1 | FileCheck %s 
--check-prefix=NYI
+// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir \
+// RUN:   -emit-cir -DARRAY %s -o %t.cir 2>&1 | FileCheck %s --check-prefix=NYI
+// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir \
+// RUN:   -emit-cir -x c++ -DBASE %s -o %t.cir 2>&1 | FileCheck %s \
+// RUN:   --check-prefix=NYI
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir \
+// RUN:   -DPTR %s -o %t.cir
+// RUN: FileCheck --check-prefix=PTR --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir \
+// RUN:   -DDECAY %s -o %t.cir
+// RUN: FileCheck --check-prefix=DECAY --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir \
+// RUN:   -x c++ -DREF %s -o %t.cir
+// RUN: FileCheck --check-prefix=REF --input-file=%t.cir %s
+
+// NYI: ClangIR code gen Not Yet Implemented: passing or returning atomic types
+
+#ifdef ARG
+void atomic_arg(_Atomic int x) {}
+#endif
+
+#ifdef RET
+_Atomic int atomic_ret(void) { return 0; }
+#endif
+
+#ifdef STRUCT
+struct HasAtomic {
+  _Atomic int x;
+};
+void atomic_struct(struct HasAtomic s) {}
+#endif
+
+#ifdef ARRAY
+struct HasAtomicArray {
+  _Atomic int a[2];
+};
+void atomic_array(struct HasAtomicArray s) {}
+#endif
+
+#ifdef BASE
+struct AtomicBase {
+  _Atomic int x;
+};
+struct AtomicDerived : AtomicBase {};
+void atomic_base(AtomicDerived d) {}
+#endif
+
+#ifdef PTR
+void atomic_ptr(_Atomic int *p) {}
+struct HasAtomicPtr {
+  _Atomic int *p;
+};
+void atomic_ptr_in_struct(struct HasAtomicPtr s) {}
+// PTR-LABEL: @atomic_ptr
+// PTR-LABEL: @atomic_ptr_in_struct
+#endif
+
+#ifdef DECAY
+// Array parameters decay to pointers, so this is not an atomic by-value ABI
+// type.
+void atomic_array_param(_Atomic int a[2]) {}
+// DECAY-LABEL: @atomic_array_param
+#endif
+
+#ifdef REF
+void atomic_ref(_Atomic int &x) {}
+// REF-LABEL: @_Z10atomic_refRU7_Atomici
+#endif

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to