forked from OSchip/llvm-project
[libclang] Fix operations (token annotation, getting cursor, etc.) with a file region
inside an objc container that "contains" other file-level declarations. When getting the array of file-level declarations that overlap with a file region, we failed to report that the region overlaps with an objc container, if the container had other file-level declarations declared lexically inside it. Fix this by marking such declarations as "isTopLevelDeclInObjCContainer" in the AST and handling them appropriately. llvm-svn: 145109
This commit is contained in:
parent
e4d082827d
commit
8ad3bab505
|
@ -244,6 +244,12 @@ private:
|
|||
/// are regarded as "referenced" but not "used".
|
||||
unsigned Referenced : 1;
|
||||
|
||||
/// \brief Whether this declaration is a top-level declaration (function,
|
||||
/// global variable, etc.) that is lexically inside an objc container
|
||||
/// definition.
|
||||
/// FIXME: Consider setting the lexical context to the objc container.
|
||||
unsigned TopLevelDeclInObjCContainer : 1;
|
||||
|
||||
protected:
|
||||
/// Access - Used by C++ decls for the access specifier.
|
||||
// NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
|
||||
|
@ -282,7 +288,7 @@ protected:
|
|||
: NextDeclInContext(0), DeclCtx(DC),
|
||||
Loc(L), DeclKind(DK), InvalidDecl(0),
|
||||
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
|
||||
Access(AS_none), FromASTFile(0),
|
||||
TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0),
|
||||
ModulePrivate(0),
|
||||
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
|
||||
HasCachedLinkage(0)
|
||||
|
@ -293,7 +299,7 @@ protected:
|
|||
Decl(Kind DK, EmptyShell Empty)
|
||||
: NextDeclInContext(0), DeclKind(DK), InvalidDecl(0),
|
||||
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
|
||||
Access(AS_none), FromASTFile(0),
|
||||
TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0),
|
||||
ModulePrivate(0),
|
||||
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
|
||||
HasCachedLinkage(0)
|
||||
|
@ -452,6 +458,17 @@ public:
|
|||
|
||||
void setReferenced(bool R = true) { Referenced = R; }
|
||||
|
||||
/// \brief Whether this declaration is a top-level declaration (function,
|
||||
/// global variable, etc.) that is lexically inside an objc container
|
||||
/// definition.
|
||||
bool isTopLevelDeclInObjCContainer() const {
|
||||
return TopLevelDeclInObjCContainer;
|
||||
}
|
||||
|
||||
void setTopLevelDeclInObjCContainer(bool V = true) {
|
||||
TopLevelDeclInObjCContainer = V;
|
||||
}
|
||||
|
||||
/// \brief Determine the availability of the given declaration.
|
||||
///
|
||||
/// This routine will determine the most restrictive availability of
|
||||
|
|
|
@ -2546,6 +2546,13 @@ void ASTUnit::findFileRegionDecls(FileID File, unsigned Offset, unsigned Length,
|
|||
if (BeginIt != LocDecls.begin())
|
||||
--BeginIt;
|
||||
|
||||
// If we are pointing at a top-level decl inside an objc container, we need
|
||||
// to backtrack until we find it otherwise we will fail to report that the
|
||||
// region overlaps with an objc container.
|
||||
while (BeginIt != LocDecls.begin() &&
|
||||
BeginIt->second->isTopLevelDeclInObjCContainer())
|
||||
--BeginIt;
|
||||
|
||||
LocDeclsTy::iterator
|
||||
EndIt = std::upper_bound(LocDecls.begin(), LocDecls.end(),
|
||||
std::make_pair(Offset+Length, (Decl*)0),
|
||||
|
|
|
@ -3152,7 +3152,13 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
|
|||
|
||||
Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) {
|
||||
D.setFunctionDefinitionKind(FDK_Declaration);
|
||||
return HandleDeclarator(S, D, MultiTemplateParamsArg(*this));
|
||||
Decl *Dcl = HandleDeclarator(S, D, MultiTemplateParamsArg(*this));
|
||||
|
||||
if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer() &&
|
||||
Dcl->getDeclContext()->isFileContext())
|
||||
Dcl->setTopLevelDeclInObjCContainer();
|
||||
|
||||
return Dcl;
|
||||
}
|
||||
|
||||
/// DiagnoseClassNameShadow - Implement C++ [class.mem]p13:
|
||||
|
@ -4788,6 +4794,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
isVirtualOkay);
|
||||
if (!NewFD) return 0;
|
||||
|
||||
if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer())
|
||||
NewFD->setTopLevelDeclInObjCContainer();
|
||||
|
||||
if (getLangOptions().CPlusPlus) {
|
||||
bool isInline = D.getDeclSpec().isInlineSpecified();
|
||||
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
|
||||
|
|
|
@ -2326,6 +2326,8 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
|||
|
||||
for (unsigned i = 0; i != tuvNum; i++) {
|
||||
DeclGroupRef DG = allTUVars[i].getAsVal<DeclGroupRef>();
|
||||
for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
|
||||
(*I)->setTopLevelDeclInObjCContainer();
|
||||
Consumer.HandleTopLevelDeclInObjCContainer(DG);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4293,6 +4293,14 @@ void ASTReader::FindFileRegionDecls(FileID File,
|
|||
if (BeginIt != DInfo.Decls.begin())
|
||||
--BeginIt;
|
||||
|
||||
// If we are pointing at a top-level decl inside an objc container, we need
|
||||
// to backtrack until we find it otherwise we will fail to report that the
|
||||
// region overlaps with an objc container.
|
||||
while (BeginIt != DInfo.Decls.begin() &&
|
||||
GetDecl(getGlobalDeclID(*DInfo.Mod, *BeginIt))
|
||||
->isTopLevelDeclInObjCContainer())
|
||||
--BeginIt;
|
||||
|
||||
ArrayRef<serialization::LocalDeclID>::iterator
|
||||
EndIt = std::upper_bound(DInfo.Decls.begin(), DInfo.Decls.end(),
|
||||
EndLoc, DIDComp);
|
||||
|
|
|
@ -249,6 +249,7 @@ void ASTDeclReader::VisitDecl(Decl *D) {
|
|||
D->setImplicit(Record[Idx++]);
|
||||
D->setUsed(Record[Idx++]);
|
||||
D->setReferenced(Record[Idx++]);
|
||||
D->TopLevelDeclInObjCContainer = Record[Idx++];
|
||||
D->setAccess((AccessSpecifier)Record[Idx++]);
|
||||
D->FromASTFile = true;
|
||||
D->ModulePrivate = Record[Idx++];
|
||||
|
|
|
@ -154,6 +154,7 @@ void ASTDeclWriter::VisitDecl(Decl *D) {
|
|||
Record.push_back(D->isImplicit());
|
||||
Record.push_back(D->isUsed(false));
|
||||
Record.push_back(D->isReferenced());
|
||||
Record.push_back(D->TopLevelDeclInObjCContainer);
|
||||
Record.push_back(D->getAccess());
|
||||
Record.push_back(D->ModulePrivate);
|
||||
}
|
||||
|
@ -1278,6 +1279,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // isUsed
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // isReferenced
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // AccessSpecifier
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate
|
||||
// NamedDecl
|
||||
|
@ -1308,6 +1310,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // isUsed
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // isReferenced
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // AccessSpecifier
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate
|
||||
// NamedDecl
|
||||
|
@ -1343,6 +1346,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // isUsed
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // isReferenced
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer
|
||||
Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate
|
||||
// NamedDecl
|
||||
|
@ -1388,6 +1392,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // isUsed
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // isReferenced
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer
|
||||
Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate
|
||||
// NamedDecl
|
||||
|
@ -1427,6 +1432,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // isUsed
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // isReferenced
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer
|
||||
Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate
|
||||
// NamedDecl
|
||||
|
@ -1473,6 +1479,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // isUsed
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // isReferenced
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer
|
||||
Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate
|
||||
// NamedDecl
|
||||
|
@ -1499,6 +1506,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // isUsed
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // isReferenced
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer
|
||||
Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate
|
||||
// NamedDecl
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
@interface Foo
|
||||
void func1(int);
|
||||
void func2(int);
|
||||
|
||||
-(void)meth1;
|
||||
-(void)meth2;
|
||||
@end
|
||||
|
||||
@implementation Foo
|
||||
void func(int);
|
||||
static int glob1;
|
||||
static int glob2;
|
||||
|
||||
-(void)meth1 {}
|
||||
-(void)meth2 {}
|
||||
@end
|
||||
|
||||
// RUN: c-index-test -write-pch %t.h.pch -x objective-c-header %s.h
|
||||
|
||||
// RUN: c-index-test -test-annotate-tokens=%s:5:1:7:1 %s -include %t.h \
|
||||
// RUN: | FileCheck -check-prefix=INTER %s
|
||||
// CHECK-INTER: Identifier: "meth1" [5:8 - 5:13] ObjCInstanceMethodDecl=meth1:5:1
|
||||
// CHECK-INTER: Identifier: "meth2" [6:8 - 6:13] ObjCInstanceMethodDecl=meth2:6:1
|
||||
|
||||
// RUN: c-index-test -test-annotate-tokens=%s:14:1:16:1 %s -include %t.h \
|
||||
// RUN: | FileCheck -check-prefix=IMPL %s
|
||||
// CHECK-IMPL: Identifier: "meth1" [14:8 - 14:13] ObjCInstanceMethodDecl=meth1:14:1 (Definition)
|
||||
// CHECK-IMPL: Identifier: "meth2" [15:8 - 15:13] ObjCInstanceMethodDecl=meth2:15:1 (Definition)
|
||||
|
||||
// RUN: c-index-test -test-annotate-tokens=%s.h:5:1:7:1 %s -include %t.h \
|
||||
// RUN: | FileCheck -check-prefix=PCH %s
|
||||
// CHECK-PCH: Identifier: "meth1" [5:8 - 5:13] ObjCInstanceMethodDecl=meth1:5:1
|
||||
// CHECK-PCH: Identifier: "meth2" [6:8 - 6:13] ObjCInstanceMethodDecl=meth2:6:1
|
|
@ -0,0 +1,7 @@
|
|||
@interface FooPCH
|
||||
void funcPCH1(int);
|
||||
void funcPCH2(int);
|
||||
|
||||
-(void)meth1;
|
||||
-(void)meth2;
|
||||
@end
|
|
@ -260,7 +260,7 @@ void CursorVisitor::visitDeclsFromFileRegion(FileID File,
|
|||
|
||||
// If we didn't find any file level decls for the file, try looking at the
|
||||
// file that it was included from.
|
||||
while (Decls.empty()) {
|
||||
while (Decls.empty() || Decls.front()->isTopLevelDeclInObjCContainer()) {
|
||||
bool Invalid = false;
|
||||
const SrcMgr::SLocEntry &SLEntry = SM.getSLocEntry(File, &Invalid);
|
||||
if (Invalid)
|
||||
|
|
Loading…
Reference in New Issue