Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -118,6 +118,11 @@ Modified Compiler Flags ----------------------- +- Introducing a new default calling convention for ``-fdefault-calling-conv``: + ``rtdcall``. This new default CC only works for M68k and will use the new + ``m68k_rtdcc`` CC on every functions that are not variadic. The ``-mrtd`` + driver/frontend flag has the same effect when targeting M68k. + Removed Compiler Flags ------------------------- Index: clang/include/clang-c/Index.h =================================================================== --- clang/include/clang-c/Index.h +++ clang/include/clang-c/Index.h @@ -2976,6 +2976,7 @@ CXCallingConv_AArch64VectorCall = 16, CXCallingConv_SwiftAsync = 17, CXCallingConv_AArch64SVEPCS = 18, + CXCallingConv_M68kRTD = 19, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -2782,6 +2782,11 @@ let Documentation = [PreserveAllDocs]; } +def M68kRTD: DeclOrTypeAttr { + let Spellings = [Clang<"m68k_rtd">]; + let Documentation = [M68kRTDDocs]; +} + def Target : InheritableAttr { let Spellings = [GCC<"target">]; let Args = [StringArgument<"featuresStr">]; Index: clang/include/clang/Basic/AttrDocs.td =================================================================== --- clang/include/clang/Basic/AttrDocs.td +++ clang/include/clang/Basic/AttrDocs.td @@ -2821,6 +2821,18 @@ }]; } +def M68kRTDDocs : Documentation { + let Category = DocCatCallingConvs; + let Content = [{ +On M68k targets, this attribute changes the calling convention of a function +to clear parameters off the stack on return. In other words, callee is +responsible for cleaning out the stack space allocated for incoming paramters. +This convention does not support variadic calls or unprototyped functions in C. +When targeting M68010 or newer CPUs, this calling convention is implemented +using the `rtd` instruction. + }]; +} + def DocCatConsumed : DocumentationCategory<"Consumed Annotation Checking"> { let Content = [{ Clang supports additional attributes for checking basic resource management Index: clang/include/clang/Basic/LangOptions.h =================================================================== --- clang/include/clang/Basic/LangOptions.h +++ clang/include/clang/Basic/LangOptions.h @@ -133,7 +133,8 @@ DCC_FastCall, DCC_StdCall, DCC_VectorCall, - DCC_RegCall + DCC_RegCall, + DCC_RtdCall }; enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off }; Index: clang/include/clang/Basic/Specifiers.h =================================================================== --- clang/include/clang/Basic/Specifiers.h +++ clang/include/clang/Basic/Specifiers.h @@ -288,6 +288,7 @@ CC_AArch64VectorCall, // __attribute__((aarch64_vector_pcs)) CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs)) CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel)) + CC_M68kRTD, // __attribute__((m68k_rtd)) }; /// Checks whether the given calling convention supports variadic @@ -304,6 +305,7 @@ case CC_OpenCLKernel: case CC_Swift: case CC_SwiftAsync: + case CC_M68kRTD: return false; default: return true; Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -7340,9 +7340,9 @@ ImpliedByAnyOf<[open_cl.KeyPath, render_script.KeyPath, hlsl.KeyPath]>; def fdefault_calling_conv_EQ : Joined<["-"], "fdefault-calling-conv=">, HelpText<"Set default calling convention">, - Values<"cdecl,fastcall,stdcall,vectorcall,regcall">, + Values<"cdecl,fastcall,stdcall,vectorcall,regcall,rtdcall">, NormalizedValuesScope<"LangOptions">, - NormalizedValues<["DCC_CDecl", "DCC_FastCall", "DCC_StdCall", "DCC_VectorCall", "DCC_RegCall"]>, + NormalizedValues<["DCC_CDecl", "DCC_FastCall", "DCC_StdCall", "DCC_VectorCall", "DCC_RegCall", "DCC_RtdCall"]>, MarshallingInfoEnum, "DCC_None">; // These options cannot be marshalled, because they are used to set up the LangOptions defaults. Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -12007,6 +12007,10 @@ if (!IsVariadic) return CC_X86RegCall; break; + case LangOptions::DCC_RtdCall: + if (!IsVariadic) + return CC_M68kRTD; + break; } } return Target->getDefaultCallingConv(); Index: clang/lib/AST/ItaniumMangle.cpp =================================================================== --- clang/lib/AST/ItaniumMangle.cpp +++ clang/lib/AST/ItaniumMangle.cpp @@ -3273,6 +3273,7 @@ case CC_OpenCLKernel: case CC_PreserveMost: case CC_PreserveAll: + case CC_M68kRTD: // FIXME: we should be mangling all of the above. return ""; Index: clang/lib/AST/Type.cpp =================================================================== --- clang/lib/AST/Type.cpp +++ clang/lib/AST/Type.cpp @@ -3374,6 +3374,7 @@ case CC_SwiftAsync: return "swiftasynccall"; case CC_PreserveMost: return "preserve_most"; case CC_PreserveAll: return "preserve_all"; + case CC_M68kRTD: return "m68k_rtd"; } llvm_unreachable("Invalid calling convention."); @@ -3853,6 +3854,7 @@ case attr::IntelOclBicc: case attr::PreserveMost: case attr::PreserveAll: + case attr::M68kRTD: return true; } llvm_unreachable("invalid attr kind"); Index: clang/lib/AST/TypePrinter.cpp =================================================================== --- clang/lib/AST/TypePrinter.cpp +++ clang/lib/AST/TypePrinter.cpp @@ -1044,6 +1044,9 @@ case CC_PreserveAll: OS << " __attribute__((preserve_all))"; break; + case CC_M68kRTD: + OS << " __attribute__((m68k_rtd))"; + break; } } @@ -1879,6 +1882,9 @@ case attr::PreserveAll: OS << "preserve_all"; break; + case attr::M68kRTD: + OS << "m68k_rtd"; + break; case attr::NoDeref: OS << "noderef"; break; Index: clang/lib/Basic/Targets/M68k.h =================================================================== --- clang/lib/Basic/Targets/M68k.h +++ clang/lib/Basic/Targets/M68k.h @@ -54,6 +54,7 @@ std::string_view getClobbers() const override; BuiltinVaListKind getBuiltinVaListKind() const override; bool setCPU(const std::string &Name) override; + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override; }; } // namespace targets Index: clang/lib/Basic/Targets/M68k.cpp =================================================================== --- clang/lib/Basic/Targets/M68k.cpp +++ clang/lib/Basic/Targets/M68k.cpp @@ -250,5 +250,15 @@ return TargetInfo::VoidPtrBuiltinVaList; } +TargetInfo::CallingConvCheckResult +M68kTargetInfo::checkCallingConvention(CallingConv CC) const { + switch (CC) { + case CC_C: + case CC_M68kRTD: + return CCCR_OK; + default: + return TargetInfo::checkCallingConvention(CC); + } +} } // namespace targets } // namespace clang Index: clang/lib/CodeGen/CGCall.cpp =================================================================== --- clang/lib/CodeGen/CGCall.cpp +++ clang/lib/CodeGen/CGCall.cpp @@ -73,6 +73,7 @@ case CC_PreserveAll: return llvm::CallingConv::PreserveAll; case CC_Swift: return llvm::CallingConv::Swift; case CC_SwiftAsync: return llvm::CallingConv::SwiftTail; + case CC_M68kRTD: return llvm::CallingConv::M68k_RTD; } } @@ -253,6 +254,9 @@ if (D->hasAttr()) return CC_PreserveAll; + if (D->hasAttr()) + return CC_M68kRTD; + return CC_C; } Index: clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- clang/lib/CodeGen/CGDebugInfo.cpp +++ clang/lib/CodeGen/CGDebugInfo.cpp @@ -1442,6 +1442,8 @@ return llvm::dwarf::DW_CC_LLVM_PreserveAll; case CC_X86RegCall: return llvm::dwarf::DW_CC_LLVM_X86RegCall; + case CC_M68kRTD: + return llvm::dwarf::DW_CC_LLVM_M68kRTD; } return 0; } Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -5459,8 +5459,12 @@ } } - if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false)) - CmdArgs.push_back("-fdefault-calling-conv=stdcall"); + if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false)) { + if (Triple.getArch() == llvm::Triple::m68k) + CmdArgs.push_back("-fdefault-calling-conv=rtdcall"); + else + CmdArgs.push_back("-fdefault-calling-conv=stdcall"); + } if (Args.hasArg(options::OPT_fenable_matrix)) { // enable-matrix is needed by both the LangOpts and by LLVM. Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -554,6 +554,7 @@ emitError |= (DefaultCC == LangOptions::DCC_VectorCall || DefaultCC == LangOptions::DCC_RegCall) && !T.isX86(); + emitError |= DefaultCC == LangOptions::DCC_RtdCall && Arch != llvm::Triple::m68k; if (emitError) Diags.Report(diag::err_drv_argument_not_allowed_with) << A->getSpelling() << T.getTriple(); @@ -3754,11 +3755,17 @@ Diags.Report(diag::err_drv_argument_not_allowed_with) << A->getSpelling() << "-fdefault-calling-conv"; else { - if (T.getArch() != llvm::Triple::x86) + switch (T.getArch()) { + case llvm::Triple::x86: + Opts.setDefaultCallingConv(LangOptions::DCC_StdCall); + break; + case llvm::Triple::m68k: + Opts.setDefaultCallingConv(LangOptions::DCC_RtdCall); + break; + default: Diags.Report(diag::err_drv_argument_not_allowed_with) << A->getSpelling() << T.getTriple(); - else - Opts.setDefaultCallingConv(LangOptions::DCC_StdCall); + } } } Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -5209,6 +5209,9 @@ case ParsedAttr::AT_PreserveAll: D->addAttr(::new (S.Context) PreserveAllAttr(S.Context, AL)); return; + case ParsedAttr::AT_M68kRTD: + D->addAttr(::new (S.Context) M68kRTDAttr(S.Context, AL)); + return; default: llvm_unreachable("unexpected attribute kind"); } @@ -5405,6 +5408,9 @@ case ParsedAttr::AT_PreserveAll: CC = CC_PreserveAll; break; + case ParsedAttr::AT_M68kRTD: + CC = CC_M68kRTD; + break; default: llvm_unreachable("unexpected attribute kind"); } @@ -9282,6 +9288,7 @@ case ParsedAttr::AT_AArch64VectorPcs: case ParsedAttr::AT_AArch64SVEPcs: case ParsedAttr::AT_AMDGPUKernelCall: + case ParsedAttr::AT_M68kRTD: handleCallConvAttr(S, D, AL); break; case ParsedAttr::AT_Suppress: Index: clang/lib/Sema/SemaType.cpp =================================================================== --- clang/lib/Sema/SemaType.cpp +++ clang/lib/Sema/SemaType.cpp @@ -134,7 +134,8 @@ case ParsedAttr::AT_Pcs: \ case ParsedAttr::AT_IntelOclBicc: \ case ParsedAttr::AT_PreserveMost: \ - case ParsedAttr::AT_PreserveAll + case ParsedAttr::AT_PreserveAll: \ + case ParsedAttr::AT_M68kRTD // Function type attributes. #define FUNCTION_TYPE_ATTRS_CASELIST \ @@ -7771,6 +7772,8 @@ return createSimpleAttr(Ctx, Attr); case ParsedAttr::AT_PreserveAll: return createSimpleAttr(Ctx, Attr); + case ParsedAttr::AT_M68kRTD: + return createSimpleAttr(Ctx, Attr); } llvm_unreachable("unexpected attribute kind!"); } Index: clang/test/CodeGen/mrtd.c =================================================================== --- clang/test/CodeGen/mrtd.c +++ clang/test/CodeGen/mrtd.c @@ -1,20 +1,24 @@ -// RUN: %clang_cc1 -mrtd -triple i386-unknown-unknown -std=c89 -emit-llvm -o - %s 2>&1 | FileCheck %s - -// CHECK: mrtd.c:10:3: warning: function with no prototype cannot use the stdcall calling convention +// RUN: %clang_cc1 -mrtd -triple i386-unknown-unknown -std=c89 -emit-llvm -o - %s 2>&1 | FileCheck --check-prefixes=CHECK,X86 %s +// RUN: %clang_cc1 -mrtd -triple m68k-unknown-unknown -std=c89 -emit-llvm -o - %s 2>&1 | FileCheck --check-prefixes=CHECK,M68k %s void baz(int arg); -// CHECK: define{{.*}} x86_stdcallcc void @foo(i32 noundef %arg) [[NUW:#[0-9]+]] +// X86: define{{.*}} x86_stdcallcc void @foo(i32 noundef %arg) [[NUW:#[0-9]+]] +// M68k: define{{.*}} m68k_rtdcc void @foo(i32 noundef %arg) void foo(int arg) { -// CHECK: call x86_stdcallcc i32 @bar( +// X86: call x86_stdcallcc i32 @bar( +#ifndef mc68000 bar(arg); -// CHECK: call x86_stdcallcc void @baz(i32 +#endif +// X86: call x86_stdcallcc void @baz(i32 +// M68k: call m68k_rtdcc void @baz(i32 baz(arg); } -// CHECK: declare x86_stdcallcc i32 @bar(...) +// X86: declare x86_stdcallcc i32 @bar(...) -// CHECK: declare x86_stdcallcc void @baz(i32 noundef) +// X86: declare x86_stdcallcc void @baz(i32 noundef) +// M68k: declare m68k_rtdcc void @baz(i32 noundef) void qux(int arg, ...) { } // CHECK: define{{.*}} void @qux(i32 noundef %arg, ...) @@ -22,7 +26,8 @@ void quux(int a1, int a2, int a3) { qux(a1, a2, a3); } -// CHECK-LABEL: define{{.*}} x86_stdcallcc void @quux +// X86-LABEL: define{{.*}} x86_stdcallcc void @quux +// M68k-LABEL: define{{.*}} m68k_rtdcc void @quux // CHECK: call void (i32, ...) @qux -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } +// X86: attributes [[NUW]] = { noinline nounwind{{.*}} } Index: clang/test/CodeGenCXX/default_calling_conv.cpp =================================================================== --- clang/test/CodeGenCXX/default_calling_conv.cpp +++ clang/test/CodeGenCXX/default_calling_conv.cpp @@ -1,43 +1,50 @@ -// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -fdefault-calling-conv=cdecl -emit-llvm -o - %s | FileCheck %s --check-prefix=CDECL --check-prefix=ALL -// RUN: %clang_cc1 -triple i786-unknown-linux-gnu -target-feature +sse4.2 -fdefault-calling-conv=fastcall -emit-llvm -o - %s | FileCheck %s --check-prefix=FASTCALL --check-prefix=ALL -// RUN: %clang_cc1 -triple i486-unknown-linux-gnu -fdefault-calling-conv=stdcall -emit-llvm -o - %s | FileCheck %s --check-prefix=STDCALL --check-prefix=ALL -// RUN: %clang_cc1 -triple i486-unknown-linux-gnu -mrtd -emit-llvm -o - %s | FileCheck %s --check-prefix=STDCALL --check-prefix=ALL -// RUN: %clang_cc1 -triple i986-unknown-linux-gnu -fdefault-calling-conv=vectorcall -emit-llvm -o - %s | FileCheck %s --check-prefix=VECTORCALL --check-prefix=ALL -// RUN: %clang_cc1 -triple i986-unknown-linux-gnu -fdefault-calling-conv=regcall -emit-llvm -o - %s | FileCheck %s --check-prefix=REGCALL --check-prefix=ALL +// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -fdefault-calling-conv=cdecl -emit-llvm -o - %s | FileCheck %s --check-prefix=CDECL --check-prefix=X86 --check-prefix=ALL +// RUN: %clang_cc1 -triple i786-unknown-linux-gnu -target-feature +sse4.2 -fdefault-calling-conv=fastcall -emit-llvm -o - %s | FileCheck %s --check-prefix=FASTCALL --check-prefix=X86 --check-prefix=ALL +// RUN: %clang_cc1 -triple i486-unknown-linux-gnu -fdefault-calling-conv=stdcall -emit-llvm -o - %s | FileCheck %s --check-prefix=STDCALL --check-prefix=X86 --check-prefix=ALL +// RUN: %clang_cc1 -triple i486-unknown-linux-gnu -mrtd -emit-llvm -o - %s | FileCheck %s --check-prefix=STDCALL --check-prefix=X86 --check-prefix=ALL +// RUN: %clang_cc1 -triple i986-unknown-linux-gnu -fdefault-calling-conv=vectorcall -emit-llvm -o - %s | FileCheck %s --check-prefix=VECTORCALL --check-prefix=X86 --check-prefix=ALL +// RUN: %clang_cc1 -triple i986-unknown-linux-gnu -fdefault-calling-conv=regcall -emit-llvm -o - %s | FileCheck %s --check-prefix=REGCALL --check-prefix=X86 --check-prefix=ALL // RUN: %clang_cc1 -triple i686-pc-win32 -fdefault-calling-conv=vectorcall -emit-llvm -o - %s -DWINDOWS | FileCheck %s --check-prefix=WIN32 // RUN: %clang_cc1 -triple x86_64-windows-msvc -fdefault-calling-conv=vectorcall -emit-llvm -o - %s -DWINDOWS | FileCheck %s --check-prefix=WIN64 // RUN: %clang_cc1 -triple i686-pc-win32 -emit-llvm -o - %s -DEXPLICITCC | FileCheck %s --check-prefix=EXPLICITCC +// RUN: %clang_cc1 -triple m68k-unknown-linux-gnu -mrtd -emit-llvm -o - %s | FileCheck %s --check-prefix=RTDCALL --check-prefix=ALL +// RUN: %clang_cc1 -triple m68k-unknown-linux-gnu -fdefault-calling-conv=rtdcall -emit-llvm -o - %s | FileCheck %s --check-prefix=RTDCALL --check-prefix=ALL // CDECL: define{{.*}} void @_Z5test1v // FASTCALL: define{{.*}} x86_fastcallcc void @_Z5test1v // STDCALL: define{{.*}} x86_stdcallcc void @_Z5test1v // VECTORCALL: define{{.*}} x86_vectorcallcc void @_Z5test1v // REGCALL: define{{.*}} x86_regcallcc void @_Z17__regcall3__test1v +// RTDCALL: define{{.*}} m68k_rtdcc void @_Z5test1v void test1() {} -// fastcall, stdcall, vectorcall and regcall do not support variadic functions. +// fastcall, stdcall, vectorcall, regcall and m68k_rtd do not support variadic functions. // CDECL: define{{.*}} void @_Z12testVariadicz // FASTCALL: define{{.*}} void @_Z12testVariadicz // STDCALL: define{{.*}} void @_Z12testVariadicz // VECTORCALL: define{{.*}} void @_Z12testVariadicz // REGCALL: define{{.*}} void @_Z12testVariadicz +// RTDCALL: define{{.*}} void @_Z12testVariadicz void testVariadic(...){} -// ALL: define{{.*}} void @_Z5test2v +// X86: define{{.*}} void @_Z5test2v void __attribute__((cdecl)) test2() {} -// ALL: define{{.*}} x86_fastcallcc void @_Z5test3v +// X86: define{{.*}} x86_fastcallcc void @_Z5test3v void __attribute__((fastcall)) test3() {} -// ALL: define{{.*}} x86_stdcallcc void @_Z5test4v +// X86: define{{.*}} x86_stdcallcc void @_Z5test4v void __attribute__((stdcall)) test4() {} -// ALL: define{{.*}} x86_vectorcallcc void @_Z5test5v +// X86: define{{.*}} x86_vectorcallcc void @_Z5test5v void __attribute__((vectorcall)) test5() {} -// ALL: define{{.*}} x86_regcallcc void @_Z17__regcall3__test6v +// X86: define{{.*}} x86_regcallcc void @_Z17__regcall3__test6v void __attribute__((regcall)) test6() {} +// RTDCALL: define{{.*}} m68k_rtdcc void @_Z5test7v +void __attribute__((m68k_rtd)) test7() {} + // ALL: define linkonce_odr void @_ZN1A11test_memberEv class A { public: @@ -47,6 +54,10 @@ void test() { A a; a.test_member(); + +// ALL: define internal void @"_ZZ{{.*}}testvENK3$_0clEi" + auto f = [](int b) {}; + f(87); } // ALL: define{{.*}} i32 @main Index: clang/test/CodeGenCXX/m68k-rtdcall.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/m68k-rtdcall.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple m68k-linux-gnu -emit-llvm -o - %s | FileCheck %s + +class A { +public: +// CHECK: define{{.*}} m68k_rtdcc void @_ZN1A6memberEv + void __attribute__((m68k_rtd)) member() {} +}; + +void test() { + A a; + a.member(); + +// CHECK: define{{.*}} m68k_rtdcc void @"_ZZ4testvENK3$_0clEi" + auto f = [](int b) __attribute__((m68k_rtd)) {}; + f(87); +}; Index: clang/test/Sema/m68k-rtdcall.c =================================================================== --- /dev/null +++ clang/test/Sema/m68k-rtdcall.c @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -triple m68k-unknown-unknown -mrtd -std=c89 -verify -verify=rtd %s +// RUN: %clang_cc1 -triple m68k-unknown-unknown -std=c89 -verify -verify=nortd %s + +// rtd-error@+2 {{function with no prototype cannot use the m68k_rtd calling convention}} +void foo(int arg) { + bar(arg); +} + +// nortd-note@+4 {{previous declaration is here}} +// nortd-error@+4 {{function declared 'm68k_rtd' here was previously declared without calling convention}} +// nortd-note@+4 {{previous declaration is here}} +// nortd-error@+4 {{function declared 'm68k_rtd' here was previously declared without calling convention}} +void nonvariadic1(int a, int b, int c); +void __attribute__((m68k_rtd)) nonvariadic1(int a, int b, int c); +void nonvariadic2(int a, int b, int c); +void __attribute__((m68k_rtd)) nonvariadic2(int a, int b, int c) { } + +// expected-error@+2 {{variadic function cannot use m68k_rtd calling convention}} +void variadic(int a, ...); +void __attribute__((m68k_rtd)) variadic(int a, ...); + +// rtd-note@+2 {{previous declaration is here}} +// rtd-error@+2 {{redeclaration of 'a' with a different type: 'void ((*))(int, int) __attribute__((cdecl))' vs 'void (*)(int, int) __attribute__((m68k_rtd))'}} +extern void (*a)(int, int); +__attribute__((cdecl)) extern void (*a)(int, int); + +extern void (*b)(int, ...); +__attribute__((cdecl)) extern void (*b)(int, ...); + +// nortd-note@+2 {{previous declaration is here}} +// nortd-error@+2 {{redeclaration of 'c' with a different type: 'void ((*))(int, int) __attribute__((m68k_rtd))' vs 'void (*)(int, int)'}} +extern void (*c)(int, int); +__attribute__((m68k_rtd)) extern void (*c)(int, int); + +// expected-error@+2 {{variadic function cannot use m68k_rtd calling convention}} +extern void (*d)(int, ...); +__attribute__((m68k_rtd)) extern void (*d)(int, ...); + +// expected-warning@+1 {{'m68k_rtd' only applies to function types; type here is 'int'}} +__attribute__((m68k_rtd)) static int g = 0; + +// expected-error@+1 {{'m68k_rtd' attribute takes no arguments}} +void __attribute__((m68k_rtd("invalid"))) z(int a); + +// expected-error@+1 {{function with no prototype cannot use the m68k_rtd calling convention}} +void __attribute__((m68k_rtd)) e(); Index: clang/test/SemaCXX/m68k-rtdcall.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/m68k-rtdcall.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple m68k-linux-gnu -fsyntax-only %s + +class A { +public: + void __attribute__((m68k_rtd)) member() {} +}; + +void test() { + A a; + a.member(); + + auto f = [](int b) __attribute__((m68k_rtd)) {}; + f(87); +}; Index: clang/tools/libclang/CXType.cpp =================================================================== --- clang/tools/libclang/CXType.cpp +++ clang/tools/libclang/CXType.cpp @@ -678,6 +678,7 @@ TCALLINGCONV(SwiftAsync); TCALLINGCONV(PreserveMost); TCALLINGCONV(PreserveAll); + TCALLINGCONV(M68kRTD); case CC_SpirFunction: return CXCallingConv_Unexposed; case CC_AMDGPUKernelCall: return CXCallingConv_Unexposed; case CC_OpenCLKernel: return CXCallingConv_Unexposed;