[libclang] Sync-up the way top-level decls in an ASTUnit are handled with how decls in a DeclContext are handled.

rdar://19775013

llvm-svn: 274378
This commit is contained in:
Argyrios Kyrtzidis 2016-07-01 19:10:54 +00:00
parent 0ba05f1835
commit e7c91045da
3 changed files with 46 additions and 33 deletions

View File

@ -70,7 +70,7 @@
// CHECK-NOT: properties-class-extensions.m:16:25: ObjCInstanceMethodDecl=bar:16:25 Extent=[16:25 - 16:28]
// CHECK: properties-class-extensions.m:19:26: ObjCInstanceMethodDecl=setBar::19:26 Extent=[19:26 - 19:29]
// CHECK: properties-class-extensions.m:19:26: ParmDecl=bar:19:26 (Definition) Extent=[19:26 - 19:29]
// CHECK: properties-class-extensions.m:24:8: ObjCInterfaceDecl=Rdar8467189_Bar:24:8 Extent=[24:1 - 24:23]
// CHECK-NOT: properties-class-extensions.m:24:8: ObjCInterfaceDecl=Rdar8467189_Bar:24:8
// CHECK: properties-class-extensions.m:24:8: ObjCClassRef=Rdar8467189_Bar:24:8 Extent=[24:8 - 24:23]
// CHECK: properties-class-extensions.m:25:11: ObjCProtocolDecl=Rdar8467189_FooProtocol:25:11 (Definition) Extent=[25:1 - 27:5]
// CHECK: properties-class-extensions.m:26:39: ObjCPropertyDecl=Rdar8467189_Bar:26:39 [readonly,] Extent=[26:1 - 26:54]

View File

@ -523,8 +523,10 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) {
for (ASTUnit::top_level_iterator TL = CXXUnit->top_level_begin(),
TLEnd = CXXUnit->top_level_end();
TL != TLEnd; ++TL) {
if (Visit(MakeCXCursor(*TL, TU, RegionOfInterest), true))
return true;
const Optional<bool> V = handleDeclForVisitation(*TL);
if (!V.hasValue())
continue;
return V.getValue();
}
} else if (VisitDeclContext(
CXXUnit->getASTContext().getTranslationUnitDecl()))
@ -621,42 +623,50 @@ bool CursorVisitor::VisitDeclContext(DeclContext *DC) {
Decl *D = *I;
if (D->getLexicalDeclContext() != DC)
continue;
CXCursor Cursor = MakeCXCursor(D, TU, RegionOfInterest);
// Ignore synthesized ivars here, otherwise if we have something like:
// @synthesize prop = _prop;
// and '_prop' is not declared, we will encounter a '_prop' ivar before
// encountering the 'prop' synthesize declaration and we will think that
// we passed the region-of-interest.
if (ObjCIvarDecl *ivarD = dyn_cast<ObjCIvarDecl>(D)) {
if (ivarD->getSynthesize())
continue;
}
// FIXME: ObjCClassRef/ObjCProtocolRef for forward class/protocol
// declarations is a mismatch with the compiler semantics.
if (Cursor.kind == CXCursor_ObjCInterfaceDecl) {
ObjCInterfaceDecl *ID = cast<ObjCInterfaceDecl>(D);
if (!ID->isThisDeclarationADefinition())
Cursor = MakeCursorObjCClassRef(ID, ID->getLocation(), TU);
} else if (Cursor.kind == CXCursor_ObjCProtocolDecl) {
ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(D);
if (!PD->isThisDeclarationADefinition())
Cursor = MakeCursorObjCProtocolRef(PD, PD->getLocation(), TU);
}
const Optional<bool> &V = shouldVisitCursor(Cursor);
const Optional<bool> V = handleDeclForVisitation(D);
if (!V.hasValue())
continue;
if (!V.getValue())
return false;
if (Visit(Cursor, true))
return true;
return V.getValue();
}
return false;
}
Optional<bool> CursorVisitor::handleDeclForVisitation(const Decl *D) {
CXCursor Cursor = MakeCXCursor(D, TU, RegionOfInterest);
// Ignore synthesized ivars here, otherwise if we have something like:
// @synthesize prop = _prop;
// and '_prop' is not declared, we will encounter a '_prop' ivar before
// encountering the 'prop' synthesize declaration and we will think that
// we passed the region-of-interest.
if (auto *ivarD = dyn_cast<ObjCIvarDecl>(D)) {
if (ivarD->getSynthesize())
return None;
}
// FIXME: ObjCClassRef/ObjCProtocolRef for forward class/protocol
// declarations is a mismatch with the compiler semantics.
if (Cursor.kind == CXCursor_ObjCInterfaceDecl) {
auto *ID = cast<ObjCInterfaceDecl>(D);
if (!ID->isThisDeclarationADefinition())
Cursor = MakeCursorObjCClassRef(ID, ID->getLocation(), TU);
} else if (Cursor.kind == CXCursor_ObjCProtocolDecl) {
auto *PD = cast<ObjCProtocolDecl>(D);
if (!PD->isThisDeclarationADefinition())
Cursor = MakeCursorObjCProtocolRef(PD, PD->getLocation(), TU);
}
const Optional<bool> V = shouldVisitCursor(Cursor);
if (!V.hasValue())
return None;
if (!V.getValue())
return false;
if (Visit(Cursor, true))
return true;
return None;
}
bool CursorVisitor::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
llvm_unreachable("Translation units are visited directly by Visit()");
}

View File

@ -265,6 +265,9 @@ public:
bool RunVisitorWorkList(VisitorWorkList &WL);
void EnqueueWorkList(VisitorWorkList &WL, const Stmt *S);
LLVM_ATTRIBUTE_NOINLINE bool Visit(const Stmt *S);
private:
Optional<bool> handleDeclForVisitation(const Decl *D);
};
}