diff options
-rw-r--r-- | include/clang/AST/DeclBase.h | 21 | ||||
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 11 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 2 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 8 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 1 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 8 | ||||
-rw-r--r-- | test/Index/annotate-toplevel-in-objccontainer.m | 33 | ||||
-rw-r--r-- | test/Index/annotate-toplevel-in-objccontainer.m.h | 7 | ||||
-rw-r--r-- | tools/libclang/CIndex.cpp | 2 |
10 files changed, 96 insertions, 4 deletions
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index b11570fe2d..313cf606b8 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -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 diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 6cd0784215..a04a4403ea 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -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), diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 418ca3c741..cd2f071515 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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(); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index ebb0cb5463..667a12fea4 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -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); } } diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index de90c7b929..2569e225b5 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -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); diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 3eb867f18e..d242bc39bb 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -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++]; diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index cb42339cd9..22b3acabd4 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -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 diff --git a/test/Index/annotate-toplevel-in-objccontainer.m b/test/Index/annotate-toplevel-in-objccontainer.m new file mode 100644 index 0000000000..61c0f04a1b --- /dev/null +++ b/test/Index/annotate-toplevel-in-objccontainer.m @@ -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 diff --git a/test/Index/annotate-toplevel-in-objccontainer.m.h b/test/Index/annotate-toplevel-in-objccontainer.m.h new file mode 100644 index 0000000000..191a10cf93 --- /dev/null +++ b/test/Index/annotate-toplevel-in-objccontainer.m.h @@ -0,0 +1,7 @@ +@interface FooPCH +void funcPCH1(int); +void funcPCH2(int); + +-(void)meth1; +-(void)meth2; +@end diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 42adfa1cbc..4fda8bc313 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -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) |