aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/DeclObjC.h204
-rw-r--r--include/clang/Serialization/ASTReader.h6
-rw-r--r--lib/AST/ASTImporter.cpp140
-rw-r--r--lib/AST/DeclObjC.cpp108
-rw-r--r--lib/AST/DeclPrinter.cpp5
-rw-r--r--lib/Sema/SemaCodeComplete.cpp5
-rw-r--r--lib/Sema/SemaDeclObjC.cpp18
-rw-r--r--lib/Sema/SemaExprObjC.cpp11
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp103
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp62
-rw-r--r--tools/libclang/IndexingContext.cpp5
11 files changed, 434 insertions, 233 deletions
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 597eb45672..06fa4cb11e 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -545,45 +545,63 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
/// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType
mutable const Type *TypeForDecl;
friend class ASTContext;
+
+ struct DefinitionData {
+ /// Class's super class.
+ ObjCInterfaceDecl *SuperClass;
- /// Class's super class.
- ObjCInterfaceDecl *SuperClass;
+ /// Protocols referenced in the @interface declaration
+ ObjCProtocolList ReferencedProtocols;
- /// Protocols referenced in the @interface declaration
- ObjCProtocolList ReferencedProtocols;
+ /// Protocols reference in both the @interface and class extensions.
+ ObjCList<ObjCProtocolDecl> AllReferencedProtocols;
- /// Protocols reference in both the @interface and class extensions.
- ObjCList<ObjCProtocolDecl> AllReferencedProtocols;
+ /// \brief List of categories and class extensions defined for this class.
+ ///
+ /// Categories are stored as a linked list in the AST, since the categories
+ /// and class extensions come long after the initial interface declaration,
+ /// and we avoid dynamically-resized arrays in the AST wherever possible.
+ ObjCCategoryDecl *CategoryList;
- /// \brief List of categories and class extensions defined for this class.
- ///
- /// Categories are stored as a linked list in the AST, since the categories
- /// and class extensions come long after the initial interface declaration,
- /// and we avoid dynamically-resized arrays in the AST wherever possible.
- ObjCCategoryDecl *CategoryList;
+ /// IvarList - List of all ivars defined by this class; including class
+ /// extensions and implementation. This list is built lazily.
+ ObjCIvarDecl *IvarList;
+
+ /// \brief Indicates that the contents of this Objective-C class will be
+ /// completed by the external AST source when required.
+ mutable bool ExternallyCompleted : 1;
+
+ SourceLocation SuperClassLoc; // location of the super class identifier.
+ };
+
+ ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
+ SourceLocation CLoc, bool FD, bool isInternal);
+
+ void LoadExternalDefinition() const;
+
+ /// \brief Contains a pointer to the data associated with this class,
+ /// which will be NULL if this class has not yet been defined.
+ DefinitionData *Definition;
- /// IvarList - List of all ivars defined by this class; including class
- /// extensions and implementation. This list is built lazily.
- ObjCIvarDecl *IvarList;
+ /// \brief The location of the last location in this declaration, e.g.,
+ /// the '>', '}', or identifier.
+ /// FIXME: This seems like the wrong location to care about.
+ SourceLocation EndLoc;
/// \brief True if it was initially declared with @class.
/// Differs with \see ForwardDecl in that \see ForwardDecl will change to
/// false when we see the @interface, but InitiallyForwardDecl will remain
/// true.
bool InitiallyForwardDecl : 1;
- bool ForwardDecl:1; // declared with @class.
-
- /// \brief Indicates that the contents of this Objective-C class will be
- /// completed by the external AST source when required.
- mutable bool ExternallyCompleted : 1;
- SourceLocation SuperClassLoc; // location of the super class identifier.
- SourceLocation EndLoc; // marks the '>', '}', or identifier.
-
- ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
- SourceLocation CLoc, bool FD, bool isInternal);
+ DefinitionData &data() const {
+ assert(Definition != 0 && "Declaration is not a definition!");
+ return *Definition;
+ }
- void LoadExternalDefinition() const;
+ /// \brief Allocate the definition data for this class.
+ void allocateDefinitionData();
+
public:
static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation atLoc,
@@ -604,10 +622,10 @@ public:
void setExternallyCompleted();
const ObjCProtocolList &getReferencedProtocols() const {
- if (ExternallyCompleted)
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
- return ReferencedProtocols;
+ return data().ReferencedProtocols;
}
ObjCImplementationDecl *getImplementation() const;
@@ -626,55 +644,93 @@ public:
typedef ObjCProtocolList::iterator protocol_iterator;
protocol_iterator protocol_begin() const {
- if (ExternallyCompleted)
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return protocol_iterator();
+
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
- return ReferencedProtocols.begin();
+ return data().ReferencedProtocols.begin();
}
protocol_iterator protocol_end() const {
- if (ExternallyCompleted)
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return protocol_iterator();
+
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
- return ReferencedProtocols.end();
+ return data().ReferencedProtocols.end();
}
typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
protocol_loc_iterator protocol_loc_begin() const {
- if (ExternallyCompleted)
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return protocol_loc_iterator();
+
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
- return ReferencedProtocols.loc_begin();
+ return data().ReferencedProtocols.loc_begin();
}
protocol_loc_iterator protocol_loc_end() const {
- if (ExternallyCompleted)
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return protocol_loc_iterator();
+
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
- return ReferencedProtocols.loc_end();
+ return data().ReferencedProtocols.loc_end();
}
typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator;
all_protocol_iterator all_referenced_protocol_begin() const {
- if (ExternallyCompleted)
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return all_protocol_iterator();
+
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
- return AllReferencedProtocols.empty() ? protocol_begin()
- : AllReferencedProtocols.begin();
+ return data().AllReferencedProtocols.empty()
+ ? protocol_begin()
+ : data().AllReferencedProtocols.begin();
}
all_protocol_iterator all_referenced_protocol_end() const {
- if (ExternallyCompleted)
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return all_protocol_iterator();
+
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
- return AllReferencedProtocols.empty() ? protocol_end()
- : AllReferencedProtocols.end();
+ return data().AllReferencedProtocols.empty()
+ ? protocol_end()
+ : data().AllReferencedProtocols.end();
}
typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
- ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); }
- ivar_iterator ivar_end() const { return ivar_iterator(decls_end()); }
+ ivar_iterator ivar_begin() const {
+ if (const ObjCInterfaceDecl *Def = getDefinition())
+ return ivar_iterator(Def->decls_begin());
+
+ // FIXME: Should make sure no callers ever do this.
+ return ivar_iterator();
+ }
+ ivar_iterator ivar_end() const {
+ if (const ObjCInterfaceDecl *Def = getDefinition())
+ return ivar_iterator(Def->decls_end());
+
+ // FIXME: Should make sure no callers ever do this.
+ return ivar_iterator();
+ }
unsigned ivar_size() const {
return std::distance(ivar_begin(), ivar_end());
@@ -688,13 +744,13 @@ public:
// the ivar chain is essentially a cached property of ObjCInterfaceDecl.
return const_cast<ObjCInterfaceDecl *>(this)->all_declared_ivar_begin();
}
- void setIvarList(ObjCIvarDecl *ivar) { IvarList = ivar; }
+ void setIvarList(ObjCIvarDecl *ivar) { data().IvarList = ivar; }
/// setProtocolList - Set the list of protocols that this interface
/// implements.
void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
const SourceLocation *Locs, ASTContext &C) {
- ReferencedProtocols.set(List, Num, Locs, C);
+ data().ReferencedProtocols.set(List, Num, Locs, C);
}
/// mergeClassExtensionProtocolList - Merge class extension's protocol list
@@ -706,30 +762,63 @@ public:
/// \brief True if it was initially declared with @class.
/// Differs with \see isForwardDecl in that \see isForwardDecl will change to
/// false when we see the @interface, but this will remain true.
- bool isInitiallyForwardDecl() const { return InitiallyForwardDecl; }
+ bool isInitiallyForwardDecl() const {
+ return InitiallyForwardDecl;
+ }
- bool isForwardDecl() const { return ForwardDecl; }
+ /// \brief Determine whether this declaration is a forward declaration of
+ /// the class.
+ bool isForwardDecl() const { return Definition == 0; }
- void completedForwardDecl();
+ /// \brief Determine whether this class has been defined.
+ bool hasDefinition() const { return Definition != 0; }
+
+ /// \brief Retrieve the definition of this class, or NULL if this class
+ /// has been forward-declared (with @class) but not yet defined (with
+ /// @interface).
+ ObjCInterfaceDecl *getDefinition() {
+ return hasDefinition()? this : 0;
+ }
+
+ /// \brief Retrieve the definition of this class, or NULL if this class
+ /// has been forward-declared (with @class) but not yet defined (with
+ /// @interface).
+ const ObjCInterfaceDecl *getDefinition() const {
+ return hasDefinition()? this : 0;
+ }
+ /// \brief Starts the definition of this Objective-C class, taking it from
+ /// a forward declaration (@class) to a definition (@interface).
+ void startDefinition();
+
ObjCInterfaceDecl *getSuperClass() const {
- if (ExternallyCompleted)
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return 0;
+
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
- return SuperClass;
+ return data().SuperClass;
}
- void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
+ void setSuperClass(ObjCInterfaceDecl * superCls) {
+ data().SuperClass = superCls;
+ }
ObjCCategoryDecl* getCategoryList() const {
- if (ExternallyCompleted)
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return 0;
+
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
- return CategoryList;
+ return data().CategoryList;
}
void setCategoryList(ObjCCategoryDecl *category) {
- CategoryList = category;
+ data().CategoryList = category;
}
ObjCCategoryDecl* getFirstClassExtension() const;
@@ -744,6 +833,7 @@ public:
while (I != NULL) {
if (declaresSameEntity(this, I))
return true;
+
I = I->getSuperClass();
}
return false;
@@ -787,8 +877,8 @@ public:
SourceLocation getLocEnd() const { return EndLoc; }
void setLocEnd(SourceLocation LE) { EndLoc = LE; }
- void setSuperClassLoc(SourceLocation Loc) { SuperClassLoc = Loc; }
- SourceLocation getSuperClassLoc() const { return SuperClassLoc; }
+ void setSuperClassLoc(SourceLocation Loc) { data().SuperClassLoc = Loc; }
+ SourceLocation getSuperClassLoc() const { return data().SuperClassLoc; }
/// isImplicitInterfaceDecl - check that this is an implicitly declared
/// ObjCInterfaceDecl node. This is for legacy objective-c @implementation
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 5e9da51b97..e145cb74b2 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -329,14 +329,16 @@ private:
/// haven't been loaded yet.
DeclContextVisibleUpdatesPending PendingVisibleUpdates;
- typedef SmallVector<CXXRecordDecl *, 4> ForwardRefs;
- typedef llvm::DenseMap<const CXXRecordDecl *, ForwardRefs>
+ typedef SmallVector<Decl *, 4> ForwardRefs;
+ typedef llvm::DenseMap<const Decl *, ForwardRefs>
PendingForwardRefsMap;
+
/// \brief Forward references that have a definition but the definition decl
/// is still initializing. When the definition gets read it will update
/// the DefinitionData pointer of all pending references.
PendingForwardRefsMap PendingForwardRefs;
+
typedef llvm::DenseMap<serialization::DeclID, serialization::DeclID>
FirstLatestDeclIDMap;
/// \brief Map of first declarations from a chained PCH that point to the
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index e409f0a1d3..949db7972a 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -3178,7 +3178,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
}
ObjCInterfaceDecl *ToIface = MergeWithIface;
- if (!ToIface || ToIface->isForwardDecl()) {
+ if (!ToIface || !ToIface->hasDefinition()) {
if (!ToIface) {
ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
Importer.Import(D->getAtStartLoc()),
@@ -3187,88 +3187,98 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
D->isImplicitInterfaceDecl());
ToIface->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToIface);
- if (D->isInitiallyForwardDecl() && !D->isForwardDecl())
- ToIface->completedForwardDecl();
}
Importer.Imported(D, ToIface);
- if (D->getSuperClass()) {
- ObjCInterfaceDecl *Super
- = cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getSuperClass()));
- if (!Super)
- return 0;
+ if (D->hasDefinition()) {
+ if (!ToIface->hasDefinition())
+ ToIface->startDefinition();
- ToIface->setSuperClass(Super);
- ToIface->setSuperClassLoc(Importer.Import(D->getSuperClassLoc()));
- }
-
- // Import protocols
- SmallVector<ObjCProtocolDecl *, 4> Protocols;
- SmallVector<SourceLocation, 4> ProtocolLocs;
- ObjCInterfaceDecl::protocol_loc_iterator
- FromProtoLoc = D->protocol_loc_begin();
-
- // FIXME: Should we be usng all_referenced_protocol_begin() here?
- for (ObjCInterfaceDecl::protocol_iterator FromProto = D->protocol_begin(),
- FromProtoEnd = D->protocol_end();
- FromProto != FromProtoEnd;
- ++FromProto, ++FromProtoLoc) {
- ObjCProtocolDecl *ToProto
- = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
- if (!ToProto)
- return 0;
- Protocols.push_back(ToProto);
- ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
+ if (D->getSuperClass()) {
+ ObjCInterfaceDecl *Super
+ = cast_or_null<ObjCInterfaceDecl>(
+ Importer.Import(D->getSuperClass()));
+ if (!Super)
+ return 0;
+
+ ToIface->setSuperClass(Super);
+ ToIface->setSuperClassLoc(Importer.Import(D->getSuperClassLoc()));
+ }
+
+ // Import protocols
+ SmallVector<ObjCProtocolDecl *, 4> Protocols;
+ SmallVector<SourceLocation, 4> ProtocolLocs;
+ ObjCInterfaceDecl::protocol_loc_iterator
+ FromProtoLoc = D->protocol_loc_begin();
+
+ for (ObjCInterfaceDecl::protocol_iterator FromProto = D->protocol_begin(),
+ FromProtoEnd = D->protocol_end();
+ FromProto != FromProtoEnd;
+ ++FromProto, ++FromProtoLoc) {
+ ObjCProtocolDecl *ToProto
+ = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
+ if (!ToProto)
+ return 0;
+ Protocols.push_back(ToProto);
+ ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
+ }
+
+ // FIXME: If we're merging, make sure that the protocol list is the same.
+ ToIface->setProtocolList(Protocols.data(), Protocols.size(),
+ ProtocolLocs.data(), Importer.getToContext());
}
- // FIXME: If we're merging, make sure that the protocol list is the same.
- ToIface->setProtocolList(Protocols.data(), Protocols.size(),
- ProtocolLocs.data(), Importer.getToContext());
-
// Import @end range
ToIface->setAtEndRange(Importer.Import(D->getAtEndRange()));
} else {
Importer.Imported(D, ToIface);
- // Check for consistency of superclasses.
- DeclarationName FromSuperName, ToSuperName;
-
- // If the superclass hasn't been imported yet, do so before checking.
- ObjCInterfaceDecl *DSuperClass = D->getSuperClass();
- ObjCInterfaceDecl *ToIfaceSuperClass = ToIface->getSuperClass();
-
- if (DSuperClass && !ToIfaceSuperClass) {
- Decl *ImportedSuperClass = Importer.Import(DSuperClass);
- ObjCInterfaceDecl *ImportedSuperIface = cast<ObjCInterfaceDecl>(ImportedSuperClass);
- ToIface->setSuperClass(ImportedSuperIface);
- }
+ if (D->hasDefinition()) {
+ // Check for consistency of superclasses.
+ DeclarationName FromSuperName, ToSuperName;
+
+ // If the superclass hasn't been imported yet, do so before checking.
+ ObjCInterfaceDecl *DSuperClass = D->getSuperClass();
+ ObjCInterfaceDecl *ToIfaceSuperClass = ToIface->getSuperClass();
+
+ if (DSuperClass && !ToIfaceSuperClass) {
+ Decl *ImportedSuperClass = Importer.Import(DSuperClass);
+ ObjCInterfaceDecl *ImportedSuperIface
+ = cast<ObjCInterfaceDecl>(ImportedSuperClass);
+
+ ToIface->setSuperClass(ImportedSuperIface);
+ }
- if (D->getSuperClass())
- FromSuperName = Importer.Import(D->getSuperClass()->getDeclName());
- if (ToIface->getSuperClass())
- ToSuperName = ToIface->getSuperClass()->getDeclName();
- if (FromSuperName != ToSuperName) {
- Importer.ToDiag(ToIface->getLocation(),
- diag::err_odr_objc_superclass_inconsistent)
- << ToIface->getDeclName();
+ if (D->getSuperClass())
+ FromSuperName = Importer.Import(D->getSuperClass()->getDeclName());
if (ToIface->getSuperClass())
- Importer.ToDiag(ToIface->getSuperClassLoc(),
- diag::note_odr_objc_superclass)
- << ToIface->getSuperClass()->getDeclName();
- else
+ ToSuperName = ToIface->getSuperClass()->getDeclName();
+ if (FromSuperName != ToSuperName) {
Importer.ToDiag(ToIface->getLocation(),
- diag::note_odr_objc_missing_superclass);
- if (D->getSuperClass())
- Importer.FromDiag(D->getSuperClassLoc(),
+ diag::err_odr_objc_superclass_inconsistent)
+ << ToIface->getDeclName();
+ if (ToIface->getSuperClass())
+ Importer.ToDiag(ToIface->getSuperClassLoc(),
diag::note_odr_objc_superclass)
- << D->getSuperClass()->getDeclName();
- else
- Importer.FromDiag(D->getLocation(),
+ << ToIface->getSuperClass()->getDeclName();
+ else
+ Importer.ToDiag(ToIface->getLocation(),
diag::note_odr_objc_missing_superclass);
- return 0;
+ if (D->getSuperClass())
+ Importer.FromDiag(D->getSuperClassLoc(),
+ diag::note_odr_objc_superclass)
+ << D->getSuperClass()->getDeclName();
+ else
+ Importer.FromDiag(D->getLocation(),
+ diag::note_odr_objc_missing_superclass);
+ return 0;
+ }
}
}
+ if (!D->hasDefinition())
+ return ToIface;
+
// Import categories. When the categories themselves are imported, they'll
// hook themselves into this interface.
for (ObjCCategoryDecl *FromCat = D->getCategoryList(); FromCat;
@@ -3279,7 +3289,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
ImportDeclContext(D);
// If we have an @implementation, import it as well.
- if (D->getImplementation()) {
+ if ( D->getImplementation()) {
ObjCImplementationDecl *Impl = cast_or_null<ObjCImplementationDecl>(
Importer.Import(D->getImplementation()));
if (!Impl)
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index 38efadf3b5..decbd54c6d 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -154,7 +154,11 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
ObjCPropertyDecl *
ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
IdentifierInfo *PropertyId) const {
- if (ExternallyCompleted)
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return 0;
+
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
if (ObjCPropertyDecl *PD =
@@ -175,11 +179,12 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
ASTContext &C)
{
- if (ExternallyCompleted)
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
- if (AllReferencedProtocols.empty() && ReferencedProtocols.empty()) {
- AllReferencedProtocols.set(ExtList, ExtNum, C);
+ if (data().AllReferencedProtocols.empty() &&
+ data().ReferencedProtocols.empty()) {
+ data().AllReferencedProtocols.set(ExtList, ExtNum, C);
return;
}
@@ -214,12 +219,16 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
ProtocolRefs.push_back(*p);
}
- AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(), C);
+ data().AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(),C);
}
-void ObjCInterfaceDecl::completedForwardDecl() {
- assert(isForwardDecl() && "Only valid to call for forward refs");
- ForwardDecl = false;
+void ObjCInterfaceDecl::allocateDefinitionData() {
+ assert(!hasDefinition() && "ObjC class already has a definition");
+ Definition = new (getASTContext()) DefinitionData();
+}
+
+void ObjCInterfaceDecl::startDefinition() {
+ allocateDefinitionData();
if (ASTMutationListener *L = getASTContext().getASTMutationListener())
L->CompletedObjCForwardRef(this);
}
@@ -244,7 +253,11 @@ const ObjCCategoryDecl* ObjCCategoryDecl::getNextClassExtension() const {
ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
ObjCInterfaceDecl *&clsDeclared) {
- if (ExternallyCompleted)
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return 0;
+
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
ObjCInterfaceDecl* ClassDecl = this;
@@ -271,7 +284,11 @@ ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
/// the it returns NULL.
ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass(
const IdentifierInfo*ICName) {
- if (ExternallyCompleted)
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return 0;
+
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
ObjCInterfaceDecl* ClassDecl = this;
@@ -287,10 +304,14 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass(
/// the class, its categories, and its super classes (using a linear search).
ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
bool isInstance) const {
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return 0;
+
const ObjCInterfaceDecl* ClassDecl = this;
ObjCMethodDecl *MethodDecl = 0;
- if (ExternallyCompleted)
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
while (ClassDecl != NULL) {
@@ -328,7 +349,11 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod(
const Selector &Sel,
bool Instance) {
- if (ExternallyCompleted)
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return 0;
+
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
ObjCMethodDecl *Method = 0;
@@ -651,16 +676,14 @@ ObjCInterfaceDecl::
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
SourceLocation CLoc, bool FD, bool isInternal)
: ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, atLoc),
- TypeForDecl(0), SuperClass(0),
- CategoryList(0), IvarList(0),
- InitiallyForwardDecl(FD), ForwardDecl(FD),
- ExternallyCompleted(false) {
+ TypeForDecl(0), Definition(), InitiallyForwardDecl(FD)
+{
setImplicit(isInternal);
}
void ObjCInterfaceDecl::LoadExternalDefinition() const {
- assert(ExternallyCompleted && "Class is not externally completed");
- ExternallyCompleted = false;
+ assert(data().ExternallyCompleted && "Class is not externally completed");
+ data().ExternallyCompleted = false;
getASTContext().getExternalSource()->CompleteType(
const_cast<ObjCInterfaceDecl *>(this));
}
@@ -668,13 +691,17 @@ void ObjCInterfaceDecl::LoadExternalDefinition() const {
void ObjCInterfaceDecl::setExternallyCompleted() {
assert(getASTContext().getExternalSource() &&
"Class can't be externally completed without an external source");
- assert(!ForwardDecl &&
+ assert(hasDefinition() &&
"Forward declarations can't be externally completed");
- ExternallyCompleted = true;
+ data().ExternallyCompleted = true;
}
ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
- if (ExternallyCompleted)
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return 0;
+
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
return getASTContext().getObjCImplementation(
@@ -689,14 +716,18 @@ void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
/// its extensions and its implementation. Lazily build the list on first
/// access.
ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
- if (IvarList)
- return IvarList;
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return 0;
+
+ if (data().IvarList)
+ return data().IvarList;
ObjCIvarDecl *curIvar = 0;
if (!ivar_empty()) {
ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end();
- IvarList = (*I); ++I;
- for (curIvar = IvarList; I != E; curIvar = *I, ++I)
+ data().IvarList = (*I); ++I;
+ for (curIvar = data().IvarList; I != E; curIvar = *I, ++I)
curIvar->setNextIvar(*I);
}
@@ -705,9 +736,9 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
if (!CDecl->ivar_empty()) {
ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(),
E = CDecl->ivar_end();
- if (!IvarList) {
- IvarList = (*I); ++I;
- curIvar = IvarList;
+ if (!data().IvarList) {
+ data().IvarList = (*I); ++I;
+ curIvar = data().IvarList;
}
for ( ;I != E; curIvar = *I, ++I)
curIvar->setNextIvar(*I);
@@ -718,15 +749,15 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
if (!ImplDecl->ivar_empty()) {
ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
E = ImplDecl->ivar_end();
- if (!IvarList) {
- IvarList = (*I); ++I;
- curIvar = IvarList;
+ if (!data().IvarList) {
+ data().IvarList = (*I); ++I;
+ curIvar = data().IvarList;
}
for ( ;I != E; curIvar = *I, ++I)
curIvar->setNextIvar(*I);
}
}
- return IvarList;
+ return data().IvarList;
}
/// FindCategoryDeclaration - Finds category declaration in the list of
@@ -735,7 +766,7 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
///
ObjCCategoryDecl *
ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const {
- if (ExternallyCompleted)
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
for (ObjCCategoryDecl *Category = getCategoryList();
@@ -770,6 +801,9 @@ ObjCMethodDecl *ObjCInterfaceDecl::getCategoryClassMethod(Selector Sel) const {
bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
bool lookupCategory,
bool RHSIsQualifiedID) {
+ if (!hasDefinition())
+ return false;
+
ObjCInterfaceDecl *IDecl = this;
// 1st, look up the class.
const ObjCList<ObjCProtocolDecl> &Protocols =
@@ -997,9 +1031,11 @@ ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC,
if (IDecl) {
// Link this category into its class's category list.
CatDecl->NextClassCategory = IDecl->getCategoryList();
- IDecl->setCategoryList(CatDecl);
- if (ASTMutationListener *L = C.getASTMutationListener())
- L->AddedObjCCategoryToInterface(CatDecl, IDecl);
+ if (IDecl->hasDefinition()) {
+ IDecl->setCategoryList(CatDecl);
+ if (ASTMutationListener *L = C.getASTMutationListener())
+ L->AddedObjCCategoryToInterface(CatDecl, IDecl);
+ }
}
return CatDecl;
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 91b011fbda..ec7d6de71a 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -905,6 +905,11 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
else
Out << "@interface " << I;
+ if (OID->isForwardDecl()) {
+ Out << "@end";
+ return;
+ }
+
// Protocols?
const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
if (!Protocols.empty()) {
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 3d2d0930d8..7e7e87a065 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -4558,7 +4558,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
}
ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
- if (!IFace)
+ if (!IFace || !IFace->hasDefinition())
return;
// Add methods in protocols.
@@ -5783,6 +5783,9 @@ static void FindImplementableMethods(ASTContext &Context,
bool InOriginalClass = true) {
if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
// Recurse into protocols.
+ if (!IFace->hasDefinition())
+ return;
+
const ObjCList<ObjCProtocolDecl> &Protocols
= IFace->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index b70c982955..6947d7e211 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -368,10 +368,10 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
ObjCInterfaceDecl* IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
if (IDecl) {
// Class already seen. Is it a forward declaration?
- if (!IDecl->isForwardDecl()) {
+ if (ObjCInterfaceDecl *Def = IDecl->getDefinition()) {
IDecl->setInvalidDecl();
Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<<IDecl->getDeclName();
- Diag(IDecl->getLocation(), diag::note_previous_definition);
+ Diag(Def->getLocation(), diag::note_previous_definition);
// Create a new one; the other may be in a different DeclContex, (e.g.
// this one may be in a LinkageSpecDecl while the other is not) which
@@ -392,8 +392,6 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
IDecl->setLexicalDeclContext(CurContext);
CurContext->addDecl(IDecl);
- IDecl->completedForwardDecl();
-
if (AttrList)
ProcessDeclAttributeList(TUScope, IDecl, AttrList);
}
@@ -406,6 +404,9 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
PushOnScopeChains(IDecl, TUScope);
}
+ if (!IDecl->hasDefinition())
+ IDecl->startDefinition();
+
if (SuperName) {
// Check if a different kind of symbol declared in this scope.
PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc,
@@ -942,6 +943,7 @@ Decl *Sema::ActOnStartClassImplementation(
// copy them over.
IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc,
ClassName, ClassLoc, false, true);
+ IDecl->startDefinition();
IDecl->setSuperClass(SDecl);
IDecl->setLocEnd(ClassLoc);
@@ -950,8 +952,8 @@ Decl *Sema::ActOnStartClassImplementation(
// Mark the interface as being completed, even if it was just as
// @class ....;
// declaration; the user cannot reopen it.
- if (IDecl->isForwardDecl())
- IDecl->completedForwardDecl();
+ if (!IDecl->hasDefinition())
+ IDecl->startDefinition();
}
ObjCImplementationDecl* IMPDecl =
@@ -2540,7 +2542,9 @@ private:
void searchFrom(ObjCInterfaceDecl *iface) {
// A method in a class declaration overrides declarations from
-
+ if (!iface->hasDefinition())
+ return;
+
// - categories,
for (ObjCCategoryDecl *category = iface->getCategoryList();
category; category = category->getNextClassCategory())
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index fbae96071e..20c3b75431 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -512,6 +512,9 @@ ObjCMethodDecl *Sema::LookupPrivateClassMethod(Selector Sel,
ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel,