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
