Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 7723fec

Browse files
committed
Keep track of all declarations of an Objective-C class (both forward
declarations and definitions) as ObjCInterfaceDecls within the same redeclaration chain. This new representation matches what we do for C/C++ variables/functions/classes/templates/etc., and makes it possible to answer the query "where are all of the declarations of this class?" git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146679 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 0188872 commit 7723fec

21 files changed

+117
-132
lines changed

include/clang/AST/DeclObjC.h

+8-22
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
583583
};
584584

585585
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
586-
SourceLocation CLoc, bool FD, bool isInternal);
586+
SourceLocation CLoc, bool isInternal);
587587

588588
void LoadExternalDefinition() const;
589589

@@ -596,12 +596,6 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
596596
/// FIXME: This seems like the wrong location to care about.
597597
SourceLocation EndLoc;
598598

599-
/// \brief True if it was initially declared with @class.
600-
/// Differs with \see ForwardDecl in that \see ForwardDecl will change to
601-
/// false when we see the @interface, but InitiallyForwardDecl will remain
602-
/// true.
603-
bool InitiallyForwardDecl : 1;
604-
605599
DefinitionData &data() const {
606600
assert(Data != 0 && "Declaration has no definition!");
607601
return *Data;
@@ -620,13 +614,13 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
620614
SourceLocation atLoc,
621615
IdentifierInfo *Id,
622616
SourceLocation ClassLoc = SourceLocation(),
623-
bool ForwardDecl = false,
624617
bool isInternal = false);
625618

626619
virtual SourceRange getSourceRange() const {
627-
if (isForwardDecl())
628-
return SourceRange(getAtStartLoc(), getLocation());
629-
return ObjCContainerDecl::getSourceRange();
620+
if (isThisDeclarationADefinition())
621+
return ObjCContainerDecl::getSourceRange();
622+
623+
return SourceRange(getAtStartLoc(), getLocation());
630624
}
631625

632626
/// \brief Indicate that this Objective-C class is complete, but that
@@ -772,20 +766,10 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
772766
unsigned Num,
773767
ASTContext &C);
774768

775-
/// \brief True if it was initially declared with @class.
776-
/// Differs with \see isForwardDecl in that \see isForwardDecl will change to
777-
/// false when we see the @interface, but this will remain true.
778-
bool isInitiallyForwardDecl() const {
779-
return InitiallyForwardDecl;
780-
}
781-
782-
/// \brief Determine whether this class has only ever been forward-declared.
783-
bool isForwardDecl() const { return Data == 0; }
784-
785769
/// \brief Determine whether this particular declaration of this class is
786770
/// actually also a definition.
787771
bool isThisDeclarationADefinition() const {
788-
return Data == 0 || Data->Definition != this;
772+
return Data && Data->Definition == this;
789773
}
790774

791775
/// \brief Determine whether this class has been defined.
@@ -927,6 +911,8 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
927911
return getFirstDeclaration();
928912
}
929913

914+
void setPreviousDeclaration(ObjCInterfaceDecl *PrevDecl);
915+
930916
// Low-level accessor
931917
const Type *getTypeForDecl() const { return TypeForDecl; }
932918
void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; }

lib/ARCMigrate/Transforms.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ bool trans::canApplyWeak(ASTContext &Ctx, QualType type,
8080
ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl();
8181
if (!AllowOnUnknownClass && (!Class || Class->getName() == "NSObject"))
8282
return false; // id/NSObject is not safe for weak.
83-
if (!AllowOnUnknownClass && Class->isForwardDecl())
83+
if (!AllowOnUnknownClass && !Class->hasDefinition())
8484
return false; // forward classes are not verifiable, therefore not safe.
8585
if (Class->isArcWeakrefUnavailable())
8686
return false;

lib/AST/ASTImporter.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -3183,7 +3183,6 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
31833183
ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
31843184
Importer.Import(D->getAtStartLoc()),
31853185
Name.getAsIdentifierInfo(), Loc,
3186-
D->isInitiallyForwardDecl(),
31873186
D->isImplicitInterfaceDecl());
31883187
ToIface->setLexicalDeclContext(LexicalDC);
31893188
LexicalDC->addDeclInternal(ToIface);

lib/AST/DeclObjC.cpp

+22-14
Original file line numberDiff line numberDiff line change
@@ -675,16 +675,15 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(ASTContext &C,
675675
SourceLocation atLoc,
676676
IdentifierInfo *Id,
677677
SourceLocation ClassLoc,
678-
bool ForwardDecl, bool isInternal){
679-
return new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, ForwardDecl,
680-
isInternal);
678+
bool isInternal){
679+
return new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, isInternal);
681680
}
682681

683682
ObjCInterfaceDecl::
684683
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
685-
SourceLocation CLoc, bool FD, bool isInternal)
684+
SourceLocation CLoc, bool isInternal)
686685
: ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, atLoc),
687-
TypeForDecl(0), Data(), InitiallyForwardDecl(FD)
686+
TypeForDecl(0), Data()
688687
{
689688
setImplicit(isInternal);
690689
}
@@ -705,19 +704,20 @@ void ObjCInterfaceDecl::setExternallyCompleted() {
705704
}
706705

707706
ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
707+
if (const ObjCInterfaceDecl *Def = getDefinition()) {
708+
if (data().ExternallyCompleted)
709+
LoadExternalDefinition();
710+
711+
return getASTContext().getObjCImplementation(
712+
const_cast<ObjCInterfaceDecl*>(Def));
713+
}
714+
708715
// FIXME: Should make sure no callers ever do this.
709-
if (!hasDefinition())
710-
return 0;
711-
712-
if (data().ExternallyCompleted)
713-
LoadExternalDefinition();
714-
715-
return getASTContext().getObjCImplementation(
716-
const_cast<ObjCInterfaceDecl*>(this));
716+
return 0;
717717
}
718718

719719
void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
720-
getASTContext().setObjCImplementation(this, ImplD);
720+
getASTContext().setObjCImplementation(getDefinition(), ImplD);
721721
}
722722

723723
/// all_declared_ivar_begin - return first ivar declared in this class,
@@ -851,6 +851,14 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
851851
return false;
852852
}
853853

854+
void ObjCInterfaceDecl::setPreviousDeclaration(ObjCInterfaceDecl *PrevDecl) {
855+
redeclarable_base::setPreviousDeclaration(PrevDecl);
856+
857+
// Inherit the 'Data' pointer from the previous declaration.
858+
if (PrevDecl)
859+
Data = PrevDecl->Data;
860+
}
861+
854862
//===----------------------------------------------------------------------===//
855863
// ObjCIvarDecl
856864
//===----------------------------------------------------------------------===//

lib/AST/DeclPrinter.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -900,16 +900,16 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
900900
std::string I = OID->getNameAsString();
901901
ObjCInterfaceDecl *SID = OID->getSuperClass();
902902

903+
if (!OID->isThisDeclarationADefinition()) {
904+
Out << "@class " << I << ";";
905+
return;
906+
}
907+
903908
if (SID)
904909
Out << "@interface " << I << " : " << *SID;
905910
else
906911
Out << "@interface " << I;
907912

908-
if (OID->isForwardDecl()) {
909-
Out << "@end";
910-
return;
911-
}
912-
913913
// Protocols?
914914
const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
915915
if (!Protocols.empty()) {

lib/AST/DumpXML.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
755755
}
756756
void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) {
757757
setPointer("typeptr", D->getTypeForDecl());
758-
setFlag("forward_decl", D->isForwardDecl());
758+
setFlag("forward_decl", !D->isThisDeclarationADefinition());
759759
setFlag("implicit_interface", D->isImplicitInterfaceDecl());
760760
}
761761
void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) {

lib/AST/RecordLayoutBuilder.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -2161,7 +2161,7 @@ const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) {
21612161
const ASTRecordLayout &
21622162
ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
21632163
const ObjCImplementationDecl *Impl) const {
2164-
assert(!D->isForwardDecl() && "Invalid interface decl!");
2164+
assert(D->isThisDeclarationADefinition() && "Invalid interface decl!");
21652165

21662166
// Look up this layout, if already laid out, return what we have.
21672167
ObjCContainerDecl *Key =

lib/AST/Type.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,7 @@ bool Type::isIncompleteType() const {
927927
->isIncompleteType();
928928
case ObjCInterface:
929929
// ObjC interfaces are incomplete if they are @class, not @interface.
930-
return cast<ObjCInterfaceType>(CanonicalType)->getDecl()->isForwardDecl();
930+
return !cast<ObjCInterfaceType>(CanonicalType)->getDecl()->hasDefinition();
931931
}
932932
}
933933

lib/Analysis/CocoaConventions.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ bool cocoa::isCocoaObjectRef(QualType Ty) {
115115

116116
// Assume that anything declared with a forward declaration and no
117117
// @interface subclasses NSObject.
118-
if (ID->isForwardDecl())
118+
if (!ID->hasDefinition())
119119
return true;
120120

121121
for ( ; ID ; ID = ID->getSuperClass())

lib/CodeGen/CGDebugInfo.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1211,7 +1211,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
12111211

12121212
// If this is just a forward declaration return a special forward-declaration
12131213
// debug type since we won't be able to lay out the entire type.
1214-
if (ID->isForwardDecl()) {
1214+
if (!ID->isThisDeclarationADefinition()) {
12151215
llvm::DIType FwdDecl =
12161216
DBuilder.createStructType(Unit, ID->getName(),
12171217
DefUnit, Line, 0, 0,

lib/Rewrite/RewriteObjC.cpp

+16-6
Original file line numberDiff line numberDiff line change
@@ -653,8 +653,9 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
653653
ConstantStringClassReference = FVD;
654654
return;
655655
}
656-
} else if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D)) {
657-
RewriteInterfaceDecl(MD);
656+
} else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
657+
if (ID->isThisDeclarationADefinition())
658+
RewriteInterfaceDecl(ID);
658659
} else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
659660
RewriteCategoryDecl(CD);
660661
} else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
@@ -673,9 +674,18 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
673674
SourceLocation Loc = D->getLocation();
674675
while (DI != DIEnd &&
675676
isa<ObjCClassDecl>(D) && D->getLocation() == Loc) {
677+
ObjCClassDecl *Class = cast<ObjCClassDecl>(D);
676678
DG.push_back(D);
677679
++DI;
678680
D = (*DI);
681+
682+
// Following the ObjCClassDecl, we should have the corresponding
683+
// ObjCInterfaceDecl. Skip over it.
684+
if (DI != DIEnd && isa<ObjCInterfaceDecl>(D) &&
685+
Class->getForwardInterfaceDecl() == D) {
686+
++DI;
687+
D = (*DI);
688+
}
679689
}
680690
RewriteForwardClassDecl(DG);
681691
continue;
@@ -1179,7 +1189,7 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) {
11791189

11801190
void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
11811191
std::string ResultStr;
1182-
if (!ObjCForwardDecls.count(ClassDecl)) {
1192+
if (!ObjCForwardDecls.count(ClassDecl->getCanonicalDecl())) {
11831193
// we haven't seen a forward decl - generate a typedef.
11841194
ResultStr = "#ifndef _REWRITER_typedef_";
11851195
ResultStr += ClassDecl->getNameAsString();
@@ -1191,7 +1201,7 @@ void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
11911201
ResultStr += ClassDecl->getNameAsString();
11921202
ResultStr += ";\n#endif\n";
11931203
// Mark this typedef as having been generated.
1194-
ObjCForwardDecls.insert(ClassDecl);
1204+
ObjCForwardDecls.insert(ClassDecl->getCanonicalDecl());
11951205
}
11961206
RewriteObjCInternalStruct(ClassDecl, ResultStr);
11971207

@@ -3130,7 +3140,7 @@ void RewriteObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
31303140

31313141
// If no ivars and no root or if its root, directly or indirectly,
31323142
// have no ivars (thus not synthesized) then no need to synthesize this class.
3133-
if ((CDecl->isForwardDecl() || NumIvars == 0) &&
3143+
if ((!CDecl->isThisDeclarationADefinition() || NumIvars == 0) &&
31343144
(!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
31353145
endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
31363146
ReplaceText(LocStart, endBuf-startBuf, Result);
@@ -5357,7 +5367,7 @@ void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDe
53575367

53585368
// Explicitly declared @interface's are already synthesized.
53595369
if (CDecl->isImplicitInterfaceDecl()) {
5360-
// FIXME: Implementation of a class with no @interface (legacy) doese not
5370+
// FIXME: Implementation of a class with no @interface (legacy) does not
53615371
// produce correct synthesis as yet.
53625372
RewriteObjCInternalStruct(CDecl, Result);
53635373
}

lib/Sema/IdentifierResolver.cpp

-9
Original file line numberDiff line numberDiff line change
@@ -318,15 +318,6 @@ static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) {
318318
return DMK_Ignore;
319319
}
320320

321-
// If the declarations are both Objective-C classes, and one is a forward
322-
// declaration and the other is not, take the full definition.
323-
// FIXME: At some point, we'll actually have to detect collisions better.
324-
// This logic, however, belongs in the AST reader, not here.
325-
if (ObjCInterfaceDecl *ExistingIFace = dyn_cast<ObjCInterfaceDecl>(Existing))
326-
if (ObjCInterfaceDecl *NewIFace = dyn_cast<ObjCInterfaceDecl>(New))
327-
if (ExistingIFace->isForwardDecl() != NewIFace->isForwardDecl())
328-
return ExistingIFace->isForwardDecl()? DMK_Replace : DMK_Ignore;
329-
330321
return DMK_Different;
331322
}
332323

lib/Sema/SemaCodeComplete.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -5487,14 +5487,14 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
54875487
D != DEnd; ++D) {
54885488
// Record any interfaces we find.
54895489
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
5490-
if ((!OnlyForwardDeclarations || Class->isForwardDecl()) &&
5490+
if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
54915491
(!OnlyUnimplemented || !Class->getImplementation()))
54925492
Results.AddResult(Result(Class, 0), CurContext, 0, false);
54935493

54945494
// Record any forward-declared interfaces we find.
54955495
if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) {
54965496
ObjCInterfaceDecl *IDecl = Forward->getForwardInterfaceDecl();
5497-
if ((!OnlyForwardDeclarations || IDecl->isForwardDecl()) &&
5497+
if ((!OnlyForwardDeclarations || !IDecl->hasDefinition()) &&
54985498
(!OnlyUnimplemented || !IDecl->getImplementation()))
54995499
Results.AddResult(Result(IDecl, 0), CurContext,
55005500
0, false);

0 commit comments

Comments
 (0)