diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2009-09-29 19:43:35 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2009-09-29 19:43:35 +0000 |
commit | f352bddf015e537350416c296dd2963524f554f9 (patch) | |
tree | ccbf5d7635646b159523395c8a0b32dd5e9c9c43 | |
parent | 24fab41057e4b67ed69a6b4027d5ae0f2f6934dc (diff) |
Introduce ObjCProtocolListLoc for keeping source location information for protocol references.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83094 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/TypeLoc.h | 67 | ||||
-rw-r--r-- | include/clang/AST/TypeLocNodes.def | 1 | ||||
-rw-r--r-- | lib/AST/TypeLoc.cpp | 24 | ||||
-rw-r--r-- | lib/Frontend/PCHReaderDecl.cpp | 6 | ||||
-rw-r--r-- | lib/Frontend/PCHWriterDecl.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 60 |
8 files changed, 152 insertions, 17 deletions
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 21b7d9af52..5e8b0a0f43 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -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 { diff --git a/include/clang/AST/TypeLocNodes.def b/include/clang/AST/TypeLocNodes.def index e2604524e8..de20182c0e 100644 --- a/include/clang/AST/TypeLocNodes.def +++ b/include/clang/AST/TypeLocNodes.def @@ -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) diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index cea8dc5169..fbd7caa326 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -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(); } @@ -224,6 +230,24 @@ bool TypedefLoc::classof(const TypeLoc *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 //===----------------------------------------------------------------------===// diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 77721bdf62..550f4dba79 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -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++])); } diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index 6261db5ff6..7a8f3e8502 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -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); } diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index db2bde0d94..14c71af934 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -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); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index f2dfe3615f..7aa0261ff6 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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 diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index d064e3c3ce..89e9e4942b 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -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; } |