]> granicus.if.org Git - clang/commitdiff
[clang-cl] Improve default calling convention flag handling
authorReid Kleckner <rnk@google.com>
Wed, 31 May 2017 15:39:28 +0000 (15:39 +0000)
committerReid Kleckner <rnk@google.com>
Wed, 31 May 2017 15:39:28 +0000 (15:39 +0000)
Ignore default CC flags that don't make sense for the target arch. This
is consistent with MSVC.

Addresses part of PR33237

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@304305 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Driver/ToolChains/Clang.cpp
lib/Frontend/CompilerInvocation.cpp
test/Driver/cl-cc-flags.c [new file with mode: 0644]

index 555847aeeb23d272355b5ce75c36ed82bcb7c8d3..ce6d26131cb1bde66d1329fa916aa08095c3feb3 100644 (file)
@@ -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);
index 7d7e7d49e9f038f708b637e862f10dbc2757c228..47c763d29357c64f3e0963548dfacbee813b9708 100644 (file)
@@ -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/test/Driver/cl-cc-flags.c b/test/Driver/cl-cc-flags.c
new file mode 100644 (file)
index 0000000..64ff1cb
--- /dev/null
@@ -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=
+