forked from OSchip/llvm-project
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?" llvm-svn: 146679
This commit is contained in:
parent
918f976e66
commit
dc9166c8e1
|
@ -583,7 +583,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
|
||||||
};
|
};
|
||||||
|
|
||||||
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
|
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
|
||||||
SourceLocation CLoc, bool FD, bool isInternal);
|
SourceLocation CLoc, bool isInternal);
|
||||||
|
|
||||||
void LoadExternalDefinition() const;
|
void LoadExternalDefinition() const;
|
||||||
|
|
||||||
|
@ -596,12 +596,6 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
|
||||||
/// FIXME: This seems like the wrong location to care about.
|
/// FIXME: This seems like the wrong location to care about.
|
||||||
SourceLocation EndLoc;
|
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;
|
|
||||||
|
|
||||||
DefinitionData &data() const {
|
DefinitionData &data() const {
|
||||||
assert(Data != 0 && "Declaration has no definition!");
|
assert(Data != 0 && "Declaration has no definition!");
|
||||||
return *Data;
|
return *Data;
|
||||||
|
@ -620,13 +614,13 @@ public:
|
||||||
SourceLocation atLoc,
|
SourceLocation atLoc,
|
||||||
IdentifierInfo *Id,
|
IdentifierInfo *Id,
|
||||||
SourceLocation ClassLoc = SourceLocation(),
|
SourceLocation ClassLoc = SourceLocation(),
|
||||||
bool ForwardDecl = false,
|
|
||||||
bool isInternal = false);
|
bool isInternal = false);
|
||||||
|
|
||||||
virtual SourceRange getSourceRange() const {
|
virtual SourceRange getSourceRange() const {
|
||||||
if (isForwardDecl())
|
if (isThisDeclarationADefinition())
|
||||||
return SourceRange(getAtStartLoc(), getLocation());
|
return ObjCContainerDecl::getSourceRange();
|
||||||
return ObjCContainerDecl::getSourceRange();
|
|
||||||
|
return SourceRange(getAtStartLoc(), getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Indicate that this Objective-C class is complete, but that
|
/// \brief Indicate that this Objective-C class is complete, but that
|
||||||
|
@ -772,20 +766,10 @@ public:
|
||||||
unsigned Num,
|
unsigned Num,
|
||||||
ASTContext &C);
|
ASTContext &C);
|
||||||
|
|
||||||
/// \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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Determine whether this class has only ever been forward-declared.
|
|
||||||
bool isForwardDecl() const { return Data == 0; }
|
|
||||||
|
|
||||||
/// \brief Determine whether this particular declaration of this class is
|
/// \brief Determine whether this particular declaration of this class is
|
||||||
/// actually also a definition.
|
/// actually also a definition.
|
||||||
bool isThisDeclarationADefinition() const {
|
bool isThisDeclarationADefinition() const {
|
||||||
return Data == 0 || Data->Definition != this;
|
return Data && Data->Definition == this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Determine whether this class has been defined.
|
/// \brief Determine whether this class has been defined.
|
||||||
|
@ -927,6 +911,8 @@ public:
|
||||||
return getFirstDeclaration();
|
return getFirstDeclaration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setPreviousDeclaration(ObjCInterfaceDecl *PrevDecl);
|
||||||
|
|
||||||
// Low-level accessor
|
// Low-level accessor
|
||||||
const Type *getTypeForDecl() const { return TypeForDecl; }
|
const Type *getTypeForDecl() const { return TypeForDecl; }
|
||||||
void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; }
|
void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; }
|
||||||
|
|
|
@ -80,7 +80,7 @@ bool trans::canApplyWeak(ASTContext &Ctx, QualType type,
|
||||||
ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl();
|
ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl();
|
||||||
if (!AllowOnUnknownClass && (!Class || Class->getName() == "NSObject"))
|
if (!AllowOnUnknownClass && (!Class || Class->getName() == "NSObject"))
|
||||||
return false; // id/NSObject is not safe for weak.
|
return false; // id/NSObject is not safe for weak.
|
||||||
if (!AllowOnUnknownClass && Class->isForwardDecl())
|
if (!AllowOnUnknownClass && !Class->hasDefinition())
|
||||||
return false; // forward classes are not verifiable, therefore not safe.
|
return false; // forward classes are not verifiable, therefore not safe.
|
||||||
if (Class->isArcWeakrefUnavailable())
|
if (Class->isArcWeakrefUnavailable())
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -3183,7 +3183,6 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
|
||||||
ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
|
ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
|
||||||
Importer.Import(D->getAtStartLoc()),
|
Importer.Import(D->getAtStartLoc()),
|
||||||
Name.getAsIdentifierInfo(), Loc,
|
Name.getAsIdentifierInfo(), Loc,
|
||||||
D->isInitiallyForwardDecl(),
|
|
||||||
D->isImplicitInterfaceDecl());
|
D->isImplicitInterfaceDecl());
|
||||||
ToIface->setLexicalDeclContext(LexicalDC);
|
ToIface->setLexicalDeclContext(LexicalDC);
|
||||||
LexicalDC->addDeclInternal(ToIface);
|
LexicalDC->addDeclInternal(ToIface);
|
||||||
|
|
|
@ -675,16 +675,15 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(ASTContext &C,
|
||||||
SourceLocation atLoc,
|
SourceLocation atLoc,
|
||||||
IdentifierInfo *Id,
|
IdentifierInfo *Id,
|
||||||
SourceLocation ClassLoc,
|
SourceLocation ClassLoc,
|
||||||
bool ForwardDecl, bool isInternal){
|
bool isInternal){
|
||||||
return new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, ForwardDecl,
|
return new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, isInternal);
|
||||||
isInternal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjCInterfaceDecl::
|
ObjCInterfaceDecl::
|
||||||
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
|
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
|
||||||
SourceLocation CLoc, bool FD, bool isInternal)
|
SourceLocation CLoc, bool isInternal)
|
||||||
: ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, atLoc),
|
: ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, atLoc),
|
||||||
TypeForDecl(0), Data(), InitiallyForwardDecl(FD)
|
TypeForDecl(0), Data()
|
||||||
{
|
{
|
||||||
setImplicit(isInternal);
|
setImplicit(isInternal);
|
||||||
}
|
}
|
||||||
|
@ -705,19 +704,20 @@ void ObjCInterfaceDecl::setExternallyCompleted() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
|
ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
|
||||||
|
if (const ObjCInterfaceDecl *Def = getDefinition()) {
|
||||||
|
if (data().ExternallyCompleted)
|
||||||
|
LoadExternalDefinition();
|
||||||
|
|
||||||
|
return getASTContext().getObjCImplementation(
|
||||||
|
const_cast<ObjCInterfaceDecl*>(Def));
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Should make sure no callers ever do this.
|
// FIXME: Should make sure no callers ever do this.
|
||||||
if (!hasDefinition())
|
return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (data().ExternallyCompleted)
|
|
||||||
LoadExternalDefinition();
|
|
||||||
|
|
||||||
return getASTContext().getObjCImplementation(
|
|
||||||
const_cast<ObjCInterfaceDecl*>(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
|
void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
|
||||||
getASTContext().setObjCImplementation(this, ImplD);
|
getASTContext().setObjCImplementation(getDefinition(), ImplD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// all_declared_ivar_begin - return first ivar declared in this class,
|
/// all_declared_ivar_begin - return first ivar declared in this class,
|
||||||
|
@ -851,6 +851,14 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ObjCInterfaceDecl::setPreviousDeclaration(ObjCInterfaceDecl *PrevDecl) {
|
||||||
|
redeclarable_base::setPreviousDeclaration(PrevDecl);
|
||||||
|
|
||||||
|
// Inherit the 'Data' pointer from the previous declaration.
|
||||||
|
if (PrevDecl)
|
||||||
|
Data = PrevDecl->Data;
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// ObjCIvarDecl
|
// ObjCIvarDecl
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -900,16 +900,16 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
|
||||||
std::string I = OID->getNameAsString();
|
std::string I = OID->getNameAsString();
|
||||||
ObjCInterfaceDecl *SID = OID->getSuperClass();
|
ObjCInterfaceDecl *SID = OID->getSuperClass();
|
||||||
|
|
||||||
|
if (!OID->isThisDeclarationADefinition()) {
|
||||||
|
Out << "@class " << I << ";";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (SID)
|
if (SID)
|
||||||
Out << "@interface " << I << " : " << *SID;
|
Out << "@interface " << I << " : " << *SID;
|
||||||
else
|
else
|
||||||
Out << "@interface " << I;
|
Out << "@interface " << I;
|
||||||
|
|
||||||
if (OID->isForwardDecl()) {
|
|
||||||
Out << "@end";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Protocols?
|
// Protocols?
|
||||||
const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
|
const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
|
||||||
if (!Protocols.empty()) {
|
if (!Protocols.empty()) {
|
||||||
|
|
|
@ -755,7 +755,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
|
||||||
}
|
}
|
||||||
void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) {
|
void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) {
|
||||||
setPointer("typeptr", D->getTypeForDecl());
|
setPointer("typeptr", D->getTypeForDecl());
|
||||||
setFlag("forward_decl", D->isForwardDecl());
|
setFlag("forward_decl", !D->isThisDeclarationADefinition());
|
||||||
setFlag("implicit_interface", D->isImplicitInterfaceDecl());
|
setFlag("implicit_interface", D->isImplicitInterfaceDecl());
|
||||||
}
|
}
|
||||||
void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) {
|
void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) {
|
||||||
|
|
|
@ -2161,7 +2161,7 @@ const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) {
|
||||||
const ASTRecordLayout &
|
const ASTRecordLayout &
|
||||||
ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
|
ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
|
||||||
const ObjCImplementationDecl *Impl) const {
|
const ObjCImplementationDecl *Impl) const {
|
||||||
assert(!D->isForwardDecl() && "Invalid interface decl!");
|
assert(D->isThisDeclarationADefinition() && "Invalid interface decl!");
|
||||||
|
|
||||||
// Look up this layout, if already laid out, return what we have.
|
// Look up this layout, if already laid out, return what we have.
|
||||||
ObjCContainerDecl *Key =
|
ObjCContainerDecl *Key =
|
||||||
|
|
|
@ -927,7 +927,7 @@ bool Type::isIncompleteType() const {
|
||||||
->isIncompleteType();
|
->isIncompleteType();
|
||||||
case ObjCInterface:
|
case ObjCInterface:
|
||||||
// ObjC interfaces are incomplete if they are @class, not @interface.
|
// ObjC interfaces are incomplete if they are @class, not @interface.
|
||||||
return cast<ObjCInterfaceType>(CanonicalType)->getDecl()->isForwardDecl();
|
return !cast<ObjCInterfaceType>(CanonicalType)->getDecl()->hasDefinition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,7 @@ bool cocoa::isCocoaObjectRef(QualType Ty) {
|
||||||
|
|
||||||
// Assume that anything declared with a forward declaration and no
|
// Assume that anything declared with a forward declaration and no
|
||||||
// @interface subclasses NSObject.
|
// @interface subclasses NSObject.
|
||||||
if (ID->isForwardDecl())
|
if (!ID->hasDefinition())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
for ( ; ID ; ID = ID->getSuperClass())
|
for ( ; ID ; ID = ID->getSuperClass())
|
||||||
|
|
|
@ -1211,7 +1211,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
|
||||||
|
|
||||||
// If this is just a forward declaration return a special forward-declaration
|
// If this is just a forward declaration return a special forward-declaration
|
||||||
// debug type since we won't be able to lay out the entire type.
|
// debug type since we won't be able to lay out the entire type.
|
||||||
if (ID->isForwardDecl()) {
|
if (!ID->isThisDeclarationADefinition()) {
|
||||||
llvm::DIType FwdDecl =
|
llvm::DIType FwdDecl =
|
||||||
DBuilder.createStructType(Unit, ID->getName(),
|
DBuilder.createStructType(Unit, ID->getName(),
|
||||||
DefUnit, Line, 0, 0,
|
DefUnit, Line, 0, 0,
|
||||||
|
|
|
@ -653,8 +653,9 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
|
||||||
ConstantStringClassReference = FVD;
|
ConstantStringClassReference = FVD;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D)) {
|
} else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
|
||||||
RewriteInterfaceDecl(MD);
|
if (ID->isThisDeclarationADefinition())
|
||||||
|
RewriteInterfaceDecl(ID);
|
||||||
} else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
|
} else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
|
||||||
RewriteCategoryDecl(CD);
|
RewriteCategoryDecl(CD);
|
||||||
} else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
|
} else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
|
||||||
|
@ -673,9 +674,18 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
|
||||||
SourceLocation Loc = D->getLocation();
|
SourceLocation Loc = D->getLocation();
|
||||||
while (DI != DIEnd &&
|
while (DI != DIEnd &&
|
||||||
isa<ObjCClassDecl>(D) && D->getLocation() == Loc) {
|
isa<ObjCClassDecl>(D) && D->getLocation() == Loc) {
|
||||||
|
ObjCClassDecl *Class = cast<ObjCClassDecl>(D);
|
||||||
DG.push_back(D);
|
DG.push_back(D);
|
||||||
++DI;
|
++DI;
|
||||||
D = (*DI);
|
D = (*DI);
|
||||||
|
|
||||||
|
// Following the ObjCClassDecl, we should have the corresponding
|
||||||
|
// ObjCInterfaceDecl. Skip over it.
|
||||||
|
if (DI != DIEnd && isa<ObjCInterfaceDecl>(D) &&
|
||||||
|
Class->getForwardInterfaceDecl() == D) {
|
||||||
|
++DI;
|
||||||
|
D = (*DI);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
RewriteForwardClassDecl(DG);
|
RewriteForwardClassDecl(DG);
|
||||||
continue;
|
continue;
|
||||||
|
@ -1179,7 +1189,7 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) {
|
||||||
|
|
||||||
void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
|
void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
|
||||||
std::string ResultStr;
|
std::string ResultStr;
|
||||||
if (!ObjCForwardDecls.count(ClassDecl)) {
|
if (!ObjCForwardDecls.count(ClassDecl->getCanonicalDecl())) {
|
||||||
// we haven't seen a forward decl - generate a typedef.
|
// we haven't seen a forward decl - generate a typedef.
|
||||||
ResultStr = "#ifndef _REWRITER_typedef_";
|
ResultStr = "#ifndef _REWRITER_typedef_";
|
||||||
ResultStr += ClassDecl->getNameAsString();
|
ResultStr += ClassDecl->getNameAsString();
|
||||||
|
@ -1191,7 +1201,7 @@ void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
|
||||||
ResultStr += ClassDecl->getNameAsString();
|
ResultStr += ClassDecl->getNameAsString();
|
||||||
ResultStr += ";\n#endif\n";
|
ResultStr += ";\n#endif\n";
|
||||||
// Mark this typedef as having been generated.
|
// Mark this typedef as having been generated.
|
||||||
ObjCForwardDecls.insert(ClassDecl);
|
ObjCForwardDecls.insert(ClassDecl->getCanonicalDecl());
|
||||||
}
|
}
|
||||||
RewriteObjCInternalStruct(ClassDecl, ResultStr);
|
RewriteObjCInternalStruct(ClassDecl, ResultStr);
|
||||||
|
|
||||||
|
@ -3130,7 +3140,7 @@ void RewriteObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
|
||||||
|
|
||||||
// If no ivars and no root or if its root, directly or indirectly,
|
// If no ivars and no root or if its root, directly or indirectly,
|
||||||
// have no ivars (thus not synthesized) then no need to synthesize this class.
|
// have no ivars (thus not synthesized) then no need to synthesize this class.
|
||||||
if ((CDecl->isForwardDecl() || NumIvars == 0) &&
|
if ((!CDecl->isThisDeclarationADefinition() || NumIvars == 0) &&
|
||||||
(!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
|
(!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
|
||||||
endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
|
endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
|
||||||
ReplaceText(LocStart, endBuf-startBuf, Result);
|
ReplaceText(LocStart, endBuf-startBuf, Result);
|
||||||
|
@ -5357,7 +5367,7 @@ void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDe
|
||||||
|
|
||||||
// Explicitly declared @interface's are already synthesized.
|
// Explicitly declared @interface's are already synthesized.
|
||||||
if (CDecl->isImplicitInterfaceDecl()) {
|
if (CDecl->isImplicitInterfaceDecl()) {
|
||||||
// FIXME: Implementation of a class with no @interface (legacy) doese not
|
// FIXME: Implementation of a class with no @interface (legacy) does not
|
||||||
// produce correct synthesis as yet.
|
// produce correct synthesis as yet.
|
||||||
RewriteObjCInternalStruct(CDecl, Result);
|
RewriteObjCInternalStruct(CDecl, Result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,15 +318,6 @@ static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) {
|
||||||
return DMK_Ignore;
|
return DMK_Ignore;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the declarations are both Objective-C classes, and one is a forward
|
|
||||||
// declaration and the other is not, take the full definition.
|
|
||||||
// FIXME: At some point, we'll actually have to detect collisions better.
|
|
||||||
// This logic, however, belongs in the AST reader, not here.
|
|
||||||
if (ObjCInterfaceDecl *ExistingIFace = dyn_cast<ObjCInterfaceDecl>(Existing))
|
|
||||||
if (ObjCInterfaceDecl *NewIFace = dyn_cast<ObjCInterfaceDecl>(New))
|
|
||||||
if (ExistingIFace->isForwardDecl() != NewIFace->isForwardDecl())
|
|
||||||
return ExistingIFace->isForwardDecl()? DMK_Replace : DMK_Ignore;
|
|
||||||
|
|
||||||
return DMK_Different;
|
return DMK_Different;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5487,14 +5487,14 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
|
||||||
D != DEnd; ++D) {
|
D != DEnd; ++D) {
|
||||||
// Record any interfaces we find.
|
// Record any interfaces we find.
|
||||||
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
|
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
|
||||||
if ((!OnlyForwardDeclarations || Class->isForwardDecl()) &&
|
if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
|
||||||
(!OnlyUnimplemented || !Class->getImplementation()))
|
(!OnlyUnimplemented || !Class->getImplementation()))
|
||||||
Results.AddResult(Result(Class, 0), CurContext, 0, false);
|
Results.AddResult(Result(Class, 0), CurContext, 0, false);
|
||||||
|
|
||||||
// Record any forward-declared interfaces we find.
|
// Record any forward-declared interfaces we find.
|
||||||
if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) {
|
if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) {
|
||||||
ObjCInterfaceDecl *IDecl = Forward->getForwardInterfaceDecl();
|
ObjCInterfaceDecl *IDecl = Forward->getForwardInterfaceDecl();
|
||||||
if ((!OnlyForwardDeclarations || IDecl->isForwardDecl()) &&
|
if ((!OnlyForwardDeclarations || !IDecl->hasDefinition()) &&
|
||||||
(!OnlyUnimplemented || !IDecl->getImplementation()))
|
(!OnlyUnimplemented || !IDecl->getImplementation()))
|
||||||
Results.AddResult(Result(IDecl, 0), CurContext,
|
Results.AddResult(Result(IDecl, 0), CurContext,
|
||||||
0, false);
|
0, false);
|
||||||
|
|
|
@ -60,7 +60,7 @@ bool Sema::checkInitMethod(ObjCMethodDecl *method,
|
||||||
|
|
||||||
// It's okay for the result type to still be a forward declaration
|
// It's okay for the result type to still be a forward declaration
|
||||||
// if we're checking an interface declaration.
|
// if we're checking an interface declaration.
|
||||||
if (resultClass->isForwardDecl()) {
|
if (!resultClass->hasDefinition()) {
|
||||||
if (receiverTypeIfCall.isNull() &&
|
if (receiverTypeIfCall.isNull() &&
|
||||||
!isa<ObjCImplementationDecl>(method->getDeclContext()))
|
!isa<ObjCImplementationDecl>(method->getDeclContext()))
|
||||||
return false;
|
return false;
|
||||||
|
@ -365,45 +365,31 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
||||||
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
|
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjCInterfaceDecl* IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
|
// Create a declaration to describe this @interface.
|
||||||
if (IDecl) {
|
ObjCInterfaceDecl *IDecl
|
||||||
// Class already seen. Is it a forward declaration?
|
= ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, ClassName,
|
||||||
if (ObjCInterfaceDecl *Def = IDecl->getDefinition()) {
|
ClassLoc);
|
||||||
IDecl->setInvalidDecl();
|
|
||||||
Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<<IDecl->getDeclName();
|
ObjCInterfaceDecl* PrevIDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
|
||||||
|
if (PrevIDecl) {
|
||||||
|
// Class already seen. Was it a definition?
|
||||||
|
if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) {
|
||||||
|
Diag(AtInterfaceLoc, diag::err_duplicate_class_def)
|
||||||
|
<< PrevIDecl->getDeclName();
|
||||||
Diag(Def->getLocation(), diag::note_previous_definition);
|
Diag(Def->getLocation(), diag::note_previous_definition);
|
||||||
|
IDecl->setInvalidDecl();
|
||||||
// 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
|
|
||||||
// will break invariants.
|
|
||||||
IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc,
|
|
||||||
ClassName, ClassLoc);
|
|
||||||
if (AttrList)
|
|
||||||
ProcessDeclAttributeList(TUScope, IDecl, AttrList);
|
|
||||||
PushOnScopeChains(IDecl, TUScope);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
IDecl->setLocation(ClassLoc);
|
|
||||||
IDecl->setAtStartLoc(AtInterfaceLoc);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc,
|
|
||||||
ClassName, ClassLoc);
|
|
||||||
if (AttrList)
|
|
||||||
ProcessDeclAttributeList(TUScope, IDecl, AttrList);
|
|
||||||
|
|
||||||
PushOnScopeChains(IDecl, TUScope);
|
// Link to the previous declaration.
|
||||||
|
IDecl->setPreviousDeclaration(PrevIDecl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (AttrList)
|
||||||
|
ProcessDeclAttributeList(TUScope, IDecl, AttrList);
|
||||||
|
PushOnScopeChains(IDecl, TUScope);
|
||||||
|
|
||||||
|
// Start the definition of this class. If we're in a redefinition case, there
|
||||||
|
// may already be a definition, so we'll end up adding to it.
|
||||||
if (!IDecl->hasDefinition())
|
if (!IDecl->hasDefinition())
|
||||||
IDecl->startDefinition();
|
IDecl->startDefinition();
|
||||||
|
|
||||||
|
@ -942,7 +928,7 @@ Decl *Sema::ActOnStartClassImplementation(
|
||||||
// FIXME: Do we support attributes on the @implementation? If so we should
|
// FIXME: Do we support attributes on the @implementation? If so we should
|
||||||
// copy them over.
|
// copy them over.
|
||||||
IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc,
|
IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc,
|
||||||
ClassName, ClassLoc, false, true);
|
ClassName, ClassLoc, true);
|
||||||
IDecl->startDefinition();
|
IDecl->startDefinition();
|
||||||
IDecl->setSuperClass(SDecl);
|
IDecl->setSuperClass(SDecl);
|
||||||
IDecl->setLocEnd(ClassLoc);
|
IDecl->setLocEnd(ClassLoc);
|
||||||
|
@ -1781,22 +1767,29 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
|
||||||
PrevDecl = OI->getInterface();
|
PrevDecl = OI->getInterface();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
|
|
||||||
if (!IDecl) { // Not already seen? Make a forward decl.
|
|
||||||
IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc,
|
|
||||||
IdentList[i], IdentLocs[i], true);
|
|
||||||
|
|
||||||
// Push the ObjCInterfaceDecl on the scope chain but do *not* add it to
|
// Create a declaration to describe this forward declaration.
|
||||||
// the current DeclContext. This prevents clients that walk DeclContext
|
ObjCInterfaceDecl *IDecl
|
||||||
// from seeing the imaginary ObjCInterfaceDecl until it is actually
|
= ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc,
|
||||||
// declared later (if at all). We also take care to explicitly make
|
IdentList[i], IdentLocs[i], true);
|
||||||
// sure this declaration is visible for name lookup.
|
IDecl->setAtEndRange(IdentLocs[i]);
|
||||||
PushOnScopeChains(IDecl, TUScope, false);
|
IDecl->setLocEnd(IdentLocs[i]);
|
||||||
CurContext->makeDeclVisibleInContext(IDecl, true);
|
|
||||||
}
|
// If there was a previous declaration, link to it.
|
||||||
|
if (ObjCInterfaceDecl *PrevIDecl
|
||||||
|
= dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))
|
||||||
|
IDecl->setPreviousDeclaration(PrevIDecl);
|
||||||
|
|
||||||
|
// Create the forward declaration. Note that we intentionally do this
|
||||||
|
// before we add the ObjCInterfaceDecl we just created, so that the
|
||||||
|
// rewriter sees the ObjCClassDecl first.
|
||||||
|
// FIXME: ObjCClassDecl should probably just go away.
|
||||||
ObjCClassDecl *CDecl = ObjCClassDecl::Create(Context, CurContext, AtClassLoc,
|
ObjCClassDecl *CDecl = ObjCClassDecl::Create(Context, CurContext, AtClassLoc,
|
||||||
IDecl, IdentLocs[i]);
|
IDecl, IdentLocs[i]);
|
||||||
CurContext->addDecl(CDecl);
|
CurContext->addDecl(CDecl);
|
||||||
|
|
||||||
|
PushOnScopeChains(IDecl, TUScope);
|
||||||
|
|
||||||
CheckObjCDeclScope(CDecl);
|
CheckObjCDeclScope(CDecl);
|
||||||
DeclsInGroup.push_back(CDecl);
|
DeclsInGroup.push_back(CDecl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -629,7 +629,6 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ID->InitiallyForwardDecl = Record[Idx++];
|
|
||||||
ID->setLocEnd(ReadSourceLocation(Record, Idx));
|
ID->setLocEnd(ReadSourceLocation(Record, Idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -489,7 +489,6 @@ void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
|
||||||
Writer.AddDeclRef(D->getCategoryList(), Record);
|
Writer.AddDeclRef(D->getCategoryList(), Record);
|
||||||
}
|
}
|
||||||
|
|
||||||
Record.push_back(D->isInitiallyForwardDecl());
|
|
||||||
Writer.AddSourceLocation(D->getLocEnd(), Record);
|
Writer.AddSourceLocation(D->getLocEnd(), Record);
|
||||||
Code = serialization::DECL_OBJC_INTERFACE;
|
Code = serialization::DECL_OBJC_INTERFACE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ void function(Foo * arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-scan: [1:1 - 8:1] Invalid Cursor => NoDeclFound
|
// CHECK-scan: [1:1 - 8:1] Invalid Cursor => NoDeclFound
|
||||||
// CHECK-scan: [8:1 - 8:8] UnexposedDecl=[10:12]
|
// CHECK-scan: [8:1 - 8:8] UnexposedDecl=[8:8]
|
||||||
// CHECK-scan: [8:8 - 8:11] ObjCClassRef=Foo:10:12
|
// CHECK-scan: [8:8 - 8:11] ObjCClassRef=Foo:10:12
|
||||||
// CHECK-scan: [8:11 - 10:1] Invalid Cursor => NoDeclFound
|
// CHECK-scan: [8:11 - 10:1] Invalid Cursor => NoDeclFound
|
||||||
// CHECK-scan: [10:1 - 11:5] ObjCInterfaceDecl=Foo:10:12
|
// CHECK-scan: [10:1 - 11:5] ObjCInterfaceDecl=Foo:10:12
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||||
|
|
||||||
@class FOO, BAR; // expected-note {{forward declaration of class here}}
|
|
||||||
@class FOO, BAR;
|
@class FOO, BAR;
|
||||||
|
@class FOO, BAR; // expected-note {{forward declaration of class here}}
|
||||||
|
|
||||||
@interface INTF : FOO // expected-error {{attempting to use the forward class 'FOO' as superclass of 'INTF'}}
|
@interface INTF : FOO // expected-error {{attempting to use the forward class 'FOO' as superclass of 'INTF'}}
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -299,12 +299,7 @@ void CursorVisitor::visitDeclsFromFileRegion(FileID File,
|
||||||
|
|
||||||
// We handle forward decls via ObjCClassDecl.
|
// We handle forward decls via ObjCClassDecl.
|
||||||
if (ObjCInterfaceDecl *InterD = dyn_cast<ObjCInterfaceDecl>(D)) {
|
if (ObjCInterfaceDecl *InterD = dyn_cast<ObjCInterfaceDecl>(D)) {
|
||||||
if (InterD->isForwardDecl())
|
if (!InterD->isThisDeclarationADefinition())
|
||||||
continue;
|
|
||||||
// An interface that started as a forward decl may have changed location
|
|
||||||
// because its @interface was parsed.
|
|
||||||
if (InterD->isInitiallyForwardDecl() &&
|
|
||||||
!SM.isInFileID(SM.getFileLoc(InterD->getLocation()), File))
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3948,8 +3943,13 @@ CXCursor clang_getCursorReferenced(CXCursor C) {
|
||||||
case CXCursor_ObjCProtocolRef: {
|
case CXCursor_ObjCProtocolRef: {
|
||||||
return MakeCXCursor(getCursorObjCProtocolRef(C).first, tu);
|
return MakeCXCursor(getCursorObjCProtocolRef(C).first, tu);
|
||||||
|
|
||||||
case CXCursor_ObjCClassRef:
|
case CXCursor_ObjCClassRef: {
|
||||||
return MakeCXCursor(getCursorObjCClassRef(C).first, tu );
|
ObjCInterfaceDecl *Class = getCursorObjCClassRef(C).first;
|
||||||
|
if (ObjCInterfaceDecl *Def = Class->getDefinition())
|
||||||
|
return MakeCXCursor(Def, tu);
|
||||||
|
|
||||||
|
return MakeCXCursor(Class, tu);
|
||||||
|
}
|
||||||
|
|
||||||
case CXCursor_TypeRef:
|
case CXCursor_TypeRef:
|
||||||
return MakeCXCursor(getCursorTypeRef(C).first, tu );
|
return MakeCXCursor(getCursorTypeRef(C).first, tu );
|
||||||
|
@ -4147,8 +4147,8 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
|
||||||
// the definition; when we were provided with the interface,
|
// the definition; when we were provided with the interface,
|
||||||
// produce the @implementation as the definition.
|
// produce the @implementation as the definition.
|
||||||
if (WasReference) {
|
if (WasReference) {
|
||||||
if (!cast<ObjCInterfaceDecl>(D)->isForwardDecl())
|
if (ObjCInterfaceDecl *Def = cast<ObjCInterfaceDecl>(D)->getDefinition())
|
||||||
return C;
|
return MakeCXCursor(Def, TU);
|
||||||
} else if (ObjCImplementationDecl *Impl
|
} else if (ObjCImplementationDecl *Impl
|
||||||
= cast<ObjCInterfaceDecl>(D)->getImplementation())
|
= cast<ObjCInterfaceDecl>(D)->getImplementation())
|
||||||
return MakeCXCursor(Impl, TU);
|
return MakeCXCursor(Impl, TU);
|
||||||
|
@ -4162,8 +4162,8 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
|
||||||
case Decl::ObjCCompatibleAlias:
|
case Decl::ObjCCompatibleAlias:
|
||||||
if (ObjCInterfaceDecl *Class
|
if (ObjCInterfaceDecl *Class
|
||||||
= cast<ObjCCompatibleAliasDecl>(D)->getClassInterface())
|
= cast<ObjCCompatibleAliasDecl>(D)->getClassInterface())
|
||||||
if (!Class->isForwardDecl())
|
if (ObjCInterfaceDecl *Def = Class->getDefinition())
|
||||||
return MakeCXCursor(Class, TU);
|
return MakeCXCursor(Def, TU);
|
||||||
|
|
||||||
return clang_getNullCursor();
|
return clang_getNullCursor();
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ public:
|
||||||
|
|
||||||
bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
|
bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
|
||||||
// Forward decls are handled at VisitObjCClassDecl.
|
// Forward decls are handled at VisitObjCClassDecl.
|
||||||
if (D->isForwardDecl())
|
if (!D->isThisDeclarationADefinition())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
IndexCtx.handleObjCInterface(D);
|
IndexCtx.handleObjCInterface(D);
|
||||||
|
|
|
@ -128,7 +128,7 @@ struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo {
|
||||||
ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D)
|
ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D)
|
||||||
: ObjCContainerDeclInfo(Info_ObjCInterface,
|
: ObjCContainerDeclInfo(Info_ObjCInterface,
|
||||||
/*isForwardRef=*/false,
|
/*isForwardRef=*/false,
|
||||||
/*isRedeclaration=*/D->isInitiallyForwardDecl(),
|
/*isRedeclaration=*/D->getPreviousDeclaration() != 0,
|
||||||
/*isImplementation=*/false) { }
|
/*isImplementation=*/false) { }
|
||||||
|
|
||||||
static bool classof(const DeclInfo *D) {
|
static bool classof(const DeclInfo *D) {
|
||||||
|
|
Loading…
Reference in New Issue