aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ASTConsumer.h5
-rw-r--r--include/clang/AST/ASTContext.h5
-rw-r--r--include/clang/AST/DeclObjC.h47
-rw-r--r--include/clang/AST/Type.h2
-rw-r--r--lib/AST/ASTConsumer.cpp3
-rw-r--r--lib/AST/ASTContext.cpp30
-rw-r--r--lib/AST/ASTImporter.cpp14
-rw-r--r--lib/AST/DeclObjC.cpp26
-rw-r--r--lib/AST/DeclPrinter.cpp13
-rw-r--r--lib/AST/Type.cpp11
-rw-r--r--lib/Frontend/ASTUnit.cpp3
-rw-r--r--lib/Frontend/PCHReader.cpp4
-rw-r--r--lib/Frontend/PCHReaderDecl.cpp22
-rw-r--r--lib/Frontend/PCHWriter.cpp4
-rw-r--r--lib/Frontend/PCHWriterDecl.cpp5
-rw-r--r--lib/Sema/Sema.cpp2
-rw-r--r--lib/Sema/SemaCodeComplete.cpp26
-rw-r--r--lib/Sema/SemaDecl.cpp39
-rw-r--r--lib/Sema/SemaDeclObjC.cpp159
-rw-r--r--test/Index/TestClassDecl.m2
20 files changed, 274 insertions, 148 deletions
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h
index b01f6c6001..3f964ad0e9 100644
--- a/include/clang/AST/ASTConsumer.h
+++ b/include/clang/AST/ASTConsumer.h
@@ -49,6 +49,11 @@ public:
/// elements). Use Decl::getNextDeclarator() to walk the chain.
virtual void HandleTopLevelDecl(DeclGroupRef D);
+ /// HandleInterestingDecl - Handle the specified interesting declaration. This
+ /// is called by the PCH reader when deserializing things that might interest
+ /// the consumer. The default implementation forwards to HandleTopLevelDecl.
+ virtual void HandleInterestingDecl(DeclGroupRef D);
+
/// HandleTranslationUnit - This method is called when the ASTs for entire
/// translation unit have been parsed.
virtual void HandleTranslationUnit(ASTContext &Ctx) {}
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index aa1985a888..31686d89c2 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -668,7 +668,10 @@ public:
unsigned NumArgs,
const TemplateArgument *Args);
- QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl);
+ /// getObjCInterfaceType - Return the unique reference to the type for the
+ /// specified ObjC interface decl.
+ QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
+ const ObjCInterfaceDecl *PrevDecl = 0);
QualType getObjCObjectType(QualType Base,
ObjCProtocolDecl * const *Protocols,
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 8484216521..1fe1cf7cb4 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -450,7 +450,10 @@ public:
/// Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes
/// typically inherit from NSObject (an exception is NSProxy).
///
-class ObjCInterfaceDecl : public ObjCContainerDecl {
+class ObjCInterfaceDecl : public ObjCContainerDecl,
+ public Redeclarable<ObjCInterfaceDecl> {
+ typedef Redeclarable<ObjCInterfaceDecl> redeclarable_base;
+
/// TypeForDecl - This indicates the Type object that represents this
/// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType
mutable Type *TypeForDecl;
@@ -474,15 +477,52 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
SourceLocation EndLoc; // marks the '>', '}', or identifier.
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
- SourceLocation CLoc, bool FD, bool isInternal);
+ SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl,
+ bool FD, bool isInternal);
+
+protected:
+ virtual ObjCInterfaceDecl *getNextRedeclaration() {
+ return RedeclLink.getNext();
+ }
public:
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ redecl_iterator redecls_begin() const {
+ return redeclarable_base::redecls_begin();
+ }
+ redecl_iterator redecls_end() const {
+ return redeclarable_base::redecls_end();
+ }
+
static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation atLoc,
IdentifierInfo *Id,
- SourceLocation ClassLoc = SourceLocation(),
+ SourceLocation ClassLoc,
+ ObjCInterfaceDecl *PrevDecl,
bool ForwardDecl = false,
bool isInternal = false);
+
+ static ObjCInterfaceDecl *Create(ASTContext &C, EmptyShell Empty);
+
+ void setPreviousDeclaration(ObjCInterfaceDecl *Prev) {
+ // Adopt a type pointer if it exists.
+ TypeForDecl = Prev->TypeForDecl;
+ redeclarable_base::setPreviousDeclaration(Prev);
+ }
+
+ virtual ObjCInterfaceDecl *getCanonicalDecl() {
+ return getFirstDeclaration();
+ }
+ const ObjCInterfaceDecl *getCanonicalDecl() const {
+ return const_cast<ObjCInterfaceDecl*>(this)->getCanonicalDecl();
+ }
+
+ /// Get the interface declaration that is a definition, if there is one.
+ ObjCInterfaceDecl *getDefinition();
+ const ObjCInterfaceDecl *getDefinition() const {
+ return const_cast<ObjCInterfaceDecl*>(this)->getDefinition();
+ }
+
const ObjCProtocolList &getReferencedProtocols() const {
return ReferencedProtocols;
}
@@ -535,6 +575,7 @@ public:
ASTContext &C);
bool isForwardDecl() const { return ForwardDecl; }
+ bool isDefinition() const { return !ForwardDecl; }
void setForwardDecl(bool val) { ForwardDecl = val; }
ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 7a522f42fa..6c4ad893b4 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -3038,7 +3038,7 @@ class ObjCInterfaceType : public ObjCObjectType {
friend class ASTContext; // ASTContext creates these.
public:
/// getDecl - Get the declaration of this interface.
- ObjCInterfaceDecl *getDecl() const { return Decl; }
+ ObjCInterfaceDecl *getDecl() const;
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
diff --git a/lib/AST/ASTConsumer.cpp b/lib/AST/ASTConsumer.cpp
index f37cbdea54..04a084a06a 100644
--- a/lib/AST/ASTConsumer.cpp
+++ b/lib/AST/ASTConsumer.cpp
@@ -17,3 +17,6 @@ using namespace clang;
void ASTConsumer::HandleTopLevelDecl(DeclGroupRef D) {}
+void ASTConsumer::HandleInterestingDecl(DeclGroupRef D) {
+ HandleTopLevelDecl(D);
+}
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 7d159269c1..83cee5cc78 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -872,7 +872,7 @@ void ASTContext::ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
/// CollectNonClassIvars -
/// This routine collects all other ivars which are not declared in the class.
/// This includes synthesized ivars (via @synthesize) and those in
-// class's @implementation.
+/// class's @implementation.
///
void ASTContext::CollectNonClassIvars(const ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
@@ -2212,18 +2212,24 @@ QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) {
return QualType(QType, 0);
}
-/// getObjCInterfaceType - Return the unique reference to the type for the
-/// specified ObjC interface decl. The list of protocols is optional.
-QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl) {
- if (Decl->TypeForDecl)
- return QualType(Decl->TypeForDecl, 0);
+QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
+ const ObjCInterfaceDecl *PrevDecl) {
+ assert(Decl && "Passed null for Decl param");
- // FIXME: redeclarations?
- void *Mem = Allocate(sizeof(ObjCInterfaceType), TypeAlignment);
- ObjCInterfaceType *T = new (Mem) ObjCInterfaceType(Decl);
- Decl->TypeForDecl = T;
- Types.push_back(T);
- return QualType(T, 0);
+ if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
+
+ if (PrevDecl) {
+ assert(PrevDecl->TypeForDecl && "previous decl has no TypeForDecl");
+ Decl->TypeForDecl = PrevDecl->TypeForDecl;
+ return QualType(PrevDecl->TypeForDecl, 0);
+ }
+
+ assert(!Decl->getPreviousDeclaration() &&
+ "interface has previous declaration");
+
+ Decl->TypeForDecl = new (*this, TypeAlignment) ObjCInterfaceType(Decl);
+ Types.push_back(Decl->TypeForDecl);
+ return QualType(Decl->TypeForDecl, 0);
}
/// getTypeOfExprType - Unlike many "get<Type>" functions, we can't unique
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 5e8586f2a0..6242d40041 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -2467,6 +2467,18 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
}
Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
+ // If this interface has a definition in the translation unit we're coming
+ // from, but this particular declaration is not that definition, import the
+ // definition and map to that.
+ ObjCInterfaceDecl *Definition = D->getDefinition();
+ if (Definition && Definition != D) {
+ Decl *ImportedDef = Importer.Import(Definition);
+ if (!ImportedDef)
+ return 0;
+
+ return Importer.Imported(D, ImportedDef);
+ }
+
// Import the major distinguishing characteristics of an @interface.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
@@ -2491,7 +2503,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(),
DC, Loc,
Name.getAsIdentifierInfo(),
- Importer.Import(D->getClassLoc()),
+ Importer.Import(D->getClassLoc()), 0,
D->isForwardDecl(),
D->isImplicitInterfaceDecl());
ToIface->setForwardDecl(D->isForwardDecl());
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index 32f9433d9a..0720b203d6 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -45,6 +45,14 @@ void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts,
// ObjCInterfaceDecl
//===----------------------------------------------------------------------===//
+ObjCInterfaceDecl *ObjCInterfaceDecl::getDefinition() {
+ for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
+ if (I->isDefinition())
+ return *I;
+ }
+ return 0;
+}
+
/// getIvarDecl - This method looks up an ivar in this ContextDecl.
///
ObjCIvarDecl *
@@ -432,18 +440,30 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(ASTContext &C,
SourceLocation atLoc,
IdentifierInfo *Id,
SourceLocation ClassLoc,
+ ObjCInterfaceDecl *PrevDecl,
bool ForwardDecl, bool isInternal){
- return new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, ForwardDecl,
- isInternal);
+ ObjCInterfaceDecl *D = new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc,
+ PrevDecl, ForwardDecl,
+ isInternal);
+ C.getObjCInterfaceType(D, PrevDecl);
+ return D;
+}
+
+ObjCInterfaceDecl *ObjCInterfaceDecl::Create(ASTContext &C, EmptyShell) {
+ return new (C) ObjCInterfaceDecl(0, SourceLocation(), 0, SourceLocation(),
+ 0, false, false);
}
ObjCInterfaceDecl::
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
- SourceLocation CLoc, bool FD, bool isInternal)
+ SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl,
+ bool FD, bool isInternal)
: ObjCContainerDecl(ObjCInterface, DC, atLoc, Id),
TypeForDecl(0), SuperClass(0),
CategoryList(0), ForwardDecl(FD), InternalInterface(isInternal),
ClassLoc(CLoc) {
+ if (PrevDecl)
+ setPreviousDeclaration(PrevDecl);
}
ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index fae1e724a1..d3ebc8f508 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -727,12 +727,19 @@ void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) {
void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
std::string I = OID->getNameAsString();
+
+ if (OID->isForwardDecl()) {
+ // These shouldn't be directly visited, but in case they are, write them
+ // as an @class declaration.
+ Out << "@class " << I;
+ return;
+ }
+
ObjCInterfaceDecl *SID = OID->getSuperClass();
+ Out << "@interface " << I;
if (SID)
- Out << "@interface " << I << " : " << SID;
- else
- Out << "@interface " << I;
+ Out << " : " << SID;
// Protocols?
const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 31af6fb661..4f884989ae 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -360,6 +360,17 @@ const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const {
return 0;
}
+ObjCInterfaceDecl *ObjCInterfaceType::getDecl() const {
+ for (ObjCInterfaceDecl::redecl_iterator I = Decl->redecls_begin(),
+ E = Decl->redecls_end();
+ I != E; ++I) {
+ if (I->isDefinition())
+ return *I;
+ }
+ // If we can't find a definition, return whatever we have.
+ return Decl;
+}
+
const CXXRecordDecl *Type::getCXXRecordDeclForPointerType() const {
if (const PointerType *PT = getAs<PointerType>())
if (const RecordType *RT = PT->getPointeeType()->getAs<RecordType>())
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index b287522806..cd78abdaeb 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -320,6 +320,9 @@ public:
Unit.addTopLevelDecl(D);
}
}
+
+ // We're not interested in "interesting" decls.
+ void HandleInterestingDecl(DeclGroupRef) {}
};
class TopLevelDeclTrackerAction : public ASTFrontendAction {
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 1bfc138d4f..68acbb2faf 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -2262,7 +2262,7 @@ QualType PCHReader::ReadTypeRecord(unsigned Index) {
SavedStreamPosition SavedPosition(DeclsCursor);
ReadingKindTracker ReadingKind(Read_Type, *this);
-
+
// Note that we are loading a type record.
Deserializing AType(this);
@@ -3027,7 +3027,7 @@ void PCHReader::PassInterestingDeclsToConsumer() {
while (!InterestingDecls.empty()) {
DeclGroupRef DG(InterestingDecls.front());
InterestingDecls.pop_front();
- Consumer->HandleTopLevelDecl(DG);
+ Consumer->HandleInterestingDecl(DG);
}
}
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index 7aab7b7557..2930ca73b9 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -34,7 +34,7 @@ namespace clang {
const pch::DeclID ThisDeclID;
const PCHReader::RecordData &Record;
unsigned &Idx;
- pch::TypeID TypeIDForTypeDecl;
+ pch::TypeID TypeIDForDecl;
uint64_t GetCurrentCursorOffset();
@@ -43,7 +43,7 @@ namespace clang {
pch::DeclID thisDeclID, const PCHReader::RecordData &Record,
unsigned &Idx)
: Reader(Reader), Cursor(Cursor), ThisDeclID(thisDeclID), Record(Record),
- Idx(Idx), TypeIDForTypeDecl(0) { }
+ Idx(Idx), TypeIDForDecl(0) { }
void Visit(Decl *D);
@@ -132,9 +132,11 @@ uint64_t PCHDeclReader::GetCurrentCursorOffset() {
void PCHDeclReader::Visit(Decl *D) {
DeclVisitor<PCHDeclReader, void>::Visit(D);
+ // if we have a fully initialized Decl, we can safely read its type now.
if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
- // if we have a fully initialized TypeDecl, we can safely read its type now.
- TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtr());
+ TD->setTypeForDecl(Reader.GetType(TypeIDForDecl).getTypePtr());
+ } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
+ ID->setTypeForDecl(Reader.GetType(TypeIDForDecl).getTypePtr());
} else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
// FunctionDecl's body was written last after all other Stmts/Exprs.
if (Record[Idx++])
@@ -170,7 +172,7 @@ void PCHDeclReader::VisitNamedDecl(NamedDecl *ND) {
void PCHDeclReader::VisitTypeDecl(TypeDecl *TD) {
VisitNamedDecl(TD);
// Delay type reading until after we have fully initialized the decl.
- TypeIDForTypeDecl = Record[Idx++];
+ TypeIDForDecl = Record[Idx++];
}
void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
@@ -367,7 +369,11 @@ void PCHDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) {
void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
VisitObjCContainerDecl(ID);
- ID->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr());
+ ID->setForwardDecl(Record[Idx++]);
+ ID->setImplicitInterfaceDecl(Record[Idx++]);
+ VisitRedeclarable(ID);
+ // Must delay type reading until the redecl chain is complete.
+ TypeIDForDecl = Record[Idx++];
ID->setSuperClass(cast_or_null<ObjCInterfaceDecl>
(Reader.GetDecl(Record[Idx++])));
unsigned NumProtocols = Record[Idx++];
@@ -388,8 +394,6 @@ void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
IVars.push_back(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
ID->setCategoryList(
cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++])));
- ID->setForwardDecl(Record[Idx++]);
- ID->setImplicitInterfaceDecl(Record[Idx++]);
ID->setClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
ID->setSuperClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
ID->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
@@ -1459,7 +1463,7 @@ Decl *PCHReader::ReadDeclRecord(unsigned Index, pch::DeclID ID) {
Selector(), QualType(), 0, 0);
break;
case pch::DECL_OBJC_INTERFACE:
- D = ObjCInterfaceDecl::Create(*Context, 0, SourceLocation(), 0);
+ D = ObjCInterfaceDecl::Create(*Context, Decl::EmptyShell());
break;
case pch::DECL_OBJC_IVAR:
D = ObjCIvarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 0eed4ccd71..990641294a 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -305,7 +305,9 @@ void PCHTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) {
}
void PCHTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
- Writer.AddDeclRef(T->getDecl(), Record);
+ // The stored declaration must be the first, but getDecl() returns the
+ // definition.
+ Writer.AddDeclRef(T->getDecl()->getFirstDeclaration(), Record);
Code = pch::TYPE_OBJC_INTERFACE;
}
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index a509ed1dce..9917ad6419 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -340,6 +340,9 @@ void PCHDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
VisitObjCContainerDecl(D);
+ Record.push_back(D->isForwardDecl());
+ Record.push_back(D->isImplicitInterfaceDecl());
+ VisitRedeclarable(D);
Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
Writer.AddDeclRef(D->getSuperClass(), Record);
Record.push_back(D->protocol_size());
@@ -356,8 +359,6 @@ void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
IEnd = D->ivar_end(); I != IEnd; ++I)
Writer.AddDeclRef(*I, Record);
Writer.AddDeclRef(D->getCategoryList(), Record);
- Record.push_back(D->isForwardDecl());
- Record.push_back(D->isImplicitInterfaceDecl());
Writer.AddSourceLocation(D->getClassLoc(), Record);
Writer.AddSourceLocation(D->getSuperClassLoc(), Record);
Writer.AddSourceLocation(D->getLocEnd(), Record);
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index aeb4db987d..11d7a9191f 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -89,7 +89,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
ObjCInterfaceDecl *ProtocolDecl =
ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(),
&Context.Idents.get("Protocol"),
- SourceLocation(), true);
+ SourceLocation(), 0, true);
Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
PushOnScopeChains(ProtocolDecl, TUScope, false);
}
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 52ac8dd649..f12e1839e5 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -3748,20 +3748,28 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
for (DeclContext::decl_iterator D = Ctx->decls_begin(),
DEnd = Ctx->decls_end();
D != DEnd; ++D) {
- // Record any interfaces we find.
- if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
- if ((!OnlyForwardDeclarations || Class->isForwardDecl()) &&
- (!OnlyUnimplemented || !Class->getImplementation()))
- Results.AddResult(Result(Class, 0), CurContext, 0, false);
+ // Record any interfaces we find. Forward declarations are never registered
+ // in the lexical contest, so if we're only looking for those, don't bother.
+ if (!OnlyForwardDeclarations)
+ if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
+ if (!OnlyUnimplemented || !Class->getImplementation())
+ Results.AddResult(Result(Class, 0), CurContext, 0, false);
// Record any forward-declared interfaces we find.
if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) {
for (ObjCClassDecl::iterator C = Forward->begin(), CEnd = Forward->end();
- C != CEnd; ++C)
- if ((!OnlyForwardDeclarations || C->getInterface()->isForwardDecl()) &&
- (!OnlyUnimplemented || !C->getInterface()->getImplementation()))
- Results.AddResult(Result(C->getInterface(), 0), CurContext,
+ C != CEnd; ++C) {
+ ObjCInterfaceDecl *IDecl = C->getInterface();
+ ObjCInterfaceDecl *IDef = IDecl->getDefinition();
+ // If there's a definition, and we're looking for everything, then we
+ // already added the decl in question above.
+ if (!OnlyForwardDeclarations && !OnlyUnimplemented && IDef)
+ continue;
+ if ((!OnlyForwardDeclarations || !IDef) &&
+ (!OnlyUnimplemented || !IDef || !IDef->getImplementation()))
+ Results.AddResult(Result(IDecl, 0), CurContext,
0, false);
+ }
}
}
}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 200b8fd681..e6c5170357 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -606,45 +606,6 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
}
}
-/// \brief Look for an Objective-C class in the translation unit.
-///
-/// \param Id The name of the Objective-C class we're looking for. If
-/// typo-correction fixes this name, the Id will be updated
-/// to the fixed name.
-///
-/// \param IdLoc The location of the name in the translation unit.
-///
-/// \param TypoCorrection If true, this routine will attempt typo correction
-/// if there is no class with the given name.
-///
-/// \returns The declaration of the named Objective-C class, or NULL if the
-/// class could not be found.
-ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id,
- SourceLocation IdLoc,
- bool TypoCorrection) {
- // The third "scope" argument is 0 since we aren't enabling lazy built-in
- // creation from this context.
- NamedDecl *IDecl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName);
-
- if (!IDecl && TypoCorrection) {
- // Perform typo correction at the given location, but only if we
- // find an Objective-C class name.
- LookupResult R(*this, Id, IdLoc, LookupOrdinaryName);
- if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) &&
- (IDecl = R.getAsSingle<ObjCInterfaceDecl>())) {
- Diag(IdLoc, diag::err_undef_interface_suggest)
- << Id << IDecl->getDeclName()
- << FixItHint::CreateReplacement(IdLoc, IDecl->getNameAsString());
- Diag(IDecl->getLocation(), diag::note_previous_decl)
- << IDecl->getDeclName();
-
- Id = IDecl->getIdentifier();
- }
- }
-
- return dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);
-}
-
/// getNonFieldDeclScope - Retrieves the innermost scope, starting
/// from S, where a non-field would be declared. This routine copes
/// with the difference between C and C++ scoping rules in structs and
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 9e0d250536..283376bfde 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -20,6 +20,50 @@
#include "clang/Parse/DeclSpec.h"
using namespace clang;
+/// \brief Look for an Objective-C class in the translation unit.
+///
+/// \param Id The name of the Objective-C class we're looking for. If
+/// typo-correction fixes this name, the Id will be updated
+/// to the fixed name.
+///
+/// \param IdLoc The location of the name in the translation unit.
+///
+/// \param TypoCorrection If true, this routine will attempt typo correction
+/// if there is no class with the given name.
+///
+/// \returns The declaration of the named Objective-C class, which is also the
+/// definition if one is available, or NULL if the class could not be found.
+ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id,
+ SourceLocation IdLoc,
+ bool TypoCorrection) {
+ // The third "scope" argument is 0 since we aren't enabling lazy built-in
+ // creation from this context.
+ NamedDecl *Decl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName);
+
+ if (!Decl && TypoCorrection) {
+ // Perform typo correction at the given location, but only if we
+ // find an Objective-C class name.
+ LookupResult R(*this, Id, IdLoc, LookupOrdinaryName);
+ if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) &&
+ (Decl = R.getAsSingle<ObjCInterfaceDecl>())) {
+ Diag(IdLoc, diag::err_undef_interface_suggest)
+ << Id << Decl->getDeclName()
+ << FixItHint::CreateReplacement(IdLoc, Decl->getNameAsString());
+ Diag(Decl->getLocation(), diag::note_previous_decl)
+ << Decl->getDeclName();
+
+ Id = Decl->getIdentifier();
+ }
+ }
+
+ ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(Decl);
+ if (IDecl) {
+ if (ObjCInterfaceDecl *Def = IDecl->getDefinition())
+ IDecl = Def;
+ }
+ return IDecl;
+}
+
/// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible
/// and user declared, in the method definition's AST.
void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) {
@@ -65,6 +109,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
SourceLocation EndProtoLoc, AttributeList *AttrList) {
assert(ClassName && "Missing class identifier");
+ bool Invalid = false;
+
// Check for another declaration kind with the same name.
NamedDecl *PrevDecl = LookupSingleName(TUScope, ClassName, ClassLoc,
LookupOrdinaryName, ForRedeclaration);
@@ -72,42 +118,35 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ // Set the new decl invalid and ignore the old.
+ Invalid = true;
+ PrevDecl = 0;
}
- ObjCInterfaceDecl* IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
- if (IDecl) {
+ ObjCInterfaceDecl *ODecl = cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+ if (ODecl) {
// Class already seen. Is it a forward declaration?
- if (!IDecl->isForwardDecl()) {
- IDecl->setInvalidDecl();
- Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<<IDecl->getDeclName();
- Diag(IDecl->getLocation(), diag::note_previous_definition);
+ if (ObjCInterfaceDecl *Def = ODecl->getDefinition()) {
+ Invalid = true;
+ Diag(AtInterfaceLoc, diag::err_duplicate_class_def) << Def->getDeclName();
+ Diag(Def->getLocation(), diag::note_previous_definition);
- // Return the previous class interface.
- // FIXME: don't leak the objects passed in!
- return DeclPtrTy::make(IDecl);
- } else {
- IDecl->setLocation(AtInterfaceLoc);
- IDecl->setForwardDecl(false);
- IDecl->setClassLoc(ClassLoc);
-
- // Since this ObjCInterfaceDecl was created by a forward declaration,
- // we now add it to the DeclContext since it wasn't added before
- // (see ActOnForwardClassDeclaration).
- IDecl->setLexicalDeclContext(CurContext);
- CurContext->addDecl(IDecl);
-
- if (AttrList)
- ProcessDeclAttributeList(TUScope, IDecl, AttrList);
+ // Return the previous class interface and ignore the new one.
+ return DeclPtrTy::make(ODecl);
}
- } else {
- IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc,
- ClassName, ClassLoc);
- if (AttrList)
- ProcessDeclAttributeList(TUScope, IDecl, AttrList);
-
- PushOnScopeChains(IDecl, TUScope);
}
+ ObjCInterfaceDecl *IDecl =
+ ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc,
+ ClassName, ClassLoc, ODecl);
+ if (Invalid)
+ IDecl->setInvalidDecl();
+
+ if (AttrList)
+ ProcessDeclAttributeList(TUScope, IDecl, AttrList);
+
+ PushOnScopeChains(IDecl, TUScope);
+
if (SuperName) {
// Check if a different kind of symbol declared in this scope.
PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc,
@@ -125,6 +164,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
}
}
+ // Since we just pushed IDecl on the scope chain, if PrevDecl is the same
+ // class, it will be the same declaration.
if (PrevDecl == IDecl) {
Diag(SuperLoc, diag::err_recursive_superclass)
<< SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
@@ -140,11 +181,11 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
if (PrevDecl && SuperClassDecl == 0) {
// The previous declaration was not a class decl. Check if we have a
// typedef. If we do, get the underlying class type.
- if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(PrevDecl)) {
+ if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(PrevDecl)){
QualType T = TDecl->getUnderlyingType();
if (T->isObjCObjectType()) {
- if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface())
- SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);
+ if (NamedDecl *NDecl = T->getAs<ObjCObjectType>()->getInterface())
+ SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(NDecl);
}
}
@@ -159,6 +200,11 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
}
}
+ if (SuperClassDecl) {
+ if (ObjCInterfaceDecl *Def = SuperClassDecl->getDefinition())
+ SuperClassDecl = Def;
+ }
+
if (!dyn_cast_or_null<TypedefDecl>(PrevDecl)) {
if (!SuperClassDecl)
Diag(SuperLoc, diag::err_undef_superclass)
@@ -530,7 +576,7 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation(
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *SuperClassname,
SourceLocation SuperClassLoc) {
- ObjCInterfaceDecl* IDecl = 0;
+ ObjCInterfaceDecl *IDecl = 0, *ODecl = 0;
// Check for another declaration kind with the same name.
NamedDecl *PrevDecl
= LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName,