Replace AS_MSTypespec with AS_Keyword, for representing any attribute spelled
as a keyword. Rationalize existing attributes to use it as appropriate, and to
not lie about some __declspec attributes being GNU attributes. In passing,
remove a gross hack which was discarding attributes which we could handle. This
results in us actually respecting the __pascal keyword again.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@173746 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 2d4788c..8a3e788 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -29,8 +29,8 @@
   code CheckCode = check;
 }
 
-// This is the type of a variable which C++11 defines [[aligned()]] as being
-// a possible subject.
+// This is the type of a variable which C++11 allows alignas(...) to appertain
+// to.
 def NormalVar : SubsetSubject<Var, "non-register, non-parameter variable",
                               [{S->getStorageClass() != VarDecl::Register &&
                                 S->getKind() != Decl::ImplicitParam &&
@@ -91,6 +91,7 @@
 class CXX11<string namespace, string name> : Spelling<name, "CXX11"> {
   string Namespace = namespace;
 }
+class Keyword<string name> : Spelling<name, "Keyword">;
 
 class Attr {
   // The various ways in which an attribute can be spelled in source
@@ -125,6 +126,13 @@
 /// redeclarations, even when it's written on a parameter.
 class InheritableParamAttr : InheritableAttr;
 
+/// An ignored attribute, which we parse but discard with no checking.
+class IgnoredAttr : Attr {
+  let Ignored = 1;
+  let ASTNode = 0;
+  let SemaHandler = 0;
+}
+
 //
 // Attributes begin here
 //
@@ -141,7 +149,8 @@
 }
 
 def Aligned : InheritableAttr {
-  let Spellings = [GNU<"aligned">, GNU<"align">, CXX11<"gnu", "aligned">];
+  let Spellings = [GNU<"aligned">, Declspec<"align">, CXX11<"gnu", "aligned">,
+                   Keyword<"alignas">];
   let Subjects = [NonBitField, NormalVar, Tag];
   let Args = [AlignedArgument<"Alignment">, BoolArgument<"IsMSDeclSpec">];
 }
@@ -200,11 +209,8 @@
   let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
 }
 
-def Bounded : Attr {
+def Bounded : IgnoredAttr {
   let Spellings = [GNU<"bounded">];
-  let ASTNode = 0;
-  let SemaHandler = 0;
-  let Ignored = 1;
 }
 
 def CarriesDependency : InheritableParamAttr {
@@ -214,7 +220,7 @@
 }
 
 def CDecl : InheritableAttr {
-  let Spellings = [GNU<"cdecl">, GNU<"__cdecl">, CXX11<"gnu", "cdecl">];
+  let Spellings = [GNU<"cdecl">, CXX11<"gnu", "cdecl">, Keyword<"__cdecl">];
 }
 
 // cf_audited_transfer indicates that the given function has been
@@ -302,7 +308,7 @@
 }
 
 def OpenCLKernel : Attr {
-  let Spellings = [GNU<"opencl_kernel_function">];
+  let Spellings = [Keyword<"__kernel">, Keyword<"kernel">];
 }
 
 def OpenCLImageAccess : Attr {
@@ -333,8 +339,8 @@
 }
 
 def FastCall : InheritableAttr {
-  let Spellings = [GNU<"fastcall">, GNU<"__fastcall">,
-                   CXX11<"gnu", "fastcall">];
+  let Spellings = [GNU<"fastcall">, CXX11<"gnu", "fastcall">,
+                   Keyword<"__fastcall">];
 }
 
 def Final : InheritableAttr {
@@ -631,16 +637,17 @@
 }
 
 def StdCall : InheritableAttr {
-  let Spellings = [GNU<"stdcall">, GNU<"__stdcall">, CXX11<"gnu", "stdcall">];
+  let Spellings = [GNU<"stdcall">, CXX11<"gnu", "stdcall">,
+                   Keyword<"__stdcall">];
 }
 
 def ThisCall : InheritableAttr {
-  let Spellings = [GNU<"thiscall">, GNU<"__thiscall">,
-                   CXX11<"gnu", "thiscall">];
+  let Spellings = [GNU<"thiscall">, CXX11<"gnu", "thiscall">,
+                   Keyword<"__thiscall">];
 }
 
 def Pascal : InheritableAttr {
-  let Spellings = [GNU<"pascal">];
+  let Spellings = [GNU<"pascal">, Keyword<"__pascal">];
 }
 
 def TransparentUnion : InheritableAttr {
@@ -694,11 +701,8 @@
   let ASTNode = 0;
 }
 
-def VecTypeHint : Attr {
+def VecTypeHint : IgnoredAttr {
   let Spellings = [GNU<"vec_type_hint">];
-  let ASTNode = 0;
-  let SemaHandler = 0;
-  let Ignored = 1;
 }
 
 def Visibility : InheritableAttr {
@@ -894,29 +898,33 @@
 }
 
 def ForceInline : InheritableAttr {
-  let Spellings = [Declspec<"__forceinline">];
+  let Spellings = [Keyword<"__forceinline">];
 }
 
 def Win64 : InheritableAttr {
-  let Spellings = [Declspec<"w64">];
+  let Spellings = [Keyword<"__w64">];
 }
 
 def Ptr32 : InheritableAttr {
-  let Spellings = [Declspec<"__ptr32">];
+  let Spellings = [Keyword<"__ptr32">];
 }
 
 def Ptr64 : InheritableAttr {
-  let Spellings = [Declspec<"__ptr64">];
+  let Spellings = [Keyword<"__ptr64">];
 }
 
 def SingleInheritance : InheritableAttr {
-  let Spellings = [Declspec<"__single_inheritance">];
+  let Spellings = [Keyword<"__single_inheritance">];
 }
 
 def MultipleInheritance : InheritableAttr {
-  let Spellings = [Declspec<"__multiple_inheritance">];
+  let Spellings = [Keyword<"__multiple_inheritance">];
 }
 
 def VirtualInheritance : InheritableAttr {
-  let Spellings = [Declspec<"__virtual_inheritance">];
+  let Spellings = [Keyword<"__virtual_inheritance">];
+}
+
+def Unaligned : IgnoredAttr {
+  let Spellings = [Keyword<"__unaligned">];
 }
diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h
index 65a9595..928fb5f 100644
--- a/include/clang/Sema/AttributeList.h
+++ b/include/clang/Sema/AttributeList.h
@@ -56,12 +56,14 @@
 public:
   /// The style used to specify an attribute.
   enum Syntax {
+    /// __attribute__((...))
     AS_GNU,
+    /// [[...]]
     AS_CXX11,
+    /// __declspec(...)
     AS_Declspec,
-    // eg) __w64, __ptr32, etc.  It is implied that an MSTypespec is also
-    // a declspec.
-    AS_MSTypespec   
+    /// __ptr16, alignas(...), etc.
+    AS_Keyword
   };
 private:
   IdentifierInfo *AttrName;
@@ -227,12 +229,9 @@
   IdentifierInfo *getParameterName() const { return ParmName; }
   SourceLocation getParameterLoc() const { return ParmLoc; }
 
-  /// Returns true if the attribute is a pure __declspec or a synthesized
-  /// declspec representing a type specification (like __w64 or __ptr32).
-  bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec ||
-                                            SyntaxUsed == AS_MSTypespec; }
+  bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
   bool isCXX11Attribute() const { return SyntaxUsed == AS_CXX11; }
-  bool isMSTypespecAttribute() const { return SyntaxUsed == AS_MSTypespec; }
+  bool isKeywordAttribute() const { return SyntaxUsed == AS_Keyword; }
 
   bool isInvalid() const { return Invalid; }
   void setInvalid(bool b = true) const { Invalid = b; }
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index a851e2c..e6e010b 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -462,7 +462,7 @@
     IdentifierInfo *AttrName = Tok.getIdentifierInfo();
     SourceLocation AttrNameLoc = ConsumeToken();
     attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
-                 SourceLocation(), 0, 0, AttributeList::AS_MSTypespec);
+                 SourceLocation(), 0, 0, AttributeList::AS_Keyword);
   }
 }
 
@@ -472,21 +472,23 @@
     IdentifierInfo *AttrName = Tok.getIdentifierInfo();
     SourceLocation AttrNameLoc = ConsumeToken();
     attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
-                 SourceLocation(), 0, 0, AttributeList::AS_MSTypespec);
+                 SourceLocation(), 0, 0, AttributeList::AS_Keyword);
   }
 }
 
 void Parser::ParseOpenCLAttributes(ParsedAttributes &attrs) {
   // Treat these like attributes
   while (Tok.is(tok::kw___kernel)) {
+    IdentifierInfo *AttrName = Tok.getIdentifierInfo();
     SourceLocation AttrNameLoc = ConsumeToken();
-    attrs.addNew(PP.getIdentifierInfo("opencl_kernel_function"),
-                 AttrNameLoc, 0, AttrNameLoc, 0,
-                 SourceLocation(), 0, 0, AttributeList::AS_GNU);
+    attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
+                 SourceLocation(), 0, 0, AttributeList::AS_Keyword);
   }
 }
 
 void Parser::ParseOpenCLQualifiers(DeclSpec &DS) {
+  // FIXME: The mapping from attribute spelling to semantics should be
+  //        performed in Sema, not here.
   SourceLocation Loc = Tok.getLocation();
   switch(Tok.getKind()) {
     // OpenCL qualifiers:
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index adeb8e6..12483a3 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -4759,11 +4759,11 @@
   if (Attr.isInvalid())
     return;
 
-  // Type attributes are still treated as declaration attributes by 
-  // ParseMicrosoftTypeAttributes and ParseBorlandTypeAttributes.  We don't 
-  // want to process them, however, because we will simply warn about ignoring 
-  // them.  So instead, we will bail out early.
-  if (Attr.isMSTypespecAttribute())
+  // FIXME: Ignore unknown keyword attributes for now. We see this in the case
+  // of some Borland attributes, like __pascal.
+  // FIXME: Add these attributes to Attr.td and mark as ignored!
+  if (Attr.isKeywordAttribute() &&
+      Attr.getKind() == AttributeList::UnknownAttribute)
     return;
 
   // Ignore C++11 attributes on declarator chunks: they appertain to the type
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 4819363..c101de8 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -4336,13 +4336,6 @@
       attr.setUsedAsTypeAttr();
       break;
 
-    case AttributeList::AT_Win64:
-    case AttributeList::AT_Ptr32:
-    case AttributeList::AT_Ptr64:
-      // FIXME: don't ignore these
-      attr.setUsedAsTypeAttr();
-      break;
-
     case AttributeList::AT_NSReturnsRetained:
       if (!state.getSema().getLangOpts().ObjCAutoRefCount)
         break;
diff --git a/test/Sema/attr-print.c b/test/Sema/attr-print.c
index f952e4b..5e4c0c2 100644
--- a/test/Sema/attr-print.c
+++ b/test/Sema/attr-print.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 %s -ast-print -fms-extensions | FileCheck %s
 
 // FIXME: we need to fix the "BoolArgument<"IsMSDeclSpec">"
 // hack in Attr.td for attribute "Aligned".
@@ -6,8 +6,9 @@
 // CHECK: int x __attribute__((aligned(4, 0)));
 int x __attribute__((aligned(4)));
 
-// CHECK: int y __attribute__((align(4, 0)));
-int y __attribute__((align(4)));
+// FIXME: Print this at a valid location for a __declspec attr.
+// CHECK: int y __declspec(align(4, 1));
+__declspec(align(4)) int y;
 
 // CHECK: void foo() __attribute__((const));
 void foo() __attribute__((const));
diff --git a/test/SemaCXX/attr-print.cpp b/test/SemaCXX/attr-print.cpp
index 317ba4d..419f608 100644
--- a/test/SemaCXX/attr-print.cpp
+++ b/test/SemaCXX/attr-print.cpp
@@ -1,12 +1,13 @@
-// RUN: %clang_cc1 %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 %s -ast-print -fms-extensions | FileCheck %s
 
 // FIXME: align attribute print
 
 // CHECK: int x __attribute__((aligned(4, 0)));
 int x __attribute__((aligned(4)));
 
-// CHECK: int y __attribute__((align(4, 0)));
-int y __attribute__((align(4)));
+// FIXME: Print this at a valid location for a __declspec attr.
+// CHECK: int y __declspec(align(4, 1));
+__declspec(align(4)) int y;
 
 // CHECK: void foo() __attribute__((const));
 void foo() __attribute__((const));
diff --git a/test/SemaCXX/borland-extensions.cpp b/test/SemaCXX/borland-extensions.cpp
index 1e4bd45..f9414f8 100644
--- a/test/SemaCXX/borland-extensions.cpp
+++ b/test/SemaCXX/borland-extensions.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 %s -fsyntax-only -verify -fborland-extensions
-// expected-no-diagnostics
+// RUN: %clang_cc1 %s -fsyntax-only -fborland-extensions -triple x86_64-linux-gnu -verify
+// RUN: %clang_cc1 %s -fsyntax-only -fborland-extensions -triple i686-linux-gnu -Werror
 
 // Borland extensions
 
@@ -9,13 +9,18 @@
 // 2. test __pascal
 int _pascal f2();
 
+// expected-warning@+1 {{calling convention '__pascal' ignored for this target}}
 float __pascal gi2(int, int); 
+// expected-warning@+1 {{calling convention '__pascal' ignored for this target}}
 template<typename T> T g2(T (__pascal * const )(int, int)) { return 0; }
 
 struct M {
+    // expected-warning@+1 {{calling convention '__pascal' ignored for this target}}
     int __pascal addP();
+    // expected-warning@+1 {{calling convention '__pascal' ignored for this target}}
     float __pascal subtractP(); 
 };
+// expected-warning@+1 {{calling convention '__pascal' ignored for this target}}
 template<typename T> int h2(T (__pascal M::* const )()) { return 0; }
 void m2() {
     int i; float f;
diff --git a/test/SemaCXX/cxx11-attr-print.cpp b/test/SemaCXX/cxx11-attr-print.cpp
index 985d9a4..3cc6d00 100644
--- a/test/SemaCXX/cxx11-attr-print.cpp
+++ b/test/SemaCXX/cxx11-attr-print.cpp
@@ -1,11 +1,12 @@
-// RUN: %clang_cc1 -std=c++11 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -ast-print -fms-extensions %s | FileCheck %s
 // FIXME: align attribute print
 
 // CHECK: int x __attribute__((aligned(4, 0)));
 int x __attribute__((aligned(4)));
 
-// CHECK: int y __attribute__((align(4, 0)));
-int y __attribute__((align(4)));
+// FIXME: Print this at a valid location for a __declspec attr.
+// CHECK: int y __declspec(align(4, 1));
+__declspec(align(4)) int y;
 
 // CHECK: gnu::aligned(4, 0)]];
 int z [[gnu::aligned(4)]];
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp
index 09f4e19..d936e26 100644
--- a/utils/TableGen/ClangAttrEmitter.cpp
+++ b/utils/TableGen/ClangAttrEmitter.cpp
@@ -776,8 +776,11 @@
     } else if (Variety == "Declspec") {
       Prefix = " __declspec(";
       Suffix = ")";
+    } else if (Variety == "Keyword") {
+      Prefix = " ";
+      Suffix = "";
     } else {
-      llvm_unreachable("Unkown attribute syntax variety!");
+      llvm_unreachable("Unknown attribute syntax variety!");
     }
 
     Spelling += Name;
@@ -1149,6 +1152,7 @@
             .Case("GNU", 0)
             .Case("CXX11", 1)
             .Case("Declspec", 2)
+            .Case("Keyword", 3)
             .Default(0)
           << " && Scope == \"" << Namespace << "\")\n"
           << "        return " << I << ";\n";