aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2009-09-29 19:43:35 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2009-09-29 19:43:35 +0000
commitf352bddf015e537350416c296dd2963524f554f9 (patch)
treeccbf5d7635646b159523395c8a0b32dd5e9c9c43
parent24fab41057e4b67ed69a6b4027d5ae0f2f6934dc (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.h67
-rw-r--r--include/clang/AST/TypeLocNodes.def1
-rw-r--r--lib/AST/TypeLoc.cpp24
-rw-r--r--lib/Frontend/PCHReaderDecl.cpp6
-rw-r--r--lib/Frontend/PCHWriterDecl.cpp6
-rw-r--r--lib/Sema/Sema.h2
-rw-r--r--lib/Sema/SemaDeclCXX.cpp3
-rw-r--r--lib/Sema/SemaType.cpp60
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;
}