]> granicus.if.org Git - clang/commitdiff
Introduce an AttributedType, but don't actually use it anywhere yet.
authorJohn McCall <rjmccall@apple.com>
Thu, 6 Jan 2011 01:58:22 +0000 (01:58 +0000)
committerJohn McCall <rjmccall@apple.com>
Thu, 6 Jan 2011 01:58:22 +0000 (01:58 +0000)
The initial TreeTransform is a cop-out, but it's more-or-less equivalent
to what we were doing before, or rather what we're doing now and might
eventually stop doing in favor of using this type.
I am simultaneously intrigued by the possibilities of rebuilding a
dependent Attri

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122942 91177308-0d34-0410-b5e6-96231b3b80d8

14 files changed:
include/clang/AST/ASTContext.h
include/clang/AST/RecursiveASTVisitor.h
include/clang/AST/Type.h
include/clang/AST/TypeLoc.h
include/clang/AST/TypeNodes.def
include/clang/Serialization/ASTBitCodes.h
lib/AST/ASTContext.cpp
lib/AST/ASTImporter.cpp
lib/AST/TypeLoc.cpp
lib/AST/TypePrinter.cpp
lib/CodeGen/CGDebugInfo.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp

index beba66947ebc6a453a8142606939e0afd052cd4c..0abdbb05a599479d655debe0ffa90ce777d5383f 100644 (file)
@@ -109,6 +109,7 @@ class ASTContext {
   llvm::FoldingSet<PackExpansionType> PackExpansionTypes;
   llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes;
   llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
+  llvm::FoldingSet<AttributedType> AttributedTypes;
 
   llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
   llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
@@ -648,6 +649,10 @@ public:
 
   QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST);
 
+  QualType getAttributedType(AttributedType::Kind attrKind,
+                             QualType modifiedType,
+                             QualType equivalentType);
+
   QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced,
                                         QualType Replacement);
 
index 7e39a344a6241ea493ff6d5a1f9897256e6500c3..0a198a871885a9df0b0fb9de8186342415f17829 100644 (file)
@@ -726,6 +726,10 @@ DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
 
 DEF_TRAVERSE_TYPE(InjectedClassNameType, { })
 
+DEF_TRAVERSE_TYPE(AttributedType, {
+    TRY_TO(TraverseType(T->getModifiedType()));
+  })
+
 DEF_TRAVERSE_TYPE(ParenType, {
     TRY_TO(TraverseType(T->getInnerType()));
   })
@@ -936,6 +940,10 @@ DEF_TRAVERSE_TYPELOC(ParenType, {
     TRY_TO(TraverseTypeLoc(TL.getInnerLoc()));
   })
 
+DEF_TRAVERSE_TYPELOC(AttributedType, {
+    TRY_TO(TraverseTypeLoc(TL.getModifiedLoc()));
+  })
+
 // FIXME: use the sourceloc on qualifier?
 DEF_TRAVERSE_TYPELOC(ElaboratedType, {
     if (TL.getTypePtr()->getQualifier()) {
index 541cba4e04388cf391b20e474641cfc41234ab63..14cbb0205b19d7e40190c114a96c86fd6fc08174 100644 (file)
@@ -993,9 +993,19 @@ protected:
     unsigned NumElements : 29 - NumTypeBits;
   };
 
+  class AttributedTypeBitfields {
+    friend class AttributedType;
+
+    unsigned : NumTypeBits;
+
+    /// AttrKind - an AttributedType::Kind
+    unsigned AttrKind : 32 - NumTypeBits;
+  };
+
   union {
     TypeBitfields TypeBits;
     ArrayTypeBitfields ArrayTypeBits;
+    AttributedTypeBitfields AttributedTypeBits;
     BuiltinTypeBitfields BuiltinTypeBits;
     FunctionTypeBitfields FunctionTypeBits;
     ObjCObjectTypeBitfields ObjCObjectTypeBits;
@@ -2657,6 +2667,91 @@ public:
   static bool classof(const EnumType *) { return true; }
 };
 
+/// AttributedType - An attributed type is a type to which a type
+/// attribute has been applied.  The "modified type" is the
+/// fully-sugared type to which the attributed type was applied;
+/// generally it is not canonically equivalent to the attributed type.
+/// The "equivalent type" is the minimally-desugared type which the
+/// type is canonically equivalent to.
+///
+/// For example, in the following attributed type:
+///     int32_t __attribute__((vector_size(16)))
+///   - the modified type is the TypedefType for int32_t
+///   - the equivalent type is VectorType(16, int32_t)
+///   - the canonical type is VectorType(16, int)
+class AttributedType : public Type, public llvm::FoldingSetNode {
+public:
+  // It is really silly to have yet another attribute-kind enum, but
+  // clang::attr::Kind doesn't currently cover the pure type attrs.
+  enum Kind {
+    // Expression operand.
+    address_space,
+    regparm,
+    vector_size,
+    neon_vector_type,
+    neon_polyvector_type,
+
+    FirstExprOperandKind = address_space,
+    LastExprOperandKind = neon_polyvector_type,
+
+    // Enumerated operand (string or keyword).
+    objc_gc,
+
+    FirstEnumOperandKind = objc_gc,
+    LastEnumOperandKind = objc_gc,
+
+    // No operand.
+    noreturn,
+    cdecl,
+    fastcall,
+    stdcall,
+    thiscall,
+    pascal
+  };
+
+private:
+  QualType ModifiedType;
+  QualType EquivalentType;
+
+  friend class ASTContext; // creates these
+
+  AttributedType(QualType canon, Kind attrKind,
+                 QualType modified, QualType equivalent)
+    : Type(Attributed, canon, canon->isDependentType(),
+           canon->isVariablyModifiedType(),
+           canon->containsUnexpandedParameterPack()),
+      ModifiedType(modified), EquivalentType(equivalent) {
+    AttributedTypeBits.AttrKind = attrKind;
+  }
+
+public:
+  Kind getAttrKind() const {
+    return static_cast<Kind>(AttributedTypeBits.AttrKind);
+  }
+
+  QualType getModifiedType() const { return ModifiedType; }
+  QualType getEquivalentType() const { return EquivalentType; }
+
+  bool isSugared() const { return true; }
+  QualType desugar() const { return getEquivalentType(); }
+
+  void Profile(llvm::FoldingSetNodeID &ID) {
+    Profile(ID, getAttrKind(), ModifiedType, EquivalentType);
+  }
+
+  static void Profile(llvm::FoldingSetNodeID &ID, Kind attrKind,
+                      QualType modified, QualType equivalent) {
+    ID.AddInteger(attrKind);
+    ID.AddPointer(modified.getAsOpaquePtr());
+    ID.AddPointer(equivalent.getAsOpaquePtr());
+  }
+
+  static bool classof(const Type *T) {
+    return T->getTypeClass() == Attributed;
+  }
+  static bool classof(const AttributedType *T) { return true; }
+};
+
 class TemplateTypeParmType : public Type, public llvm::FoldingSetNode {
   unsigned Depth : 15;
   unsigned ParameterPack : 1;
index 3480681fe161f233c8319b34cfd91b2566a73f01..c5497b814937d290a33a3c5a0168cd1e736948aa 100644 (file)
@@ -592,6 +592,130 @@ class SubstTemplateTypeParmTypeLoc :
                                      SubstTemplateTypeParmType> {
 };
 
+struct AttributedLocInfo {
+  union {
+    Expr *ExprOperand;
+
+    /// A raw SourceLocation.
+    unsigned EnumOperandLoc;
+  };
+
+  SourceRange OperandParens;
+
+  SourceLocation AttrLoc;
+};
+
+/// \brief Type source information for an attributed type.
+class AttributedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+                                                 AttributedTypeLoc,
+                                                 AttributedType,
+                                                 AttributedLocInfo> {
+public:
+  AttributedType::Kind getAttrKind() const {
+    return getTypePtr()->getAttrKind();
+  }
+
+  bool hasAttrExprOperand() const {
+    return (getAttrKind() >= AttributedType::FirstExprOperandKind &&
+            getAttrKind() <= AttributedType::LastExprOperandKind);
+  }
+
+  bool hasAttrEnumOperand() const {
+    return (getAttrKind() >= AttributedType::FirstEnumOperandKind &&
+            getAttrKind() <= AttributedType::LastEnumOperandKind);
+  }
+
+  bool hasAttrOperand() const {
+    return hasAttrExprOperand() || hasAttrEnumOperand();
+  }
+
+  /// The modified type, which is generally canonically different from
+  /// the attribute type.
+  ///    int main(int, char**) __attribute__((noreturn))
+  ///    ~~~     ~~~~~~~~~~~~~
+  TypeLoc getModifiedLoc() const {
+    return getInnerTypeLoc();
+  }
+
+  /// The location of the attribute name, i.e.
+  ///    __attribute__((regparm(1000)))
+  ///                   ^~~~~~~
+  SourceLocation getAttrNameLoc() const {
+    return getLocalData()->AttrLoc;
+  }
+  void setAttrNameLoc(SourceLocation loc) {
+    getLocalData()->AttrLoc = loc;
+  }
+
+  /// The attribute's expression operand, if it has one.
+  ///    void *cur_thread __attribute__((address_space(21)))
+  ///                                                  ^~
+  Expr *getAttrExprOperand() const {
+    assert(hasAttrExprOperand());
+    return getLocalData()->ExprOperand;
+  }
+  void setAttrExprOperand(Expr *e) {
+    assert(hasAttrExprOperand());
+    getLocalData()->ExprOperand = e;
+  }
+
+  /// The location of the attribute's enumerated operand, if it has one.
+  ///    void * __attribute__((objc_gc(weak)))
+  ///                                  ^~~~
+  SourceLocation getAttrEnumOperandLoc() const {
+    assert(hasAttrEnumOperand());
+    return SourceLocation::getFromRawEncoding(getLocalData()->EnumOperandLoc);
+  }
+  void setAttrEnumOperandLoc(SourceLocation loc) {
+    assert(hasAttrEnumOperand());
+    getLocalData()->EnumOperandLoc = loc.getRawEncoding();
+  }
+
+  /// The location of the parentheses around the operand, if there is
+  /// an operand.
+  ///    void * __attribute__((objc_gc(weak)))
+  ///                                 ^    ^
+  SourceRange getAttrOperandParensRange() const {
+    assert(hasAttrOperand());
+    return getLocalData()->OperandParens;
+  }
+  void setAttrOperandParensRange(SourceRange range) {
+    assert(hasAttrOperand());
+    getLocalData()->OperandParens = range;
+  }
+
+  SourceRange getLocalSourceRange() const {
+    // Note that this does *not* include the range of the attribute
+    // enclosure, e.g.:
+    //    __attribute__((foo(bar)))
+    //    ^~~~~~~~~~~~~~~        ~~
+    // or
+    //    [[foo(bar)]]
+    //    ^~        ~~
+    // That enclosure doesn't necessarily belong to a single attribute
+    // anyway.
+    SourceRange range(getAttrNameLoc());
+    if (hasAttrOperand())
+      range.setEnd(getAttrOperandParensRange().getEnd());
+    return range;
+  }
+
+  void initializeLocal(SourceLocation loc) {
+    setAttrNameLoc(loc);
+    if (hasAttrExprOperand()) {
+      setAttrOperandParensRange(SourceRange(loc));
+      setAttrExprOperand(0);
+    } else if (hasAttrEnumOperand()) {
+      setAttrOperandParensRange(SourceRange(loc));
+      setAttrEnumOperandLoc(loc);
+    }
+  }
+
+  QualType getInnerType() const {
+    return getTypePtr()->getModifiedType();
+  }
+};
+
 
 struct ObjCProtocolListLocInfo {
   SourceLocation LAngleLoc;
index 4e25b94c520a9f75c14117e40bbcb7ac1fe3e223..52b8f831ac449743489a3ca82a7355246c11cb73 100644 (file)
@@ -88,6 +88,7 @@ ABSTRACT_TYPE(Tag, Type)
 TYPE(Record, TagType)
 TYPE(Enum, TagType)
 NON_CANONICAL_TYPE(Elaborated, Type)
+NON_CANONICAL_TYPE(Attributed, Type)
 DEPENDENT_TYPE(TemplateTypeParm, Type)
 NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
 NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type)
index bbe7c1d2f816a7a43596b220eeb1871198786917..ea93d2e1d6c03ba33d17bf8af9c8f73f6c678f64 100644 (file)
@@ -553,7 +553,9 @@ namespace clang {
       /// \brief A ParenType record.
       TYPE_PAREN                    = 34,
       /// \brief A PackExpansionType record.
-      TYPE_PACK_EXPANSION           = 35
+      TYPE_PACK_EXPANSION           = 35,
+      /// \brief An AttributedType record.
+      TYPE_ATTRIBUTED               = 36
     };
 
     /// \brief The type IDs for special types constructed by semantic
index 6e7f7c31ea59cf913ed8e2d84559f51f1f55413a..e76238cb221e871c4fa94372adb6ef54caa831c1 100644 (file)
@@ -844,6 +844,10 @@ ASTContext::getTypeInfo(const Type *T) {
   case Type::Elaborated:
     return getTypeInfo(cast<ElaboratedType>(T)->getNamedType().getTypePtr());
 
+  case Type::Attributed:
+    return getTypeInfo(
+                  cast<AttributedType>(T)->getEquivalentType().getTypePtr());
+
   case Type::TemplateSpecialization:
     assert(getCanonicalType(T) != T &&
            "Cannot request the size of a dependent type");
@@ -1875,6 +1879,27 @@ QualType ASTContext::getEnumType(const EnumDecl *Decl) {
   return QualType(Decl->TypeForDecl, 0);
 }
 
+QualType ASTContext::getAttributedType(AttributedType::Kind attrKind,
+                                       QualType modifiedType,
+                                       QualType equivalentType) {
+  llvm::FoldingSetNodeID id;
+  AttributedType::Profile(id, attrKind, modifiedType, equivalentType);
+
+  void *insertPos = 0;
+  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);
+
+  Types.push_back(type);
+  AttributedTypes.InsertNode(type, insertPos);
+
+  return QualType(type, 0);
+}
+
+
 /// \brief Retrieve a substitution-result type.
 QualType
 ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm,
index 5a94de902010fb27178768843781d7d6e94caddf..60ea7d9081b5dca194ca0d0fa65655f42724acd9 100644 (file)
@@ -557,6 +557,17 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
       return false;
       
     break;
+
+  case Type::Attributed:
+    if (!IsStructurallyEquivalent(Context,
+                                  cast<AttributedType>(T1)->getModifiedType(),
+                                  cast<AttributedType>(T2)->getModifiedType()))
+      return false;
+    if (!IsStructurallyEquivalent(Context,
+                                cast<AttributedType>(T1)->getEquivalentType(),
+                                cast<AttributedType>(T2)->getEquivalentType()))
+      return false;
+    break;
       
   case Type::Paren:
     if (!IsStructurallyEquivalent(Context,
index 6dd5543966bc9bd9f0e594517de2b7d21991cec0..08fe267b1d1b4136e2d6af940860fe010deab940 100644 (file)
@@ -229,4 +229,3 @@ TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
     TL = PTL->getInnerLoc();
   return TL;
 }
-
index bd0467d246b82eb025f9da3530472fed9854c9a4..7e719be4e907bd554dc86ac4bc9548ec6c8cf511 100644 (file)
@@ -674,6 +674,84 @@ void TypePrinter::printPackExpansion(const PackExpansionType *T,
   S += "...";
 }
 
+void TypePrinter::printAttributed(const AttributedType *T,
+                                  std::string &S) {
+  print(T->getModifiedType(), S);
+
+  // TODO: not all attributes are GCC-style attributes.
+  S += "__attribute__((";
+  switch (T->getAttrKind()) {
+  case AttributedType::address_space:
+    S += "address_space(";
+    S += T->getEquivalentType().getAddressSpace();
+    S += ")";
+    break;
+
+  case AttributedType::vector_size: {
+    S += "__vector_size__(";
+    if (const VectorType *vector =T->getEquivalentType()->getAs<VectorType>()) {
+      S += vector->getNumElements();
+      S += " * sizeof(";
+
+      std::string tmp;
+      print(vector->getElementType(), tmp);
+      S += tmp;
+      S += ")";
+    }
+    S += ")";
+    break;
+  }
+
+  case AttributedType::neon_vector_type:
+  case AttributedType::neon_polyvector_type: {
+    if (T->getAttrKind() == AttributedType::neon_vector_type)
+      S += "neon_vector_type(";
+    else
+      S += "neon_polyvector_type(";
+    const VectorType *vector = T->getEquivalentType()->getAs<VectorType>();
+    S += llvm::utostr_32(vector->getNumElements());
+    S += ")";
+    break;
+  }
+
+  case AttributedType::regparm: {
+    S += "regparm(";
+    QualType t = T->getEquivalentType();
+    while (!t->isFunctionType())
+      t = t->getPointeeType();
+    S += t->getAs<FunctionType>()->getRegParmType();
+    S += ")";
+    break;
+  }
+
+  case AttributedType::objc_gc: {
+    S += "objc_gc(";
+
+    QualType tmp = T->getEquivalentType();
+    while (tmp.getObjCGCAttr() == Qualifiers::GCNone) {
+      QualType next = tmp->getPointeeType();
+      if (next == tmp) break;
+      tmp = next;
+    }
+
+    if (tmp.isObjCGCWeak())
+      S += "weak";
+    else
+      S += "strong";
+    S += ")";
+    break;
+  }
+
+  case AttributedType::noreturn: S += "noreturn"; break;
+  case AttributedType::cdecl: S += "cdecl"; break;
+  case AttributedType::fastcall: S += "fastcall"; break;
+  case AttributedType::stdcall: S += "stdcall"; break;
+  case AttributedType::thiscall: S += "thiscall"; break;
+  case AttributedType::pascal: S += "pascal"; break;
+  }
+  S += "))";
+}
+
 void TypePrinter::printObjCInterface(const ObjCInterfaceType *T, 
                                      std::string &S) { 
   if (!S.empty())    // Prefix the basic type, e.g. 'typedefname X'.
index 615972afbc836fbd22394fca07625c6a34de775f..37a88efcc4e2845468b9608dec7c3eb3b118b074 100644 (file)
@@ -1324,6 +1324,8 @@ static QualType UnwrapTypeForDebugInfo(QualType T) {
     case Type::Decltype:
       T = cast<DecltypeType>(T)->getUnderlyingType();
       break;
+    case Type::Attributed:
+      T = cast<AttributedType>(T)->getEquivalentType();
     case Type::Elaborated:
       T = cast<ElaboratedType>(T)->getNamedType();
       break;
@@ -1423,6 +1425,7 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
   case Type::MemberPointer:
     return CreateType(cast<MemberPointerType>(Ty), Unit);
 
+  case Type::Attributed:
   case Type::TemplateSpecialization:
   case Type::Elaborated:
   case Type::Paren:
index dc87c5bbd2aab24ead5adff2f212f62240f5700b..25ead7bba5f655f263d96a3735b7d08b391fdcbc 100644 (file)
@@ -3778,7 +3778,6 @@ QualType TreeTransform<Derived>::TransformInjectedClassNameType(
   return T;
 }
 
-
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformTemplateTypeParmType(
                                                 TypeLocBuilder &TLB,
@@ -3945,6 +3944,43 @@ TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
   return Result;
 }
 
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformAttributedType(
+                                                TypeLocBuilder &TLB,
+                                                AttributedTypeLoc TL) {
+  const AttributedType *oldType = TL.getTypePtr();
+  QualType modifiedType = getDerived().TransformType(TLB, TL.getModifiedLoc());
+  if (modifiedType.isNull())
+    return QualType();
+
+  QualType result = TL.getType();
+
+  // FIXME: dependent operand expressions?
+  if (getDerived().AlwaysRebuild() ||
+      modifiedType != oldType->getModifiedType()) {
+    // TODO: this is really lame; we should really be rebuilding the
+    // equivalent type from first principles.
+    QualType equivalentType
+      = getDerived().TransformType(oldType->getEquivalentType());
+    if (equivalentType.isNull())
+      return QualType();
+    result = SemaRef.Context.getAttributedType(oldType->getAttrKind(),
+                                               modifiedType,
+                                               equivalentType);
+  }
+
+  AttributedTypeLoc newTL = TLB.push<AttributedTypeLoc>(result);
+  newTL.setAttrNameLoc(TL.getAttrNameLoc());
+  if (TL.hasAttrOperand())
+    newTL.setAttrOperandParensRange(TL.getAttrOperandParensRange());
+  if (TL.hasAttrExprOperand())
+    newTL.setAttrExprOperand(TL.getAttrExprOperand());
+  else if (TL.hasAttrEnumOperand())
+    newTL.setAttrEnumOperandLoc(TL.getAttrEnumOperandLoc());
+
+  return result;
+}
+
 template<typename Derived>
 QualType
 TreeTransform<Derived>::TransformParenType(TypeLocBuilder &TLB,
index 3bf51e6a0e99e8188c2257dee1d0d97e89c0dfc6..7c8415a295c1ba659c6c8f3c59a0201ac7b0c44a 100644 (file)
@@ -2924,6 +2924,17 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) {
     return T;
   }
 
+  case TYPE_ATTRIBUTED: {
+    if (Record.size() != 3) {
+      Error("incorrect encoding of attributed type");
+      return QualType();
+    }
+    QualType modifiedType = GetType(Record[0]);
+    QualType equivalentType = GetType(Record[1]);
+    AttributedType::Kind kind = static_cast<AttributedType::Kind>(Record[2]);
+    return Context->getAttributedType(kind, modifiedType, equivalentType);
+  }
+
   case TYPE_PAREN: {
     if (Record.size() != 1) {
       Error("incorrect encoding of paren type");
@@ -3197,6 +3208,22 @@ void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
 void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) {
   TL.setNameLoc(ReadSourceLocation(Record, Idx));
 }
+void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
+  TL.setAttrNameLoc(ReadSourceLocation(Record, Idx));
+  if (TL.hasAttrOperand()) {
+    SourceRange range;
+    range.setBegin(ReadSourceLocation(Record, Idx));
+    range.setEnd(ReadSourceLocation(Record, Idx));
+    TL.setAttrOperandParensRange(range);
+  }
+  if (TL.hasAttrExprOperand()) {
+    if (Record[Idx++])
+      TL.setAttrExprOperand(Reader.ReadExpr(F));
+    else
+      TL.setAttrExprOperand(0);
+  } else if (TL.hasAttrEnumOperand())
+    TL.setAttrEnumOperandLoc(ReadSourceLocation(Record, Idx));
+}
 void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
   TL.setNameLoc(ReadSourceLocation(Record, Idx));
 }
index 2c0239de17e1483373600ce29de663189c977915..eb312522c7ade559224604e9642fce74cdc32ba1 100644 (file)
@@ -228,6 +228,13 @@ void ASTTypeWriter::VisitEnumType(const EnumType *T) {
   Code = TYPE_ENUM;
 }
 
+void ASTTypeWriter::VisitAttributedType(const AttributedType *T) {
+  Writer.AddTypeRef(T->getModifiedType(), Record);
+  Writer.AddTypeRef(T->getEquivalentType(), Record);
+  Record.push_back(T->getAttrKind());
+  Code = TYPE_ATTRIBUTED;
+}
+
 void
 ASTTypeWriter::VisitSubstTemplateTypeParmType(
                                         const SubstTemplateTypeParmType *T) {
@@ -462,6 +469,21 @@ void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {
 void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) {
   Writer.AddSourceLocation(TL.getNameLoc(), Record);
 }
+void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getAttrNameLoc(), Record);
+  if (TL.hasAttrOperand()) {
+    SourceRange range = TL.getAttrOperandParensRange();
+    Writer.AddSourceLocation(range.getBegin(), Record);
+    Writer.AddSourceLocation(range.getEnd(), Record);
+  }
+  if (TL.hasAttrExprOperand()) {
+    Expr *operand = TL.getAttrExprOperand();
+    Record.push_back(operand ? 1 : 0);
+    if (operand) Writer.AddStmt(operand);
+  } else if (TL.hasAttrEnumOperand()) {
+    Writer.AddSourceLocation(TL.getAttrEnumOperandLoc(), Record);
+  }
+}
 void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
   Writer.AddSourceLocation(TL.getNameLoc(), Record);
 }