зеркало из https://github.com/microsoft/clang-1.git
[libclang] For a class extension, give it a unique USR but for any property or ivar
it contains give it a USR based on its semantic context, which is the interface. This follows what we already did for objc methods. rdar://10371669 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143464 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
177dce7775
Коммит
87ec9c257c
|
@ -1614,6 +1614,11 @@ public:
|
|||
const ObjCMethodDecl *Redecl) {
|
||||
ObjCMethodRedecls[MD] = Redecl;
|
||||
}
|
||||
|
||||
/// \brief Returns the objc interface that \arg ND belongs to if it is a
|
||||
/// objc method/property/ivar etc. that is part of an interface,
|
||||
/// otherwise returns null.
|
||||
ObjCInterfaceDecl *getObjContainingInterface(NamedDecl *ND) const;
|
||||
|
||||
/// \brief Set the copy inialization expression of a block var decl.
|
||||
void setBlockVarCopyInits(VarDecl*VD, Expr* Init);
|
||||
|
|
|
@ -1261,6 +1261,17 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD,
|
|||
ObjCImpls[CatD] = ImplD;
|
||||
}
|
||||
|
||||
ObjCInterfaceDecl *ASTContext::getObjContainingInterface(NamedDecl *ND) const {
|
||||
if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ND->getDeclContext()))
|
||||
return ID;
|
||||
if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ND->getDeclContext()))
|
||||
return CD->getClassInterface();
|
||||
if (ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(ND->getDeclContext()))
|
||||
return IMD->getClassInterface();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// \brief Get the copy initialization expression of VarDecl,or NULL if
|
||||
/// none exists.
|
||||
Expr *ASTContext::getBlockVarCopyInits(const VarDecl*VD) {
|
||||
|
|
|
@ -80,6 +80,14 @@ int test_multi_declaration(void) {
|
|||
- (void)method;
|
||||
@end
|
||||
|
||||
@interface CWithExt2
|
||||
@end
|
||||
@interface CWithExt2 () {
|
||||
id var_ext;
|
||||
}
|
||||
@property (assign) id pro_ext;
|
||||
@end
|
||||
|
||||
// CHECK: usrs.m c:usrs.m@67@F@my_helper Extent=[3:1 - 3:60]
|
||||
// CHECK: usrs.m c:usrs.m@95@F@my_helper@x Extent=[3:29 - 3:34]
|
||||
// CHECK: usrs.m c:usrs.m@102@F@my_helper@y Extent=[3:36 - 3:41]
|
||||
|
@ -118,9 +126,9 @@ int test_multi_declaration(void) {
|
|||
// CHECK: usrs.m c:usrs.m@551@F@local_func@x Extent=[49:23 - 49:28]
|
||||
// CHECK: usrs.m c:objc(cs)CWithExt Extent=[51:1 - 53:5]
|
||||
// CHECK: usrs.m c:objc(cs)CWithExt(im)meth1 Extent=[52:1 - 52:14]
|
||||
// CHECK: usrs.m c:objc(cs)CWithExt Extent=[54:1 - 56:5]
|
||||
// CHECK: usrs.m c:objc(ext)CWithExt@usrs.m@612 Extent=[54:1 - 56:5]
|
||||
// CHECK: usrs.m c:objc(cs)CWithExt(im)meth2 Extent=[55:1 - 55:14]
|
||||
// CHECK: usrs.m c:objc(cs)CWithExt Extent=[57:1 - 59:5]
|
||||
// CHECK: usrs.m c:objc(ext)CWithExt@usrs.m@654 Extent=[57:1 - 59:5]
|
||||
// CHECK: usrs.m c:objc(cs)CWithExt(im)meth3 Extent=[58:1 - 58:14]
|
||||
// CHECK: usrs.m c:objc(cy)CWithExt@Bar Extent=[60:1 - 62:5]
|
||||
// CHECK: usrs.m c:objc(cs)CWithExt(im)meth4 Extent=[61:1 - 61:14]
|
||||
|
@ -137,6 +145,12 @@ int test_multi_declaration(void) {
|
|||
// CHECK: usrs.m c:usrs.m@980@F@test_multi_declaration@baz Extent=[74:25 - 74:32]
|
||||
// CHECK: usrs.m c:objc(pl)P1 Extent=[79:1 - 81:5]
|
||||
// CHECK: usrs.m c:objc(pl)P1(im)method Extent=[80:1 - 80:16]
|
||||
// CHECK: usrs.m c:objc(cs)CWithExt2 Extent=[83:1 - 84:5]
|
||||
// CHECK: usrs.m c:objc(ext)CWithExt2@usrs.m@1111 Extent=[85:1 - 89:5]
|
||||
// CHECK: usrs.m c:objc(cs)CWithExt2@var_ext Extent=[86:3 - 86:13]
|
||||
// CHECK: usrs.m c:objc(cs)CWithExt2(py)pro_ext Extent=[88:1 - 88:30]
|
||||
// CHECK: usrs.m c:objc(cs)CWithExt2(im)pro_ext Extent=[88:23 - 88:30]
|
||||
// CHECK: usrs.m c:objc(cs)CWithExt2(im)setPro_ext: Extent=[88:23 - 88:30]
|
||||
|
||||
// RUN: c-index-test -test-load-source all %s | FileCheck -check-prefix=CHECK-source %s
|
||||
// CHECK-source: usrs.m:3:19: FunctionDecl=my_helper:3:19 (Definition) Extent=[3:1 - 3:60]
|
||||
|
|
|
@ -169,7 +169,12 @@ void USRGenerator::VisitDeclContext(DeclContext *DC) {
|
|||
}
|
||||
|
||||
void USRGenerator::VisitFieldDecl(FieldDecl *D) {
|
||||
VisitDeclContext(D->getDeclContext());
|
||||
// The USR for an ivar declared in a class extension is based on the
|
||||
// ObjCInterfaceDecl, not the ObjCCategoryDecl.
|
||||
if (ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
|
||||
Visit(ID);
|
||||
else
|
||||
VisitDeclContext(D->getDeclContext());
|
||||
Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@");
|
||||
if (EmitDeclName(D)) {
|
||||
// Bit fields can be anonymous.
|
||||
|
@ -336,9 +341,11 @@ void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) {
|
|||
IgnoreResults = true;
|
||||
return;
|
||||
}
|
||||
// Specially handle class extensions, which are anonymous categories.
|
||||
// We want to mangle in the location to uniquely distinguish them.
|
||||
if (CD->IsClassExtension()) {
|
||||
// An extension semantically continues the interface of the class.
|
||||
GenObjCClass(ID->getName());
|
||||
Out << "objc(ext)" << ID->getName() << '@';
|
||||
GenLoc(CD);
|
||||
}
|
||||
else
|
||||
GenObjCCategory(ID->getName(), CD->getName());
|
||||
|
@ -366,7 +373,12 @@ void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) {
|
|||
}
|
||||
|
||||
void USRGenerator::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
|
||||
Visit(cast<Decl>(D->getDeclContext()));
|
||||
// The USR for a property declared in a class extension or category is based
|
||||
// on the ObjCInterfaceDecl, not the ObjCCategoryDecl.
|
||||
if (ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
|
||||
Visit(ID);
|
||||
else
|
||||
Visit(cast<Decl>(D->getDeclContext()));
|
||||
GenObjCProperty(D->getName());
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче