From 4b2f3269ab4103e1acdc94de09058856a75d1434 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 31 May 2017 15:39:28 +0000 Subject: [PATCH] [clang-cl] Improve default calling convention flag handling Ignore default CC flags that don't make sense for the target arch. This is consistent with MSVC. Addresses part of PR33237 llvm-svn: 304305 --- clang/lib/Driver/ToolChains/Clang.cpp | 38 ++++++++++++++++++----- clang/lib/Frontend/CompilerInvocation.cpp | 4 +-- clang/test/Driver/cl-cc-flags.c | 33 ++++++++++++++++++++ 3 files changed, 65 insertions(+), 10 deletions(-) create mode 100644 clang/test/Driver/cl-cc-flags.c diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 555847aeeb23..ce6d26131cb1 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4781,14 +4781,36 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, CmdArgs.push_back("-fms-memptr-rep=virtual"); } - if (Args.getLastArg(options::OPT__SLASH_Gd)) - CmdArgs.push_back("-fdefault-calling-conv=cdecl"); - else if (Args.getLastArg(options::OPT__SLASH_Gr)) - CmdArgs.push_back("-fdefault-calling-conv=fastcall"); - else if (Args.getLastArg(options::OPT__SLASH_Gz)) - CmdArgs.push_back("-fdefault-calling-conv=stdcall"); - else if (Args.getLastArg(options::OPT__SLASH_Gv)) - CmdArgs.push_back("-fdefault-calling-conv=vectorcall"); + // Parse the default calling convention options. + if (Arg *CCArg = + Args.getLastArg(options::OPT__SLASH_Gd, options::OPT__SLASH_Gr, + options::OPT__SLASH_Gz, options::OPT__SLASH_Gv)) { + unsigned DCCOptId = CCArg->getOption().getID(); + const char *DCCFlag = nullptr; + bool ArchSupported = true; + llvm::Triple::ArchType Arch = getToolChain().getArch(); + switch (DCCOptId) { + case options::OPT__SLASH_Gd: + DCCFlag = "-fdefault-calling-convention=cdecl"; + break; + case options::OPT__SLASH_Gr: + ArchSupported = Arch == llvm::Triple::x86; + DCCFlag = "-fdefault-calling-convention=fastcall"; + break; + case options::OPT__SLASH_Gz: + ArchSupported = Arch == llvm::Triple::x86; + DCCFlag = "-fdefault-calling-convention=stdcall"; + break; + case options::OPT__SLASH_Gv: + ArchSupported = Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64; + DCCFlag = "-fdefault-calling-convention=vectorcall"; + break; + } + + // MSVC doesn't warn if /Gr or /Gz is used on x64, so we don't either. + if (ArchSupported && DCCFlag) + CmdArgs.push_back(DCCFlag); + } if (Arg *A = Args.getLastArg(options::OPT_vtordisp_mode_EQ)) A->render(Args, CmdArgs); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 7d7e7d49e9f0..47c763d29357 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2214,8 +2214,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, llvm::Triple T(TargetOpts.Triple); llvm::Triple::ArchType Arch = T.getArch(); bool emitError = (DefaultCC == LangOptions::DCC_FastCall || - DefaultCC == LangOptions::DCC_StdCall) && - Arch != llvm::Triple::x86; + DefaultCC == LangOptions::DCC_StdCall) && + Arch != llvm::Triple::x86; emitError |= DefaultCC == LangOptions::DCC_VectorCall && !(Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64); if (emitError) diff --git a/clang/test/Driver/cl-cc-flags.c b/clang/test/Driver/cl-cc-flags.c new file mode 100644 index 000000000000..64ff1cb5e8ce --- /dev/null +++ b/clang/test/Driver/cl-cc-flags.c @@ -0,0 +1,33 @@ +// Note: %s must be preceded by --, otherwise it may be interpreted as a +// command-line option, e.g. on Mac where %s is commonly under /Users. + +// RUN: %clang_cl --target=i686-windows-msvc /Gd -### -- %s 2>&1 | FileCheck --check-prefix=CDECL %s +// CDECL: -fdefault-calling-convention=cdecl + +// RUN: %clang_cl --target=i686-windows-msvc /Gr -### -- %s 2>&1 | FileCheck --check-prefix=FASTCALL %s +// FASTCALL: -fdefault-calling-convention=fastcall + +// RUN: %clang_cl --target=i686-windows-msvc /Gz -### -- %s 2>&1 | FileCheck --check-prefix=STDCALL %s +// STDCALL: -fdefault-calling-convention=stdcall + +// RUN: %clang_cl --target=i686-windows-msvc /Gv -### -- %s 2>&1 | FileCheck --check-prefix=VECTORCALL %s +// VECTORCALL: -fdefault-calling-convention=vectorcall + +// Last one should win: + +// RUN: %clang_cl --target=i686-windows-msvc /Gd /Gv -### -- %s 2>&1 | FileCheck --check-prefix=LASTWINS_VECTOR %s +// LASTWINS_VECTOR: -fdefault-calling-convention=vectorcall + +// RUN: %clang_cl --target=i686-windows-msvc /Gv /Gd -### -- %s 2>&1 | FileCheck --check-prefix=LASTWINS_CDECL %s +// LASTWINS_CDECL: -fdefault-calling-convention=cdecl + +// No fastcall or stdcall on x86_64: + +// RUN: %clang_cl --target=x86_64-windows-msvc /Gr -### -- %s 2>&1 | FileCheck --check-prefix=UNSUPPORTED %s +// RUN: %clang_cl --target=x86_64-windows-msvc /Gz -### -- %s 2>&1 | FileCheck --check-prefix=UNSUPPORTED %s +// RUN: %clang_cl --target=thumbv7-windows-msvc /Gv -### -- %s 2>&1 | FileCheck --check-prefix=UNSUPPORTED %s + +// UNSUPPORTED-NOT: error: +// UNSUPPORTED-NOT: warning: +// UNSUPPORTED-NOT: -fdefault-calling-convention= +