Support MS builtins using 'long' on LP64 platforms

This allows for -fms-extensions to work the same on LP64. For example,
_BitScanReverse is expected to be 32-bit, matching Windows/LLP64, even
though long is 64-bit on x86_64 Darwin or Linux (LP64).

Implement this by adding a new character code 'N', which is 'int' if
the target is LP64 and the same 'L' otherwise

Differential Revision: https://reviews.llvm.org/D34377

rdar://problem/32599746

llvm-svn: 305875
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 2300801..69767e0 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -8513,7 +8513,7 @@
   RequiresICE = false;
   
   // Read the prefixed modifiers first.
-  bool Done = false;
+  bool Done = false, IsSpecialLong = false;
   while (!Done) {
     switch (*Str++) {
     default: Done = true; --Str; break;
@@ -8531,12 +8531,24 @@
       Unsigned = true;
       break;
     case 'L':
+      assert(!IsSpecialLong && "Can't use 'L' with 'W' or 'N' modifiers");
       assert(HowLong <= 2 && "Can't have LLLL modifier");
       ++HowLong;
       break;
+    case 'N': {
+      // 'N' behaves like 'L' for all non LP64 targets and 'int' otherwise.
+      assert(!IsSpecialLong && "Can't use two 'N' or 'W' modifiers!");
+      assert(HowLong == 0 && "Can't use both 'L' and 'N' modifiers!");
+      IsSpecialLong = true;
+      if (Context.getTargetInfo().getLongWidth() == 32)
+        ++HowLong;
+      break;
+    }
     case 'W':
       // This modifier represents int64 type.
+      assert(!IsSpecialLong && "Can't use two 'N' or 'W' modifiers!");
       assert(HowLong == 0 && "Can't use both 'L' and 'W' modifiers!");
+      IsSpecialLong = true;
       switch (Context.getTargetInfo().getInt64Type()) {
       default:
         llvm_unreachable("Unexpected integer type");