leonardchan updated this revision to Diff 177335.

Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D51329/new/

https://reviews.llvm.org/D51329

Files:
  clang/include/clang/AST/ASTContext.h
  clang/include/clang/AST/RecursiveASTVisitor.h
  clang/include/clang/AST/Type.h
  clang/include/clang/AST/TypeLoc.h
  clang/include/clang/AST/TypeNodes.def
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/ParsedAttr.h
  clang/include/clang/Serialization/ASTBitCodes.h
  clang/lib/ARCMigrate/TransGCAttrs.cpp
  clang/lib/AST/ASTContext.cpp
  clang/lib/AST/ASTDiagnostic.cpp
  clang/lib/AST/ASTStructuralEquivalence.cpp
  clang/lib/AST/ItaniumMangle.cpp
  clang/lib/AST/Type.cpp
  clang/lib/AST/TypeLoc.cpp
  clang/lib/AST/TypePrinter.cpp
  clang/lib/CodeGen/CGDebugInfo.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/lib/Sema/SemaType.cpp
  clang/lib/Sema/TreeTransform.h
  clang/lib/Serialization/ASTReader.cpp
  clang/lib/Serialization/ASTWriter.cpp
  clang/test/Sema/address_space_print_macro.c
  clang/test/Sema/address_spaces.c
  clang/test/SemaCUDA/qualifiers.cu
  clang/tools/libclang/CIndex.cpp

Index: clang/tools/libclang/CIndex.cpp
===================================================================
--- clang/tools/libclang/CIndex.cpp
+++ clang/tools/libclang/CIndex.cpp
@@ -1618,6 +1618,10 @@
   return Visit(TL.getInnerLoc());
 }
 
+bool CursorVisitor::VisitMacroDefinedTypeLoc(MacroDefinedTypeLoc TL) {
+  return Visit(TL.getInnerLoc());
+}
+
 bool CursorVisitor::VisitPointerTypeLoc(PointerTypeLoc TL) {
   return Visit(TL.getPointeeLoc());
 }
Index: clang/test/SemaCUDA/qualifiers.cu
===================================================================
--- clang/test/SemaCUDA/qualifiers.cu
+++ clang/test/SemaCUDA/qualifiers.cu
@@ -20,16 +20,16 @@
 #if defined(__CUDA_ARCH__)
 // NVPTX does not support TLS
 __device__ int __thread device_tls_var; // expected-error {{thread-local storage is not supported for the current target}}
-// CHECK-DEVICE: device_tls_var 'int' tls
+// CHECK-DEVICE: device_tls_var 'int':'int' tls
 __shared__ int __thread shared_tls_var; // expected-error {{thread-local storage is not supported for the current target}}
-// CHECK-DEVICE: shared_tls_var 'int' tls
+// CHECK-DEVICE: shared_tls_var 'int':'int' tls
 #else
 // Device-side vars should not produce any errors during host-side
 // compilation.
 __device__ int __thread device_tls_var;
-// CHECK-HOST: device_tls_var 'int' tls
+// CHECK-HOST: device_tls_var 'int':'int' tls
 __shared__ int __thread shared_tls_var;
-// CHECK-HOST: shared_tls_var 'int' tls
+// CHECK-HOST: shared_tls_var 'int':'int' tls
 #endif
 
 __global__ void g1(int x) {}
Index: clang/test/Sema/address_spaces.c
===================================================================
--- clang/test/Sema/address_spaces.c
+++ clang/test/Sema/address_spaces.c
@@ -71,7 +71,7 @@
 
 // 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}}
 }
 
 struct SomeStruct {
Index: clang/test/Sema/address_space_print_macro.c
===================================================================
--- /dev/null
+++ clang/test/Sema/address_space_print_macro.c
@@ -0,0 +1,39 @@
+// 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)))
+
+#define ATTR __attribute__
+#define AS4 ATTR((AS(4)))
+#define AS5 __attribute__((address_space(5))) char
+
+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;
+  AS4 char *x3;
+  AS5 *x4;
+  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}}
+  y = x3; // expected-error{{assigning 'AS4 char *' to 'char *' changes address space of pointer}}
+  y = x4; // expected-error{{assigning '__attribute__((address_space(5))) char *' to 'char *' changes address space of pointer}}
+}
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -517,6 +517,12 @@
   Code = TYPE_PAREN;
 }
 
+void ASTTypeWriter::VisitMacroDefinedType(const MacroDefinedType *T) {
+  Record.AddTypeRef(T->getUnderlyingType());
+  Record.AddIdentifierRef(T->getMacroIdentifier());
+  Code = TYPE_MACRO_DEFINED;
+}
+
 void ASTTypeWriter::VisitElaboratedType(const ElaboratedType *T) {
   Record.push_back(T->getKeyword());
   Record.AddNestedNameSpecifier(T->getQualifier());
@@ -803,6 +809,8 @@
   Record.AddSourceLocation(TL.getRParenLoc());
 }
 
+void TypeLocWriter::VisitMacroDefinedTypeLoc(MacroDefinedTypeLoc TL) {}
+
 void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
   Record.AddSourceLocation(TL.getElaboratedKeywordLoc());
   Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
@@ -1220,6 +1228,7 @@
   RECORD(TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION);
   RECORD(TYPE_DEPENDENT_SIZED_ARRAY);
   RECORD(TYPE_PAREN);
+  RECORD(TYPE_MACRO_DEFINED);
   RECORD(TYPE_PACK_EXPANSION);
   RECORD(TYPE_ATTRIBUTED);
   RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK);
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -6179,6 +6179,16 @@
     return Context.getParenType(InnerType);
   }
 
+  case TYPE_MACRO_DEFINED: {
+    if (Record.size() != 2) {
+      Error("incorrect encoding of macro defined type");
+      return QualType();
+    }
+    QualType UnderlyingTy = readType(*Loc.F, Record, Idx);
+    IdentifierInfo *MacroII = GetIdentifierInfo(*Loc.F, Record, Idx);
+    return Context.getMacroDefinedType(UnderlyingTy, MacroII);
+  }
+
   case TYPE_PACK_EXPANSION: {
     if (Record.size() != 2) {
       Error("incorrect encoding of pack expansion type");
@@ -6500,6 +6510,8 @@
   // nothing to do
 }
 
+void TypeLocReader::VisitMacroDefinedTypeLoc(MacroDefinedTypeLoc TL) {}
+
 void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
   TL.setCaretLoc(ReadSourceLocation());
 }
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -874,6 +874,11 @@
     return SemaRef.Context.getTypeDeclType(Typedef);
   }
 
+  /// Build a new MacroDefined type.
+  QualType RebuildMacroDefinedType(QualType T, const IdentifierInfo *MacroII) {
+    return SemaRef.Context.getMacroDefinedType(T, MacroII);
+  }
+
   /// Build a new class/struct/union type.
   QualType RebuildRecordType(RecordDecl *Record) {
     return SemaRef.Context.getTypeDeclType(Record);
@@ -6154,6 +6159,26 @@
   return Result;
 }
 
+template <typename Derived>
+QualType
+TreeTransform<Derived>::TransformMacroDefinedType(TypeLocBuilder &TLB,
+                                                  MacroDefinedTypeLoc TL) {
+  QualType Inner = getDerived().TransformType(TLB, TL.getInnerLoc());
+  if (Inner.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() || Inner != TL.getInnerLoc().getType()) {
+    Result =
+        getDerived().RebuildMacroDefinedType(Inner, TL.getMacroIdentifier());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  TLB.push<MacroDefinedTypeLoc>(Result);
+  return Result;
+}
+
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformDependentNameType(
     TypeLocBuilder &TLB, DependentNameTypeLoc TL) {
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -34,6 +34,7 @@
 #include "clang/Sema/TemplateInstCallback.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/ErrorHandling.h"
 
@@ -5571,6 +5572,7 @@
       assert(Chunk.Kind == DeclaratorChunk::Pipe);
       TL.setKWLoc(Chunk.Loc);
     }
+    void VisitMacroDefinedTypeLoc(MacroDefinedTypeLoc TL) {}
 
     void VisitTypeLoc(TypeLoc TL) {
       llvm_unreachable("unsupported TypeLoc kind in declarator!");
@@ -5649,6 +5651,9 @@
       CurrTL = ATL.getValueLoc().getUnqualifiedLoc();
     }
 
+    while (MacroDefinedTypeLoc TL = CurrTL.getAs<MacroDefinedTypeLoc>())
+      CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
+
     while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) {
       fillAttributedTypeLoc(TL, State);
       CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
@@ -6926,11 +6931,11 @@
 }
 
 bool Sema::hasExplicitCallingConv(QualType &T) {
-  QualType R = T.IgnoreParens();
+  QualType R = T.IgnoreParens().IgnoreMacroDefinitions();
   while (const AttributedType *AT = dyn_cast<AttributedType>(R)) {
     if (AT->isCallingConv())
       return true;
-    R = AT->getModifiedType().IgnoreParens();
+    R = AT->getModifiedType().IgnoreParens().IgnoreMacroDefinitions();
   }
   return false;
 }
@@ -7329,6 +7334,7 @@
   // over that.
   ParsedAttributesView AttrsCopy{attrs};
 
+  llvm::StringSet<> FoundMacros;
   state.setParsedNoDeref(false);
 
   for (ParsedAttr &attr : AttrsCopy) {
@@ -7505,6 +7511,15 @@
         distributeFunctionTypeAttr(state, attr, type);
       break;
     }
+
+    // Handle attributes that are defined in a macro.
+    if (attr.hasMacroIdentifier() && !type.getQualifiers().hasObjCLifetime()) {
+      const IdentifierInfo *MacroII = attr.getMacroIdentifier();
+      if (FoundMacros.find(MacroII->getName()) == FoundMacros.end()) {
+        type = state.getSema().Context.getMacroDefinedType(type, MacroII);
+        FoundMacros.insert(MacroII->getName());
+      }
+    }
   }
 
   if (!state.getSema().getLangOpts().OpenCL ||
Index: clang/lib/Sema/SemaStmt.cpp
===================================================================
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -3406,9 +3406,12 @@
 }
 
 TypeLoc Sema::getReturnTypeLoc(FunctionDecl *FD) const {
-  TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens();
+  TypeLoc TL = FD->getTypeSourceInfo()
+                   ->getTypeLoc()
+                   .IgnoreParens()
+                   .IgnoreMacroDefinitions();
   while (auto ATL = TL.getAs<AttributedTypeLoc>())
-    TL = ATL.getModifiedLoc().IgnoreParens();
+    TL = ATL.getModifiedLoc().IgnoreParens().IgnoreMacroDefinitions();
   return TL.castAs<FunctionProtoTypeLoc>().getReturnLoc();
 }
 
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -4006,6 +4006,7 @@
     case Type::Attributed:
     case Type::SubstTemplateTypeParm:
     case Type::PackExpansion:
+    case Type::MacroDefined:
       // Keep walking after single level desugaring.
       T = T.getSingleStepDesugaredType(Context);
       break;
Index: clang/lib/Parse/ParseDecl.cpp
===================================================================
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -87,6 +87,50 @@
 #undef CLANG_ATTR_LATE_PARSED_LIST
 }
 
+/// Attempt to find the outermost macro expansions that contains a given start
+/// and end source location that share the same FileID.
+static bool FindLocsWithCommonFileID(SourceManager &SM, SourceLocation StartLoc,
+                                     SourceLocation EndLoc,
+                                     SourceLocation &FoundStartLocExpansion,
+                                     SourceLocation &FoundEndLocExpansion) {
+  llvm::SmallVector<SourceLocation, 8> StartLocs;
+
+  // Generate starting locations FileIDs
+  while (StartLoc.isMacroID()) {
+    FileID FID = SM.getFileID(StartLoc);
+    const SrcMgr::SLocEntry *E = &SM.getSLocEntry(FID);
+    const SrcMgr::ExpansionInfo &Expansion = E->getExpansion();
+    if (!Expansion.isFunctionMacroExpansion())
+      StartLocs.push_back(StartLoc);
+    StartLoc = Expansion.getExpansionLocStart();
+  }
+
+  // Generate end location FileIDs
+  llvm::DenseMap<FileID, SourceLocation> EndLocs;
+  while (EndLoc.isMacroID()) {
+    FileID FID = SM.getFileID(EndLoc);
+    const SrcMgr::SLocEntry *E = &SM.getSLocEntry(FID);
+    const SrcMgr::ExpansionInfo &Expansion = E->getExpansion();
+    if (!Expansion.isFunctionMacroExpansion())
+      EndLocs[FID] = EndLoc;
+    EndLoc = Expansion.getExpansionLocStart();
+  }
+
+  // Find last common FileID. This will just be the last found starting FileID
+  // found from the starting loc expansion.
+  for (auto I = StartLocs.rbegin(); I != StartLocs.rend(); ++I) {
+    FileID FID = SM.getFileID(*I);
+    auto FoundEndLoc = EndLocs.find(FID);
+    if (FoundEndLoc != EndLocs.end()) {
+      FoundStartLocExpansion = *I;
+      FoundEndLocExpansion = FoundEndLoc->second;
+      return true;
+    }
+  }
+
+  return false;
+}
+
 /// ParseGNUAttributes - Parse a non-empty attributes list.
 ///
 /// [GNU] attributes:
@@ -135,7 +179,10 @@
   assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!");
 
   while (Tok.is(tok::kw___attribute)) {
-    ConsumeToken();
+    SourceLocation AttrTokLoc = ConsumeToken();
+    unsigned OldNumAttrs = attrs.size();
+    unsigned OldNumLateAttrs = LateAttrs ? LateAttrs->size() : 0;
+
     if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
                          "attribute")) {
       SkipUntil(tok::r_paren, StopAtSemi); // skip until ) or ;
@@ -203,6 +250,33 @@
       SkipUntil(tok::r_paren, StopAtSemi);
     if (endLoc)
       *endLoc = Loc;
+
+    // If this was declared in a macro, attatch the macro IdentifierInfo to the
+    // parsed attribute.
+    auto &SrcMgr = PP.getSourceManager();
+    SourceLocation StartLoc, EndLoc;
+    if (FindLocsWithCommonFileID(SrcMgr, AttrTokLoc, Loc, StartLoc, EndLoc)) {
+      bool AttrStartIsInMacro =
+          (StartLoc.isMacroID() && Lexer::isAtStartOfMacroExpansion(
+                                       StartLoc, SrcMgr, PP.getLangOpts()));
+      bool AttrEndIsInMacro =
+          (EndLoc.isMacroID() &&
+           Lexer::isAtEndOfMacroExpansion(EndLoc, SrcMgr, PP.getLangOpts()));
+
+      if (AttrStartIsInMacro && AttrEndIsInMacro) {
+        StringRef name = Lexer::getSourceText(
+            SrcMgr.getExpansionRange(StartLoc), SrcMgr, PP.getLangOpts());
+        IdentifierInfo *MacroII = PP.getIdentifierInfo(name);
+
+        for (unsigned i = OldNumAttrs; i < attrs.size(); ++i)
+          attrs[i].setMacroIdentifier(MacroII);
+
+        if (LateAttrs) {
+          for (unsigned i = OldNumLateAttrs; i < LateAttrs->size(); ++i)
+            (*LateAttrs)[i]->MacroII = MacroII;
+        }
+      }
+    }
   }
 }
 
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2137,6 +2137,7 @@
     case Type::Attributed:
     case Type::SubstTemplateTypeParm:
     case Type::PackExpansion:
+    case Type::MacroDefined:
       // Keep walking after single level desugaring.
       type = type.getSingleStepDesugaredType(getContext());
       break;
Index: clang/lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.cpp
+++ clang/lib/CodeGen/CGDebugInfo.cpp
@@ -2742,6 +2742,9 @@
     case Type::Paren:
       T = cast<ParenType>(T)->getInnerType();
       break;
+    case Type::MacroDefined:
+      T = cast<MacroDefinedType>(T)->getUnderlyingType();
+      break;
     case Type::SubstTemplateTypeParm:
       T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
       break;
@@ -2921,6 +2924,7 @@
   case Type::DeducedTemplateSpecialization:
   case Type::Elaborated:
   case Type::Paren:
+  case Type::MacroDefined:
   case Type::SubstTemplateTypeParm:
   case Type::TypeOfExpr:
   case Type::TypeOf:
Index: clang/lib/AST/TypePrinter.cpp
===================================================================
--- clang/lib/AST/TypePrinter.cpp
+++ clang/lib/AST/TypePrinter.cpp
@@ -219,6 +219,7 @@
     case Type::ObjCInterface:
     case Type::Atomic:
     case Type::Pipe:
+    case Type::MacroDefined:
       CanPrefixQualifiers = true;
       break;
 
@@ -957,6 +958,25 @@
   printTypeSpec(T->getDecl(), OS);
 }
 
+void TypePrinter::printMacroDefinedBefore(const MacroDefinedType *T,
+                                          raw_ostream &OS) {
+  if (const auto *AttrTy = dyn_cast<AttributedType>(T->getUnderlyingType())) {
+    if (AttrTy->getAttrKind() == attr::AddressSpace) {
+      OS << T->getMacroIdentifier()->getName() << " ";
+
+      // Skip the address_space attribute and got straight to the underlying
+      // type.
+      return printBefore(AttrTy->getModifiedType(), OS);
+    }
+  }
+  printBefore(T->getUnderlyingType(), OS);
+}
+
+void TypePrinter::printMacroDefinedAfter(const MacroDefinedType *T,
+                                         raw_ostream &OS) {
+  printAfter(T->getUnderlyingType(), OS);
+}
+
 void TypePrinter::printTypedefAfter(const TypedefType *T, raw_ostream &OS) {}
 
 void TypePrinter::printTypeOfExprBefore(const TypeOfExprType *T,
Index: clang/lib/AST/TypeLoc.cpp
===================================================================
--- clang/lib/AST/TypeLoc.cpp
+++ clang/lib/AST/TypeLoc.cpp
@@ -406,6 +406,13 @@
   return TL;
 }
 
+TypeLoc TypeLoc::IgnoreMacroDefinitions() const {
+  TypeLoc Result = *this;
+  while (auto MDTL = Result.getAs<MacroDefinedTypeLoc>())
+    Result = MDTL.getInnerLoc();
+  return Result;
+}
+
 SourceLocation TypeLoc::findNullabilityLoc() const {
   if (auto ATL = getAs<AttributedTypeLoc>()) {
     const Attr *A = ATL.getAttr();
Index: clang/lib/AST/Type.cpp
===================================================================
--- clang/lib/AST/Type.cpp
+++ clang/lib/AST/Type.cpp
@@ -380,6 +380,12 @@
   return T;
 }
 
+QualType QualType::IgnoreMacroDefinitions(QualType T) {
+  while (const auto *MDT = T->getAs<MacroDefinedType>())
+    T = MDT->getUnderlyingType();
+  return T;
+}
+
 /// This will check for a T (which should be a Type which can act as
 /// sugar, such as a TypedefType) by removing any existing sugar until it
 /// reaches a T or a non-sugared type.
@@ -955,6 +961,17 @@
     return Ctx.getParenType(innerType);
   }
 
+  QualType VisitMacroDefinedType(const MacroDefinedType *T) {
+    QualType innerType = recurse(T->getUnderlyingType());
+    if (innerType.isNull())
+      return {};
+
+    if (innerType.getAsOpaquePtr() == T->getUnderlyingType().getAsOpaquePtr())
+      return QualType(T, 0);
+
+    return Ctx.getMacroDefinedType(innerType, T->getMacroIdentifier());
+  }
+
   TRIVIAL_TYPE_CLASS(Typedef)
   TRIVIAL_TYPE_CLASS(ObjCTypeParam)
 
@@ -1716,6 +1733,10 @@
     Type *VisitAdjustedType(const AdjustedType *T) {
       return Visit(T->getOriginalType());
     }
+
+    Type *VisitMacroDefinedType(const MacroDefinedType *T) {
+      return Visit(T->getUnderlyingType());
+    }
   };
 
 } // namespace
@@ -3076,6 +3097,8 @@
   return getDecl()->getUnderlyingType();
 }
 
+QualType MacroDefinedType::desugar() const { return getUnderlyingType(); }
+
 TypeOfExprType::TypeOfExprType(Expr *E, QualType can)
     : Type(TypeOfExpr, can, E->isTypeDependent(),
            E->isInstantiationDependent(),
Index: clang/lib/AST/ItaniumMangle.cpp
===================================================================
--- clang/lib/AST/ItaniumMangle.cpp
+++ clang/lib/AST/ItaniumMangle.cpp
@@ -1942,6 +1942,7 @@
   case Type::ObjCTypeParam:
   case Type::Atomic:
   case Type::Pipe:
+  case Type::MacroDefined:
     llvm_unreachable("type is illegal as a nested name specifier");
 
   case Type::SubstTemplateTypeParmPack:
Index: clang/lib/AST/ASTStructuralEquivalence.cpp
===================================================================
--- clang/lib/AST/ASTStructuralEquivalence.cpp
+++ clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -569,6 +569,13 @@
       return false;
     break;
 
+  case Type::MacroDefined:
+    if (!IsStructurallyEquivalent(
+            Context, cast<MacroDefinedType>(T1)->getUnderlyingType(),
+            cast<MacroDefinedType>(T2)->getUnderlyingType()))
+      return false;
+    break;
+
   case Type::Typedef:
     if (!IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->getDecl(),
                                   cast<TypedefType>(T2)->getDecl()))
Index: clang/lib/AST/ASTDiagnostic.cpp
===================================================================
--- clang/lib/AST/ASTDiagnostic.cpp
+++ clang/lib/AST/ASTDiagnostic.cpp
@@ -42,6 +42,11 @@
       QT = PT->desugar();
       continue;
     }
+    // ... or a macro defined type ...
+    if (const MacroDefinedType *MDT = dyn_cast<MacroDefinedType>(Ty)) {
+      QT = MDT->desugar();
+      continue;
+    }
     // ...or a substituted template type parameter ...
     if (const SubstTemplateTypeParmType *ST =
           dyn_cast<SubstTemplateTypeParmType>(Ty)) {
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -2057,6 +2057,10 @@
   case Type::Paren:
     return getTypeInfo(cast<ParenType>(T)->getInnerType().getTypePtr());
 
+  case Type::MacroDefined:
+    return getTypeInfo(
+        cast<MacroDefinedType>(T)->getUnderlyingType().getTypePtr());
+
   case Type::ObjCTypeParam:
     return getTypeInfo(cast<ObjCTypeParamType>(T)->desugar().getTypePtr());
 
@@ -3937,7 +3941,7 @@
 
   QualType canon = getCanonicalType(equivalentType);
   type = new (*this, TypeAlignment)
-           AttributedType(canon, attrKind, modifiedType, equivalentType);
+      AttributedType(canon, attrKind, modifiedType, equivalentType);
 
   Types.push_back(type);
   AttributedTypes.InsertNode(type, insertPos);
@@ -4218,6 +4222,18 @@
   return QualType(T, 0);
 }
 
+QualType ASTContext::getMacroDefinedType(QualType UnderlyingTy,
+                                         const IdentifierInfo *MacroII) const {
+  QualType Canon = UnderlyingTy;
+  if (!Canon.isCanonical())
+    Canon = getCanonicalType(UnderlyingTy);
+
+  auto *newType =
+      new (*this, TypeAlignment) MacroDefinedType(UnderlyingTy, Canon, MacroII);
+  Types.push_back(newType);
+  return QualType(newType, 0);
+}
+
 QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
                                           NestedNameSpecifier *NNS,
                                           const IdentifierInfo *Name,
Index: clang/lib/ARCMigrate/TransGCAttrs.cpp
===================================================================
--- clang/lib/ARCMigrate/TransGCAttrs.cpp
+++ clang/lib/ARCMigrate/TransGCAttrs.cpp
@@ -69,6 +69,8 @@
         if (handleAttr(Attr, D))
           break;
         TL = Attr.getModifiedLoc();
+      } else if (MacroDefinedTypeLoc MDTL = TL.getAs<MacroDefinedTypeLoc>()) {
+        TL = MDTL.getInnerLoc();
       } else if (ArrayTypeLoc Arr = TL.getAs<ArrayTypeLoc>()) {
         TL = Arr.getElementLoc();
       } else if (PointerTypeLoc PT = TL.getAs<PointerTypeLoc>()) {
Index: clang/include/clang/Serialization/ASTBitCodes.h
===================================================================
--- clang/include/clang/Serialization/ASTBitCodes.h
+++ clang/include/clang/Serialization/ASTBitCodes.h
@@ -1174,7 +1174,10 @@
       TYPE_DEPENDENT_ADDRESS_SPACE = 47,
 
       /// A dependentSizedVectorType record.
-      TYPE_DEPENDENT_SIZED_VECTOR = 48
+      TYPE_DEPENDENT_SIZED_VECTOR = 48,
+
+      /// A type defined in a macro.
+      TYPE_MACRO_DEFINED = 49
     };
 
     /// The type IDs for special types constructed by semantic
Index: clang/include/clang/Sema/ParsedAttr.h
===================================================================
--- clang/include/clang/Sema/ParsedAttr.h
+++ clang/include/clang/Sema/ParsedAttr.h
@@ -168,6 +168,7 @@
 private:
   IdentifierInfo *AttrName;
   IdentifierInfo *ScopeName;
+  IdentifierInfo *MacroII = nullptr;
   SourceRange AttrRange;
   SourceLocation ScopeLoc;
   SourceLocation EllipsisLoc;
@@ -539,6 +540,17 @@
     return getPropertyDataBuffer().SetterId;
   }
 
+  /// Set the macro identifier info object that this parsed attribute was
+  /// declared in if it was declared in a macro.
+  void setMacroIdentifier(IdentifierInfo *MacroName) { MacroII = MacroName; }
+
+  /// Returns true if this attribute was declared in a macro.
+  bool hasMacroIdentifier() const { return MacroII != nullptr; }
+
+  /// Return the macro identifier if this attribute was declared in a macro.
+  /// nullptr is returned if it was not declared in a macro.
+  IdentifierInfo *getMacroIdentifier() 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: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -1119,6 +1119,7 @@
     Parser *Self;
     CachedTokens Toks;
     IdentifierInfo &AttrName;
+    IdentifierInfo *MacroII = nullptr;
     SourceLocation AttrNameLoc;
     SmallVector<Decl*, 2> Decls;
 
Index: clang/include/clang/AST/TypeNodes.def
===================================================================
--- clang/include/clang/AST/TypeNodes.def
+++ clang/include/clang/AST/TypeNodes.def
@@ -83,6 +83,7 @@
 DEPENDENT_TYPE(UnresolvedUsing, Type)
 NON_CANONICAL_TYPE(Paren, Type)
 NON_CANONICAL_TYPE(Typedef, Type)
+NON_CANONICAL_TYPE(MacroDefined, Type)
 NON_CANONICAL_TYPE(Adjusted, Type)
 NON_CANONICAL_TYPE(Decayed, AdjustedType)
 NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type)
Index: clang/include/clang/AST/TypeLoc.h
===================================================================
--- clang/include/clang/AST/TypeLoc.h
+++ clang/include/clang/AST/TypeLoc.h
@@ -174,6 +174,9 @@
 
   TypeLoc IgnoreParens() const;
 
+  /// Strips MacroDefinitionTypeLocs from a type location.
+  TypeLoc IgnoreMacroDefinitions() const;
+
   /// Find a type with the location of an explicit type qualifier.
   ///
   /// The result, if non-null, will be one of:
@@ -1081,6 +1084,33 @@
   }
 };
 
+struct MacroDefinedLocInfo {};
+
+class MacroDefinedTypeLoc
+    : public ConcreteTypeLoc<UnqualTypeLoc, MacroDefinedTypeLoc,
+                             MacroDefinedType, MacroDefinedLocInfo> {
+public:
+  void initializeLocal(ASTContext &Context, SourceLocation Loc) {} // Do nothing
+
+  TypeLoc getInnerLoc() const { return getInnerTypeLoc(); }
+
+  const IdentifierInfo *getMacroIdentifier() const {
+    return getTypePtr()->getMacroIdentifier();
+  }
+
+  QualType getInnerType() const { return getTypePtr()->getUnderlyingType(); }
+
+  SourceRange getLocalSourceRange() const {
+    return getInnerLoc().getLocalSourceRange();
+  }
+
+  unsigned getLocalDataSize() const {
+    // sizeof(MacroDefinedLocInfo) is 1, but we don't need its address to be
+    // unique anyway.  TypeLocBuilder can't handle data sizes of 1.
+    return 0; // No data.
+  }
+};
+
 struct ParenLocInfo {
   SourceLocation LParenLoc;
   SourceLocation RParenLoc;
Index: clang/include/clang/AST/Type.h
===================================================================
--- clang/include/clang/AST/Type.h
+++ clang/include/clang/AST/Type.h
@@ -964,6 +964,13 @@
     return *this;
   }
 
+  /// Returns the specified type after dropping any outer MacroDefinedTypes.
+  QualType IgnoreMacroDefinitions() const {
+    if (isa<MacroDefinedType>(*this))
+      return QualType::IgnoreMacroDefinitions(*this);
+    return *this;
+  }
+
   /// Indicate whether the specified types and qualifiers are identical.
   friend bool operator==(const QualType &LHS, const QualType &RHS) {
     return LHS.Value == RHS.Value;
@@ -1232,6 +1239,7 @@
   static QualType getSingleStepDesugaredTypeImpl(QualType type,
                                                  const ASTContext &C);
   static QualType IgnoreParens(QualType T);
+  static QualType IgnoreMacroDefinitions(QualType T);
   static DestructionKind isDestructedTypeImpl(QualType type);
 };
 
@@ -4158,6 +4166,33 @@
   static bool classof(const Type *T) { return T->getTypeClass() == Typedef; }
 };
 
+/// Sugar type that represents a type that was defined in a macro.
+class MacroDefinedType : public Type {
+  friend class ASTContext; // ASTContext creates these.
+
+  QualType UnderlyingTy;
+  const IdentifierInfo *MacroII;
+
+  MacroDefinedType(QualType UnderlyingTy, QualType CanonTy,
+                   const IdentifierInfo *MacroII)
+      : Type(MacroDefined, CanonTy, UnderlyingTy->isDependentType(),
+             UnderlyingTy->isInstantiationDependentType(),
+             UnderlyingTy->isVariablyModifiedType(),
+             UnderlyingTy->containsUnexpandedParameterPack()),
+        UnderlyingTy(UnderlyingTy), MacroII(MacroII) {}
+
+public:
+  const IdentifierInfo *getMacroIdentifier() const { return MacroII; }
+  QualType getUnderlyingType() const { return UnderlyingTy; }
+
+  bool isSugared() const { return true; }
+  QualType desugar() const;
+
+  static bool classof(const Type *T) {
+    return T->getTypeClass() == MacroDefined;
+  }
+};
+
 /// Represents a `typeof` (or __typeof__) expression (a GCC extension).
 class TypeOfExprType : public Type {
   Expr *TOExpr;
Index: clang/include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1081,6 +1081,9 @@
 
 DEF_TRAVERSE_TYPE(ParenType, { TRY_TO(TraverseType(T->getInnerType())); })
 
+DEF_TRAVERSE_TYPE(MacroDefinedType,
+                  { TRY_TO(TraverseType(T->getUnderlyingType())); })
+
 DEF_TRAVERSE_TYPE(ElaboratedType, {
   if (T->getQualifier()) {
     TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
@@ -1324,6 +1327,9 @@
 
 DEF_TRAVERSE_TYPELOC(ParenType, { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); })
 
+DEF_TRAVERSE_TYPELOC(MacroDefinedType,
+                     { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); })
+
 DEF_TRAVERSE_TYPELOC(AttributedType,
                      { TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); })
 
Index: clang/include/clang/AST/ASTContext.h
===================================================================
--- clang/include/clang/AST/ASTContext.h
+++ clang/include/clang/AST/ASTContext.h
@@ -1451,6 +1451,9 @@
 
   QualType getParenType(QualType NamedType) const;
 
+  QualType getMacroDefinedType(QualType UnderlyingTy,
+                               const IdentifierInfo *MacroII) const;
+
   QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
                              NestedNameSpecifier *NNS, QualType NamedType,
                              TagDecl *OwnedTagDecl = nullptr) const;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to