Browse Source

[NFCI]Create CommonAttributeInfo Type as base type of *Attr and ParsedAttr.

In order to enable future improvements to our attribute diagnostics,
this moves info from ParsedAttr into CommonAttributeInfo, then makes
this type the base of the *Attr and ParsedAttr types. Quite a bit of
refactoring took place, including removing a bunch of redundant Spelling
Index propogation.

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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@371875 91177308-0d34-0410-b5e6-96231b3b80d8
Erich Keane 6 years ago
parent
commit
063c2472fa

+ 75 - 76
include/clang/AST/Attr.h

@@ -19,6 +19,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/Type.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/AttrKinds.h"
 #include "clang/Basic/AttrKinds.h"
+#include "clang/Basic/AttributeCommonInfo.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/OpenMPKinds.h"
 #include "clang/Basic/OpenMPKinds.h"
 #include "clang/Basic/Sanitizers.h"
 #include "clang/Basic/Sanitizers.h"
@@ -32,6 +33,7 @@
 
 
 namespace clang {
 namespace clang {
   class ASTContext;
   class ASTContext;
+  class AttributeCommonInfo;
   class IdentifierInfo;
   class IdentifierInfo;
   class ObjCInterfaceDecl;
   class ObjCInterfaceDecl;
   class Expr;
   class Expr;
@@ -40,84 +42,79 @@ namespace clang {
   class TypeSourceInfo;
   class TypeSourceInfo;
 
 
 /// Attr - This represents one attribute.
 /// Attr - This represents one attribute.
-class Attr {
-private:
-  SourceRange Range;
-  unsigned AttrKind : 16;
-
-protected:
-  /// An index into the spelling list of an
-  /// attribute defined in Attr.td file.
-  unsigned SpellingListIndex : 4;
-  unsigned Inherited : 1;
-  unsigned IsPackExpansion : 1;
-  unsigned Implicit : 1;
-  // FIXME: These are properties of the attribute kind, not state for this
-  // instance of the attribute.
-  unsigned IsLateParsed : 1;
-  unsigned InheritEvenIfAlreadyPresent : 1;
-
-  void *operator new(size_t bytes) noexcept {
-    llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
-  }
-  void operator delete(void *data) noexcept {
-    llvm_unreachable("Attrs cannot be released with regular 'delete'.");
-  }
-
-public:
-  // Forward so that the regular new and delete do not hide global ones.
-  void *operator new(size_t Bytes, ASTContext &C,
-                     size_t Alignment = 8) noexcept {
-    return ::operator new(Bytes, C, Alignment);
-  }
-  void operator delete(void *Ptr, ASTContext &C, size_t Alignment) noexcept {
-    return ::operator delete(Ptr, C, Alignment);
-  }
+  class Attr : public AttributeCommonInfo {
+  private:
+    unsigned AttrKind : 16;
+
+  protected:
+    /// An index into the spelling list of an
+    /// attribute defined in Attr.td file.
+    unsigned Inherited : 1;
+    unsigned IsPackExpansion : 1;
+    unsigned Implicit : 1;
+    // FIXME: These are properties of the attribute kind, not state for this
+    // instance of the attribute.
+    unsigned IsLateParsed : 1;
+    unsigned InheritEvenIfAlreadyPresent : 1;
+
+    void *operator new(size_t bytes) noexcept {
+      llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
+    }
+    void operator delete(void *data) noexcept {
+      llvm_unreachable("Attrs cannot be released with regular 'delete'.");
+    }
 
 
-protected:
-  Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
-       bool IsLateParsed)
-    : Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex),
-      Inherited(false), IsPackExpansion(false), Implicit(false),
-      IsLateParsed(IsLateParsed), InheritEvenIfAlreadyPresent(false) {}
+  public:
+    // Forward so that the regular new and delete do not hide global ones.
+    void *operator new(size_t Bytes, ASTContext &C,
+                       size_t Alignment = 8) noexcept {
+      return ::operator new(Bytes, C, Alignment);
+    }
+    void operator delete(void *Ptr, ASTContext &C, size_t Alignment) noexcept {
+      return ::operator delete(Ptr, C, Alignment);
+    }
 
 
-public:
+  protected:
+    Attr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
+         attr::Kind AK, bool IsLateParsed)
+        : AttributeCommonInfo(CommonInfo), AttrKind(AK), Inherited(false),
+          IsPackExpansion(false), Implicit(false), IsLateParsed(IsLateParsed),
+          InheritEvenIfAlreadyPresent(false) {}
 
 
-  attr::Kind getKind() const {
-    return static_cast<attr::Kind>(AttrKind);
-  }
+  public:
+    attr::Kind getKind() const { return static_cast<attr::Kind>(AttrKind); }
 
 
-  unsigned getSpellingListIndex() const { return SpellingListIndex; }
-  const char *getSpelling() const;
+    unsigned getSpellingListIndex() const {
+      return getAttributeSpellingListIndex();
+    }
+    const char *getSpelling() const;
 
 
-  SourceLocation getLocation() const { return Range.getBegin(); }
-  SourceRange getRange() const { return Range; }
-  void setRange(SourceRange R) { Range = R; }
+    SourceLocation getLocation() const { return getRange().getBegin(); }
 
 
-  bool isInherited() const { return Inherited; }
+    bool isInherited() const { return Inherited; }
 
 
-  /// Returns true if the attribute has been implicitly created instead
-  /// of explicitly written by the user.
-  bool isImplicit() const { return Implicit; }
-  void setImplicit(bool I) { Implicit = I; }
+    /// Returns true if the attribute has been implicitly created instead
+    /// of explicitly written by the user.
+    bool isImplicit() const { return Implicit; }
+    void setImplicit(bool I) { Implicit = I; }
 
 
-  void setPackExpansion(bool PE) { IsPackExpansion = PE; }
-  bool isPackExpansion() const { return IsPackExpansion; }
+    void setPackExpansion(bool PE) { IsPackExpansion = PE; }
+    bool isPackExpansion() const { return IsPackExpansion; }
 
 
-  // Clone this attribute.
-  Attr *clone(ASTContext &C) const;
+    // Clone this attribute.
+    Attr *clone(ASTContext &C) const;
 
 
-  bool isLateParsed() const { return IsLateParsed; }
+    bool isLateParsed() const { return IsLateParsed; }
 
 
-  // Pretty print this attribute.
-  void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
-};
+    // Pretty print this attribute.
+    void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
+  };
 
 
 class TypeAttr : public Attr {
 class TypeAttr : public Attr {
 protected:
 protected:
-  TypeAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
-           bool IsLateParsed)
-      : Attr(AK, R, SpellingListIndex, IsLateParsed) {}
+  TypeAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
+           attr::Kind AK, bool IsLateParsed)
+      : Attr(Context, CommonInfo, AK, IsLateParsed) {}
 
 
 public:
 public:
   static bool classof(const Attr *A) {
   static bool classof(const Attr *A) {
@@ -128,9 +125,9 @@ public:
 
 
 class StmtAttr : public Attr {
 class StmtAttr : public Attr {
 protected:
 protected:
-  StmtAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
-                  bool IsLateParsed)
-      : Attr(AK, R, SpellingListIndex, IsLateParsed) {}
+  StmtAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
+           attr::Kind AK, bool IsLateParsed)
+      : Attr(Context, CommonInfo, AK, IsLateParsed) {}
 
 
 public:
 public:
   static bool classof(const Attr *A) {
   static bool classof(const Attr *A) {
@@ -141,9 +138,10 @@ public:
 
 
 class InheritableAttr : public Attr {
 class InheritableAttr : public Attr {
 protected:
 protected:
-  InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
-                  bool IsLateParsed, bool InheritEvenIfAlreadyPresent)
-      : Attr(AK, R, SpellingListIndex, IsLateParsed) {
+  InheritableAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
+                  attr::Kind AK, bool IsLateParsed,
+                  bool InheritEvenIfAlreadyPresent)
+      : Attr(Context, CommonInfo, AK, IsLateParsed) {
     this->InheritEvenIfAlreadyPresent = InheritEvenIfAlreadyPresent;
     this->InheritEvenIfAlreadyPresent = InheritEvenIfAlreadyPresent;
   }
   }
 
 
@@ -165,9 +163,10 @@ public:
 
 
 class InheritableParamAttr : public InheritableAttr {
 class InheritableParamAttr : public InheritableAttr {
 protected:
 protected:
-  InheritableParamAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
+  InheritableParamAttr(ASTContext &Context,
+                       const AttributeCommonInfo &CommonInfo, attr::Kind AK,
                        bool IsLateParsed, bool InheritEvenIfAlreadyPresent)
                        bool IsLateParsed, bool InheritEvenIfAlreadyPresent)
-      : InheritableAttr(AK, R, SpellingListIndex, IsLateParsed,
+      : InheritableAttr(Context, CommonInfo, AK, IsLateParsed,
                         InheritEvenIfAlreadyPresent) {}
                         InheritEvenIfAlreadyPresent) {}
 
 
 public:
 public:
@@ -182,11 +181,11 @@ public:
 /// for the parameter.
 /// for the parameter.
 class ParameterABIAttr : public InheritableParamAttr {
 class ParameterABIAttr : public InheritableParamAttr {
 protected:
 protected:
-  ParameterABIAttr(attr::Kind AK, SourceRange R,
-                   unsigned SpellingListIndex, bool IsLateParsed,
+  ParameterABIAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
+                   attr::Kind AK, bool IsLateParsed,
                    bool InheritEvenIfAlreadyPresent)
                    bool InheritEvenIfAlreadyPresent)
-    : InheritableParamAttr(AK, R, SpellingListIndex, IsLateParsed,
-                           InheritEvenIfAlreadyPresent) {}
+      : InheritableParamAttr(Context, CommonInfo, AK, IsLateParsed,
+                             InheritEvenIfAlreadyPresent) {}
 
 
 public:
 public:
   ParameterABI getABI() const {
   ParameterABI getABI() const {

+ 2 - 2
include/clang/Basic/Attr.td

@@ -3042,7 +3042,7 @@ def LoopHint : Attr {
   }
   }
 
 
   void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
   void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
-    unsigned SpellingIndex = getSpellingListIndex();
+    unsigned SpellingIndex = getAttributeSpellingListIndex();
     // For "#pragma unroll" and "#pragma nounroll" the string "unroll" or
     // For "#pragma unroll" and "#pragma nounroll" the string "unroll" or
     // "nounroll" is already emitted as the pragma name.
     // "nounroll" is already emitted as the pragma name.
     if (SpellingIndex == Pragma_nounroll || SpellingIndex == Pragma_nounroll_and_jam)
     if (SpellingIndex == Pragma_nounroll || SpellingIndex == Pragma_nounroll_and_jam)
@@ -3078,7 +3078,7 @@ def LoopHint : Attr {
 
 
   // Return a string suitable for identifying this attribute in diagnostics.
   // Return a string suitable for identifying this attribute in diagnostics.
   std::string getDiagnosticName(const PrintingPolicy &Policy) const {
   std::string getDiagnosticName(const PrintingPolicy &Policy) const {
-    unsigned SpellingIndex = getSpellingListIndex();
+    unsigned SpellingIndex = getAttributeSpellingListIndex();
     if (SpellingIndex == Pragma_nounroll)
     if (SpellingIndex == Pragma_nounroll)
       return "#pragma nounroll";
       return "#pragma nounroll";
     else if (SpellingIndex == Pragma_unroll)
     else if (SpellingIndex == Pragma_unroll)

+ 190 - 0
include/clang/Basic/AttributeCommonInfo.h

@@ -0,0 +1,190 @@
+//======- AttributeCommonInfo.h - Base info about Attributes-----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the AttributeCommonInfo type, which is the base for a
+// ParsedAttr and is used by Attr as a way to share info between the two.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
+#define LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+class IdentifierInfo;
+class ASTRecordWriter;
+
+class AttributeCommonInfo {
+public:
+  /// The style used to specify an attribute.
+  enum Syntax {
+    /// __attribute__((...))
+    AS_GNU,
+
+    /// [[...]]
+    AS_CXX11,
+
+    /// [[...]]
+    AS_C2x,
+
+    /// __declspec(...)
+    AS_Declspec,
+
+    /// [uuid("...")] class Foo
+    AS_Microsoft,
+
+    /// __ptr16, alignas(...), etc.
+    AS_Keyword,
+
+    /// #pragma ...
+    AS_Pragma,
+
+    // Note TableGen depends on the order above.  Do not add or change the order
+    // without adding related code to TableGen/ClangAttrEmitter.cpp.
+    /// Context-sensitive version of a keyword attribute.
+    AS_ContextSensitiveKeyword,
+  };
+  enum Kind {
+#define PARSED_ATTR(NAME) AT_##NAME,
+#include "clang/Sema/AttrParsedAttrList.inc"
+#undef PARSED_ATTR
+    NoSemaHandlerAttribute,
+    IgnoredAttribute,
+    UnknownAttribute,
+  };
+
+private:
+  const IdentifierInfo *AttrName = nullptr;
+  const IdentifierInfo *ScopeName = nullptr;
+  SourceRange AttrRange;
+  const SourceLocation ScopeLoc;
+  // Corresponds to the Kind enum.
+  unsigned AttrKind : 16;
+  /// Corresponds to the Syntax enum.
+  unsigned SyntaxUsed : 3;
+  unsigned SpellingIndex : 4;
+
+protected:
+  static constexpr unsigned SpellingNotCalculated = 0xf;
+
+public:
+  AttributeCommonInfo(SourceRange AttrRange)
+      : AttrRange(AttrRange), AttrKind(0), SyntaxUsed(0),
+        SpellingIndex(SpellingNotCalculated) {}
+
+  AttributeCommonInfo(SourceLocation AttrLoc)
+      : AttrRange(AttrLoc), AttrKind(0), SyntaxUsed(0),
+        SpellingIndex(SpellingNotCalculated) {}
+
+  AttributeCommonInfo(const IdentifierInfo *AttrName,
+                      const IdentifierInfo *ScopeName, SourceRange AttrRange,
+                      SourceLocation ScopeLoc, Syntax SyntaxUsed)
+      : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange),
+        ScopeLoc(ScopeLoc),
+        AttrKind(getParsedKind(AttrName, ScopeName, SyntaxUsed)),
+        SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated) {}
+
+  AttributeCommonInfo(const IdentifierInfo *AttrName,
+                      const IdentifierInfo *ScopeName, SourceRange AttrRange,
+                      SourceLocation ScopeLoc, Kind AttrKind, Syntax SyntaxUsed)
+      : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange),
+        ScopeLoc(ScopeLoc), AttrKind(AttrKind), SyntaxUsed(SyntaxUsed),
+        SpellingIndex(SpellingNotCalculated) {}
+
+  AttributeCommonInfo(const IdentifierInfo *AttrName,
+                      const IdentifierInfo *ScopeName, SourceRange AttrRange,
+                      SourceLocation ScopeLoc, Kind AttrKind, Syntax SyntaxUsed,
+                      unsigned Spelling)
+      : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange),
+        ScopeLoc(ScopeLoc), AttrKind(AttrKind), SyntaxUsed(SyntaxUsed),
+        SpellingIndex(Spelling) {}
+
+  AttributeCommonInfo(const IdentifierInfo *AttrName, SourceRange AttrRange,
+                      Syntax SyntaxUsed)
+      : AttrName(AttrName), ScopeName(nullptr), AttrRange(AttrRange),
+        ScopeLoc(), AttrKind(getParsedKind(AttrName, ScopeName, SyntaxUsed)),
+        SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated) {}
+
+  AttributeCommonInfo(SourceRange AttrRange, Kind K, Syntax SyntaxUsed)
+      : AttrName(nullptr), ScopeName(nullptr), AttrRange(AttrRange), ScopeLoc(),
+        AttrKind(K), SyntaxUsed(SyntaxUsed),
+        SpellingIndex(SpellingNotCalculated) {}
+
+  AttributeCommonInfo(SourceRange AttrRange, Kind K, Syntax SyntaxUsed,
+                      unsigned Spelling)
+      : AttrName(nullptr), ScopeName(nullptr), AttrRange(AttrRange), ScopeLoc(),
+        AttrKind(K), SyntaxUsed(SyntaxUsed), SpellingIndex(Spelling) {}
+
+  AttributeCommonInfo(AttributeCommonInfo &&) = default;
+  AttributeCommonInfo(const AttributeCommonInfo &) = default;
+
+  Kind getParsedKind() const { return Kind(AttrKind); }
+  Syntax getSyntax() const { return Syntax(SyntaxUsed); }
+  const IdentifierInfo *getAttrName() const { return AttrName; }
+  SourceLocation getLoc() const { return AttrRange.getBegin(); }
+  SourceRange getRange() const { return AttrRange; }
+  void setRange(SourceRange R) { AttrRange = R; }
+
+  bool hasScope() const { return ScopeName; }
+  const IdentifierInfo *getScopeName() const { return ScopeName; }
+  SourceLocation getScopeLoc() const { return ScopeLoc; }
+
+  bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
+  bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }
+
+  bool isGNUScope() const;
+
+  bool isAlignasAttribute() const {
+    // FIXME: Use a better mechanism to determine this.
+    return getParsedKind() == AT_Aligned && isKeywordAttribute();
+  }
+
+  bool isCXX11Attribute() const {
+    return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
+  }
+
+  bool isC2xAttribute() const { return SyntaxUsed == AS_C2x; }
+
+  bool isKeywordAttribute() const {
+    return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
+  }
+
+  bool isContextSensitiveKeywordAttribute() const {
+    return SyntaxUsed == AS_ContextSensitiveKeyword;
+  }
+
+  unsigned getAttributeSpellingListIndex() const {
+    assert((isAttributeSpellingListCalculated() || AttrName) &&
+           "Spelling cannot be found");
+    return isAttributeSpellingListCalculated()
+               ? SpellingIndex
+               : calculateAttributeSpellingListIndex();
+  }
+  void setAttributeSpellingListIndex(unsigned V) { SpellingIndex = V; }
+
+  static Kind getParsedKind(const IdentifierInfo *Name,
+                            const IdentifierInfo *Scope, Syntax SyntaxUsed);
+
+private:
+  /// Get an index into the attribute spelling list
+  /// defined in Attr.td. This index is used by an attribute
+  /// to pretty print itself.
+  unsigned calculateAttributeSpellingListIndex() const;
+
+  friend class clang::ASTRecordWriter;
+  // Used exclusively by ASTDeclWriter to get the raw spelling list state.
+  unsigned getAttributeSpellingListIndexRaw() const { return SpellingIndex; }
+
+protected:
+  bool isAttributeSpellingListCalculated() const {
+    return SpellingIndex != SpellingNotCalculated;
+  }
+};
+} // namespace clang
+
+#endif // LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H

+ 8 - 6
include/clang/Lex/Preprocessor.h

@@ -371,9 +371,9 @@ class Preprocessor {
   /// it expects a '.' or ';'.
   /// it expects a '.' or ';'.
   bool ModuleImportExpectsIdentifier = false;
   bool ModuleImportExpectsIdentifier = false;
 
 
-  /// The source location of the currently-active
+  /// The identifier and source location of the currently-active
   /// \#pragma clang arc_cf_code_audited begin.
   /// \#pragma clang arc_cf_code_audited begin.
-  SourceLocation PragmaARCCFCodeAuditedLoc;
+  std::pair<IdentifierInfo *, SourceLocation> PragmaARCCFCodeAuditedInfo;
 
 
   /// The source location of the currently-active
   /// The source location of the currently-active
   /// \#pragma clang assume_nonnull begin.
   /// \#pragma clang assume_nonnull begin.
@@ -1602,14 +1602,16 @@ public:
   /// arc_cf_code_audited begin.
   /// arc_cf_code_audited begin.
   ///
   ///
   /// Returns an invalid location if there is no such pragma active.
   /// Returns an invalid location if there is no such pragma active.
-  SourceLocation getPragmaARCCFCodeAuditedLoc() const {
-    return PragmaARCCFCodeAuditedLoc;
+  std::pair<IdentifierInfo *, SourceLocation>
+  getPragmaARCCFCodeAuditedInfo() const {
+    return PragmaARCCFCodeAuditedInfo;
   }
   }
 
 
   /// Set the location of the currently-active \#pragma clang
   /// Set the location of the currently-active \#pragma clang
   /// arc_cf_code_audited begin.  An invalid location ends the pragma.
   /// arc_cf_code_audited begin.  An invalid location ends the pragma.
-  void setPragmaARCCFCodeAuditedLoc(SourceLocation Loc) {
-    PragmaARCCFCodeAuditedLoc = Loc;
+  void setPragmaARCCFCodeAuditedInfo(IdentifierInfo *Ident,
+                                     SourceLocation Loc) {
+    PragmaARCCFCodeAuditedInfo = {Ident, Loc};
   }
   }
 
 
   /// The location of the currently-active \#pragma clang
   /// The location of the currently-active \#pragma clang

+ 65 - 147
include/clang/Sema/ParsedAttr.h

@@ -15,6 +15,7 @@
 #define LLVM_CLANG_SEMA_ATTRIBUTELIST_H
 #define LLVM_CLANG_SEMA_ATTRIBUTELIST_H
 
 
 #include "clang/Basic/AttrSubjectMatchRules.h"
 #include "clang/Basic/AttrSubjectMatchRules.h"
+#include "clang/Basic/AttributeCommonInfo.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TargetInfo.h"
@@ -114,7 +115,8 @@ using ArgsVector = llvm::SmallVector<ArgsUnion, 12U>;
 /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
 /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
 ///
 ///
 class ParsedAttr final
 class ParsedAttr final
-    : private llvm::TrailingObjects<
+    : public AttributeCommonInfo,
+      private llvm::TrailingObjects<
           ParsedAttr, ArgsUnion, detail::AvailabilityData,
           ParsedAttr, ArgsUnion, detail::AvailabilityData,
           detail::TypeTagForDatatypeData, ParsedType, detail::PropertyData> {
           detail::TypeTagForDatatypeData, ParsedType, detail::PropertyData> {
   friend TrailingObjects;
   friend TrailingObjects;
@@ -134,54 +136,15 @@ class ParsedAttr final
     return IsProperty;
     return IsProperty;
   }
   }
 
 
-public:
-  /// The style used to specify an attribute.
-  enum Syntax {
-    /// __attribute__((...))
-    AS_GNU,
-
-    /// [[...]]
-    AS_CXX11,
-
-    /// [[...]]
-    AS_C2x,
-
-    /// __declspec(...)
-    AS_Declspec,
-
-    /// [uuid("...")] class Foo
-    AS_Microsoft,
-
-    /// __ptr16, alignas(...), etc.
-    AS_Keyword,
-
-    /// #pragma ...
-    AS_Pragma,
-
-    // Note TableGen depends on the order above.  Do not add or change the order
-    // without adding related code to TableGen/ClangAttrEmitter.cpp.
-    /// Context-sensitive version of a keyword attribute.
-    AS_ContextSensitiveKeyword,
-  };
-
 private:
 private:
-  IdentifierInfo *AttrName;
-  IdentifierInfo *ScopeName;
   IdentifierInfo *MacroII = nullptr;
   IdentifierInfo *MacroII = nullptr;
   SourceLocation MacroExpansionLoc;
   SourceLocation MacroExpansionLoc;
-  SourceRange AttrRange;
-  SourceLocation ScopeLoc;
   SourceLocation EllipsisLoc;
   SourceLocation EllipsisLoc;
 
 
-  unsigned AttrKind : 16;
-
   /// The number of expression arguments this attribute has.
   /// The number of expression arguments this attribute has.
   /// The expressions themselves are stored after the object.
   /// The expressions themselves are stored after the object.
   unsigned NumArgs : 16;
   unsigned NumArgs : 16;
 
 
-  /// Corresponds to the Syntax enum.
-  unsigned SyntaxUsed : 3;
-
   /// True if already diagnosed as invalid.
   /// True if already diagnosed as invalid.
   mutable unsigned Invalid : 1;
   mutable unsigned Invalid : 1;
 
 
@@ -239,14 +202,14 @@ private:
              IdentifierInfo *scopeName, SourceLocation scopeLoc,
              IdentifierInfo *scopeName, SourceLocation scopeLoc,
              ArgsUnion *args, unsigned numArgs, Syntax syntaxUsed,
              ArgsUnion *args, unsigned numArgs, Syntax syntaxUsed,
              SourceLocation ellipsisLoc)
              SourceLocation ellipsisLoc)
-      : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
-        ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs),
-        SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false),
-        IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
-        HasParsedType(false), HasProcessingCache(false),
-        IsPragmaClangAttribute(false) {
-    if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));
-    AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
+      : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc,
+                            syntaxUsed),
+        EllipsisLoc(ellipsisLoc), NumArgs(numArgs), Invalid(false),
+        UsedAsTypeAttr(false), IsAvailability(false),
+        IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
+        HasProcessingCache(false), IsPragmaClangAttribute(false) {
+    if (numArgs)
+      memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));
   }
   }
 
 
   /// Constructor for availability attributes.
   /// Constructor for availability attributes.
@@ -257,9 +220,9 @@ private:
              const AvailabilityChange &obsoleted, SourceLocation unavailable,
              const AvailabilityChange &obsoleted, SourceLocation unavailable,
              const Expr *messageExpr, Syntax syntaxUsed, SourceLocation strict,
              const Expr *messageExpr, Syntax syntaxUsed, SourceLocation strict,
              const Expr *replacementExpr)
              const Expr *replacementExpr)
-      : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
-        ScopeLoc(scopeLoc), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
-        UsedAsTypeAttr(false), IsAvailability(true),
+      : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc,
+                            syntaxUsed),
+        NumArgs(1), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
         IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
         IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
         HasProcessingCache(false), IsPragmaClangAttribute(false),
         HasProcessingCache(false), IsPragmaClangAttribute(false),
         UnavailableLoc(unavailable), MessageExpr(messageExpr) {
         UnavailableLoc(unavailable), MessageExpr(messageExpr) {
@@ -267,7 +230,6 @@ private:
     memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
     memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
     new (getAvailabilityData()) detail::AvailabilityData(
     new (getAvailabilityData()) detail::AvailabilityData(
         introduced, deprecated, obsoleted, strict, replacementExpr);
         introduced, deprecated, obsoleted, strict, replacementExpr);
-    AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
   }
   }
 
 
   /// Constructor for objc_bridge_related attributes.
   /// Constructor for objc_bridge_related attributes.
@@ -275,16 +237,16 @@ private:
              IdentifierInfo *scopeName, SourceLocation scopeLoc,
              IdentifierInfo *scopeName, SourceLocation scopeLoc,
              IdentifierLoc *Parm1, IdentifierLoc *Parm2, IdentifierLoc *Parm3,
              IdentifierLoc *Parm1, IdentifierLoc *Parm2, IdentifierLoc *Parm3,
              Syntax syntaxUsed)
              Syntax syntaxUsed)
-      : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
-        ScopeLoc(scopeLoc), NumArgs(3), SyntaxUsed(syntaxUsed), Invalid(false),
-        UsedAsTypeAttr(false), IsAvailability(false),
-        IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
-        HasProcessingCache(false), IsPragmaClangAttribute(false) {
+      : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc,
+                            syntaxUsed),
+        NumArgs(3), Invalid(false), UsedAsTypeAttr(false),
+        IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
+        HasParsedType(false), HasProcessingCache(false),
+        IsPragmaClangAttribute(false) {
     ArgsUnion *Args = getArgsBuffer();
     ArgsUnion *Args = getArgsBuffer();
     Args[0] = Parm1;
     Args[0] = Parm1;
     Args[1] = Parm2;
     Args[1] = Parm2;
     Args[2] = Parm3;
     Args[2] = Parm3;
-    AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
   }
   }
 
 
   /// Constructor for type_tag_for_datatype attribute.
   /// Constructor for type_tag_for_datatype attribute.
@@ -292,31 +254,31 @@ private:
              IdentifierInfo *scopeName, SourceLocation scopeLoc,
              IdentifierInfo *scopeName, SourceLocation scopeLoc,
              IdentifierLoc *ArgKind, ParsedType matchingCType,
              IdentifierLoc *ArgKind, ParsedType matchingCType,
              bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed)
              bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed)
-      : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
-        ScopeLoc(scopeLoc), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
-        UsedAsTypeAttr(false), IsAvailability(false),
-        IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false),
-        HasProcessingCache(false), IsPragmaClangAttribute(false) {
+      : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc,
+                            syntaxUsed),
+        NumArgs(1), Invalid(false), UsedAsTypeAttr(false),
+        IsAvailability(false), IsTypeTagForDatatype(true), IsProperty(false),
+        HasParsedType(false), HasProcessingCache(false),
+        IsPragmaClangAttribute(false) {
     ArgsUnion PVal(ArgKind);
     ArgsUnion PVal(ArgKind);
     memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
     memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
     detail::TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
     detail::TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
     new (&ExtraData.MatchingCType) ParsedType(matchingCType);
     new (&ExtraData.MatchingCType) ParsedType(matchingCType);
     ExtraData.LayoutCompatible = layoutCompatible;
     ExtraData.LayoutCompatible = layoutCompatible;
     ExtraData.MustBeNull = mustBeNull;
     ExtraData.MustBeNull = mustBeNull;
-    AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
   }
   }
 
 
   /// Constructor for attributes with a single type argument.
   /// Constructor for attributes with a single type argument.
   ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
   ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
              IdentifierInfo *scopeName, SourceLocation scopeLoc,
              IdentifierInfo *scopeName, SourceLocation scopeLoc,
              ParsedType typeArg, Syntax syntaxUsed)
              ParsedType typeArg, Syntax syntaxUsed)
-      : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
-        ScopeLoc(scopeLoc), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false),
-        UsedAsTypeAttr(false), IsAvailability(false),
-        IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true),
-        HasProcessingCache(false), IsPragmaClangAttribute(false) {
+      : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc,
+                            syntaxUsed),
+        NumArgs(0), Invalid(false), UsedAsTypeAttr(false),
+        IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
+        HasParsedType(true), HasProcessingCache(false),
+        IsPragmaClangAttribute(false) {
     new (&getTypeBuffer()) ParsedType(typeArg);
     new (&getTypeBuffer()) ParsedType(typeArg);
-    AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
   }
   }
 
 
   /// Constructor for microsoft __declspec(property) attribute.
   /// Constructor for microsoft __declspec(property) attribute.
@@ -324,13 +286,13 @@ private:
              IdentifierInfo *scopeName, SourceLocation scopeLoc,
              IdentifierInfo *scopeName, SourceLocation scopeLoc,
              IdentifierInfo *getterId, IdentifierInfo *setterId,
              IdentifierInfo *getterId, IdentifierInfo *setterId,
              Syntax syntaxUsed)
              Syntax syntaxUsed)
-      : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
-        ScopeLoc(scopeLoc), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false),
-        UsedAsTypeAttr(false), IsAvailability(false),
-        IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false),
-        HasProcessingCache(false), IsPragmaClangAttribute(false) {
+      : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc,
+                            syntaxUsed),
+        NumArgs(0), Invalid(false), UsedAsTypeAttr(false),
+        IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(true),
+        HasParsedType(false), HasProcessingCache(false),
+        IsPragmaClangAttribute(false) {
     new (&getPropertyDataBuffer()) detail::PropertyData(getterId, setterId);
     new (&getPropertyDataBuffer()) detail::PropertyData(getterId, setterId);
-    AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
   }
   }
 
 
   /// Type tag information is stored immediately following the arguments, if
   /// Type tag information is stored immediately following the arguments, if
@@ -372,27 +334,6 @@ public:
 
 
   void operator delete(void *) = delete;
   void operator delete(void *) = delete;
 
 
-  enum Kind {
-    #define PARSED_ATTR(NAME) AT_##NAME,
-    #include "clang/Sema/AttrParsedAttrList.inc"
-    #undef PARSED_ATTR
-    IgnoredAttribute,
-    UnknownAttribute
-  };
-
-  IdentifierInfo *getName() const { return AttrName; }
-  SourceLocation getLoc() const { return AttrRange.getBegin(); }
-  SourceRange getRange() const { return AttrRange; }
-
-  bool hasScope() const { return ScopeName; }
-  IdentifierInfo *getScopeName() const { return ScopeName; }
-  SourceLocation getScopeLoc() const { return ScopeLoc; }
-
-  bool isGNUScope() const {
-    return ScopeName &&
-           (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
-  }
-
   bool hasParsedType() const { return HasParsedType; }
   bool hasParsedType() const { return HasParsedType; }
 
 
   /// Is this the Microsoft __declspec(property) attribute?
   /// Is this the Microsoft __declspec(property) attribute?
@@ -400,30 +341,6 @@ public:
     return IsProperty;
     return IsProperty;
   }
   }
 
 
-  bool isAlignasAttribute() const {
-    // FIXME: Use a better mechanism to determine this.
-    return getKind() == AT_Aligned && isKeywordAttribute();
-  }
-
-  bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
-  bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }
-
-  bool isCXX11Attribute() const {
-    return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
-  }
-
-  bool isC2xAttribute() const {
-    return SyntaxUsed == AS_C2x;
-  }
-
-  bool isKeywordAttribute() const {
-    return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
-  }
-
-  bool isContextSensitiveKeywordAttribute() const {
-    return SyntaxUsed == AS_ContextSensitiveKeyword;
-  }
-
   bool isInvalid() const { return Invalid; }
   bool isInvalid() const { return Invalid; }
   void setInvalid(bool b = true) const { Invalid = b; }
   void setInvalid(bool b = true) const { Invalid = b; }
 
 
@@ -450,10 +367,6 @@ public:
   bool isPackExpansion() const { return EllipsisLoc.isValid(); }
   bool isPackExpansion() const { return EllipsisLoc.isValid(); }
   SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
   SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
 
 
-  Kind getKind() const { return Kind(AttrKind); }
-  static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope,
-                      Syntax SyntaxUsed);
-
   /// getNumArgs - Return the number of actual arguments to this attribute.
   /// getNumArgs - Return the number of actual arguments to this attribute.
   unsigned getNumArgs() const { return NumArgs; }
   unsigned getNumArgs() const { return NumArgs; }
 
 
@@ -480,54 +393,61 @@ public:
   }
   }
 
 
   const AvailabilityChange &getAvailabilityIntroduced() const {
   const AvailabilityChange &getAvailabilityIntroduced() const {
-    assert(getKind() == AT_Availability && "Not an availability attribute");
+    assert(getParsedKind() == AT_Availability &&
+           "Not an availability attribute");
     return getAvailabilityData()->Changes[detail::IntroducedSlot];
     return getAvailabilityData()->Changes[detail::IntroducedSlot];
   }
   }
 
 
   const AvailabilityChange &getAvailabilityDeprecated() const {
   const AvailabilityChange &getAvailabilityDeprecated() const {
-    assert(getKind() == AT_Availability && "Not an availability attribute");
+    assert(getParsedKind() == AT_Availability &&
+           "Not an availability attribute");
     return getAvailabilityData()->Changes[detail::DeprecatedSlot];
     return getAvailabilityData()->Changes[detail::DeprecatedSlot];
   }
   }
 
 
   const AvailabilityChange &getAvailabilityObsoleted() const {
   const AvailabilityChange &getAvailabilityObsoleted() const {
-    assert(getKind() == AT_Availability && "Not an availability attribute");
+    assert(getParsedKind() == AT_Availability &&
+           "Not an availability attribute");
     return getAvailabilityData()->Changes[detail::ObsoletedSlot];
     return getAvailabilityData()->Changes[detail::ObsoletedSlot];
   }
   }
 
 
   SourceLocation getStrictLoc() const {
   SourceLocation getStrictLoc() const {
-    assert(getKind() == AT_Availability && "Not an availability attribute");
+    assert(getParsedKind() == AT_Availability &&
+           "Not an availability attribute");
     return getAvailabilityData()->StrictLoc;
     return getAvailabilityData()->StrictLoc;
   }
   }
 
 
   SourceLocation getUnavailableLoc() const {
   SourceLocation getUnavailableLoc() const {
-    assert(getKind() == AT_Availability && "Not an availability attribute");
+    assert(getParsedKind() == AT_Availability &&
+           "Not an availability attribute");
     return UnavailableLoc;
     return UnavailableLoc;
   }
   }
 
 
   const Expr * getMessageExpr() const {
   const Expr * getMessageExpr() const {
-    assert(getKind() == AT_Availability && "Not an availability attribute");
+    assert(getParsedKind() == AT_Availability &&
+           "Not an availability attribute");
     return MessageExpr;
     return MessageExpr;
   }
   }
 
 
   const Expr *getReplacementExpr() const {
   const Expr *getReplacementExpr() const {
-    assert(getKind() == AT_Availability && "Not an availability attribute");
+    assert(getParsedKind() == AT_Availability &&
+           "Not an availability attribute");
     return getAvailabilityData()->Replacement;
     return getAvailabilityData()->Replacement;
   }
   }
 
 
   const ParsedType &getMatchingCType() const {
   const ParsedType &getMatchingCType() const {
-    assert(getKind() == AT_TypeTagForDatatype &&
+    assert(getParsedKind() == AT_TypeTagForDatatype &&
            "Not a type_tag_for_datatype attribute");
            "Not a type_tag_for_datatype attribute");
     return getTypeTagForDatatypeDataSlot().MatchingCType;
     return getTypeTagForDatatypeDataSlot().MatchingCType;
   }
   }
 
 
   bool getLayoutCompatible() const {
   bool getLayoutCompatible() const {
-    assert(getKind() == AT_TypeTagForDatatype &&
+    assert(getParsedKind() == AT_TypeTagForDatatype &&
            "Not a type_tag_for_datatype attribute");
            "Not a type_tag_for_datatype attribute");
     return getTypeTagForDatatypeDataSlot().LayoutCompatible;
     return getTypeTagForDatatypeDataSlot().LayoutCompatible;
   }
   }
 
 
   bool getMustBeNull() const {
   bool getMustBeNull() const {
-    assert(getKind() == AT_TypeTagForDatatype &&
+    assert(getParsedKind() == AT_TypeTagForDatatype &&
            "Not a type_tag_for_datatype attribute");
            "Not a type_tag_for_datatype attribute");
     return getTypeTagForDatatypeDataSlot().MustBeNull;
     return getTypeTagForDatatypeDataSlot().MustBeNull;
   }
   }
@@ -570,11 +490,6 @@ public:
     return MacroExpansionLoc;
     return MacroExpansionLoc;
   }
   }
 
 
-  /// Get an index into the attribute spelling list
-  /// defined in Attr.td. This index is used by an attribute
-  /// to pretty print itself.
-  unsigned getAttributeSpellingListIndex() const;
-
   bool isTargetSpecificAttr() const;
   bool isTargetSpecificAttr() const;
   bool isTypeAttr() const;
   bool isTypeAttr() const;
   bool isStmtAttr() const;
   bool isStmtAttr() const;
@@ -603,7 +518,7 @@ public:
   /// If this is an OpenCL addr space attribute returns its representation
   /// If this is an OpenCL addr space attribute returns its representation
   /// in LangAS, otherwise returns default addr space.
   /// in LangAS, otherwise returns default addr space.
   LangAS asOpenCLLangAS() const {
   LangAS asOpenCLLangAS() const {
-    switch (getKind()) {
+    switch (getParsedKind()) {
     case ParsedAttr::AT_OpenCLConstantAddressSpace:
     case ParsedAttr::AT_OpenCLConstantAddressSpace:
       return LangAS::opencl_constant;
       return LangAS::opencl_constant;
     case ParsedAttr::AT_OpenCLGlobalAddressSpace:
     case ParsedAttr::AT_OpenCLGlobalAddressSpace:
@@ -618,6 +533,8 @@ public:
       return LangAS::Default;
       return LangAS::Default;
     }
     }
   }
   }
+
+  AttributeCommonInfo::Kind getKind() const { return getParsedKind(); }
 };
 };
 
 
 class AttributePool;
 class AttributePool;
@@ -889,8 +806,9 @@ public:
   }
   }
 
 
   bool hasAttribute(ParsedAttr::Kind K) const {
   bool hasAttribute(ParsedAttr::Kind K) const {
-    return llvm::any_of(
-        AttrList, [K](const ParsedAttr *AL) { return AL->getKind() == K; });
+    return llvm::any_of(AttrList, [K](const ParsedAttr *AL) {
+      return AL->getParsedKind() == K;
+    });
   }
   }
 
 
 private:
 private:
@@ -1038,28 +956,28 @@ enum AttributeDeclKind {
 
 
 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
                                            const ParsedAttr &At) {
                                            const ParsedAttr &At) {
-  DB.AddTaggedVal(reinterpret_cast<intptr_t>(At.getName()),
+  DB.AddTaggedVal(reinterpret_cast<intptr_t>(At.getAttrName()),
                   DiagnosticsEngine::ak_identifierinfo);
                   DiagnosticsEngine::ak_identifierinfo);
   return DB;
   return DB;
 }
 }
 
 
 inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
 inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
                                            const ParsedAttr &At) {
                                            const ParsedAttr &At) {
-  PD.AddTaggedVal(reinterpret_cast<intptr_t>(At.getName()),
+  PD.AddTaggedVal(reinterpret_cast<intptr_t>(At.getAttrName()),
                   DiagnosticsEngine::ak_identifierinfo);
                   DiagnosticsEngine::ak_identifierinfo);
   return PD;
   return PD;
 }
 }
 
 
 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
                                            const ParsedAttr *At) {
                                            const ParsedAttr *At) {
-  DB.AddTaggedVal(reinterpret_cast<intptr_t>(At->getName()),
+  DB.AddTaggedVal(reinterpret_cast<intptr_t>(At->getAttrName()),
                   DiagnosticsEngine::ak_identifierinfo);
                   DiagnosticsEngine::ak_identifierinfo);
   return DB;
   return DB;
 }
 }
 
 
 inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
 inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
                                            const ParsedAttr *At) {
                                            const ParsedAttr *At) {
-  PD.AddTaggedVal(reinterpret_cast<intptr_t>(At->getName()),
+  PD.AddTaggedVal(reinterpret_cast<intptr_t>(At->getAttrName()),
                   DiagnosticsEngine::ak_identifierinfo);
                   DiagnosticsEngine::ak_identifierinfo);
   return PD;
   return PD;
 }
 }

+ 49 - 54
include/clang/Sema/Sema.h

@@ -2665,48 +2665,44 @@ public:
   };
   };
 
 
   /// Attribute merging methods. Return true if a new attribute was added.
   /// Attribute merging methods. Return true if a new attribute was added.
-  AvailabilityAttr *mergeAvailabilityAttr(
-      NamedDecl *D, SourceRange Range, IdentifierInfo *Platform, bool Implicit,
-      VersionTuple Introduced, VersionTuple Deprecated, VersionTuple Obsoleted,
-      bool IsUnavailable, StringRef Message, bool IsStrict,
-      StringRef Replacement, AvailabilityMergeKind AMK, int Priority,
-      unsigned AttrSpellingListIndex);
-  TypeVisibilityAttr *mergeTypeVisibilityAttr(Decl *D, SourceRange Range,
-                                       TypeVisibilityAttr::VisibilityType Vis,
-                                              unsigned AttrSpellingListIndex);
-  VisibilityAttr *mergeVisibilityAttr(Decl *D, SourceRange Range,
-                                      VisibilityAttr::VisibilityType Vis,
-                                      unsigned AttrSpellingListIndex);
-  UuidAttr *mergeUuidAttr(Decl *D, SourceRange Range,
-                          unsigned AttrSpellingListIndex, StringRef Uuid);
-  DLLImportAttr *mergeDLLImportAttr(Decl *D, SourceRange Range,
-                                    unsigned AttrSpellingListIndex);
-  DLLExportAttr *mergeDLLExportAttr(Decl *D, SourceRange Range,
-                                    unsigned AttrSpellingListIndex);
+  AvailabilityAttr *
+  mergeAvailabilityAttr(NamedDecl *D, const AttributeCommonInfo &CI,
+                        IdentifierInfo *Platform, bool Implicit,
+                        VersionTuple Introduced, VersionTuple Deprecated,
+                        VersionTuple Obsoleted, bool IsUnavailable,
+                        StringRef Message, bool IsStrict, StringRef Replacement,
+                        AvailabilityMergeKind AMK, int Priority);
+  TypeVisibilityAttr *
+  mergeTypeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI,
+                          TypeVisibilityAttr::VisibilityType Vis);
+  VisibilityAttr *mergeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI,
+                                      VisibilityAttr::VisibilityType Vis);
+  UuidAttr *mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI,
+                          StringRef Uuid);
+  DLLImportAttr *mergeDLLImportAttr(Decl *D, const AttributeCommonInfo &CI);
+  DLLExportAttr *mergeDLLExportAttr(Decl *D, const AttributeCommonInfo &CI);
   MSInheritanceAttr *
   MSInheritanceAttr *
-  mergeMSInheritanceAttr(Decl *D, SourceRange Range, bool BestCase,
-                         unsigned AttrSpellingListIndex,
+  mergeMSInheritanceAttr(Decl *D, const AttributeCommonInfo &CI, bool BestCase,
                          MSInheritanceAttr::Spelling SemanticSpelling);
                          MSInheritanceAttr::Spelling SemanticSpelling);
-  FormatAttr *mergeFormatAttr(Decl *D, SourceRange Range,
+  FormatAttr *mergeFormatAttr(Decl *D, const AttributeCommonInfo &CI,
                               IdentifierInfo *Format, int FormatIdx,
                               IdentifierInfo *Format, int FormatIdx,
-                              int FirstArg, unsigned AttrSpellingListIndex);
-  SectionAttr *mergeSectionAttr(Decl *D, SourceRange Range, StringRef Name,
-                                unsigned AttrSpellingListIndex);
-  CodeSegAttr *mergeCodeSegAttr(Decl *D, SourceRange Range, StringRef Name,
-                                unsigned AttrSpellingListIndex);
-  AlwaysInlineAttr *mergeAlwaysInlineAttr(Decl *D, SourceRange Range,
-                                          IdentifierInfo *Ident,
-                                          unsigned AttrSpellingListIndex);
-  MinSizeAttr *mergeMinSizeAttr(Decl *D, SourceRange Range,
-                                unsigned AttrSpellingListIndex);
+                              int FirstArg);
+  SectionAttr *mergeSectionAttr(Decl *D, const AttributeCommonInfo &CI,
+                                StringRef Name);
+  CodeSegAttr *mergeCodeSegAttr(Decl *D, const AttributeCommonInfo &CI,
+                                StringRef Name);
+  AlwaysInlineAttr *mergeAlwaysInlineAttr(Decl *D,
+                                          const AttributeCommonInfo &CI,
+                                          const IdentifierInfo *Ident);
+  MinSizeAttr *mergeMinSizeAttr(Decl *D, const AttributeCommonInfo &CI);
   NoSpeculativeLoadHardeningAttr *
   NoSpeculativeLoadHardeningAttr *
   mergeNoSpeculativeLoadHardeningAttr(Decl *D,
   mergeNoSpeculativeLoadHardeningAttr(Decl *D,
                                       const NoSpeculativeLoadHardeningAttr &AL);
                                       const NoSpeculativeLoadHardeningAttr &AL);
   SpeculativeLoadHardeningAttr *
   SpeculativeLoadHardeningAttr *
   mergeSpeculativeLoadHardeningAttr(Decl *D,
   mergeSpeculativeLoadHardeningAttr(Decl *D,
                                     const SpeculativeLoadHardeningAttr &AL);
                                     const SpeculativeLoadHardeningAttr &AL);
-  OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D, SourceRange Range,
-                                          unsigned AttrSpellingListIndex);
+  OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D,
+                                          const AttributeCommonInfo &CI);
   InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const ParsedAttr &AL);
   InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const ParsedAttr &AL);
   InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D,
   InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D,
                                                 const InternalLinkageAttr &AL);
                                                 const InternalLinkageAttr &AL);
@@ -8899,51 +8895,50 @@ public:
   void AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, SourceLocation Loc);
   void AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, SourceLocation Loc);
 
 
   /// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
   /// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
-  void AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
-                      unsigned SpellingListIndex, bool IsPackExpansion);
-  void AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *T,
-                      unsigned SpellingListIndex, bool IsPackExpansion);
+  void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
+                      bool IsPackExpansion);
+  void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, TypeSourceInfo *T,
+                      bool IsPackExpansion);
 
 
   /// AddAssumeAlignedAttr - Adds an assume_aligned attribute to a particular
   /// AddAssumeAlignedAttr - Adds an assume_aligned attribute to a particular
   /// declaration.
   /// declaration.
-  void AddAssumeAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, Expr *OE,
-                            unsigned SpellingListIndex);
+  void AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
+                            Expr *OE);
 
 
   /// AddAllocAlignAttr - Adds an alloc_align attribute to a particular
   /// AddAllocAlignAttr - Adds an alloc_align attribute to a particular
   /// declaration.
   /// declaration.
-  void AddAllocAlignAttr(SourceRange AttrRange, Decl *D, Expr *ParamExpr,
-                         unsigned SpellingListIndex);
+  void AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI,
+                         Expr *ParamExpr);
 
 
   /// AddAlignValueAttr - Adds an align_value attribute to a particular
   /// AddAlignValueAttr - Adds an align_value attribute to a particular
   /// declaration.
   /// declaration.
-  void AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
-                         unsigned SpellingListIndex);
+  void AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E);
 
 
   /// AddLaunchBoundsAttr - Adds a launch_bounds attribute to a particular
   /// AddLaunchBoundsAttr - Adds a launch_bounds attribute to a particular
   /// declaration.
   /// declaration.
-  void AddLaunchBoundsAttr(SourceRange AttrRange, Decl *D, Expr *MaxThreads,
-                           Expr *MinBlocks, unsigned SpellingListIndex);
+  void AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI,
+                           Expr *MaxThreads, Expr *MinBlocks);
 
 
   /// AddModeAttr - Adds a mode attribute to a particular declaration.
   /// AddModeAttr - Adds a mode attribute to a particular declaration.
-  void AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
-                   unsigned SpellingListIndex, bool InInstantiation = false);
+  void AddModeAttr(Decl *D, const AttributeCommonInfo &CI, IdentifierInfo *Name,
+                   bool InInstantiation = false);
 
 
-  void AddParameterABIAttr(SourceRange AttrRange, Decl *D,
-                           ParameterABI ABI, unsigned SpellingListIndex);
+  void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
+                           ParameterABI ABI);
 
 
   enum class RetainOwnershipKind {NS, CF, OS};
   enum class RetainOwnershipKind {NS, CF, OS};
-  void AddXConsumedAttr(Decl *D, SourceRange SR, unsigned SpellingIndex,
+  void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
                         RetainOwnershipKind K, bool IsTemplateInstantiation);
                         RetainOwnershipKind K, bool IsTemplateInstantiation);
 
 
   /// addAMDGPUFlatWorkGroupSizeAttr - Adds an amdgpu_flat_work_group_size
   /// addAMDGPUFlatWorkGroupSizeAttr - Adds an amdgpu_flat_work_group_size
   /// attribute to a particular declaration.
   /// attribute to a particular declaration.
-  void addAMDGPUFlatWorkGroupSizeAttr(SourceRange AttrRange, Decl *D, Expr *Min,
-                                      Expr *Max, unsigned SpellingListIndex);
+  void addAMDGPUFlatWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,
+                                      Expr *Min, Expr *Max);
 
 
   /// addAMDGPUWavePersEUAttr - Adds an amdgpu_waves_per_eu attribute to a
   /// addAMDGPUWavePersEUAttr - Adds an amdgpu_waves_per_eu attribute to a
   /// particular declaration.
   /// particular declaration.
-  void addAMDGPUWavesPerEUAttr(SourceRange AttrRange, Decl *D, Expr *Min,
-                               Expr *Max, unsigned SpellingListIndex);
+  void addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI,
+                               Expr *Min, Expr *Max);
 
 
   bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
   bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
 
 

+ 1 - 1
include/clang/Serialization/ASTBitCodes.h

@@ -41,7 +41,7 @@ namespace serialization {
     /// Version 4 of AST files also requires that the version control branch and
     /// Version 4 of AST files also requires that the version control branch and
     /// revision match exactly, since there is no backward compatibility of
     /// revision match exactly, since there is no backward compatibility of
     /// AST files at this time.
     /// AST files at this time.
-    const unsigned VERSION_MAJOR = 7;
+    const unsigned VERSION_MAJOR = 8;
 
 
     /// AST file minor version number supported by this version of
     /// AST file minor version number supported by this version of
     /// Clang.
     /// Clang.

+ 3 - 2
lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp

@@ -291,10 +291,11 @@ static RecordDecl *buildRecordForGlobalizedVars(
                                      static_cast<CharUnits::QuantityType>(
                                      static_cast<CharUnits::QuantityType>(
                                          GlobalMemoryAlignment)));
                                          GlobalMemoryAlignment)));
       Field->addAttr(AlignedAttr::CreateImplicit(
       Field->addAttr(AlignedAttr::CreateImplicit(
-          C, AlignedAttr::GNU_aligned, /*IsAlignmentExpr=*/true,
+          C, /*IsAlignmentExpr=*/true,
           IntegerLiteral::Create(C, Align,
           IntegerLiteral::Create(C, Align,
                                  C.getIntTypeForBitwidth(32, /*Signed=*/0),
                                  C.getIntTypeForBitwidth(32, /*Signed=*/0),
-                                 SourceLocation())));
+                                 SourceLocation()),
+          {}, AttributeCommonInfo::AS_GNU, AlignedAttr::GNU_aligned));
     }
     }
     GlobalizedRD->addDecl(Field);
     GlobalizedRD->addDecl(Field);
     MappedDeclsFields.try_emplace(VD, Field);
     MappedDeclsFields.try_emplace(VD, Field);

+ 3 - 3
lib/Lex/PPDirectives.cpp

@@ -1870,12 +1870,12 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
   SourceLocation StartLoc = IsImportDecl ? IncludeTok.getLocation() : HashLoc;
   SourceLocation StartLoc = IsImportDecl ? IncludeTok.getLocation() : HashLoc;
 
 
   // Complain about attempts to #include files in an audit pragma.
   // Complain about attempts to #include files in an audit pragma.
-  if (PragmaARCCFCodeAuditedLoc.isValid()) {
+  if (PragmaARCCFCodeAuditedInfo.second.isValid()) {
     Diag(StartLoc, diag::err_pp_include_in_arc_cf_code_audited) << IsImportDecl;
     Diag(StartLoc, diag::err_pp_include_in_arc_cf_code_audited) << IsImportDecl;
-    Diag(PragmaARCCFCodeAuditedLoc, diag::note_pragma_entered_here);
+    Diag(PragmaARCCFCodeAuditedInfo.second, diag::note_pragma_entered_here);
 
 
     // Immediately leave the pragma.
     // Immediately leave the pragma.
-    PragmaARCCFCodeAuditedLoc = SourceLocation();
+    PragmaARCCFCodeAuditedInfo = {nullptr, SourceLocation()};
   }
   }
 
 
   // Complain about attempts to #include files in an assume-nonnull pragma.
   // Complain about attempts to #include files in an assume-nonnull pragma.

+ 5 - 4
lib/Lex/PPLexerChange.cpp

@@ -376,12 +376,13 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
   // Complain about reaching a true EOF within arc_cf_code_audited.
   // Complain about reaching a true EOF within arc_cf_code_audited.
   // We don't want to complain about reaching the end of a macro
   // We don't want to complain about reaching the end of a macro
   // instantiation or a _Pragma.
   // instantiation or a _Pragma.
-  if (PragmaARCCFCodeAuditedLoc.isValid() &&
-      !isEndOfMacro && !(CurLexer && CurLexer->Is_PragmaLexer)) {
-    Diag(PragmaARCCFCodeAuditedLoc, diag::err_pp_eof_in_arc_cf_code_audited);
+  if (PragmaARCCFCodeAuditedInfo.second.isValid() && !isEndOfMacro &&
+      !(CurLexer && CurLexer->Is_PragmaLexer)) {
+    Diag(PragmaARCCFCodeAuditedInfo.second,
+         diag::err_pp_eof_in_arc_cf_code_audited);
 
 
     // Recover by leaving immediately.
     // Recover by leaving immediately.
-    PragmaARCCFCodeAuditedLoc = SourceLocation();
+    PragmaARCCFCodeAuditedInfo = {nullptr, SourceLocation()};
   }
   }
 
 
   // Complain about reaching a true EOF within assume_nonnull.
   // Complain about reaching a true EOF within assume_nonnull.

+ 2 - 2
lib/Lex/Pragma.cpp

@@ -1722,7 +1722,7 @@ struct PragmaARCCFCodeAuditedHandler : public PragmaHandler {
       PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
       PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
 
 
     // The start location of the active audit.
     // The start location of the active audit.
-    SourceLocation BeginLoc = PP.getPragmaARCCFCodeAuditedLoc();
+    SourceLocation BeginLoc = PP.getPragmaARCCFCodeAuditedInfo().second;
 
 
     // The start location we want after processing this.
     // The start location we want after processing this.
     SourceLocation NewLoc;
     SourceLocation NewLoc;
@@ -1743,7 +1743,7 @@ struct PragmaARCCFCodeAuditedHandler : public PragmaHandler {
       NewLoc = SourceLocation();
       NewLoc = SourceLocation();
     }
     }
 
 
-    PP.setPragmaARCCFCodeAuditedLoc(NewLoc);
+    PP.setPragmaARCCFCodeAuditedInfo(NameTok.getIdentifierInfo(), NewLoc);
   }
   }
 };
 };
 
 

+ 5 - 5
lib/Parse/ParseDecl.cpp

@@ -347,7 +347,7 @@ unsigned Parser::ParseAttributeArgsCommon(
     bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName) ||
     bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName) ||
                            attributeHasVariadicIdentifierArg(*AttrName);
                            attributeHasVariadicIdentifierArg(*AttrName);
     ParsedAttr::Kind AttrKind =
     ParsedAttr::Kind AttrKind =
-        ParsedAttr::getKind(AttrName, ScopeName, Syntax);
+        ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax);
 
 
     // If we don't know how to parse this attribute, but this is the only
     // If we don't know how to parse this attribute, but this is the only
     // token in this argument, assume it's meant to be an identifier.
     // token in this argument, assume it's meant to be an identifier.
@@ -438,7 +438,7 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
   assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
   assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
 
 
   ParsedAttr::Kind AttrKind =
   ParsedAttr::Kind AttrKind =
-      ParsedAttr::getKind(AttrName, ScopeName, Syntax);
+      ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax);
 
 
   if (AttrKind == ParsedAttr::AT_Availability) {
   if (AttrKind == ParsedAttr::AT_Availability) {
     ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
     ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
@@ -488,7 +488,7 @@ unsigned Parser::ParseClangAttributeArgs(
   assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
   assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
 
 
   ParsedAttr::Kind AttrKind =
   ParsedAttr::Kind AttrKind =
-      ParsedAttr::getKind(AttrName, ScopeName, Syntax);
+      ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax);
 
 
   switch (AttrKind) {
   switch (AttrKind) {
   default:
   default:
@@ -1689,9 +1689,9 @@ void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
     if (!AL.isCXX11Attribute() && !AL.isC2xAttribute())
     if (!AL.isCXX11Attribute() && !AL.isC2xAttribute())
       continue;
       continue;
     if (AL.getKind() == ParsedAttr::UnknownAttribute)
     if (AL.getKind() == ParsedAttr::UnknownAttribute)
-      Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL.getName();
+      Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL;
     else {
     else {
-      Diag(AL.getLoc(), DiagID) << AL.getName();
+      Diag(AL.getLoc(), DiagID) << AL;
       AL.setInvalid();
       AL.setInvalid();
     }
     }
   }
   }

+ 2 - 1
lib/Parse/ParseDeclCXX.cpp

@@ -3916,7 +3916,8 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) {
 
 
 static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
 static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
                                               IdentifierInfo *ScopeName) {
                                               IdentifierInfo *ScopeName) {
-  switch (ParsedAttr::getKind(AttrName, ScopeName, ParsedAttr::AS_CXX11)) {
+  switch (
+      ParsedAttr::getParsedKind(AttrName, ScopeName, ParsedAttr::AS_CXX11)) {
   case ParsedAttr::AT_CarriesDependency:
   case ParsedAttr::AT_CarriesDependency:
   case ParsedAttr::AT_Deprecated:
   case ParsedAttr::AT_Deprecated:
   case ParsedAttr::AT_FallThrough:
   case ParsedAttr::AT_FallThrough:

+ 1 - 1
lib/Parse/ParseExprCXX.cpp

@@ -1214,7 +1214,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
             A.getKind() == ParsedAttr::AT_CUDAHost ||
             A.getKind() == ParsedAttr::AT_CUDAHost ||
             A.getKind() == ParsedAttr::AT_CUDAGlobal)
             A.getKind() == ParsedAttr::AT_CUDAGlobal)
           Diag(A.getLoc(), diag::warn_cuda_attr_lambda_position)
           Diag(A.getLoc(), diag::warn_cuda_attr_lambda_position)
-              << A.getName()->getName();
+              << A.getAttrName()->getName();
   };
   };
 
 
   // FIXME: Consider allowing this as an extension for GCC compatibiblity.
   // FIXME: Consider allowing this as an extension for GCC compatibiblity.

+ 4 - 4
lib/Parse/ParsePragma.cpp

@@ -1468,9 +1468,9 @@ void Parser::HandlePragmaAttribute() {
     if (Tok.getIdentifierInfo()) {
     if (Tok.getIdentifierInfo()) {
       // If we suspect that this is an attribute suggest the use of
       // If we suspect that this is an attribute suggest the use of
       // '__attribute__'.
       // '__attribute__'.
-      if (ParsedAttr::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
-                              ParsedAttr::AS_GNU) !=
-          ParsedAttr::UnknownAttribute) {
+      if (ParsedAttr::getParsedKind(
+              Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
+              ParsedAttr::AS_GNU) != ParsedAttr::UnknownAttribute) {
         SourceLocation InsertStartLoc = Tok.getLocation();
         SourceLocation InsertStartLoc = Tok.getLocation();
         ConsumeToken();
         ConsumeToken();
         if (Tok.is(tok::l_paren)) {
         if (Tok.is(tok::l_paren)) {
@@ -1504,7 +1504,7 @@ void Parser::HandlePragmaAttribute() {
   ParsedAttr &Attribute = *Attrs.begin();
   ParsedAttr &Attribute = *Attrs.begin();
   if (!Attribute.isSupportedByPragmaAttribute()) {
   if (!Attribute.isSupportedByPragmaAttribute()) {
     Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
     Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
-        << Attribute.getName();
+        << Attribute;
     SkipToEnd();
     SkipToEnd();
     return;
     return;
   }
   }

+ 1 - 2
lib/Parse/Parser.cpp

@@ -1174,8 +1174,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
   if (Tok.isNot(tok::equal)) {
   if (Tok.isNot(tok::equal)) {
     for (const ParsedAttr &AL : D.getAttributes())
     for (const ParsedAttr &AL : D.getAttributes())
       if (AL.isKnownToGCC() && !AL.isCXX11Attribute())
       if (AL.isKnownToGCC() && !AL.isCXX11Attribute())
-        Diag(AL.getLoc(), diag::warn_attribute_on_function_definition)
-            << AL.getName();
+        Diag(AL.getLoc(), diag::warn_attribute_on_function_definition) << AL;
   }
   }
 
 
   // In delayed template parsing mode, for function template we consume the
   // In delayed template parsing mode, for function template we consume the

+ 12 - 8
lib/Sema/ParsedAttr.cpp

@@ -134,9 +134,13 @@ static StringRef normalizeAttrName(StringRef AttrName,
   return AttrName;
   return AttrName;
 }
 }
 
 
-ParsedAttr::Kind ParsedAttr::getKind(const IdentifierInfo *Name,
-                                     const IdentifierInfo *ScopeName,
-                                     Syntax SyntaxUsed) {
+bool AttributeCommonInfo::isGNUScope() const {
+  return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
+}
+AttributeCommonInfo::Kind
+AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,
+                                   const IdentifierInfo *ScopeName,
+                                   Syntax SyntaxUsed) {
   StringRef AttrName = Name->getName();
   StringRef AttrName = Name->getName();
 
 
   SmallString<64> FullName;
   SmallString<64> FullName;
@@ -154,16 +158,16 @@ ParsedAttr::Kind ParsedAttr::getKind(const IdentifierInfo *Name,
   return ::getAttrKind(FullName, SyntaxUsed);
   return ::getAttrKind(FullName, SyntaxUsed);
 }
 }
 
 
-unsigned ParsedAttr::getAttributeSpellingListIndex() const {
+unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
   // Both variables will be used in tablegen generated
   // Both variables will be used in tablegen generated
   // attribute spell list index matching code.
   // attribute spell list index matching code.
-  auto Syntax = static_cast<ParsedAttr::Syntax>(SyntaxUsed);
+  auto Syntax = static_cast<ParsedAttr::Syntax>(getSyntax());
   StringRef Scope =
   StringRef Scope =
-      ScopeName ? normalizeAttrScopeName(ScopeName->getName(), Syntax) : "";
-  StringRef Name = normalizeAttrName(AttrName->getName(), Scope, Syntax);
+      getScopeName() ? normalizeAttrScopeName(getScopeName()->getName(), Syntax)
+                     : "";
+  StringRef Name = normalizeAttrName(getAttrName()->getName(), Scope, Syntax);
 
 
 #include "clang/Sema/AttrSpellingListIndex.inc"
 #include "clang/Sema/AttrSpellingListIndex.inc"
-
 }
 }
 
 
 struct ParsedAttrInfo {
 struct ParsedAttrInfo {

+ 10 - 5
lib/Sema/SemaAttr.cpp

@@ -571,12 +571,15 @@ void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
   if (VD->isUsed())
   if (VD->isUsed())
     Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name;
     Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name;
 
 
-  VD->addAttr(UnusedAttr::CreateImplicit(Context, UnusedAttr::GNU_unused,
-                                         IdTok.getLocation()));
+  VD->addAttr(UnusedAttr::CreateImplicit(Context, IdTok.getLocation(),
+                                         AttributeCommonInfo::AS_Pragma,
+                                         UnusedAttr::GNU_unused));
 }
 }
 
 
 void Sema::AddCFAuditedAttribute(Decl *D) {
 void Sema::AddCFAuditedAttribute(Decl *D) {
-  SourceLocation Loc = PP.getPragmaARCCFCodeAuditedLoc();
+  IdentifierInfo *Ident;
+  SourceLocation Loc;
+  std::tie(Ident, Loc) = PP.getPragmaARCCFCodeAuditedInfo();
   if (!Loc.isValid()) return;
   if (!Loc.isValid()) return;
 
 
   // Don't add a redundant or conflicting attribute.
   // Don't add a redundant or conflicting attribute.
@@ -584,7 +587,9 @@ void Sema::AddCFAuditedAttribute(Decl *D) {
       D->hasAttr<CFUnknownTransferAttr>())
       D->hasAttr<CFUnknownTransferAttr>())
     return;
     return;
 
 
-  D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Loc));
+  AttributeCommonInfo Info(Ident, SourceRange(Loc),
+                           AttributeCommonInfo::AS_Pragma);
+  D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Info));
 }
 }
 
 
 namespace {
 namespace {
@@ -735,7 +740,7 @@ void Sema::ActOnPragmaAttributeAttribute(
   if (!Rules.empty()) {
   if (!Rules.empty()) {
     auto Diagnostic =
     auto Diagnostic =
         Diag(PragmaLoc, diag::err_pragma_attribute_invalid_matchers)
         Diag(PragmaLoc, diag::err_pragma_attribute_invalid_matchers)
-        << Attribute.getName();
+        << Attribute;
     SmallVector<attr::SubjectMatchRule, 2> ExtraRules;
     SmallVector<attr::SubjectMatchRule, 2> ExtraRules;
     for (const auto &Rule : Rules) {
     for (const auto &Rule : Rules) {
       ExtraRules.push_back(attr::SubjectMatchRule(Rule.first));
       ExtraRules.push_back(attr::SubjectMatchRule(Rule.first));

+ 71 - 82
lib/Sema/SemaDecl.cpp

@@ -2474,43 +2474,33 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
   // previous decl", for example if the attribute needs to be consistent
   // previous decl", for example if the attribute needs to be consistent
   // between redeclarations, you need to call a custom merge function here.
   // between redeclarations, you need to call a custom merge function here.
   InheritableAttr *NewAttr = nullptr;
   InheritableAttr *NewAttr = nullptr;
-  unsigned AttrSpellingListIndex = Attr->getSpellingListIndex();
   if (const auto *AA = dyn_cast<AvailabilityAttr>(Attr))
   if (const auto *AA = dyn_cast<AvailabilityAttr>(Attr))
     NewAttr = S.mergeAvailabilityAttr(
     NewAttr = S.mergeAvailabilityAttr(
-        D, AA->getRange(), AA->getPlatform(), AA->isImplicit(),
-        AA->getIntroduced(), AA->getDeprecated(), AA->getObsoleted(),
-        AA->getUnavailable(), AA->getMessage(), AA->getStrict(),
-        AA->getReplacement(), AMK, AA->getPriority(), AttrSpellingListIndex);
+        D, *AA, AA->getPlatform(), AA->isImplicit(), AA->getIntroduced(),
+        AA->getDeprecated(), AA->getObsoleted(), AA->getUnavailable(),
+        AA->getMessage(), AA->getStrict(), AA->getReplacement(), AMK,
+        AA->getPriority());
   else if (const auto *VA = dyn_cast<VisibilityAttr>(Attr))
   else if (const auto *VA = dyn_cast<VisibilityAttr>(Attr))
-    NewAttr = S.mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility(),
-                                    AttrSpellingListIndex);
+    NewAttr = S.mergeVisibilityAttr(D, *VA, VA->getVisibility());
   else if (const auto *VA = dyn_cast<TypeVisibilityAttr>(Attr))
   else if (const auto *VA = dyn_cast<TypeVisibilityAttr>(Attr))
-    NewAttr = S.mergeTypeVisibilityAttr(D, VA->getRange(), VA->getVisibility(),
-                                        AttrSpellingListIndex);
+    NewAttr = S.mergeTypeVisibilityAttr(D, *VA, VA->getVisibility());
   else if (const auto *ImportA = dyn_cast<DLLImportAttr>(Attr))
   else if (const auto *ImportA = dyn_cast<DLLImportAttr>(Attr))
-    NewAttr = S.mergeDLLImportAttr(D, ImportA->getRange(),
-                                   AttrSpellingListIndex);
+    NewAttr = S.mergeDLLImportAttr(D, *ImportA);
   else if (const auto *ExportA = dyn_cast<DLLExportAttr>(Attr))
   else if (const auto *ExportA = dyn_cast<DLLExportAttr>(Attr))
-    NewAttr = S.mergeDLLExportAttr(D, ExportA->getRange(),
-                                   AttrSpellingListIndex);
+    NewAttr = S.mergeDLLExportAttr(D, *ExportA);
   else if (const auto *FA = dyn_cast<FormatAttr>(Attr))
   else if (const auto *FA = dyn_cast<FormatAttr>(Attr))
-    NewAttr = S.mergeFormatAttr(D, FA->getRange(), FA->getType(),
-                                FA->getFormatIdx(), FA->getFirstArg(),
-                                AttrSpellingListIndex);
+    NewAttr = S.mergeFormatAttr(D, *FA, FA->getType(), FA->getFormatIdx(),
+                                FA->getFirstArg());
   else if (const auto *SA = dyn_cast<SectionAttr>(Attr))
   else if (const auto *SA = dyn_cast<SectionAttr>(Attr))
-    NewAttr = S.mergeSectionAttr(D, SA->getRange(), SA->getName(),
-                                 AttrSpellingListIndex);
+    NewAttr = S.mergeSectionAttr(D, *SA, SA->getName());
   else if (const auto *CSA = dyn_cast<CodeSegAttr>(Attr))
   else if (const auto *CSA = dyn_cast<CodeSegAttr>(Attr))
-    NewAttr = S.mergeCodeSegAttr(D, CSA->getRange(), CSA->getName(),
-                                 AttrSpellingListIndex);
+    NewAttr = S.mergeCodeSegAttr(D, *CSA, CSA->getName());
   else if (const auto *IA = dyn_cast<MSInheritanceAttr>(Attr))
   else if (const auto *IA = dyn_cast<MSInheritanceAttr>(Attr))
-    NewAttr = S.mergeMSInheritanceAttr(D, IA->getRange(), IA->getBestCase(),
-                                       AttrSpellingListIndex,
+    NewAttr = S.mergeMSInheritanceAttr(D, *IA, IA->getBestCase(),
                                        IA->getSemanticSpelling());
                                        IA->getSemanticSpelling());
   else if (const auto *AA = dyn_cast<AlwaysInlineAttr>(Attr))
   else if (const auto *AA = dyn_cast<AlwaysInlineAttr>(Attr))
-    NewAttr = S.mergeAlwaysInlineAttr(D, AA->getRange(),
-                                      &S.Context.Idents.get(AA->getSpelling()),
-                                      AttrSpellingListIndex);
+    NewAttr = S.mergeAlwaysInlineAttr(D, *AA,
+                                      &S.Context.Idents.get(AA->getSpelling()));
   else if (S.getLangOpts().CUDA && isa<FunctionDecl>(D) &&
   else if (S.getLangOpts().CUDA && isa<FunctionDecl>(D) &&
            (isa<CUDAHostAttr>(Attr) || isa<CUDADeviceAttr>(Attr) ||
            (isa<CUDAHostAttr>(Attr) || isa<CUDADeviceAttr>(Attr) ||
             isa<CUDAGlobalAttr>(Attr))) {
             isa<CUDAGlobalAttr>(Attr))) {
@@ -2518,9 +2508,9 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
     // overloading purposes and must not be merged.
     // overloading purposes and must not be merged.
     return false;
     return false;
   } else if (const auto *MA = dyn_cast<MinSizeAttr>(Attr))
   } else if (const auto *MA = dyn_cast<MinSizeAttr>(Attr))
-    NewAttr = S.mergeMinSizeAttr(D, MA->getRange(), AttrSpellingListIndex);
+    NewAttr = S.mergeMinSizeAttr(D, *MA);
   else if (const auto *OA = dyn_cast<OptimizeNoneAttr>(Attr))
   else if (const auto *OA = dyn_cast<OptimizeNoneAttr>(Attr))
-    NewAttr = S.mergeOptimizeNoneAttr(D, OA->getRange(), AttrSpellingListIndex);
+    NewAttr = S.mergeOptimizeNoneAttr(D, *OA);
   else if (const auto *InternalLinkageA = dyn_cast<InternalLinkageAttr>(Attr))
   else if (const auto *InternalLinkageA = dyn_cast<InternalLinkageAttr>(Attr))
     NewAttr = S.mergeInternalLinkageAttr(D, *InternalLinkageA);
     NewAttr = S.mergeInternalLinkageAttr(D, *InternalLinkageA);
   else if (const auto *CommonA = dyn_cast<CommonAttr>(Attr))
   else if (const auto *CommonA = dyn_cast<CommonAttr>(Attr))
@@ -2534,8 +2524,7 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
             AMK == Sema::AMK_ProtocolImplementation))
             AMK == Sema::AMK_ProtocolImplementation))
     NewAttr = nullptr;
     NewAttr = nullptr;
   else if (const auto *UA = dyn_cast<UuidAttr>(Attr))
   else if (const auto *UA = dyn_cast<UuidAttr>(Attr))
-    NewAttr = S.mergeUuidAttr(D, UA->getRange(), AttrSpellingListIndex,
-                              UA->getGuid());
+    NewAttr = S.mergeUuidAttr(D, *UA, UA->getGuid());
   else if (const auto *SLHA = dyn_cast<SpeculativeLoadHardeningAttr>(Attr))
   else if (const auto *SLHA = dyn_cast<SpeculativeLoadHardeningAttr>(Attr))
     NewAttr = S.mergeSpeculativeLoadHardeningAttr(D, *SLHA);
     NewAttr = S.mergeSpeculativeLoadHardeningAttr(D, *SLHA);
   else if (const auto *SLHA = dyn_cast<NoSpeculativeLoadHardeningAttr>(Attr))
   else if (const auto *SLHA = dyn_cast<NoSpeculativeLoadHardeningAttr>(Attr))
@@ -4612,7 +4601,7 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
         TypeSpecType == DeclSpec::TST_enum) {
         TypeSpecType == DeclSpec::TST_enum) {
       for (const ParsedAttr &AL : DS.getAttributes())
       for (const ParsedAttr &AL : DS.getAttributes())
         Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored)
         Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored)
-            << AL.getName() << GetDiagnosticTypeSpecifierID(TypeSpecType);
+            << AL << GetDiagnosticTypeSpecifierID(TypeSpecType);
     }
     }
   }
   }
 
 
@@ -6288,9 +6277,8 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
           << NewDecl;
           << NewDecl;
       S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
       S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
       NewDecl->dropAttr<DLLImportAttr>();
       NewDecl->dropAttr<DLLImportAttr>();
-      NewDecl->addAttr(::new (S.Context) DLLExportAttr(
-          NewImportAttr->getRange(), S.Context,
-          NewImportAttr->getSpellingListIndex()));
+      NewDecl->addAttr(
+          DLLExportAttr::CreateImplicit(S.Context, NewImportAttr->getRange()));
     } else {
     } else {
       S.Diag(NewDecl->getLocation(),
       S.Diag(NewDecl->getLocation(),
              diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
              diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
@@ -6866,9 +6854,9 @@ NamedDecl *Sema::ActOnVariableDeclarator(
       Diag(D.getDeclSpec().getConstexprSpecLoc(),
       Diag(D.getDeclSpec().getConstexprSpecLoc(),
            diag::err_constinit_local_variable);
            diag::err_constinit_local_variable);
     else
     else
-      NewVD->addAttr(::new (Context) ConstInitAttr(
-          SourceRange(D.getDeclSpec().getConstexprSpecLoc()), Context,
-          ConstInitAttr::Keyword_constinit));
+      NewVD->addAttr(ConstInitAttr::Create(
+          Context, D.getDeclSpec().getConstexprSpecLoc(),
+          AttributeCommonInfo::AS_Keyword, ConstInitAttr::Keyword_constinit));
     break;
     break;
   }
   }
 
 
@@ -6990,8 +6978,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
       }
       }
     }
     }
 
 
-    NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0),
-                                                Context, Label, 0));
+    NewVD->addAttr(::new (Context)
+                       AsmLabelAttr(Context, SE->getStrTokenLoc(0), Label));
   } else if (!ExtnameUndeclaredIdentifiers.empty()) {
   } else if (!ExtnameUndeclaredIdentifiers.empty()) {
     llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
     llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
       ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
       ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
@@ -8889,8 +8877,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
   if (Expr *E = (Expr*) D.getAsmLabel()) {
   if (Expr *E = (Expr*) D.getAsmLabel()) {
     // The parser guarantees this is a string.
     // The parser guarantees this is a string.
     StringLiteral *SE = cast<StringLiteral>(E);
     StringLiteral *SE = cast<StringLiteral>(E);
-    NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context,
-                                                SE->getString(), 0));
+    NewFD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getStrTokenLoc(0),
+                                                SE->getString()));
   } else if (!ExtnameUndeclaredIdentifiers.empty()) {
   } else if (!ExtnameUndeclaredIdentifiers.empty()) {
     llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
     llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
       ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
       ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
@@ -8988,9 +8976,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
   NewFD->setParams(Params);
   NewFD->setParams(Params);
 
 
   if (D.getDeclSpec().isNoreturnSpecified())
   if (D.getDeclSpec().isNoreturnSpecified())
-    NewFD->addAttr(
-        ::new(Context) C11NoReturnAttr(D.getDeclSpec().getNoreturnSpecLoc(),
-                                       Context, 0));
+    NewFD->addAttr(C11NoReturnAttr::Create(Context,
+                                           D.getDeclSpec().getNoreturnSpecLoc(),
+                                           AttributeCommonInfo::AS_Keyword));
 
 
   // Functions returning a variably modified type violate C99 6.7.5.2p2
   // Functions returning a variably modified type violate C99 6.7.5.2p2
   // because all functions have linkage.
   // because all functions have linkage.
@@ -9002,19 +8990,18 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
 
 
   // Apply an implicit SectionAttr if '#pragma clang section text' is active
   // Apply an implicit SectionAttr if '#pragma clang section text' is active
   if (PragmaClangTextSection.Valid && D.isFunctionDefinition() &&
   if (PragmaClangTextSection.Valid && D.isFunctionDefinition() &&
-      !NewFD->hasAttr<SectionAttr>()) {
-    NewFD->addAttr(PragmaClangTextSectionAttr::CreateImplicit(Context,
-                                                 PragmaClangTextSection.SectionName,
-                                                 PragmaClangTextSection.PragmaLocation));
-  }
+      !NewFD->hasAttr<SectionAttr>())
+    NewFD->addAttr(PragmaClangTextSectionAttr::CreateImplicit(
+        Context, PragmaClangTextSection.SectionName,
+        PragmaClangTextSection.PragmaLocation, AttributeCommonInfo::AS_Pragma));
 
 
   // Apply an implicit SectionAttr if #pragma code_seg is active.
   // Apply an implicit SectionAttr if #pragma code_seg is active.
   if (CodeSegStack.CurrentValue && D.isFunctionDefinition() &&
   if (CodeSegStack.CurrentValue && D.isFunctionDefinition() &&
       !NewFD->hasAttr<SectionAttr>()) {
       !NewFD->hasAttr<SectionAttr>()) {
-    NewFD->addAttr(
-        SectionAttr::CreateImplicit(Context, SectionAttr::Declspec_allocate,
-                                    CodeSegStack.CurrentValue->getString(),
-                                    CodeSegStack.CurrentPragmaLocation));
+    NewFD->addAttr(SectionAttr::CreateImplicit(
+        Context, CodeSegStack.CurrentValue->getString(),
+        CodeSegStack.CurrentPragmaLocation, AttributeCommonInfo::AS_Pragma,
+        SectionAttr::Declspec_allocate));
     if (UnifySection(CodeSegStack.CurrentValue->getString(),
     if (UnifySection(CodeSegStack.CurrentValue->getString(),
                      ASTContext::PSF_Implicit | ASTContext::PSF_Execute |
                      ASTContext::PSF_Implicit | ASTContext::PSF_Execute |
                          ASTContext::PSF_Read,
                          ASTContext::PSF_Read,
@@ -9550,12 +9537,11 @@ Attr *Sema::getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD,
   if (Attr *A = getImplicitCodeSegAttrFromClass(*this, FD))
   if (Attr *A = getImplicitCodeSegAttrFromClass(*this, FD))
     return A;
     return A;
   if (!FD->hasAttr<SectionAttr>() && IsDefinition &&
   if (!FD->hasAttr<SectionAttr>() && IsDefinition &&
-      CodeSegStack.CurrentValue) {
-    return SectionAttr::CreateImplicit(getASTContext(),
-                                       SectionAttr::Declspec_allocate,
-                                       CodeSegStack.CurrentValue->getString(),
-                                       CodeSegStack.CurrentPragmaLocation);
-  }
+      CodeSegStack.CurrentValue)
+    return SectionAttr::CreateImplicit(
+        getASTContext(), CodeSegStack.CurrentValue->getString(),
+        CodeSegStack.CurrentPragmaLocation, AttributeCommonInfo::AS_Pragma,
+        SectionAttr::Declspec_allocate);
   return nullptr;
   return nullptr;
 }
 }
 
 
@@ -12401,11 +12387,11 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
       Stack = &DataSegStack;
       Stack = &DataSegStack;
       SectionFlags |= ASTContext::PSF_Write;
       SectionFlags |= ASTContext::PSF_Write;
     }
     }
-    if (Stack->CurrentValue && !var->hasAttr<SectionAttr>()) {
+    if (Stack->CurrentValue && !var->hasAttr<SectionAttr>())
       var->addAttr(SectionAttr::CreateImplicit(
       var->addAttr(SectionAttr::CreateImplicit(
-          Context, SectionAttr::Declspec_allocate,
-          Stack->CurrentValue->getString(), Stack->CurrentPragmaLocation));
-    }
+          Context, Stack->CurrentValue->getString(),
+          Stack->CurrentPragmaLocation, AttributeCommonInfo::AS_Pragma,
+          SectionAttr::Declspec_allocate));
     if (const SectionAttr *SA = var->getAttr<SectionAttr>())
     if (const SectionAttr *SA = var->getAttr<SectionAttr>())
       if (UnifySection(SA->getName(), SectionFlags, var))
       if (UnifySection(SA->getName(), SectionFlags, var))
         var->dropAttr<SectionAttr>();
         var->dropAttr<SectionAttr>();
@@ -12415,7 +12401,8 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
     // attribute.
     // attribute.
     if (CurInitSeg && var->getInit())
     if (CurInitSeg && var->getInit())
       var->addAttr(InitSegAttr::CreateImplicit(Context, CurInitSeg->getString(),
       var->addAttr(InitSegAttr::CreateImplicit(Context, CurInitSeg->getString(),
-                                               CurInitSegLoc));
+                                               CurInitSegLoc,
+                                               AttributeCommonInfo::AS_Pragma));
   }
   }
 
 
   // All the following checks are C++ only.
   // All the following checks are C++ only.
@@ -12548,9 +12535,7 @@ void Sema::CheckStaticLocalForDllExport(VarDecl *VD) {
     NewAttr->setInherited(true);
     NewAttr->setInherited(true);
     VD->addAttr(NewAttr);
     VD->addAttr(NewAttr);
   } else if (Attr *A = FD->getAttr<DLLExportStaticLocalAttr>()) {
   } else if (Attr *A = FD->getAttr<DLLExportStaticLocalAttr>()) {
-    auto *NewAttr = ::new (getASTContext()) DLLExportAttr(A->getRange(),
-                                                          getASTContext(),
-                                                          A->getSpellingListIndex());
+    auto *NewAttr = DLLExportAttr::CreateImplicit(getASTContext(), *A);
     NewAttr->setInherited(true);
     NewAttr->setInherited(true);
     VD->addAttr(NewAttr);
     VD->addAttr(NewAttr);
 
 
@@ -12560,9 +12545,7 @@ void Sema::CheckStaticLocalForDllExport(VarDecl *VD) {
       FD->addAttr(NewAttr);
       FD->addAttr(NewAttr);
 
 
   } else if (Attr *A = FD->getAttr<DLLImportStaticLocalAttr>()) {
   } else if (Attr *A = FD->getAttr<DLLImportStaticLocalAttr>()) {
-    auto *NewAttr = ::new (getASTContext()) DLLImportAttr(A->getRange(),
-                                                          getASTContext(),
-                                                          A->getSpellingListIndex());
+    auto *NewAttr = DLLImportAttr::CreateImplicit(getASTContext(), *A);
     NewAttr->setInherited(true);
     NewAttr->setInherited(true);
     VD->addAttr(NewAttr);
     VD->addAttr(NewAttr);
   }
   }
@@ -12582,17 +12565,20 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) {
   if (VD->hasGlobalStorage() && VD->isThisDeclarationADefinition() &&
   if (VD->hasGlobalStorage() && VD->isThisDeclarationADefinition() &&
       !inTemplateInstantiation() && !VD->hasAttr<SectionAttr>()) {
       !inTemplateInstantiation() && !VD->hasAttr<SectionAttr>()) {
     if (PragmaClangBSSSection.Valid)
     if (PragmaClangBSSSection.Valid)
-      VD->addAttr(PragmaClangBSSSectionAttr::CreateImplicit(Context,
-                                                            PragmaClangBSSSection.SectionName,
-                                                            PragmaClangBSSSection.PragmaLocation));
+      VD->addAttr(PragmaClangBSSSectionAttr::CreateImplicit(
+          Context, PragmaClangBSSSection.SectionName,
+          PragmaClangBSSSection.PragmaLocation,
+          AttributeCommonInfo::AS_Pragma));
     if (PragmaClangDataSection.Valid)
     if (PragmaClangDataSection.Valid)
-      VD->addAttr(PragmaClangDataSectionAttr::CreateImplicit(Context,
-                                                             PragmaClangDataSection.SectionName,
-                                                             PragmaClangDataSection.PragmaLocation));
+      VD->addAttr(PragmaClangDataSectionAttr::CreateImplicit(
+          Context, PragmaClangDataSection.SectionName,
+          PragmaClangDataSection.PragmaLocation,
+          AttributeCommonInfo::AS_Pragma));
     if (PragmaClangRodataSection.Valid)
     if (PragmaClangRodataSection.Valid)
-      VD->addAttr(PragmaClangRodataSectionAttr::CreateImplicit(Context,
-                                                               PragmaClangRodataSection.SectionName,
-                                                               PragmaClangRodataSection.PragmaLocation));
+      VD->addAttr(PragmaClangRodataSectionAttr::CreateImplicit(
+          Context, PragmaClangRodataSection.SectionName,
+          PragmaClangRodataSection.PragmaLocation,
+          AttributeCommonInfo::AS_Pragma));
   }
   }
 
 
   if (auto *DD = dyn_cast<DecompositionDecl>(ThisDecl)) {
   if (auto *DD = dyn_cast<DecompositionDecl>(ThisDecl)) {
@@ -15630,8 +15616,9 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD,
     return;
     return;
 
 
   if (FinalLoc.isValid())
   if (FinalLoc.isValid())
-    Record->addAttr(new (Context)
-                    FinalAttr(FinalLoc, Context, IsFinalSpelledSealed));
+    Record->addAttr(FinalAttr::Create(
+        Context, FinalLoc, AttributeCommonInfo::AS_Keyword,
+        static_cast<FinalAttr::Spelling>(IsFinalSpelledSealed)));
 
 
   // C++ [class]p2:
   // C++ [class]p2:
   //   [...] The class-name is also inserted into the scope of the
   //   [...] The class-name is also inserted into the scope of the
@@ -17551,8 +17538,10 @@ void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
                                       SourceLocation AliasNameLoc) {
                                       SourceLocation AliasNameLoc) {
   NamedDecl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc,
   NamedDecl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc,
                                          LookupOrdinaryName);
                                          LookupOrdinaryName);
+  AttributeCommonInfo Info(AliasName, SourceRange(AliasNameLoc),
+                           AttributeCommonInfo::AS_Pragma);
   AsmLabelAttr *Attr =
   AsmLabelAttr *Attr =
-      AsmLabelAttr::CreateImplicit(Context, AliasName->getName(), AliasNameLoc);
+      AsmLabelAttr::CreateImplicit(Context, AliasName->getName(), Info);
 
 
   // If a declaration that:
   // If a declaration that:
   // 1) declares a function or a variable
   // 1) declares a function or a variable
@@ -17575,7 +17564,7 @@ void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
   Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName);
   Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName);
 
 
   if (PrevDecl) {
   if (PrevDecl) {
-    PrevDecl->addAttr(WeakAttr::CreateImplicit(Context, PragmaLoc));
+    PrevDecl->addAttr(WeakAttr::CreateImplicit(Context, PragmaLoc, AttributeCommonInfo::AS_Pragma));
   } else {
   } else {
     (void)WeakUndeclaredIdentifiers.insert(
     (void)WeakUndeclaredIdentifiers.insert(
       std::pair<IdentifierInfo*,WeakInfo>
       std::pair<IdentifierInfo*,WeakInfo>

File diff suppressed because it is too large
+ 138 - 263
lib/Sema/SemaDeclAttr.cpp


+ 10 - 12
lib/Sema/SemaDeclCXX.cpp

@@ -24,6 +24,7 @@
 #include "clang/AST/StmtVisitor.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/AST/TypeOrdering.h"
 #include "clang/AST/TypeOrdering.h"
+#include "clang/Basic/AttributeCommonInfo.h"
 #include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Lex/LiteralSupport.h"
 #include "clang/Lex/LiteralSupport.h"
@@ -2500,7 +2501,7 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
     Diag(AL.getLoc(), AL.getKind() == ParsedAttr::UnknownAttribute
     Diag(AL.getLoc(), AL.getKind() == ParsedAttr::UnknownAttribute
                           ? (unsigned)diag::warn_unknown_attribute_ignored
                           ? (unsigned)diag::warn_unknown_attribute_ignored
                           : (unsigned)diag::err_base_specifier_attribute)
                           : (unsigned)diag::err_base_specifier_attribute)
-        << AL.getName();
+        << AL;
   }
   }
 
 
   TypeSourceInfo *TInfo = nullptr;
   TypeSourceInfo *TInfo = nullptr;
@@ -3344,10 +3345,12 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
   }
   }
 
 
   if (VS.isOverrideSpecified())
   if (VS.isOverrideSpecified())
-    Member->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context, 0));
+    Member->addAttr(OverrideAttr::Create(Context, VS.getOverrideLoc(),
+                                         AttributeCommonInfo::AS_Keyword));
   if (VS.isFinalSpecified())
   if (VS.isFinalSpecified())
-    Member->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context,
-                                            VS.isFinalSpelledSealed()));
+    Member->addAttr(FinalAttr::Create(
+        Context, VS.getFinalLoc(), AttributeCommonInfo::AS_Keyword,
+        static_cast<FinalAttr::Spelling>(VS.isFinalSpelledSealed())));
 
 
   if (VS.getLastLocation().isValid()) {
   if (VS.getLastLocation().isValid()) {
     // Update the end location of a method that has a virt-specifiers.
     // Update the end location of a method that has a virt-specifiers.
@@ -5920,14 +5923,10 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
           TSK != TSK_ExplicitInstantiationDefinition) {
           TSK != TSK_ExplicitInstantiationDefinition) {
         if (ClassExported) {
         if (ClassExported) {
           NewAttr = ::new (getASTContext())
           NewAttr = ::new (getASTContext())
-            DLLExportStaticLocalAttr(ClassAttr->getRange(),
-                                     getASTContext(),
-                                     ClassAttr->getSpellingListIndex());
+              DLLExportStaticLocalAttr(getASTContext(), *ClassAttr);
         } else {
         } else {
           NewAttr = ::new (getASTContext())
           NewAttr = ::new (getASTContext())
-            DLLImportStaticLocalAttr(ClassAttr->getRange(),
-                                     getASTContext(),
-                                     ClassAttr->getSpellingListIndex());
+              DLLImportStaticLocalAttr(getASTContext(), *ClassAttr);
         }
         }
       } else {
       } else {
         NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
         NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
@@ -8101,8 +8100,7 @@ void Sema::ActOnFinishCXXMemberSpecification(
     if (AL.getKind() != ParsedAttr::AT_Visibility)
     if (AL.getKind() != ParsedAttr::AT_Visibility)
       continue;
       continue;
     AL.setInvalid();
     AL.setInvalid();
-    Diag(AL.getLoc(), diag::warn_attribute_after_definition_ignored)
-        << AL.getName();
+    Diag(AL.getLoc(), diag::warn_attribute_after_definition_ignored) << AL;
   }
   }
 
 
   ActOnFields(S, RLoc, TagDecl, llvm::makeArrayRef(
   ActOnFields(S, RLoc, TagDecl, llvm::makeArrayRef(

+ 6 - 6
lib/Sema/SemaObjCProperty.cpp

@@ -2419,9 +2419,9 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) {
         ObjCReturnsInnerPointerAttr::CreateImplicit(Context, Loc));
         ObjCReturnsInnerPointerAttr::CreateImplicit(Context, Loc));
 
 
     if (const SectionAttr *SA = property->getAttr<SectionAttr>())
     if (const SectionAttr *SA = property->getAttr<SectionAttr>())
-      GetterMethod->addAttr(
-          SectionAttr::CreateImplicit(Context, SectionAttr::GNU_section,
-                                      SA->getName(), Loc));
+      GetterMethod->addAttr(SectionAttr::CreateImplicit(
+          Context, SA->getName(), Loc, AttributeCommonInfo::AS_GNU,
+          SectionAttr::GNU_section));
 
 
     if (getLangOpts().ObjCAutoRefCount)
     if (getLangOpts().ObjCAutoRefCount)
       CheckARCMethodDecl(GetterMethod);
       CheckARCMethodDecl(GetterMethod);
@@ -2485,9 +2485,9 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) {
 
 
       CD->addDecl(SetterMethod);
       CD->addDecl(SetterMethod);
       if (const SectionAttr *SA = property->getAttr<SectionAttr>())
       if (const SectionAttr *SA = property->getAttr<SectionAttr>())
-        SetterMethod->addAttr(
-            SectionAttr::CreateImplicit(Context, SectionAttr::GNU_section,
-                                        SA->getName(), Loc));
+        SetterMethod->addAttr(SectionAttr::CreateImplicit(
+            Context, SA->getName(), Loc, AttributeCommonInfo::AS_GNU,
+            SectionAttr::GNU_section));
       // It's possible for the user to have set a very odd custom
       // It's possible for the user to have set a very odd custom
       // setter selector that causes it to have a method family.
       // setter selector that causes it to have a method family.
       if (getLangOpts().ObjCAutoRefCount)
       if (getLangOpts().ObjCAutoRefCount)

+ 12 - 6
lib/Sema/SemaOpenMP.cpp

@@ -3154,7 +3154,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
     // function directly.
     // function directly.
     getCurCapturedRegion()->TheCapturedDecl->addAttr(
     getCurCapturedRegion()->TheCapturedDecl->addAttr(
         AlwaysInlineAttr::CreateImplicit(
         AlwaysInlineAttr::CreateImplicit(
-            Context, AlwaysInlineAttr::Keyword_forceinline));
+            Context, {}, AttributeCommonInfo::AS_Keyword,
+            AlwaysInlineAttr::Keyword_forceinline));
     Sema::CapturedParamNameType ParamsTarget[] = {
     Sema::CapturedParamNameType ParamsTarget[] = {
         std::make_pair(StringRef(), QualType()) // __context with shared vars
         std::make_pair(StringRef(), QualType()) // __context with shared vars
     };
     };
@@ -3198,7 +3199,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
     // function directly.
     // function directly.
     getCurCapturedRegion()->TheCapturedDecl->addAttr(
     getCurCapturedRegion()->TheCapturedDecl->addAttr(
         AlwaysInlineAttr::CreateImplicit(
         AlwaysInlineAttr::CreateImplicit(
-            Context, AlwaysInlineAttr::Keyword_forceinline));
+            Context, {}, AttributeCommonInfo::AS_Keyword,
+            AlwaysInlineAttr::Keyword_forceinline));
     ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
     ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
                              std::make_pair(StringRef(), QualType()),
                              std::make_pair(StringRef(), QualType()),
                              /*OpenMPCaptureLevel=*/1);
                              /*OpenMPCaptureLevel=*/1);
@@ -3250,7 +3252,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
     // function directly.
     // function directly.
     getCurCapturedRegion()->TheCapturedDecl->addAttr(
     getCurCapturedRegion()->TheCapturedDecl->addAttr(
         AlwaysInlineAttr::CreateImplicit(
         AlwaysInlineAttr::CreateImplicit(
-            Context, AlwaysInlineAttr::Keyword_forceinline));
+            Context, {}, AttributeCommonInfo::AS_Keyword,
+            AlwaysInlineAttr::Keyword_forceinline));
     break;
     break;
   }
   }
   case OMPD_taskloop:
   case OMPD_taskloop:
@@ -3292,7 +3295,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
     // function directly.
     // function directly.
     getCurCapturedRegion()->TheCapturedDecl->addAttr(
     getCurCapturedRegion()->TheCapturedDecl->addAttr(
         AlwaysInlineAttr::CreateImplicit(
         AlwaysInlineAttr::CreateImplicit(
-            Context, AlwaysInlineAttr::Keyword_forceinline));
+            Context, {}, AttributeCommonInfo::AS_Keyword,
+            AlwaysInlineAttr::Keyword_forceinline));
     break;
     break;
   }
   }
   case OMPD_distribute_parallel_for_simd:
   case OMPD_distribute_parallel_for_simd:
@@ -3338,7 +3342,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
     // function directly.
     // function directly.
     getCurCapturedRegion()->TheCapturedDecl->addAttr(
     getCurCapturedRegion()->TheCapturedDecl->addAttr(
         AlwaysInlineAttr::CreateImplicit(
         AlwaysInlineAttr::CreateImplicit(
-            Context, AlwaysInlineAttr::Keyword_forceinline));
+            Context, {}, AttributeCommonInfo::AS_Keyword,
+            AlwaysInlineAttr::Keyword_forceinline));
     Sema::CapturedParamNameType ParamsTarget[] = {
     Sema::CapturedParamNameType ParamsTarget[] = {
         std::make_pair(StringRef(), QualType()) // __context with shared vars
         std::make_pair(StringRef(), QualType()) // __context with shared vars
     };
     };
@@ -3424,7 +3429,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
     // function directly.
     // function directly.
     getCurCapturedRegion()->TheCapturedDecl->addAttr(
     getCurCapturedRegion()->TheCapturedDecl->addAttr(
         AlwaysInlineAttr::CreateImplicit(
         AlwaysInlineAttr::CreateImplicit(
-            Context, AlwaysInlineAttr::Keyword_forceinline));
+            Context, {}, AttributeCommonInfo::AS_Keyword,
+            AlwaysInlineAttr::Keyword_forceinline));
     break;
     break;
   }
   }
   case OMPD_threadprivate:
   case OMPD_threadprivate:

+ 7 - 12
lib/Sema/SemaStmtAttr.cpp

@@ -23,8 +23,7 @@ using namespace sema;
 
 
 static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A,
 static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A,
                                    SourceRange Range) {
                                    SourceRange Range) {
-  FallThroughAttr Attr(A.getRange(), S.Context,
-                       A.getAttributeSpellingListIndex());
+  FallThroughAttr Attr(S.Context, A);
   if (!isa<NullStmt>(St)) {
   if (!isa<NullStmt>(St)) {
     S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_wrong_target)
     S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_wrong_target)
         << Attr.getSpelling() << St->getBeginLoc();
         << Attr.getSpelling() << St->getBeginLoc();
@@ -45,10 +44,10 @@ static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A,
   // about using it as an extension.
   // about using it as an extension.
   if (!S.getLangOpts().CPlusPlus17 && A.isCXX11Attribute() &&
   if (!S.getLangOpts().CPlusPlus17 && A.isCXX11Attribute() &&
       !A.getScopeName())
       !A.getScopeName())
-    S.Diag(A.getLoc(), diag::ext_cxx17_attr) << A.getName();
+    S.Diag(A.getLoc(), diag::ext_cxx17_attr) << A;
 
 
   FnScope->setHasFallthroughStmt();
   FnScope->setHasFallthroughStmt();
-  return ::new (S.Context) auto(Attr);
+  return ::new (S.Context) FallThroughAttr(S.Context, A);
 }
 }
 
 
 static Attr *handleSuppressAttr(Sema &S, Stmt *St, const ParsedAttr &A,
 static Attr *handleSuppressAttr(Sema &S, Stmt *St, const ParsedAttr &A,
@@ -71,8 +70,7 @@ static Attr *handleSuppressAttr(Sema &S, Stmt *St, const ParsedAttr &A,
   }
   }
 
 
   return ::new (S.Context) SuppressAttr(
   return ::new (S.Context) SuppressAttr(
-      A.getRange(), S.Context, DiagnosticIdentifiers.data(),
-      DiagnosticIdentifiers.size(), A.getAttributeSpellingListIndex());
+      S.Context, A, DiagnosticIdentifiers.data(), DiagnosticIdentifiers.size());
 }
 }
 
 
 static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
 static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
@@ -97,8 +95,6 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
     return nullptr;
     return nullptr;
   }
   }
 
 
-  LoopHintAttr::Spelling Spelling =
-      LoopHintAttr::Spelling(A.getAttributeSpellingListIndex());
   LoopHintAttr::OptionType Option;
   LoopHintAttr::OptionType Option;
   LoopHintAttr::LoopHintState State;
   LoopHintAttr::LoopHintState State;
 
 
@@ -171,8 +167,7 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
       llvm_unreachable("bad loop hint");
       llvm_unreachable("bad loop hint");
   }
   }
 
 
-  return LoopHintAttr::CreateImplicit(S.Context, Spelling, Option, State,
-                                      ValueExpr, A.getRange());
+  return LoopHintAttr::CreateImplicit(S.Context, Option, State, ValueExpr, A);
 }
 }
 
 
 static void
 static void
@@ -330,7 +325,7 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
     S.Diag(A.getLoc(), A.isDeclspecAttribute()
     S.Diag(A.getLoc(), A.isDeclspecAttribute()
                            ? (unsigned)diag::warn_unhandled_ms_attribute_ignored
                            ? (unsigned)diag::warn_unhandled_ms_attribute_ignored
                            : (unsigned)diag::warn_unknown_attribute_ignored)
                            : (unsigned)diag::warn_unknown_attribute_ignored)
-        << A.getName();
+        << A;
     return nullptr;
     return nullptr;
   case ParsedAttr::AT_FallThrough:
   case ParsedAttr::AT_FallThrough:
     return handleFallThroughAttr(S, St, A, Range);
     return handleFallThroughAttr(S, St, A, Range);
@@ -344,7 +339,7 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
     // if we're here, then we parsed a known attribute, but didn't recognize
     // if we're here, then we parsed a known attribute, but didn't recognize
     // it as a statement attribute => it is declaration attribute
     // it as a statement attribute => it is declaration attribute
     S.Diag(A.getRange().getBegin(), diag::err_decl_attribute_invalid_on_stmt)
     S.Diag(A.getRange().getBegin(), diag::err_decl_attribute_invalid_on_stmt)
-        << A.getName() << St->getBeginLoc();
+        << A << St->getBeginLoc();
     return nullptr;
     return nullptr;
   }
   }
 }
 }

+ 2 - 3
lib/Sema/SemaTemplateInstantiate.cpp

@@ -1258,9 +1258,8 @@ TemplateInstantiator::TransformLoopHintAttr(const LoopHintAttr *LH) {
 
 
   // Create new LoopHintValueAttr with integral expression in place of the
   // Create new LoopHintValueAttr with integral expression in place of the
   // non-type template parameter.
   // non-type template parameter.
-  return LoopHintAttr::CreateImplicit(
-      getSema().Context, LH->getSemanticSpelling(), LH->getOption(),
-      LH->getState(), TransformedExpr, LH->getRange());
+  return LoopHintAttr::CreateImplicit(getSema().Context, LH->getOption(),
+                                      LH->getState(), TransformedExpr, *LH);
 }
 }
 
 
 ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
 ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(

+ 16 - 29
lib/Sema/SemaTemplateInstantiateDecl.cpp

@@ -86,15 +86,13 @@ static void instantiateDependentAlignedAttr(
         S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
         S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
     ExprResult Result = S.SubstExpr(Aligned->getAlignmentExpr(), TemplateArgs);
     ExprResult Result = S.SubstExpr(Aligned->getAlignmentExpr(), TemplateArgs);
     if (!Result.isInvalid())
     if (!Result.isInvalid())
-      S.AddAlignedAttr(Aligned->getLocation(), New, Result.getAs<Expr>(),
-                       Aligned->getSpellingListIndex(), IsPackExpansion);
+      S.AddAlignedAttr(New, *Aligned, Result.getAs<Expr>(), IsPackExpansion);
   } else {
   } else {
     TypeSourceInfo *Result = S.SubstType(Aligned->getAlignmentType(),
     TypeSourceInfo *Result = S.SubstType(Aligned->getAlignmentType(),
                                          TemplateArgs, Aligned->getLocation(),
                                          TemplateArgs, Aligned->getLocation(),
                                          DeclarationName());
                                          DeclarationName());
     if (Result)
     if (Result)
-      S.AddAlignedAttr(Aligned->getLocation(), New, Result,
-                       Aligned->getSpellingListIndex(), IsPackExpansion);
+      S.AddAlignedAttr(New, *Aligned, Result, IsPackExpansion);
   }
   }
 }
 }
 
 
@@ -156,8 +154,7 @@ static void instantiateDependentAssumeAlignedAttr(
     OE = Result.getAs<Expr>();
     OE = Result.getAs<Expr>();
   }
   }
 
 
-  S.AddAssumeAlignedAttr(Aligned->getLocation(), New, E, OE,
-                         Aligned->getSpellingListIndex());
+  S.AddAssumeAlignedAttr(New, *Aligned, E, OE);
 }
 }
 
 
 static void instantiateDependentAlignValueAttr(
 static void instantiateDependentAlignValueAttr(
@@ -168,8 +165,7 @@ static void instantiateDependentAlignValueAttr(
       S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
       S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
   ExprResult Result = S.SubstExpr(Aligned->getAlignment(), TemplateArgs);
   ExprResult Result = S.SubstExpr(Aligned->getAlignment(), TemplateArgs);
   if (!Result.isInvalid())
   if (!Result.isInvalid())
-    S.AddAlignValueAttr(Aligned->getLocation(), New, Result.getAs<Expr>(),
-                        Aligned->getSpellingListIndex());
+    S.AddAlignValueAttr(New, *Aligned, Result.getAs<Expr>());
 }
 }
 
 
 static void instantiateDependentAllocAlignAttr(
 static void instantiateDependentAllocAlignAttr(
@@ -179,8 +175,7 @@ static void instantiateDependentAllocAlignAttr(
       S.getASTContext(),
       S.getASTContext(),
       llvm::APInt(64, Align->getParamIndex().getSourceIndex()),
       llvm::APInt(64, Align->getParamIndex().getSourceIndex()),
       S.getASTContext().UnsignedLongLongTy, Align->getLocation());
       S.getASTContext().UnsignedLongLongTy, Align->getLocation());
-  S.AddAllocAlignAttr(Align->getLocation(), New, Param,
-                      Align->getSpellingListIndex());
+  S.AddAllocAlignAttr(New, *Align, Param);
 }
 }
 
 
 static Expr *instantiateDependentFunctionAttrCondition(
 static Expr *instantiateDependentFunctionAttrCondition(
@@ -221,9 +216,8 @@ static void instantiateDependentEnableIfAttr(
       S, TemplateArgs, EIA, EIA->getCond(), Tmpl, New);
       S, TemplateArgs, EIA, EIA->getCond(), Tmpl, New);
 
 
   if (Cond)
   if (Cond)
-    New->addAttr(new (S.getASTContext()) EnableIfAttr(
-        EIA->getLocation(), S.getASTContext(), Cond, EIA->getMessage(),
-        EIA->getSpellingListIndex()));
+    New->addAttr(new (S.getASTContext()) EnableIfAttr(S.getASTContext(), *EIA,
+                                                      Cond, EIA->getMessage()));
 }
 }
 
 
 static void instantiateDependentDiagnoseIfAttr(
 static void instantiateDependentDiagnoseIfAttr(
@@ -234,9 +228,8 @@ static void instantiateDependentDiagnoseIfAttr(
 
 
   if (Cond)
   if (Cond)
     New->addAttr(new (S.getASTContext()) DiagnoseIfAttr(
     New->addAttr(new (S.getASTContext()) DiagnoseIfAttr(
-        DIA->getLocation(), S.getASTContext(), Cond, DIA->getMessage(),
-        DIA->getDiagnosticType(), DIA->getArgDependent(), New,
-        DIA->getSpellingListIndex()));
+        S.getASTContext(), *DIA, Cond, DIA->getMessage(),
+        DIA->getDiagnosticType(), DIA->getArgDependent(), New));
 }
 }
 
 
 // Constructs and adds to New a new instance of CUDALaunchBoundsAttr using
 // Constructs and adds to New a new instance of CUDALaunchBoundsAttr using
@@ -261,16 +254,15 @@ static void instantiateDependentCUDALaunchBoundsAttr(
     MinBlocks = Result.getAs<Expr>();
     MinBlocks = Result.getAs<Expr>();
   }
   }
 
 
-  S.AddLaunchBoundsAttr(Attr.getLocation(), New, MaxThreads, MinBlocks,
-                        Attr.getSpellingListIndex());
+  S.AddLaunchBoundsAttr(New, Attr, MaxThreads, MinBlocks);
 }
 }
 
 
 static void
 static void
 instantiateDependentModeAttr(Sema &S,
 instantiateDependentModeAttr(Sema &S,
                              const MultiLevelTemplateArgumentList &TemplateArgs,
                              const MultiLevelTemplateArgumentList &TemplateArgs,
                              const ModeAttr &Attr, Decl *New) {
                              const ModeAttr &Attr, Decl *New) {
-  S.AddModeAttr(Attr.getRange(), New, Attr.getMode(),
-                Attr.getSpellingListIndex(), /*InInstantiation=*/true);
+  S.AddModeAttr(New, Attr, Attr.getMode(),
+                /*InInstantiation=*/true);
 }
 }
 
 
 /// Instantiation of 'declare simd' attribute and its arguments.
 /// Instantiation of 'declare simd' attribute and its arguments.
@@ -373,8 +365,7 @@ static void instantiateDependentAMDGPUFlatWorkGroupSizeAttr(
     return;
     return;
   Expr *MaxExpr = Result.getAs<Expr>();
   Expr *MaxExpr = Result.getAs<Expr>();
 
 
-  S.addAMDGPUFlatWorkGroupSizeAttr(Attr.getLocation(), New, MinExpr, MaxExpr,
-                                   Attr.getSpellingListIndex());
+  S.addAMDGPUFlatWorkGroupSizeAttr(New, Attr, MinExpr, MaxExpr);
 }
 }
 
 
 static ExplicitSpecifier
 static ExplicitSpecifier
@@ -420,8 +411,7 @@ static void instantiateDependentAMDGPUWavesPerEUAttr(
     MaxExpr = Result.getAs<Expr>();
     MaxExpr = Result.getAs<Expr>();
   }
   }
 
 
-  S.addAMDGPUWavesPerEUAttr(Attr.getLocation(), New, MinExpr, MaxExpr,
-                            Attr.getSpellingListIndex());
+  S.addAMDGPUWavesPerEUAttr(New, Attr, MinExpr, MaxExpr);
 }
 }
 
 
 void Sema::InstantiateAttrsForDecl(
 void Sema::InstantiateAttrsForDecl(
@@ -536,16 +526,13 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
     }
     }
 
 
     if (const auto *ABIAttr = dyn_cast<ParameterABIAttr>(TmplAttr)) {
     if (const auto *ABIAttr = dyn_cast<ParameterABIAttr>(TmplAttr)) {
-      AddParameterABIAttr(ABIAttr->getRange(), New, ABIAttr->getABI(),
-                          ABIAttr->getSpellingListIndex());
+      AddParameterABIAttr(New, *ABIAttr, ABIAttr->getABI());
       continue;
       continue;
     }
     }
 
 
     if (isa<NSConsumedAttr>(TmplAttr) || isa<OSConsumedAttr>(TmplAttr) ||
     if (isa<NSConsumedAttr>(TmplAttr) || isa<OSConsumedAttr>(TmplAttr) ||
         isa<CFConsumedAttr>(TmplAttr)) {
         isa<CFConsumedAttr>(TmplAttr)) {
-      AddXConsumedAttr(New, TmplAttr->getRange(),
-                       TmplAttr->getSpellingListIndex(),
-                       attrToRetainOwnershipKind(TmplAttr),
+      AddXConsumedAttr(New, *TmplAttr, attrToRetainOwnershipKind(TmplAttr),
                        /*template instantiation=*/true);
                        /*template instantiation=*/true);
       continue;
       continue;
     }
     }

+ 31 - 37
lib/Sema/SemaType.cpp

@@ -82,7 +82,7 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr,
   }
   }
 
 
   SourceLocation loc = attr.getLoc();
   SourceLocation loc = attr.getLoc();
-  StringRef name = attr.getName()->getName();
+  StringRef name = attr.getAttrName()->getName();
 
 
   // The GC attributes are usually written with macros;  special-case them.
   // The GC attributes are usually written with macros;  special-case them.
   IdentifierInfo *II = attr.isArgIdent(0) ? attr.getArgAsIdent(0)->Ident
   IdentifierInfo *II = attr.isArgIdent(0) ? attr.getArgAsIdent(0)->Ident
@@ -811,7 +811,7 @@ static bool checkOmittedBlockReturnType(Sema &S, Declarator &declarator,
       continue;
       continue;
     S.Diag(AL.getLoc(),
     S.Diag(AL.getLoc(),
            diag::warn_block_literal_attributes_on_omitted_return_type)
            diag::warn_block_literal_attributes_on_omitted_return_type)
-        << AL.getName();
+        << AL;
     ToBeRemoved.push_back(&AL);
     ToBeRemoved.push_back(&AL);
   }
   }
   // Remove bad attributes from the list.
   // Remove bad attributes from the list.
@@ -3942,10 +3942,9 @@ static bool IsNoDerefableChunk(DeclaratorChunk Chunk) {
 }
 }
 
 
 template<typename AttrT>
 template<typename AttrT>
-static AttrT *createSimpleAttr(ASTContext &Ctx, ParsedAttr &Attr) {
-  Attr.setUsedAsTypeAttr();
-  return ::new (Ctx)
-      AttrT(Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex());
+static AttrT *createSimpleAttr(ASTContext &Ctx, ParsedAttr &AL) {
+  AL.setUsedAsTypeAttr();
+  return ::new (Ctx) AttrT(Ctx, AL);
 }
 }
 
 
 static Attr *createNullabilityAttr(ASTContext &Ctx, ParsedAttr &Attr,
 static Attr *createNullabilityAttr(ASTContext &Ctx, ParsedAttr &Attr,
@@ -5983,9 +5982,8 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
     }
     }
 
 
     ASTContext &Ctx = S.Context;
     ASTContext &Ctx = S.Context;
-    auto *ASAttr = ::new (Ctx)
-        AddressSpaceAttr(Attr.getRange(), Ctx, static_cast<unsigned>(ASIdx),
-                         Attr.getAttributeSpellingListIndex());
+    auto *ASAttr =
+        ::new (Ctx) AddressSpaceAttr(Ctx, Attr, static_cast<unsigned>(ASIdx));
 
 
     // If the expression is not value dependent (not templated), then we can
     // If the expression is not value dependent (not templated), then we can
     // apply the address space qualifiers just to the equivalent type.
     // apply the address space qualifiers just to the equivalent type.
@@ -6082,8 +6080,7 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
   else if (II->isStr("autoreleasing"))
   else if (II->isStr("autoreleasing"))
     lifetime = Qualifiers::OCL_Autoreleasing;
     lifetime = Qualifiers::OCL_Autoreleasing;
   else {
   else {
-    S.Diag(AttrLoc, diag::warn_attribute_type_not_supported)
-      << attr.getName() << II;
+    S.Diag(AttrLoc, diag::warn_attribute_type_not_supported) << attr << II;
     attr.setInvalid();
     attr.setInvalid();
     return true;
     return true;
   }
   }
@@ -6125,7 +6122,7 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
   underlyingType.Quals.addObjCLifetime(lifetime);
   underlyingType.Quals.addObjCLifetime(lifetime);
 
 
   if (NonObjCPointer) {
   if (NonObjCPointer) {
-    StringRef name = attr.getName()->getName();
+    StringRef name = attr.getAttrName()->getName();
     switch (lifetime) {
     switch (lifetime) {
     case Qualifiers::OCL_None:
     case Qualifiers::OCL_None:
     case Qualifiers::OCL_ExplicitNone:
     case Qualifiers::OCL_ExplicitNone:
@@ -6164,9 +6161,8 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
   // If we have a valid source location for the attribute, use an
   // If we have a valid source location for the attribute, use an
   // AttributedType instead.
   // AttributedType instead.
   if (AttrLoc.isValid()) {
   if (AttrLoc.isValid()) {
-    type = state.getAttributedType(::new (S.Context) ObjCOwnershipAttr(
-                                       attr.getRange(), S.Context, II,
-                                       attr.getAttributeSpellingListIndex()),
+    type = state.getAttributedType(::new (S.Context)
+                                       ObjCOwnershipAttr(S.Context, attr, II),
                                    origType, type);
                                    origType, type);
   }
   }
 
 
@@ -6258,7 +6254,7 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
     GCAttr = Qualifiers::Strong;
     GCAttr = Qualifiers::Strong;
   else {
   else {
     S.Diag(attr.getLoc(), diag::warn_attribute_type_not_supported)
     S.Diag(attr.getLoc(), diag::warn_attribute_type_not_supported)
-      << attr.getName() << II;
+        << attr << II;
     attr.setInvalid();
     attr.setInvalid();
     return true;
     return true;
   }
   }
@@ -6269,9 +6265,7 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
   // Make an attributed type to preserve the source information.
   // Make an attributed type to preserve the source information.
   if (attr.getLoc().isValid())
   if (attr.getLoc().isValid())
     type = state.getAttributedType(
     type = state.getAttributedType(
-        ::new (S.Context) ObjCGCAttr(attr.getRange(), S.Context, II,
-                                     attr.getAttributeSpellingListIndex()),
-        origType, type);
+        ::new (S.Context) ObjCGCAttr(S.Context, attr, II), origType, type);
 
 
   return true;
   return true;
 }
 }
@@ -6443,8 +6437,7 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
     // You cannot specify duplicate type attributes, so if the attribute has
     // You cannot specify duplicate type attributes, so if the attribute has
     // already been applied, flag it.
     // already been applied, flag it.
     if (NewAttrKind == CurAttrKind) {
     if (NewAttrKind == CurAttrKind) {
-      S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact)
-        << PAttr.getName();
+      S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact) << PAttr;
       return true;
       return true;
     }
     }
 
 
@@ -6713,9 +6706,9 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
     if (chunk.Kind != DeclaratorChunk::MemberPointer) {
     if (chunk.Kind != DeclaratorChunk::MemberPointer) {
       diag << FixItHint::CreateRemoval(attr.getLoc())
       diag << FixItHint::CreateRemoval(attr.getLoc())
            << FixItHint::CreateInsertion(
            << FixItHint::CreateInsertion(
-                state.getSema().getPreprocessor()
-                  .getLocForEndOfToken(chunk.Loc),
-                " " + attr.getName()->getName().str() + " ");
+                  state.getSema().getPreprocessor().getLocForEndOfToken(
+                      chunk.Loc),
+                  " " + attr.getAttrName()->getName().str() + " ");
     }
     }
 
 
     moveAttrFromListToList(attr, state.getCurrentAttributes(),
     moveAttrFromListToList(attr, state.getCurrentAttributes(),
@@ -6793,8 +6786,7 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
     PcsAttr::PCSType Type;
     PcsAttr::PCSType Type;
     if (!PcsAttr::ConvertStrToPCSType(Str, Type))
     if (!PcsAttr::ConvertStrToPCSType(Str, Type))
       llvm_unreachable("already validated the attribute");
       llvm_unreachable("already validated the attribute");
-    return ::new (Ctx) PcsAttr(Attr.getRange(), Ctx, Type,
-                               Attr.getAttributeSpellingListIndex());
+    return ::new (Ctx) PcsAttr(Ctx, Attr, Type);
   }
   }
   case ParsedAttr::AT_IntelOclBicc:
   case ParsedAttr::AT_IntelOclBicc:
     return createSimpleAttr<IntelOclBiccAttr>(Ctx, Attr);
     return createSimpleAttr<IntelOclBiccAttr>(Ctx, Attr);
@@ -7313,7 +7305,7 @@ static void HandleOpenCLAccessAttr(QualType &CurType, const ParsedAttr &Attr,
     } else {
     } else {
       llvm_unreachable("unexpected type");
       llvm_unreachable("unexpected type");
     }
     }
-    StringRef AttrName = Attr.getName()->getName();
+    StringRef AttrName = Attr.getAttrName()->getName();
     if (PrevAccessQual == AttrName.ltrim("_")) {
     if (PrevAccessQual == AttrName.ltrim("_")) {
       // Duplicated qualifiers
       // Duplicated qualifiers
       S.Diag(Attr.getLoc(), diag::warn_duplicate_declspec)
       S.Diag(Attr.getLoc(), diag::warn_duplicate_declspec)
@@ -7510,7 +7502,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
                                IsTypeAttr
                                IsTypeAttr
                                    ? diag::warn_gcc_ignores_type_attr
                                    ? diag::warn_gcc_ignores_type_attr
                                    : diag::warn_cxx11_gnu_attribute_on_type)
                                    : diag::warn_cxx11_gnu_attribute_on_type)
-              << attr.getName();
+              << attr;
           if (!IsTypeAttr)
           if (!IsTypeAttr)
             continue;
             continue;
         }
         }
@@ -7539,7 +7531,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
       if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk)
       if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk)
         state.getSema().Diag(attr.getLoc(),
         state.getSema().Diag(attr.getLoc(),
                              diag::warn_unknown_attribute_ignored)
                              diag::warn_unknown_attribute_ignored)
-          << attr.getName();
+            << attr;
       break;
       break;
 
 
     case ParsedAttr::IgnoredAttribute:
     case ParsedAttr::IgnoredAttribute:
@@ -7933,14 +7925,16 @@ static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) {
       break;
       break;
     }
     }
 
 
-    RD->addAttr(MSInheritanceAttr::CreateImplicit(
-        S.getASTContext(), IM,
-        /*BestCase=*/S.MSPointerToMemberRepresentationMethod ==
-            LangOptions::PPTMK_BestCase,
-        S.ImplicitMSInheritanceAttrLoc.isValid()
-            ? S.ImplicitMSInheritanceAttrLoc
-            : RD->getSourceRange()));
-    S.Consumer.AssignInheritanceModel(RD);
+    SourceRange Loc = 
+    S.ImplicitMSInheritanceAttrLoc.isValid()
+                                 ? S.ImplicitMSInheritanceAttrLoc
+                                 : RD->getSourceRange();
+  RD->addAttr(MSInheritanceAttr::CreateImplicit(
+      S.getASTContext(),
+      /*BestCase=*/S.MSPointerToMemberRepresentationMethod ==
+          LangOptions::PPTMK_BestCase,
+      Loc, AttributeCommonInfo::AS_Microsoft, IM));
+  S.Consumer.AssignInheritanceModel(RD);
   }
   }
 }
 }
 
 

+ 23 - 5
lib/Serialization/ASTReaderDecl.cpp

@@ -2748,6 +2748,10 @@ public:
     return Reader->ReadSourceRange(*F, Record, Idx);
     return Reader->ReadSourceRange(*F, Record, Idx);
   }
   }
 
 
+  SourceLocation readSourceLocation() {
+    return Reader->ReadSourceLocation(*F, Record, Idx);
+  }
+
   Expr *readExpr() { return Reader->ReadExpr(*F); }
   Expr *readExpr() { return Reader->ReadExpr(*F); }
 
 
   std::string readString() {
   std::string readString() {
@@ -2783,9 +2787,20 @@ Attr *ASTReader::ReadAttr(ModuleFile &M, const RecordData &Rec,
   // Kind is stored as a 1-based integer because 0 is used to indicate a null
   // Kind is stored as a 1-based integer because 0 is used to indicate a null
   // Attr pointer.
   // Attr pointer.
   auto Kind = static_cast<attr::Kind>(V - 1);
   auto Kind = static_cast<attr::Kind>(V - 1);
-  SourceRange Range = Record.readSourceRange();
   ASTContext &Context = getContext();
   ASTContext &Context = getContext();
 
 
+  IdentifierInfo *AttrName = Record.getIdentifierInfo();
+  IdentifierInfo *ScopeName = Record.getIdentifierInfo();
+  SourceRange AttrRange = Record.readSourceRange();
+  SourceLocation ScopeLoc = Record.readSourceLocation();
+  unsigned ParsedKind = Record.readInt();
+  unsigned Syntax = Record.readInt();
+  unsigned SpellingIndex = Record.readInt();
+
+  AttributeCommonInfo Info(AttrName, ScopeName, AttrRange, ScopeLoc,
+                           AttributeCommonInfo::Kind(ParsedKind),
+                           AttributeCommonInfo::Syntax(Syntax), SpellingIndex);
+
 #include "clang/Serialization/AttrPCHRead.inc"
 #include "clang/Serialization/AttrPCHRead.inc"
 
 
   assert(New && "Unable to decode attribute?");
   assert(New && "Unable to decode attribute?");
@@ -4551,8 +4566,9 @@ void ASTDeclReader::UpdateDecl(Decl *D,
       break;
       break;
 
 
     case UPD_DECL_MARKED_OPENMP_THREADPRIVATE:
     case UPD_DECL_MARKED_OPENMP_THREADPRIVATE:
-      D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(Reader.getContext(),
-                                                          ReadSourceRange()));
+      D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
+          Reader.getContext(), ReadSourceRange(),
+          AttributeCommonInfo::AS_Pragma));
       break;
       break;
 
 
     case UPD_DECL_MARKED_OPENMP_ALLOCATE: {
     case UPD_DECL_MARKED_OPENMP_ALLOCATE: {
@@ -4561,7 +4577,8 @@ void ASTDeclReader::UpdateDecl(Decl *D,
       Expr *Allocator = Record.readExpr();
       Expr *Allocator = Record.readExpr();
       SourceRange SR = ReadSourceRange();
       SourceRange SR = ReadSourceRange();
       D->addAttr(OMPAllocateDeclAttr::CreateImplicit(
       D->addAttr(OMPAllocateDeclAttr::CreateImplicit(
-          Reader.getContext(), AllocatorKind, Allocator, SR));
+          Reader.getContext(), AllocatorKind, Allocator, SR,
+          AttributeCommonInfo::AS_Pragma));
       break;
       break;
     }
     }
 
 
@@ -4580,7 +4597,8 @@ void ASTDeclReader::UpdateDecl(Decl *D,
       OMPDeclareTargetDeclAttr::DevTypeTy DevType =
       OMPDeclareTargetDeclAttr::DevTypeTy DevType =
           static_cast<OMPDeclareTargetDeclAttr::DevTypeTy>(Record.readInt());
           static_cast<OMPDeclareTargetDeclAttr::DevTypeTy>(Record.readInt());
       D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(
       D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(
-          Reader.getContext(), MapType, DevType, ReadSourceRange()));
+          Reader.getContext(), MapType, DevType, ReadSourceRange(),
+          AttributeCommonInfo::AS_Pragma));
       break;
       break;
     }
     }
 
 

+ 7 - 0
lib/Serialization/ASTWriter.cpp

@@ -4522,7 +4522,14 @@ void ASTRecordWriter::AddAttr(const Attr *A) {
   if (!A)
   if (!A)
     return Record.push_back(0);
     return Record.push_back(0);
   Record.push_back(A->getKind() + 1); // FIXME: stable encoding, target attrs
   Record.push_back(A->getKind() + 1); // FIXME: stable encoding, target attrs
+
+  Record.AddIdentifierRef(A->getAttrName());
+  Record.AddIdentifierRef(A->getScopeName());
   Record.AddSourceRange(A->getRange());
   Record.AddSourceRange(A->getRange());
+  Record.AddSourceLocation(A->getScopeLoc());
+  Record.push_back(A->getParsedKind());
+  Record.push_back(A->getSyntax());
+  Record.push_back(A->getAttributeSpellingListIndexRaw());
 
 
 #include "clang/Serialization/AttrPCHWrite.inc"
 #include "clang/Serialization/AttrPCHWrite.inc"
 }
 }

+ 107 - 57
utils/TableGen/ClangAttrEmitter.cpp

@@ -1347,7 +1347,7 @@ static void writeGetSpellingFunction(Record &R, raw_ostream &OS) {
     return;
     return;
   }
   }
 
 
-  OS << "  switch (SpellingListIndex) {\n"
+  OS << "  switch (getAttributeSpellingListIndex()) {\n"
         "  default:\n"
         "  default:\n"
         "    llvm_unreachable(\"Unknown attribute spelling!\");\n"
         "    llvm_unreachable(\"Unknown attribute spelling!\");\n"
         "    return \"(No spelling)\";\n";
         "    return \"(No spelling)\";\n";
@@ -1375,11 +1375,10 @@ writePrettyPrintFunction(Record &R,
     return;
     return;
   }
   }
 
 
-  OS <<
-    "  switch (SpellingListIndex) {\n"
-    "  default:\n"
-    "    llvm_unreachable(\"Unknown attribute spelling!\");\n"
-    "    break;\n";
+  OS << "  switch (getAttributeSpellingListIndex()) {\n"
+        "  default:\n"
+        "    llvm_unreachable(\"Unknown attribute spelling!\");\n"
+        "    break;\n";
 
 
   for (unsigned I = 0; I < Spellings.size(); ++ I) {
   for (unsigned I = 0; I < Spellings.size(); ++ I) {
     llvm::SmallString<16> Prefix;
     llvm::SmallString<16> Prefix;
@@ -1560,11 +1559,12 @@ static void writeAttrAccessorDefinition(const Record &R, raw_ostream &OS) {
     const StringRef Name = Accessor->getValueAsString("Name");
     const StringRef Name = Accessor->getValueAsString("Name");
     std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Accessor);
     std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Accessor);
 
 
-    OS << "  bool " << Name << "() const { return SpellingListIndex == ";
+    OS << "  bool " << Name
+       << "() const { return getAttributeSpellingListIndex() == ";
     for (unsigned Index = 0; Index < Spellings.size(); ++Index) {
     for (unsigned Index = 0; Index < Spellings.size(); ++Index) {
       OS << getSpellingListIndex(SpellingList, Spellings[Index]);
       OS << getSpellingListIndex(SpellingList, Spellings[Index]);
       if (Index != Spellings.size() - 1)
       if (Index != Spellings.size() - 1)
-        OS << " ||\n    SpellingListIndex == ";
+        OS << " ||\n    getAttributeSpellingListIndex() == ";
       else
       else
         OS << "; }\n";
         OS << "; }\n";
     }
     }
@@ -2221,6 +2221,7 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
   OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
   OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
 
 
   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+  ParsedAttrMap AttrMap = getParsedAttrList(Records);
 
 
   for (const auto *Attr : Attrs) {
   for (const auto *Attr : Attrs) {
     const Record &R = *Attr;
     const Record &R = *Attr;
@@ -2289,38 +2290,97 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
     if (!ElideSpelling)
     if (!ElideSpelling)
       OS << CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
       OS << CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
 
 
+    const auto &ParsedAttrSpellingItr = llvm::find_if(
+        AttrMap, [R](const std::pair<std::string, const Record *> &P) {
+          return &R == P.second;
+        });
+
     // Emit CreateImplicit factory methods.
     // Emit CreateImplicit factory methods.
-    auto emitCreateImplicit = [&](bool emitFake) {
-      OS << "  static " << R.getName() << "Attr *CreateImplicit(";
+    auto emitCreate = [&](bool Implicit, bool emitFake) {
+      OS << "  static " << R.getName() << "Attr *Create";
+        if (Implicit)
+          OS << "Implicit";
+      OS << "(";
       OS << "ASTContext &Ctx";
       OS << "ASTContext &Ctx";
-      if (!ElideSpelling)
-        OS << ", Spelling S";
       for (auto const &ai : Args) {
       for (auto const &ai : Args) {
         if (ai->isFake() && !emitFake) continue;
         if (ai->isFake() && !emitFake) continue;
         OS << ", ";
         OS << ", ";
         ai->writeCtorParameters(OS);
         ai->writeCtorParameters(OS);
       }
       }
-      OS << ", SourceRange Loc = SourceRange()";
-      OS << ") {\n";
+      OS << ", const AttributeCommonInfo &CommonInfo = {SourceRange{}}) {\n";
       OS << "    auto *A = new (Ctx) " << R.getName();
       OS << "    auto *A = new (Ctx) " << R.getName();
-      OS << "Attr(Loc, Ctx, ";
+      OS << "Attr(Ctx, CommonInfo";
       for (auto const &ai : Args) {
       for (auto const &ai : Args) {
         if (ai->isFake() && !emitFake) continue;
         if (ai->isFake() && !emitFake) continue;
-        ai->writeImplicitCtorArgs(OS);
         OS << ", ";
         OS << ", ";
+        ai->writeImplicitCtorArgs(OS);
+      }
+      OS << ");\n";
+      if (Implicit) {
+        OS << "    A->setImplicit(true);\n";
+      }
+      if (Implicit || ElideSpelling) {
+        OS << "    if (!A->isAttributeSpellingListCalculated() && "
+              "!A->getAttrName())\n";
+        OS << "      A->setAttributeSpellingListIndex(0);\n";
       }
       }
-      OS << (ElideSpelling ? "0" : "S") << ");\n";
-      OS << "    A->setImplicit(true);\n";
       OS << "    return A;\n  }\n\n";
       OS << "    return A;\n  }\n\n";
     };
     };
 
 
+    auto emitCreateNoCI = [&](bool Implicit, bool emitFake) {
+      OS <<"  static " << R.getName() << "Attr *Create";
+      if (Implicit)
+        OS << "Implicit";
+      OS << "(";
+      OS << "ASTContext &Ctx";
+      for (auto const &ai : Args) {
+        if (ai->isFake() && !emitFake) continue;
+        OS << ", ";
+        ai->writeCtorParameters(OS);
+      }
+      OS << ", SourceRange Range, AttributeCommonInfo::Syntax Syntax";
+      if (!ElideSpelling)
+        OS << ", " << R.getName()
+           << "Attr::Spelling Spelling = "
+              "static_cast<Spelling>(SpellingNotCalculated)";
+      OS << ") {\n";
+      OS << "    AttributeCommonInfo I(Range, ";
+
+      if (ParsedAttrSpellingItr != std::end(AttrMap))
+        OS << "AT_" << ParsedAttrSpellingItr->first;
+      else
+        OS << "NoSemaHandlerAttribute";
+
+      OS << ", Syntax";
+      if (!ElideSpelling)
+        OS << ", Spelling";
+      OS << ");\n";
+      OS << "    return Create";
+      if (Implicit)
+        OS << "Implicit";
+      OS << "(Ctx";
+      for (auto const &ai : Args) {
+        if (ai->isFake() && !emitFake) continue;
+        OS << ", ";
+        ai->writeImplicitCtorArgs(OS);
+      }
+      OS << ", I);\n";
+      OS << "  }\n";
+    };
+
+    auto emitCreates = [&](bool emitFake) {
+      emitCreate(true, emitFake);
+      emitCreate(false, emitFake);
+      emitCreateNoCI(true, emitFake);
+      emitCreateNoCI(false, emitFake);
+    };
+
     // Emit a CreateImplicit that takes all the arguments.
     // Emit a CreateImplicit that takes all the arguments.
-    emitCreateImplicit(true);
+    emitCreates(true);
 
 
     // Emit a CreateImplicit that takes all the non-fake arguments.
     // Emit a CreateImplicit that takes all the non-fake arguments.
-    if (HasFakeArg) {
-      emitCreateImplicit(false);
-    }
+    if (HasFakeArg)
+      emitCreates(false);
 
 
     // Emit constructors.
     // Emit constructors.
     auto emitCtor = [&](bool emitOpt, bool emitFake) {
     auto emitCtor = [&](bool emitOpt, bool emitFake) {
@@ -2329,8 +2389,9 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
         if (arg->isOptional()) return emitOpt;
         if (arg->isOptional()) return emitOpt;
         return true;
         return true;
       };
       };
-
-      OS << "  " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
+      OS << "  " << R.getName()
+         << "Attr(ASTContext &Ctx, const AttributeCommonInfo &CommonInfo";
+      OS << '\n';
       for (auto const &ai : Args) {
       for (auto const &ai : Args) {
         if (!shouldEmitArg(ai)) continue;
         if (!shouldEmitArg(ai)) continue;
         OS << "              , ";
         OS << "              , ";
@@ -2338,12 +2399,10 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
         OS << "\n";
         OS << "\n";
       }
       }
 
 
-      OS << "              , ";
-      OS << "unsigned SI\n";
-
       OS << "             )\n";
       OS << "             )\n";
-      OS << "    : " << SuperName << "(attr::" << R.getName() << ", R, SI, "
-         << ( R.getValueAsBit("LateParsed") ? "true" : "false" );
+      OS << "    : " << SuperName << "(Ctx, CommonInfo, ";
+      OS << "attr::" << R.getName() << ", "
+         << (R.getValueAsBit("LateParsed") ? "true" : "false");
       if (Inheritable) {
       if (Inheritable) {
         OS << ", "
         OS << ", "
            << (R.getValueAsBit("InheritEvenIfAlreadyPresent") ? "true"
            << (R.getValueAsBit("InheritEvenIfAlreadyPresent") ? "true"
@@ -2375,14 +2434,12 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
     emitCtor(true, true);
     emitCtor(true, true);
 
 
     // Emit a constructor that takes all the non-fake arguments.
     // Emit a constructor that takes all the non-fake arguments.
-    if (HasFakeArg) {
+    if (HasFakeArg)
       emitCtor(true, false);
       emitCtor(true, false);
-    }
  
  
     // Emit a constructor that takes all the non-fake, non-optional arguments.
     // Emit a constructor that takes all the non-fake, non-optional arguments.
-    if (HasOptArg) {
+    if (HasOptArg)
       emitCtor(false, false);
       emitCtor(false, false);
-    }
 
 
     OS << "  " << R.getName() << "Attr *clone(ASTContext &C) const;\n";
     OS << "  " << R.getName() << "Attr *clone(ASTContext &C) const;\n";
     OS << "  void printPretty(raw_ostream &OS,\n"
     OS << "  void printPretty(raw_ostream &OS,\n"
@@ -2392,8 +2449,8 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
     if (!ElideSpelling) {
     if (!ElideSpelling) {
       assert(!SemanticToSyntacticMap.empty() && "Empty semantic mapping list");
       assert(!SemanticToSyntacticMap.empty() && "Empty semantic mapping list");
       OS << "  Spelling getSemanticSpelling() const {\n";
       OS << "  Spelling getSemanticSpelling() const {\n";
-      WriteSemanticSpellingSwitch("SpellingListIndex", SemanticToSyntacticMap,
-                                  OS);
+      WriteSemanticSpellingSwitch("getAttributeSpellingListIndex()",
+                                  SemanticToSyntacticMap, OS);
       OS << "  }\n";
       OS << "  }\n";
     }
     }
 
 
@@ -2447,15 +2504,15 @@ void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
 
 
     OS << R.getName() << "Attr *" << R.getName()
     OS << R.getName() << "Attr *" << R.getName()
        << "Attr::clone(ASTContext &C) const {\n";
        << "Attr::clone(ASTContext &C) const {\n";
-    OS << "  auto *A = new (C) " << R.getName() << "Attr(getLocation(), C";
+    OS << "  auto *A = new (C) " << R.getName() << "Attr(C, *this";
     for (auto const &ai : Args) {
     for (auto const &ai : Args) {
       OS << ", ";
       OS << ", ";
       ai->writeCloneArgs(OS);
       ai->writeCloneArgs(OS);
     }
     }
-    OS << ", getSpellingListIndex());\n";
+    OS << ");\n";
     OS << "  A->Inherited = Inherited;\n";
     OS << "  A->Inherited = Inherited;\n";
     OS << "  A->IsPackExpansion = IsPackExpansion;\n";
     OS << "  A->IsPackExpansion = IsPackExpansion;\n";
-    OS << "  A->Implicit = Implicit;\n";
+    OS << "  A->setImplicit(Implicit);\n";
     OS << "  return A;\n}\n\n";
     OS << "  return A;\n}\n\n";
 
 
     writePrettyPrintFunction(R, Args, OS);
     writePrettyPrintFunction(R, Args, OS);
@@ -2755,24 +2812,23 @@ void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) {
     const Record &R = *Attr;
     const Record &R = *Attr;
     if (!R.getValueAsBit("ASTNode"))
     if (!R.getValueAsBit("ASTNode"))
       continue;
       continue;
-    
+
     OS << "  case attr::" << R.getName() << ": {\n";
     OS << "  case attr::" << R.getName() << ": {\n";
     if (R.isSubClassOf(InhClass))
     if (R.isSubClassOf(InhClass))
       OS << "    bool isInherited = Record.readInt();\n";
       OS << "    bool isInherited = Record.readInt();\n";
     OS << "    bool isImplicit = Record.readInt();\n";
     OS << "    bool isImplicit = Record.readInt();\n";
-    OS << "    unsigned Spelling = Record.readInt();\n";
     ArgRecords = R.getValueAsListOfDefs("Args");
     ArgRecords = R.getValueAsListOfDefs("Args");
     Args.clear();
     Args.clear();
     for (const auto *Arg : ArgRecords) {
     for (const auto *Arg : ArgRecords) {
       Args.emplace_back(createArgument(*Arg, R.getName()));
       Args.emplace_back(createArgument(*Arg, R.getName()));
       Args.back()->writePCHReadDecls(OS);
       Args.back()->writePCHReadDecls(OS);
     }
     }
-    OS << "    New = new (Context) " << R.getName() << "Attr(Range, Context";
+    OS << "    New = new (Context) " << R.getName() << "Attr(Context, Info";
     for (auto const &ri : Args) {
     for (auto const &ri : Args) {
       OS << ", ";
       OS << ", ";
       ri->writePCHReadArgs(OS);
       ri->writePCHReadArgs(OS);
     }
     }
-    OS << ", Spelling);\n";
+    OS << ");\n";
     if (R.isSubClassOf(InhClass))
     if (R.isSubClassOf(InhClass))
       OS << "    cast<InheritableAttr>(New)->setInherited(isInherited);\n";
       OS << "    cast<InheritableAttr>(New)->setInherited(isInherited);\n";
     OS << "    New->setImplicit(isImplicit);\n";
     OS << "    New->setImplicit(isImplicit);\n";
@@ -2802,7 +2858,6 @@ void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
     if (R.isSubClassOf(InhClass))
     if (R.isSubClassOf(InhClass))
       OS << "    Record.push_back(SA->isInherited());\n";
       OS << "    Record.push_back(SA->isInherited());\n";
     OS << "    Record.push_back(A->isImplicit());\n";
     OS << "    Record.push_back(A->isImplicit());\n";
-    OS << "    Record.push_back(A->getSpellingListIndex());\n";
 
 
     for (const auto *Arg : Args)
     for (const auto *Arg : Args)
       createArgument(*Arg, R.getName())->writePCHWrite(OS);
       createArgument(*Arg, R.getName())->writePCHWrite(OS);
@@ -3019,7 +3074,11 @@ void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
   emitSourceFileHeader("Code to translate different attribute spellings "
   emitSourceFileHeader("Code to translate different attribute spellings "
                        "into internal identifiers", OS);
                        "into internal identifiers", OS);
 
 
-  OS << "  switch (AttrKind) {\n";
+  OS << "  switch (getParsedKind()) {\n";
+  OS << "    case IgnoredAttribute:\n";
+  OS << "    case UnknownAttribute:\n";
+  OS << "    case NoSemaHandlerAttribute:\n";
+  OS << "      llvm_unreachable(\"Ignored/unknown shouldn't get here\");\n";
 
 
   ParsedAttrMap Attrs = getParsedAttrList(Records);
   ParsedAttrMap Attrs = getParsedAttrList(Records);
   for (const auto &I : Attrs) {
   for (const auto &I : Attrs) {
@@ -3028,16 +3087,7 @@ void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
     OS << "  case AT_" << I.first << ": {\n";
     OS << "  case AT_" << I.first << ": {\n";
     for (unsigned I = 0; I < Spellings.size(); ++ I) {
     for (unsigned I = 0; I < Spellings.size(); ++ I) {
       OS << "    if (Name == \"" << Spellings[I].name() << "\" && "
       OS << "    if (Name == \"" << Spellings[I].name() << "\" && "
-         << "SyntaxUsed == "
-         << StringSwitch<unsigned>(Spellings[I].variety())
-                .Case("GNU", 0)
-                .Case("CXX11", 1)
-                .Case("C2x", 2)
-                .Case("Declspec", 3)
-                .Case("Microsoft", 4)
-                .Case("Keyword", 5)
-                .Case("Pragma", 6)
-                .Default(0)
+         << "getSyntax() == AttributeCommonInfo::AS_" << Spellings[I].variety()
          << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
          << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
          << "        return " << I << ";\n";
          << "        return " << I << ";\n";
     }
     }
@@ -3158,12 +3208,12 @@ void EmitClangAttrTemplateInstantiateHelper(const std::vector<Record *> &Attrs,
     for (auto const &ai : Args)
     for (auto const &ai : Args)
       ai->writeTemplateInstantiation(OS);
       ai->writeTemplateInstantiation(OS);
 
 
-    OS << "      return new (C) " << R.getName() << "Attr(A->getLocation(), C";
+    OS << "        return new (C) " << R.getName() << "Attr(C, *A";
     for (auto const &ai : Args) {
     for (auto const &ai : Args) {
       OS << ", ";
       OS << ", ";
       ai->writeTemplateInstantiationArgs(OS);
       ai->writeTemplateInstantiationArgs(OS);
     }
     }
-    OS << ", A->getSpellingListIndex());\n    }\n";
+    OS << ");\n    }\n";
   }
   }
   OS << "  } // end switch\n"
   OS << "  } // end switch\n"
      << "  llvm_unreachable(\"Unknown attribute!\");\n"
      << "  llvm_unreachable(\"Unknown attribute!\");\n"
@@ -3481,7 +3531,7 @@ static std::string GenerateLangOptRequirements(const Record &R,
   OS << "  if (" << GenerateTestExpression(LangOpts) << ")\n";
   OS << "  if (" << GenerateTestExpression(LangOpts) << ")\n";
   OS << "    return true;\n\n";
   OS << "    return true;\n\n";
   OS << "  S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) ";
   OS << "  S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) ";
-  OS << "<< Attr.getName();\n";
+  OS << "<< Attr;\n";
   OS << "  return false;\n";
   OS << "  return false;\n";
   OS << "}\n\n";
   OS << "}\n\n";
 
 

Some files were not shown because too many files changed in this diff