[MS] Treat ignored explicit calling conventions as an explicit __cdecl

The CCCR_Ignore action is only used for Microsoft calling conventions,
mainly because MSVC does not warn when a calling convention would be
ignored by the current target. This behavior is actually somewhat
important, since windows.h uses WINAPI (which expands to __stdcall)
widely. This distinction didn't matter much before the introduction of
__vectorcall to x64 and the ability to make that the default calling
convention with /Gv. Now, we can't just ignore __stdcall for x64, we
have to treat it as an explicit __cdecl annotation.

Fixes PR42531

llvm-svn: 365579
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index e4e6a19..802ca52 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -4655,10 +4655,22 @@
   } else {
     A = TI.checkCallingConvention(CC);
   }
-  if (A != TargetInfo::CCCR_OK) {
-    if (A == TargetInfo::CCCR_Warning)
-      Diag(Attrs.getLoc(), diag::warn_cconv_ignored)
-          << Attrs << (int)CallingConventionIgnoredReason::ForThisTarget;
+
+  switch (A) {
+  case TargetInfo::CCCR_OK:
+    break;
+
+  case TargetInfo::CCCR_Ignore:
+    // Treat an ignored convention as if it was an explicit C calling convention
+    // attribute. For example, __stdcall on Win x64 functions as __cdecl, so
+    // that command line flags that change the default convention to
+    // __vectorcall don't affect declarations marked __stdcall.
+    CC = CC_C;
+    break;
+
+  case TargetInfo::CCCR_Warning: {
+    Diag(Attrs.getLoc(), diag::warn_cconv_ignored)
+        << Attrs << (int)CallingConventionIgnoredReason::ForThisTarget;
 
     // This convention is not valid for the target. Use the default function or
     // method calling convention.
@@ -4668,6 +4680,8 @@
       IsVariadic = FD->isVariadic();
     }
     CC = Context.getDefaultCallingConvention(IsVariadic, IsCXXMethod);
+    break;
+  }
   }
 
   Attrs.setProcessingCache((unsigned) CC);