]> granicus.if.org Git - clang/commitdiff
Introduce ObjCProtocolListLoc for keeping source location information for protocol...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 29 Sep 2009 19:43:35 +0000 (19:43 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 29 Sep 2009 19:43:35 +0000 (19:43 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83094 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/TypeLoc.h
include/clang/AST/TypeLocNodes.def
lib/AST/TypeLoc.cpp
lib/Frontend/PCHReaderDecl.cpp
lib/Frontend/PCHWriterDecl.cpp
lib/Sema/Sema.h
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaType.cpp

index 21b7d9af523cb9c8749f7c69253680dd5540eb8a..5e8b0a0f43f43edcc30e69c16cb6c211ee2e2658 100644 (file)
@@ -150,6 +150,73 @@ public:
   static bool classof(const TypedefLoc *TL) { return true; }
 };
 
+/// \brief Wrapper for source info for ObjC protocol lists.
+class ObjCProtocolListLoc : public TypeSpecLoc {
+  struct Info {
+    SourceLocation LAngleLoc, RAngleLoc;
+  };
+  // SourceLocations are stored after Info, one for each Protocol.
+  SourceLocation *getProtocolLocArray() const {
+    return reinterpret_cast<SourceLocation*>(static_cast<Info*>(Data) + 1);
+  }
+
+public:
+  SourceLocation getLAngleLoc() const {
+    return static_cast<Info*>(Data)->LAngleLoc;
+  }
+  void setLAngleLoc(SourceLocation Loc) {
+    static_cast<Info*>(Data)->LAngleLoc = Loc;
+  }
+
+  SourceLocation getRAngleLoc() const {
+    return static_cast<Info*>(Data)->RAngleLoc;
+  }
+  void setRAngleLoc(SourceLocation Loc) {
+    static_cast<Info*>(Data)->RAngleLoc = Loc;
+  }
+
+  unsigned getNumProtocols() const {
+    return cast<ObjCProtocolListType>(Ty)->getNumProtocols();
+  }
+
+  SourceLocation getProtocolLoc(unsigned i) const {
+    assert(i < getNumProtocols() && "Index is out of bounds!");
+    return getProtocolLocArray()[i];
+  }
+  void setProtocolLoc(unsigned i, SourceLocation Loc) {
+    assert(i < getNumProtocols() && "Index is out of bounds!");
+    getProtocolLocArray()[i] = Loc;
+  }
+
+  ObjCProtocolDecl *getProtocol(unsigned i) const {
+    assert(i < getNumProtocols() && "Index is out of bounds!");
+    return *(cast<ObjCProtocolListType>(Ty)->qual_begin() + i);
+  }
+  
+  TypeLoc getBaseTypeLoc() const {
+    void *Next = static_cast<char*>(Data) + getLocalDataSize();
+    return TypeLoc(cast<ObjCProtocolListType>(Ty)->getBaseType(), Next);
+  }
+
+  SourceRange getSourceRange() const {
+    return SourceRange(getLAngleLoc(), getRAngleLoc());
+  }
+
+  /// \brief Returns the size of the type source info data block that is
+  /// specific to this type.
+  unsigned getLocalDataSize() const {
+    return sizeof(Info) + getNumProtocols() * sizeof(SourceLocation);
+  }
+
+  /// \brief Returns the size of the type source info data block.
+  unsigned getFullDataSize() const {
+    return getLocalDataSize() + getBaseTypeLoc().getFullDataSize();
+  }
+
+  static bool classof(const TypeLoc *TL);
+  static bool classof(const ObjCProtocolListLoc *TL) { return true; }
+};
+
 /// \brief Wrapper for source info for pointers.
 class PointerLoc : public DeclaratorLoc {
   struct Info {
index e2604524e89f887e4fa252f8c94fffb947f31d9e..de20182c0ee675780a84d9f218de610b0e3d4906 100644 (file)
@@ -37,6 +37,7 @@
 
 TYPESPEC_TYPELOC(DefaultTypeSpecLoc, Type)
 TYPESPEC_TYPELOC(TypedefLoc, TypedefType)
+TYPESPEC_TYPELOC(ObjCProtocolListLoc, ObjCProtocolListType)
 DECLARATOR_TYPELOC(PointerLoc, PointerType)
 DECLARATOR_TYPELOC(BlockPointerLoc, BlockPointerType)
 DECLARATOR_TYPELOC(MemberPointerLoc, MemberPointerType)
index cea8dc51698d3a1d9e42d494a530f841ef7443de..fbd7caa3268e4f8ef7de07e9bc2264b78b816538 100644 (file)
@@ -83,6 +83,7 @@ public:
 
 /// \brief Returns the size of the type source info data block.
 unsigned TypeLoc::getFullDataSize() const {
+  if (isNull()) return 0;
   return TypeSizer().Visit(*this);
 }
 
@@ -98,6 +99,7 @@ public:
 #include "clang/AST/TypeLocNodes.def"
 
   TypeLoc VisitTypeSpecLoc(TypeLoc TyLoc) { return TypeLoc(); }
+  TypeLoc VisitObjCProtocolListLoc(ObjCProtocolListLoc TL);
 
   TypeLoc VisitTypeLoc(TypeLoc TyLoc) {
     assert(0 && "A declarator loc wrapper was not handled!");
@@ -107,6 +109,10 @@ public:
 
 }
 
+TypeLoc NextLoc::VisitObjCProtocolListLoc(ObjCProtocolListLoc TL) {
+  return TL.getBaseTypeLoc();
+}
+
 TypeLoc NextLoc::VisitPointerLoc(PointerLoc TL) {
   return TL.getPointeeLoc();
 }
@@ -223,6 +229,24 @@ bool TypedefLoc::classof(const TypeLoc *TL) {
   return TypedefLocChecker().Visit(*TL);
 }
 
+//===----------------------------------------------------------------------===//
+// ObjCProtocolListLoc Implementation
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class ObjCProtocolListLocChecker :
+  public TypeLocVisitor<ObjCProtocolListLocChecker, bool> {
+public:
+  bool VisitObjCProtocolListLoc(ObjCProtocolListLoc TyLoc) { return true; }
+};
+
+}
+
+bool ObjCProtocolListLoc::classof(const TypeLoc *TL) {
+  return ObjCProtocolListLocChecker().Visit(*TL);
+}
+
 //===----------------------------------------------------------------------===//
 // PointerLoc Implementation
 //===----------------------------------------------------------------------===//
index 77721bdf629e92864640a32e6fbaf88ffeb23b1c..550f4dba79907315d5db55327ff528f1e883df59 100644 (file)
@@ -179,6 +179,12 @@ void TypeLocReader::VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) {
 void TypeLocReader::VisitTypedefLoc(TypedefLoc TyLoc) {
   TyLoc.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
 }
+void TypeLocReader::VisitObjCProtocolListLoc(ObjCProtocolListLoc TyLoc) {
+  TyLoc.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TyLoc.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  for (unsigned i = 0, e = TyLoc.getNumProtocols(); i != e; ++i)
+    TyLoc.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
 void TypeLocReader::VisitPointerLoc(PointerLoc TyLoc) {
   TyLoc.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
 }
index 6261db5ff6f98c6a06736843c01e3ffe6d2cfc51..7a8f3e85021255d1ee9c032393211a2b8174dcfa 100644 (file)
@@ -177,6 +177,12 @@ void TypeLocWriter::VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) {
 void TypeLocWriter::VisitTypedefLoc(TypedefLoc TyLoc) {
   Writer.AddSourceLocation(TyLoc.getNameLoc(), Record);
 }
+void TypeLocWriter::VisitObjCProtocolListLoc(ObjCProtocolListLoc TyLoc) {
+  Writer.AddSourceLocation(TyLoc.getLAngleLoc(), Record);
+  Writer.AddSourceLocation(TyLoc.getRAngleLoc(), Record);
+  for (unsigned i = 0, e = TyLoc.getNumProtocols(); i != e; ++i)
+    Writer.AddSourceLocation(TyLoc.getProtocolLoc(i), Record);
+}
 void TypeLocWriter::VisitPointerLoc(PointerLoc TyLoc) {
   Writer.AddSourceLocation(TyLoc.getStarLoc(), Record);
 }
index db2bde0d94be283f8b020572e4a2a25246425116..14c71af934c912954d07e0411dc4645ebcb8773c 100644 (file)
@@ -449,7 +449,7 @@ public:
   //
   QualType adjustParameterType(QualType T);
   QualType ConvertDeclSpecToType(const DeclSpec &DS, SourceLocation DeclLoc,
-                                 bool &IsInvalid);
+                                 bool &IsInvalid, QualType &SourceTy);
   void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL);
   QualType BuildPointerType(QualType T, unsigned Quals,
                             SourceLocation Loc, DeclarationName Entity);
index f2dfe3615f5494e21b2c9b4b7105ce7090bc4bf3..7aa0261ff64f7789940a3aa07f88cc0071b48adf 100644 (file)
@@ -4075,7 +4075,8 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S,
   // friend templates because ActOnTag never produces a ClassTemplateDecl
   // for a TUK_Friend.
   bool invalid = false;
-  QualType T = ConvertDeclSpecToType(DS, Loc, invalid);
+  QualType SourceTy;
+  QualType T = ConvertDeclSpecToType(DS, Loc, invalid, SourceTy);
   if (invalid) return DeclPtrTy();
 
   // This is definitely an error in C++98.  It's probably meant to
index d064e3c3cee62a0105311d855415377777be06cb..89e9e4942b5a8b063e5f20445442e15edd0c629f 100644 (file)
@@ -51,14 +51,16 @@ QualType Sema::adjustParameterType(QualType T) {
 /// object.
 /// \param DS  the declaration specifiers
 /// \param DeclLoc The location of the declarator identifier or invalid if none.
+/// \param SourceTy QualType representing the type as written in source form.
 /// \returns The type described by the declaration specifiers.  This function
 /// never returns null.
 QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
                                      SourceLocation DeclLoc,
-                                     bool &isInvalid) {
+                                     bool &isInvalid, QualType &SourceTy) {
   // FIXME: Should move the logic from DeclSpec::Finish to here for validity
   // checking.
   QualType Result;
+  SourceTy = Result;
 
   switch (DS.getTypeSpecType()) {
   case DeclSpec::TST_void:
@@ -103,6 +105,9 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
   case DeclSpec::TST_unspecified:
     // "<proto1,proto2>" is an objc qualified ID with a missing id.
     if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
+      SourceTy = Context.getObjCProtocolListType(QualType(),
+                                                 (ObjCProtocolDecl**)PQ,
+                                                 DS.getNumProtocolQualifiers());
       Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy,
                                                 (ObjCProtocolDecl**)PQ,
                                                 DS.getNumProtocolQualifiers());
@@ -214,7 +219,11 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
     Result = GetTypeFromParser(DS.getTypeRep());
 
     if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
-      if (const ObjCInterfaceType *Interface = Result->getAs<ObjCInterfaceType>())
+      SourceTy = Context.getObjCProtocolListType(Result,
+                                                 (ObjCProtocolDecl**)PQ,
+                                                 DS.getNumProtocolQualifiers());
+      if (const ObjCInterfaceType *
+            Interface = Result->getAs<ObjCInterfaceType>()) {
         // It would be nice if protocol qualifiers were only stored with the
         // ObjCObjectPointerType. Unfortunately, this isn't possible due
         // to the following typedef idiom (which is uncommon, but allowed):
@@ -227,7 +236,7 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
         Result = Context.getObjCInterfaceType(Interface->getDecl(),
                                               (ObjCProtocolDecl**)PQ,
                                               DS.getNumProtocolQualifiers());
-      else if (Result->isObjCIdType())
+      else if (Result->isObjCIdType())
         // id<protocol-list>
         Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy,
                         (ObjCProtocolDecl**)PQ, DS.getNumProtocolQualifiers());
@@ -369,6 +378,8 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
     Result = Context.getQualifiedType(Result, Quals);
   }
 
+  if (SourceTy.isNull())
+    SourceTy = Result;
   return Result;
 }
 
@@ -839,6 +850,10 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
   // Determine the type of the declarator. Not all forms of declarator
   // have a type.
   QualType T;
+  // The QualType referring to the type as written in source code. We can't use
+  // T because it can change due to semantic analysis.
+  QualType SourceTy;
+
   switch (D.getKind()) {
   case Declarator::DK_Abstract:
   case Declarator::DK_Normal:
@@ -851,7 +866,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
       T = Context.DependentTy;
     } else {
       bool isInvalid = false;
-      T = ConvertDeclSpecToType(DS, D.getIdentifierLoc(), isInvalid);
+      T = ConvertDeclSpecToType(DS, D.getIdentifierLoc(), isInvalid, SourceTy);
       if (isInvalid)
         D.setInvalidType(true);
       else if (OwnedDecl && DS.isTypeSpecOwned())
@@ -869,6 +884,9 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
     T = Context.VoidTy;
     break;
   }
+  
+  if (SourceTy.isNull())
+    SourceTy = T;
 
   if (T == Context.UndeducedAutoTy) {
     int Error = -1;
@@ -919,9 +937,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
     Name = D.getIdentifier();
 
   bool ShouldBuildInfo = DInfo != 0;
-  // The QualType referring to the type as written in source code. We can't use
-  // T because it can change due to semantic analysis.
-  QualType SourceTy = T;
 
   // Walk the DeclTypeInfo, building the recursive type as we go.
   // DeclTypeInfos are ordered from the identifier out, which is
@@ -1278,6 +1293,27 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
   return T;
 }
 
+static void FillTypeSpecLoc(TypeLoc TSL, const DeclSpec &DS) {
+  if (TSL.isNull()) return;
+
+  if (TypedefLoc *TL = dyn_cast<TypedefLoc>(&TSL)) {
+    TL->setNameLoc(DS.getTypeSpecTypeLoc());
+
+  } else if (ObjCProtocolListLoc *PLL = dyn_cast<ObjCProtocolListLoc>(&TSL)) {
+    assert(PLL->getNumProtocols() == DS.getNumProtocolQualifiers());
+    PLL->setLAngleLoc(DS.getProtocolLAngleLoc());
+    PLL->setRAngleLoc(DS.getSourceRange().getEnd());
+    for (unsigned i = 0; i != DS.getNumProtocolQualifiers(); ++i)
+      PLL->setProtocolLoc(i, DS.getProtocolLocs()[i]);
+    FillTypeSpecLoc(PLL->getBaseTypeLoc(), DS);
+
+  } else {
+    //FIXME: Other typespecs.
+    DefaultTypeSpecLoc &DTL = cast<DefaultTypeSpecLoc>(TSL);
+    DTL.setStartLoc(DS.getSourceRange().getBegin());
+  }
+}
+
 /// \brief Create and instantiate a DeclaratorInfo with type source information.
 ///
 /// \param T QualType referring to the type as written in source code.
@@ -1343,14 +1379,8 @@ Sema::GetDeclaratorInfoForDeclarator(Declarator &D, QualType T, unsigned Skip) {
 
     CurrTL = CurrTL.getNextTypeLoc();
   }
-
-  if (TypedefLoc *TL = dyn_cast<TypedefLoc>(&CurrTL)) {
-    TL->setNameLoc(D.getDeclSpec().getTypeSpecTypeLoc());
-  } else {
-    //FIXME: Other typespecs.
-    DefaultTypeSpecLoc &DTL = cast<DefaultTypeSpecLoc>(CurrTL);
-    DTL.setStartLoc(D.getDeclSpec().getSourceRange().getBegin());
-  }
+  
+  FillTypeSpecLoc(CurrTL, D.getDeclSpec());
 
   return DInfo;
 }