leonardchan updated this revision to Diff 163155.

Repository:
  rC Clang

https://reviews.llvm.org/D51329

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/Type.h
  include/clang/Lex/Preprocessor.h
  include/clang/Sema/ParsedAttr.h
  lib/AST/ASTContext.cpp
  lib/AST/TypePrinter.cpp
  lib/Lex/PPDirectives.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/SemaType.cpp
  test/Sema/address_space_print_macro.c
  test/Sema/address_spaces.c

Index: test/Sema/address_spaces.c
===================================================================
--- test/Sema/address_spaces.c
+++ test/Sema/address_spaces.c
@@ -71,5 +71,5 @@
 
 // Clang extension doesn't forbid operations on pointers to different address spaces.
 char* cmp(_AS1 char *x,  _AS2 char *y) {
-  return x < y ? x : y; // expected-error{{conditional operator with the second and third operands of type  ('__attribute__((address_space(1))) char *' and '__attribute__((address_space(2))) char *') which are pointers to non-overlapping address spaces}}
+  return x < y ? x : y; // expected-error{{conditional operator with the second and third operands of type  ('_AS1 char *' and '_AS2 char *') which are pointers to non-overlapping address spaces}}
 }
Index: test/Sema/address_space_print_macro.c
===================================================================
--- /dev/null
+++ test/Sema/address_space_print_macro.c
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify
+
+#define AS1 __attribute__((address_space(1)))
+#define AS2 __attribute__((address_space(2), annotate("foo")))
+
+#define AS(i) address_space(i)
+#define AS3 __attribute__((AS(3)))
+
+char *cmp(AS1 char *x, AS2 char *y) {
+  return x < y ? x : y; // expected-error{{conditional operator with the second and third operands of type  ('AS1 char *' and 'AS2 char *') which are pointers to non-overlapping address spaces}}
+}
+
+__attribute__((address_space(1))) char test_array[10];
+void test3(void) {
+  extern void test3_helper(char *p); // expected-note{{passing argument to parameter 'p' here}}
+  test3_helper(test_array);          // expected-error{{passing '__attribute__((address_space(1))) char *' to parameter of type 'char *' changes address space of pointer}}
+}
+
+char AS2 *test4_array;
+void test4(void) {
+  extern void test3_helper(char *p); // expected-note{{passing argument to parameter 'p' here}}
+  test3_helper(test4_array);         // expected-error{{passing 'AS2 char *' to parameter of type 'char *' changes address space of pointer}}
+}
+
+void func() {
+  char AS1 *x;
+  char AS3 *x2;
+  char *y;
+  y = x;  // expected-error{{assigning 'AS1 char *' to 'char *' changes address space of pointer}}
+  y = x2; // expected-error{{assigning 'AS3 char *' to 'char *' changes address space of pointer}}
+}
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -243,9 +243,10 @@
     /// Get an attributed type for the given attribute, and remember the Attr
     /// object so that we can attach it to the AttributedTypeLoc.
     QualType getAttributedType(Attr *A, QualType ModifiedType,
-                               QualType EquivType) {
-      QualType T =
-          sema.Context.getAttributedType(A->getKind(), ModifiedType, EquivType);
+                               QualType EquivType,
+                               IdentifierInfo *MacroII = nullptr) {
+      QualType T = sema.Context.getAttributedType(A->getKind(), ModifiedType,
+                                                  EquivType, MacroII);
       AttrsForTypes.push_back({cast<AttributedType>(T.getTypePtr()), A});
       AttrsForTypesSorted = false;
       return T;
@@ -5817,7 +5818,7 @@
       auto *ASAttr = ::new (Ctx) AddressSpaceAttr(
           Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex(),
           static_cast<unsigned>(T.getQualifiers().getAddressSpace()));
-      Type = State.getAttributedType(ASAttr, T, T);
+      Type = State.getAttributedType(ASAttr, T, T, Attr.getMacroII());
     } else {
       Attr.setInvalid();
     }
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp
+++ lib/Parse/ParseDecl.cpp
@@ -87,6 +87,39 @@
 #undef CLANG_ATTR_LATE_PARSED_LIST
 }
 
+static bool SourceLocInSourceRange(SourceLocation SpellingLoc,
+                                   SourceRange Range, const SourceManager &SM) {
+  SourceLocation RangeStart = Range.getBegin();
+  SourceLocation RangeEnd = Range.getEnd();
+  unsigned LineNo = SM.getSpellingLineNumber(SpellingLoc);
+  unsigned StartLineNo = SM.getSpellingLineNumber(RangeStart);
+  unsigned EndLineNo = SM.getSpellingLineNumber(RangeEnd);
+  unsigned ColNo = SM.getSpellingColumnNumber(SpellingLoc);
+  unsigned StartColNo = SM.getSpellingColumnNumber(RangeStart);
+  unsigned EndColNo = SM.getSpellingColumnNumber(RangeEnd);
+
+  // Outside of lines
+  if (LineNo < StartLineNo || LineNo > EndLineNo)
+    return false;
+
+  // On the same line
+  if (LineNo == StartLineNo && ColNo < StartColNo)
+    return false;
+  if (LineNo == EndLineNo && ColNo > EndColNo)
+    return false;
+
+  return true;
+}
+
+/// For the last N given parsed attributes, apply the identifier info of a macro
+/// they were defined in.
+static void ApplyMacroIIToParsedAttrs(ParsedAttributes &attrs, unsigned N,
+                                      IdentifierInfo *MacroII) {
+  assert(attrs.size() >= N);
+  for (unsigned i = attrs.size() - N; i < N; ++i)
+    attrs[i].setMacroII(MacroII);
+}
+
 /// ParseGNUAttributes - Parse a non-empty attributes list.
 ///
 /// [GNU] attributes:
@@ -133,6 +166,8 @@
                                 LateParsedAttrList *LateAttrs,
                                 Declarator *D) {
   assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!");
+  unsigned OldNumAttrs = attrs.size();
+  Token AttrTok = Tok;
 
   while (Tok.is(tok::kw___attribute)) {
     ConsumeToken();
@@ -203,6 +238,18 @@
       SkipUntil(tok::r_paren, StopAtSemi);
     if (endLoc)
       *endLoc = Loc;
+
+    unsigned NumParsedAttrs = attrs.size() - OldNumAttrs;
+
+    // If this was declared in a macro, attatch the macro IdentifierInfo to the
+    // parsed attribute.
+    for (const auto &MacroPair : PP.getAttributeMacros()) {
+      if (SourceLocInSourceRange(AttrTok.getLocation(), MacroPair.first,
+                                 PP.getSourceManager())) {
+        ApplyMacroIIToParsedAttrs(attrs, NumParsedAttrs, MacroPair.second);
+        break;
+      }
+    }
   }
 }
 
Index: lib/Lex/PPDirectives.cpp
===================================================================
--- lib/Lex/PPDirectives.cpp
+++ lib/Lex/PPDirectives.cpp
@@ -2577,6 +2577,31 @@
   MI->setDefinitionEndLoc(LastTok.getLocation());
   return MI;
 }
+
+// The minimum number of tokens used for an attribute. This includes the
+// attribute keyword, 2 opening parentheses, 2 closing parenthesis, and at least
+// one token for the attribute itself.
+static constexpr unsigned kMinAttrTokens = 6;
+
+/// This only catches macros whose whole definition is an attribute. That is, it
+/// starts with the attribute keyword and 2 opening parentheses, and ends with
+/// the 2 closing parentheses.
+static bool DefinesAttribute(const Preprocessor &PP,
+                             const ArrayRef<Token> &Tokens,
+                             SourceRange &Range) {
+  if (Tokens.size() < kMinAttrTokens)
+    return false;
+  if (Tokens[0].is(tok::kw___attribute) && Tokens[1].is(tok::l_paren) &&
+      Tokens[2].is(tok::l_paren) &&
+      Tokens[Tokens.size() - 2].is(tok::r_paren) &&
+      Tokens[Tokens.size() - 1].is(tok::r_paren)) {
+    Range.setBegin(Tokens.front().getLocation());
+    Range.setEnd(Tokens.back().getLocation());
+    return true;
+  }
+  return false;
+}
+
 /// HandleDefineDirective - Implements \#define.  This consumes the entire macro
 /// line then lets the caller lex the next real token.
 void Preprocessor::HandleDefineDirective(
@@ -2692,6 +2717,13 @@
     WarnUnusedMacroLocs.insert(MI->getDefinitionLoc());
   }
 
+  // If the macro is an attribute that contains address_space(), save this for
+  // diagnosing later.
+  SourceRange Range;
+  if (DefinesAttribute(*this, MD->getInfo()->tokens(), Range))
+    AttributeMacros.push_back(
+        std::make_pair(Range, MacroNameTok.getIdentifierInfo()));
+
   // If the callbacks want to know, tell them about the macro definition.
   if (Callbacks)
     Callbacks->MacroDefined(MacroNameTok, MD);
Index: lib/AST/TypePrinter.cpp
===================================================================
--- lib/AST/TypePrinter.cpp
+++ lib/AST/TypePrinter.cpp
@@ -1364,7 +1364,18 @@
   if (T->getAttrKind() == attr::ObjCKindOf)
     OS << "__kindof ";
 
-  printBefore(T->getModifiedType(), OS);
+  if (T->getAttrKind() == attr::AddressSpace && T->hasAddressSpaceMacroII()) {
+    OS << T->getAddressSpaceMacroII()->getName() << " ";
+
+    // Remove the underlying address_space so it won't be printed.
+    SplitQualType SplitTy = T->getModifiedType().split();
+    Qualifiers Quals = SplitTy.Quals;
+    if (Quals.getAddressSpace() >= LangAS::FirstTargetAddressSpace)
+      Quals.removeAddressSpace();
+    printBefore(SplitTy.Ty, Quals, OS);
+  } else {
+    printBefore(T->getModifiedType(), OS);
+  }
 
   if (T->isMSTypeSpec()) {
     switch (T->getAttrKind()) {
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -3878,17 +3878,18 @@
 
 QualType ASTContext::getAttributedType(attr::Kind attrKind,
                                        QualType modifiedType,
-                                       QualType equivalentType) {
+                                       QualType equivalentType,
+                                       IdentifierInfo *MacroII) {
   llvm::FoldingSetNodeID id;
-  AttributedType::Profile(id, attrKind, modifiedType, equivalentType);
+  AttributedType::Profile(id, attrKind, modifiedType, equivalentType, MacroII);
 
   void *insertPos = nullptr;
   AttributedType *type = AttributedTypes.FindNodeOrInsertPos(id, insertPos);
   if (type) return QualType(type, 0);
 
   QualType canon = getCanonicalType(equivalentType);
   type = new (*this, TypeAlignment)
-           AttributedType(canon, attrKind, modifiedType, equivalentType);
+      AttributedType(canon, attrKind, modifiedType, equivalentType, MacroII);
 
   Types.push_back(type);
   AttributedTypes.InsertNode(type, insertPos);
Index: include/clang/Sema/ParsedAttr.h
===================================================================
--- include/clang/Sema/ParsedAttr.h
+++ include/clang/Sema/ParsedAttr.h
@@ -168,6 +168,7 @@
 private:
   IdentifierInfo *AttrName;
   IdentifierInfo *ScopeName;
+  IdentifierInfo *MacroII = nullptr;
   SourceRange AttrRange;
   SourceLocation ScopeLoc;
   SourceLocation EllipsisLoc;
@@ -534,6 +535,12 @@
     return getPropertyDataBuffer().SetterId;
   }
 
+  void setMacroII(IdentifierInfo *MacroName) { MacroII = MacroName; }
+
+  bool hasMacroII() const { return MacroII != nullptr; }
+
+  IdentifierInfo *getMacroII() const { return MacroII; }
+
   /// Get an index into the attribute spelling list
   /// defined in Attr.td. This index is used by an attribute
   /// to pretty print itself.
Index: include/clang/Lex/Preprocessor.h
===================================================================
--- include/clang/Lex/Preprocessor.h
+++ include/clang/Lex/Preprocessor.h
@@ -325,6 +325,9 @@
   /// This is used when loading a precompiled preamble.
   std::pair<int, bool> SkipMainFilePreamble;
 
+  typedef std::pair<SourceRange, IdentifierInfo *> MacroPair;
+  llvm::SmallVector<MacroPair, 8> AttributeMacros;
+
 public:
   struct PreambleSkipInfo {
     SourceLocation HashTokenLoc;
@@ -341,6 +344,10 @@
           ElseLoc(ElseLoc) {}
   };
 
+  const llvm::SmallVectorImpl<MacroPair> &getAttributeMacros() const {
+    return AttributeMacros;
+  }
+
 private:
   friend class ASTReader;
   friend class MacroArgs;
Index: include/clang/AST/Type.h
===================================================================
--- include/clang/AST/Type.h
+++ include/clang/AST/Type.h
@@ -4315,13 +4315,21 @@
   QualType ModifiedType;
   QualType EquivalentType;
 
+  // If the attribute this type holds is address_space and this attribute was
+  // declared as part of a macro, we store the macro identifier information.
+  // This will be used for printing the macro name instead of
+  // `__attribute__((address_space(n)))` in diagnostics relating to differing
+  // address_spaces between types.
+  IdentifierInfo *AddressSpaceMacroII;
+
   AttributedType(QualType canon, attr::Kind attrKind, QualType modified,
-                 QualType equivalent)
+                 QualType equivalent, IdentifierInfo *addrSpaceMacroII)
       : Type(Attributed, canon, equivalent->isDependentType(),
              equivalent->isInstantiationDependentType(),
              equivalent->isVariablyModifiedType(),
              equivalent->containsUnexpandedParameterPack()),
-        ModifiedType(modified), EquivalentType(equivalent) {
+        ModifiedType(modified), EquivalentType(equivalent),
+        AddressSpaceMacroII(addrSpaceMacroII) {
     AttributedTypeBits.AttrKind = attrKind;
   }
 
@@ -4332,6 +4340,8 @@
 
   QualType getModifiedType() const { return ModifiedType; }
   QualType getEquivalentType() const { return EquivalentType; }
+  IdentifierInfo *getAddressSpaceMacroII() const { return AddressSpaceMacroII; }
+  bool hasAddressSpaceMacroII() const { return AddressSpaceMacroII != nullptr; }
 
   bool isSugared() const { return true; }
   QualType desugar() const { return getEquivalentType(); }
@@ -4387,14 +4397,17 @@
   static Optional<NullabilityKind> stripOuterNullability(QualType &T);
 
   void Profile(llvm::FoldingSetNodeID &ID) {
-    Profile(ID, getAttrKind(), ModifiedType, EquivalentType);
+    Profile(ID, getAttrKind(), ModifiedType, EquivalentType,
+            AddressSpaceMacroII);
   }
 
   static void Profile(llvm::FoldingSetNodeID &ID, Kind attrKind,
-                      QualType modified, QualType equivalent) {
+                      QualType modified, QualType equivalent,
+                      IdentifierInfo *addrSpaceMacroII) {
     ID.AddInteger(attrKind);
     ID.AddPointer(modified.getAsOpaquePtr());
     ID.AddPointer(equivalent.getAsOpaquePtr());
+    ID.AddPointer(addrSpaceMacroII);
   }
 
   static bool classof(const Type *T) {
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -1423,9 +1423,9 @@
 
   QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const;
 
-  QualType getAttributedType(attr::Kind attrKind,
-                             QualType modifiedType,
-                             QualType equivalentType);
+  QualType getAttributedType(attr::Kind attrKind, QualType modifiedType,
+                             QualType equivalentType,
+                             IdentifierInfo *MacroII = nullptr);
 
   QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced,
                                         QualType Replacement) const;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to