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,
|
||||
SourceLocation CLoc, bool FD, bool isInternal);
|
||||
SourceLocation CLoc, bool isInternal);
|
||||
|
||||
void LoadExternalDefinition() const;
|
||||
|
||||
|
@ -596,12 +596,6 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
|
|||
/// 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;
|
||||
|
||||
DefinitionData &data() const {
|
||||
assert(Data != 0 && "Declaration has no definition!");
|
||||
return *Data;
|
||||
|
@ -620,13 +614,13 @@ public:
|
|||
SourceLocation atLoc,
|
||||
IdentifierInfo *Id,
|
||||
SourceLocation ClassLoc = SourceLocation(),
|
||||
bool ForwardDecl = false,
|
||||
bool isInternal = false);
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
if (isForwardDecl())
|
||||
return SourceRange(getAtStartLoc(), getLocation());
|
||||
if (isThisDeclarationADefinition())
|
||||
return ObjCContainerDecl::getSourceRange();
|
||||
|
||||
return SourceRange(getAtStartLoc(), getLocation());
|
||||
}
|
||||
|
||||
/// \brief Indicate that this Objective-C class is complete, but that
|
||||
|
@ -772,20 +766,10 @@ public:
|
|||
unsigned Num,
|
||||
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
|
||||
/// actually also a definition.
|
||||
bool isThisDeclarationADefinition() const {
|
||||
return Data == 0 || Data->Definition != this;
|
||||
return Data && Data->Definition == this;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this class has been defined.
|
||||
|
@ -927,6 +911,8 @@ public:
|
|||
return getFirstDeclaration();
|
||||
}
|
||||
|
||||
void setPreviousDeclaration(ObjCInterfaceDecl *PrevDecl);
|
||||
|
||||
// Low-level accessor
|
||||
const Type *getTypeForDecl() const { return TypeForDecl; }
|
||||
void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; }
|
||||
|
|
|
@ -80,7 +80,7 @@ bool trans::canApplyWeak(ASTContext &Ctx, QualType type,
|
|||
ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl();
|
||||
if (!AllowOnUnknownClass && (!Class || Class->getName() == "NSObject"))
|
||||
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.
|
||||
if (Class->isArcWeakrefUnavailable())
|
||||
return false;
|
||||
|
|
|
@ -3183,7 +3183,6 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
|
|||
ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
|
||||
Importer.Import(D->getAtStartLoc()),
|
||||
Name.getAsIdentifierInfo(), Loc,
|
||||
D->isInitiallyForwardDecl(),
|
||||
D->isImplicitInterfaceDecl());
|
||||
ToIface->setLexicalDeclContext(LexicalDC);
|
||||
LexicalDC->addDeclInternal(ToIface);
|
||||
|
|
|
@ -675,16 +675,15 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(ASTContext &C,
|
|||
SourceLocation atLoc,
|
||||
IdentifierInfo *Id,
|
||||
SourceLocation ClassLoc,
|
||||
bool ForwardDecl, bool isInternal){
|
||||
return new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, ForwardDecl,
|
||||
isInternal);
|
||||
bool isInternal){
|
||||
return new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, isInternal);
|
||||
}
|
||||
|
||||
ObjCInterfaceDecl::
|
||||
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
|
||||
SourceLocation CLoc, bool FD, bool isInternal)
|
||||
SourceLocation CLoc, bool isInternal)
|
||||
: ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, atLoc),
|
||||
TypeForDecl(0), Data(), InitiallyForwardDecl(FD)
|
||||
TypeForDecl(0), Data()
|
||||
{
|
||||
setImplicit(isInternal);
|
||||
}
|
||||
|
@ -705,19 +704,20 @@ void ObjCInterfaceDecl::setExternallyCompleted() {
|
|||
}
|
||||
|
||||
ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
|
||||
// FIXME: Should make sure no callers ever do this.
|
||||
if (!hasDefinition())
|
||||
return 0;
|
||||
|
||||
if (const ObjCInterfaceDecl *Def = getDefinition()) {
|
||||
if (data().ExternallyCompleted)
|
||||
LoadExternalDefinition();
|
||||
|
||||
return getASTContext().getObjCImplementation(
|
||||
const_cast<ObjCInterfaceDecl*>(this));
|
||||
const_cast<ObjCInterfaceDecl*>(Def));
|
||||
}
|
||||
|
||||
// FIXME: Should make sure no callers ever do this.
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
|
||||
getASTContext().setObjCImplementation(this, ImplD);
|
||||
getASTContext().setObjCImplementation(getDefinition(), ImplD);
|
||||
}
|
||||
|
||||
/// all_declared_ivar_begin - return first ivar declared in this class,
|
||||
|
@ -851,6 +851,14 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
|
|||
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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -900,16 +900,16 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
|
|||
std::string I = OID->getNameAsString();
|
||||
ObjCInterfaceDecl *SID = OID->getSuperClass();
|
||||
|
||||
if (!OID->isThisDeclarationADefinition()) {
|
||||
Out << "@class " << I << ";";
|
||||
return;
|
||||
}
|
||||
|
||||
if (SID)
|
||||
Out << "@interface " << I << " : " << *SID;
|
||||
else
|
||||
Out << "@interface " << I;
|
||||
|
||||
if (OID->isForwardDecl()) {
|
||||
Out << "@end";
|
||||
return;
|
||||
}
|
||||
|
||||
// Protocols?
|
||||
const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
|
||||
if (!Protocols.empty()) {
|
||||
|
|
|
@ -755,7 +755,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
|
|||
}
|
||||
void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) {
|
||||
setPointer("typeptr", D->getTypeForDecl());
|
||||
setFlag("forward_decl", D->isForwardDecl());
|
||||
setFlag("forward_decl", !D->isThisDeclarationADefinition());
|
||||
setFlag("implicit_interface", D->isImplicitInterfaceDecl());
|
||||
}
|
||||
void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) {
|
||||
|
|
|
@ -2161,7 +2161,7 @@ const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) {
|
|||
const ASTRecordLayout &
|
||||
ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
|
||||
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.
|
||||
ObjCContainerDecl *Key =
|
||||
|
|
|
@ -927,7 +927,7 @@ bool Type::isIncompleteType() const {
|
|||
->isIncompleteType();
|
||||
case ObjCInterface:
|
||||
// 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
|
||||
// @interface subclasses NSObject.
|
||||
if (ID->isForwardDecl())
|
||||
if (!ID->hasDefinition())
|
||||
return true;
|
||||
|
||||
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
|
||||
// debug type since we won't be able to lay out the entire type.
|
||||
if (ID->isForwardDecl()) {
|
||||
if (!ID->isThisDeclarationADefinition()) {
|
||||
llvm::DIType FwdDecl =
|
||||
DBuilder.createStructType(Unit, ID->getName(),
|
||||
DefUnit, Line, 0, 0,
|
||||
|
|
|
@ -653,8 +653,9 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
|
|||
ConstantStringClassReference = FVD;
|
||||
return;
|
||||
}
|
||||
} else if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D)) {
|
||||
RewriteInterfaceDecl(MD);
|
||||
} else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
|
||||
if (ID->isThisDeclarationADefinition())
|
||||
RewriteInterfaceDecl(ID);
|
||||
} else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
|
||||
RewriteCategoryDecl(CD);
|
||||
} else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
|
||||
|
@ -673,9 +674,18 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
|
|||
SourceLocation Loc = D->getLocation();
|
||||
while (DI != DIEnd &&
|
||||
isa<ObjCClassDecl>(D) && D->getLocation() == Loc) {
|
||||
ObjCClassDecl *Class = cast<ObjCClassDecl>(D);
|
||||
DG.push_back(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);
|
||||
continue;
|
||||
|
@ -1179,7 +1189,7 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) {
|
|||
|
||||
void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
|
||||
std::string ResultStr;
|
||||
if (!ObjCForwardDecls.count(ClassDecl)) {
|
||||
if (!ObjCForwardDecls.count(ClassDecl->getCanonicalDecl())) {
|
||||
// we haven't seen a forward decl - generate a typedef.
|
||||
ResultStr = "#ifndef _REWRITER_typedef_";
|
||||
ResultStr += ClassDecl->getNameAsString();
|
||||
|
@ -1191,7 +1201,7 @@ void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
|
|||
ResultStr += ClassDecl->getNameAsString();
|
||||
ResultStr += ";\n#endif\n";
|
||||
// Mark this typedef as having been generated.
|
||||
ObjCForwardDecls.insert(ClassDecl);
|
||||
ObjCForwardDecls.insert(ClassDecl->getCanonicalDecl());
|
||||
}
|
||||
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,
|
||||
// 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))) {
|
||||
endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
|
||||
ReplaceText(LocStart, endBuf-startBuf, Result);
|
||||
|
@ -5357,7 +5367,7 @@ void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDe
|
|||
|
||||
// Explicitly declared @interface's are already synthesized.
|
||||
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.
|
||||
RewriteObjCInternalStruct(CDecl, Result);
|
||||
}
|
||||
|
|
|
@ -318,15 +318,6 @@ static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) {
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -5487,14 +5487,14 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
|
|||
D != DEnd; ++D) {
|
||||
// Record any interfaces we find.
|
||||
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
|
||||
if ((!OnlyForwardDeclarations || Class->isForwardDecl()) &&
|
||||
if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
|
||||
(!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)) {
|
||||
ObjCInterfaceDecl *IDecl = Forward->getForwardInterfaceDecl();
|
||||
if ((!OnlyForwardDeclarations || IDecl->isForwardDecl()) &&
|
||||
if ((!OnlyForwardDeclarations || !IDecl->hasDefinition()) &&
|
||||
(!OnlyUnimplemented || !IDecl->getImplementation()))
|
||||
Results.AddResult(Result(IDecl, 0), CurContext,
|
||||
0, false);
|
||||
|
|
|
@ -60,7 +60,7 @@ bool Sema::checkInitMethod(ObjCMethodDecl *method,
|
|||
|
||||
// It's okay for the result type to still be a forward declaration
|
||||
// if we're checking an interface declaration.
|
||||
if (resultClass->isForwardDecl()) {
|
||||
if (!resultClass->hasDefinition()) {
|
||||
if (receiverTypeIfCall.isNull() &&
|
||||
!isa<ObjCImplementationDecl>(method->getDeclContext()))
|
||||
return false;
|
||||
|
@ -365,45 +365,31 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
|||
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
|
||||
}
|
||||
|
||||
ObjCInterfaceDecl* IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
|
||||
if (IDecl) {
|
||||
// Class already seen. Is it a forward declaration?
|
||||
if (ObjCInterfaceDecl *Def = IDecl->getDefinition()) {
|
||||
IDecl->setInvalidDecl();
|
||||
Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<<IDecl->getDeclName();
|
||||
// Create a declaration to describe this @interface.
|
||||
ObjCInterfaceDecl *IDecl
|
||||
= ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, ClassName,
|
||||
ClassLoc);
|
||||
|
||||
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);
|
||||
IDecl->setInvalidDecl();
|
||||
}
|
||||
|
||||
// Link to the previous declaration.
|
||||
IDecl->setPreviousDeclaration(PrevIDecl);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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())
|
||||
IDecl->startDefinition();
|
||||
|
||||
|
@ -942,7 +928,7 @@ Decl *Sema::ActOnStartClassImplementation(
|
|||
// FIXME: Do we support attributes on the @implementation? If so we should
|
||||
// copy them over.
|
||||
IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc,
|
||||
ClassName, ClassLoc, false, true);
|
||||
ClassName, ClassLoc, true);
|
||||
IDecl->startDefinition();
|
||||
IDecl->setSuperClass(SDecl);
|
||||
IDecl->setLocEnd(ClassLoc);
|
||||
|
@ -1781,22 +1767,29 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
|
|||
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
|
||||
// the current DeclContext. This prevents clients that walk DeclContext
|
||||
// from seeing the imaginary ObjCInterfaceDecl until it is actually
|
||||
// declared later (if at all). We also take care to explicitly make
|
||||
// sure this declaration is visible for name lookup.
|
||||
PushOnScopeChains(IDecl, TUScope, false);
|
||||
CurContext->makeDeclVisibleInContext(IDecl, true);
|
||||
}
|
||||
// Create a declaration to describe this forward declaration.
|
||||
ObjCInterfaceDecl *IDecl
|
||||
= ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc,
|
||||
IdentList[i], IdentLocs[i], true);
|
||||
IDecl->setAtEndRange(IdentLocs[i]);
|
||||
IDecl->setLocEnd(IdentLocs[i]);
|
||||
|
||||
// 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,
|
||||
IDecl, IdentLocs[i]);
|
||||
CurContext->addDecl(CDecl);
|
||||
|
||||
PushOnScopeChains(IDecl, TUScope);
|
||||
|
||||
CheckObjCDeclScope(CDecl);
|
||||
DeclsInGroup.push_back(CDecl);
|
||||
}
|
||||
|
|
|
@ -629,7 +629,6 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
|
|||
}
|
||||
}
|
||||
|
||||
ID->InitiallyForwardDecl = Record[Idx++];
|
||||
ID->setLocEnd(ReadSourceLocation(Record, Idx));
|
||||
}
|
||||
|
||||
|
|
|
@ -489,7 +489,6 @@ void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
|
|||
Writer.AddDeclRef(D->getCategoryList(), Record);
|
||||
}
|
||||
|
||||
Record.push_back(D->isInitiallyForwardDecl());
|
||||
Writer.AddSourceLocation(D->getLocEnd(), Record);
|
||||
Code = serialization::DECL_OBJC_INTERFACE;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ void function(Foo * arg)
|
|||
}
|
||||
|
||||
// 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:11 - 10:1] Invalid Cursor => NoDeclFound
|
||||
// CHECK-scan: [10:1 - 11:5] ObjCInterfaceDecl=Foo:10:12
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
@class FOO, BAR; // expected-note {{forward declaration of class here}}
|
||||
@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'}}
|
||||
@end
|
||||
|
|
|
@ -299,12 +299,7 @@ void CursorVisitor::visitDeclsFromFileRegion(FileID File,
|
|||
|
||||
// We handle forward decls via ObjCClassDecl.
|
||||
if (ObjCInterfaceDecl *InterD = dyn_cast<ObjCInterfaceDecl>(D)) {
|
||||
if (InterD->isForwardDecl())
|
||||
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))
|
||||
if (!InterD->isThisDeclarationADefinition())
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -3948,8 +3943,13 @@ CXCursor clang_getCursorReferenced(CXCursor C) {
|
|||
case CXCursor_ObjCProtocolRef: {
|
||||
return MakeCXCursor(getCursorObjCProtocolRef(C).first, tu);
|
||||
|
||||
case CXCursor_ObjCClassRef:
|
||||
return MakeCXCursor(getCursorObjCClassRef(C).first, tu );
|
||||
case CXCursor_ObjCClassRef: {
|
||||
ObjCInterfaceDecl *Class = getCursorObjCClassRef(C).first;
|
||||
if (ObjCInterfaceDecl *Def = Class->getDefinition())
|
||||
return MakeCXCursor(Def, tu);
|
||||
|
||||
return MakeCXCursor(Class, tu);
|
||||
}
|
||||
|
||||
case CXCursor_TypeRef:
|
||||
return MakeCXCursor(getCursorTypeRef(C).first, tu );
|
||||
|
@ -4147,8 +4147,8 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
|
|||
// the definition; when we were provided with the interface,
|
||||
// produce the @implementation as the definition.
|
||||
if (WasReference) {
|
||||
if (!cast<ObjCInterfaceDecl>(D)->isForwardDecl())
|
||||
return C;
|
||||
if (ObjCInterfaceDecl *Def = cast<ObjCInterfaceDecl>(D)->getDefinition())
|
||||
return MakeCXCursor(Def, TU);
|
||||
} else if (ObjCImplementationDecl *Impl
|
||||
= cast<ObjCInterfaceDecl>(D)->getImplementation())
|
||||
return MakeCXCursor(Impl, TU);
|
||||
|
@ -4162,8 +4162,8 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
|
|||
case Decl::ObjCCompatibleAlias:
|
||||
if (ObjCInterfaceDecl *Class
|
||||
= cast<ObjCCompatibleAliasDecl>(D)->getClassInterface())
|
||||
if (!Class->isForwardDecl())
|
||||
return MakeCXCursor(Class, TU);
|
||||
if (ObjCInterfaceDecl *Def = Class->getDefinition())
|
||||
return MakeCXCursor(Def, TU);
|
||||
|
||||
return clang_getNullCursor();
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ public:
|
|||
|
||||
bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
|
||||
// Forward decls are handled at VisitObjCClassDecl.
|
||||
if (D->isForwardDecl())
|
||||
if (!D->isThisDeclarationADefinition())
|
||||
return true;
|
||||
|
||||
IndexCtx.handleObjCInterface(D);
|
||||
|
|
|
@ -128,7 +128,7 @@ struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo {
|
|||
ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D)
|
||||
: ObjCContainerDeclInfo(Info_ObjCInterface,
|
||||
/*isForwardRef=*/false,
|
||||
/*isRedeclaration=*/D->isInitiallyForwardDecl(),
|
||||
/*isRedeclaration=*/D->getPreviousDeclaration() != 0,
|
||||
/*isImplementation=*/false) { }
|
||||
|
||||
static bool classof(const DeclInfo *D) {
|
||||
|
|
Loading…
Reference in New Issue