forked from OSchip/llvm-project
Fix a major inconsistency in the representation of Objective-C
classes, categories, protocols, and class extensions, where the methods and properties of these entities would be inserted into the DeclContext in an ordering that doesn't necessarily reflect source order. The culprits were Sema::ActOnMethodDeclaration(), which did not perform the insertion of the just-created method declaration into the DeclContext for these Objective-C entities, and Sema::ActOnAtEnd(), which inserted all method declarations at the *end* of the DeclContext. With this fix in hand, clean up the code-completion actions for property setters/getters that worked around this brokenness in the AST. Fixes <rdar://problem/8062781>, where this problem manifested as poor token-annotation information, but this would have struck again in many other places. llvm-svn: 122347
This commit is contained in:
parent
be57ab185f
commit
87e927520d
|
@ -983,8 +983,7 @@ private:
|
|||
Decl *ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType,
|
||||
Decl *classDecl,
|
||||
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword);
|
||||
void ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl,
|
||||
Decl **Methods, unsigned NumMethods);
|
||||
void ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl);
|
||||
|
||||
Decl *ParseObjCMethodDefinition();
|
||||
|
||||
|
|
|
@ -4645,12 +4645,8 @@ public:
|
|||
void CodeCompleteObjCAtStatement(Scope *S);
|
||||
void CodeCompleteObjCAtExpression(Scope *S);
|
||||
void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS);
|
||||
void CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl,
|
||||
Decl **Methods,
|
||||
unsigned NumMethods);
|
||||
void CodeCompleteObjCPropertySetter(Scope *S, Decl *ClassDecl,
|
||||
Decl **Methods,
|
||||
unsigned NumMethods);
|
||||
void CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl);
|
||||
void CodeCompleteObjCPropertySetter(Scope *S, Decl *ClassDecl);
|
||||
void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS);
|
||||
void CodeCompleteObjCMessageReceiver(Scope *S);
|
||||
void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
|
||||
|
|
|
@ -426,8 +426,7 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl,
|
|||
ObjCDeclSpec OCDS;
|
||||
// Parse property attribute list, if any.
|
||||
if (Tok.is(tok::l_paren))
|
||||
ParseObjCPropertyAttribute(OCDS, interfaceDecl,
|
||||
allMethods.data(), allMethods.size());
|
||||
ParseObjCPropertyAttribute(OCDS, interfaceDecl);
|
||||
|
||||
ObjCPropertyCallback Callback(*this, interfaceDecl, allProperties,
|
||||
OCDS, AtLoc, MethodImplKind);
|
||||
|
@ -476,9 +475,7 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl,
|
|||
/// copy
|
||||
/// nonatomic
|
||||
///
|
||||
void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl,
|
||||
Decl **Methods,
|
||||
unsigned NumMethods) {
|
||||
void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl) {
|
||||
assert(Tok.getKind() == tok::l_paren);
|
||||
SourceLocation LHSLoc = ConsumeParen(); // consume '('
|
||||
|
||||
|
@ -523,11 +520,9 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl,
|
|||
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
if (IsSetter)
|
||||
Actions.CodeCompleteObjCPropertySetter(getCurScope(), ClassDecl,
|
||||
Methods, NumMethods);
|
||||
Actions.CodeCompleteObjCPropertySetter(getCurScope(), ClassDecl);
|
||||
else
|
||||
Actions.CodeCompleteObjCPropertyGetter(getCurScope(), ClassDecl,
|
||||
Methods, NumMethods);
|
||||
Actions.CodeCompleteObjCPropertyGetter(getCurScope(), ClassDecl);
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
|
|
|
@ -4171,9 +4171,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
|
|||
}
|
||||
|
||||
|
||||
void Sema::CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl,
|
||||
Decl **Methods,
|
||||
unsigned NumMethods) {
|
||||
void Sema::CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl) {
|
||||
typedef CodeCompletionResult Result;
|
||||
|
||||
// Try to find the interface where getters might live.
|
||||
|
@ -4191,19 +4189,6 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl,
|
|||
ResultBuilder Results(*this, CodeCompletionContext::CCC_Other);
|
||||
Results.EnterNewScope();
|
||||
|
||||
// FIXME: We need to do this because Objective-C methods don't get
|
||||
// pushed into DeclContexts early enough. Argh!
|
||||
for (unsigned I = 0; I != NumMethods; ++I) {
|
||||
if (ObjCMethodDecl *Method
|
||||
= dyn_cast_or_null<ObjCMethodDecl>(Methods[I]))
|
||||
if (Method->isInstanceMethod() &&
|
||||
isAcceptableObjCMethod(Method, MK_ZeroArgSelector, 0, 0)) {
|
||||
Result R = Result(Method, 0);
|
||||
R.AllParametersAreInformative = true;
|
||||
Results.MaybeAddResult(R, CurContext);
|
||||
}
|
||||
}
|
||||
|
||||
VisitedSelectorSet Selectors;
|
||||
AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
|
||||
/*AllowSameLength=*/true, Results);
|
||||
|
@ -4213,9 +4198,7 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl,
|
|||
Results.data(),Results.size());
|
||||
}
|
||||
|
||||
void Sema::CodeCompleteObjCPropertySetter(Scope *S, Decl *ObjCImplDecl,
|
||||
Decl **Methods,
|
||||
unsigned NumMethods) {
|
||||
void Sema::CodeCompleteObjCPropertySetter(Scope *S, Decl *ObjCImplDecl) {
|
||||
typedef CodeCompletionResult Result;
|
||||
|
||||
// Try to find the interface where setters might live.
|
||||
|
@ -4234,19 +4217,6 @@ void Sema::CodeCompleteObjCPropertySetter(Scope *S, Decl *ObjCImplDecl,
|
|||
ResultBuilder Results(*this, CodeCompletionContext::CCC_Other);
|
||||
Results.EnterNewScope();
|
||||
|
||||
// FIXME: We need to do this because Objective-C methods don't get
|
||||
// pushed into DeclContexts early enough. Argh!
|
||||
for (unsigned I = 0; I != NumMethods; ++I) {
|
||||
if (ObjCMethodDecl *Method
|
||||
= dyn_cast_or_null<ObjCMethodDecl>(Methods[I]))
|
||||
if (Method->isInstanceMethod() &&
|
||||
isAcceptableObjCMethod(Method, MK_OneArgSelector, 0, 0)) {
|
||||
Result R = Result(Method, 0);
|
||||
R.AllParametersAreInformative = true;
|
||||
Results.MaybeAddResult(R, CurContext);
|
||||
}
|
||||
}
|
||||
|
||||
VisitedSelectorSet Selectors;
|
||||
AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
|
||||
Selectors, /*AllowSameLength=*/true, Results);
|
||||
|
|
|
@ -1475,8 +1475,6 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
|||
Diag(L, diag::warn_missing_atend);
|
||||
}
|
||||
|
||||
DeclContext *DC = dyn_cast<DeclContext>(ClassDecl);
|
||||
|
||||
// FIXME: Remove these and use the ObjCContainerDecl/DeclContext.
|
||||
llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap;
|
||||
llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap;
|
||||
|
@ -1496,8 +1494,8 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
|||
Diag(Method->getLocation(), diag::err_duplicate_method_decl)
|
||||
<< Method->getDeclName();
|
||||
Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
|
||||
Method->setInvalidDecl();
|
||||
} else {
|
||||
DC->addDecl(Method);
|
||||
InsMap[Method->getSelector()] = Method;
|
||||
/// The following allows us to typecheck messages to "id".
|
||||
AddInstanceMethodToGlobalPool(Method);
|
||||
|
@ -1515,8 +1513,8 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
|||
Diag(Method->getLocation(), diag::err_duplicate_method_decl)
|
||||
<< Method->getDeclName();
|
||||
Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
|
||||
Method->setInvalidDecl();
|
||||
} else {
|
||||
DC->addDecl(Method);
|
||||
ClsMap[Method->getSelector()] = Method;
|
||||
/// The following allows us to typecheck messages to "Class".
|
||||
AddFactoryMethodToGlobalPool(Method);
|
||||
|
@ -1773,10 +1771,7 @@ Decl *Sema::ActOnMethodDeclaration(
|
|||
|
||||
const ObjCMethodDecl *InterfaceMD = 0;
|
||||
|
||||
// For implementations (which can be very "coarse grain"), we add the
|
||||
// method now. This allows the AST to implement lookup methods that work
|
||||
// incrementally (without waiting until we parse the @end). It also allows
|
||||
// us to flag multiple declaration errors as they occur.
|
||||
// Add the method now.
|
||||
if (ObjCImplementationDecl *ImpDecl =
|
||||
dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
|
||||
if (MethodType == tok::minus) {
|
||||
|
@ -1803,6 +1798,8 @@ Decl *Sema::ActOnMethodDeclaration(
|
|||
if (ObjCMethod->hasAttrs() &&
|
||||
containsInvalidMethodImplAttribute(ObjCMethod->getAttrs()))
|
||||
Diag(EndLoc, diag::warn_attribute_method_def);
|
||||
} else {
|
||||
cast<DeclContext>(ClassDecl)->addDecl(ObjCMethod);
|
||||
}
|
||||
if (PrevMethod) {
|
||||
// You can never have two method definitions with the same name.
|
||||
|
|
|
@ -131,6 +131,11 @@ static Rdar8595462_A * Rdar8595462_staticVar;
|
|||
}
|
||||
@end
|
||||
|
||||
@interface Rdar8062781
|
||||
+ (Foo*)getB;
|
||||
@property (readonly, nonatomic) Foo *blah;
|
||||
@end
|
||||
|
||||
// RUN: c-index-test -test-annotate-tokens=%s:1:1:118:1 %s -DIBOutlet='__attribute__((iboutlet))' -DIBAction='void)__attribute__((ibaction)' | FileCheck %s
|
||||
// CHECK: Punctuation: "@" [1:1 - 1:2] ObjCInterfaceDecl=Foo:1:12
|
||||
// CHECK: Keyword: "interface" [1:2 - 1:11] ObjCInterfaceDecl=Foo:1:12
|
||||
|
@ -305,17 +310,17 @@ static Rdar8595462_A * Rdar8595462_staticVar;
|
|||
// CHECK: Identifier: "anOutlet" [53:21 - 53:29] ObjCIvarDecl=anOutlet:53:21 (Definition)
|
||||
// CHECK: Punctuation: ";" [53:29 - 53:30] ObjCInterfaceDecl=IBOutletTests:51:12
|
||||
// CHECK: Punctuation: "}" [54:1 - 54:2] ObjCInterfaceDecl=IBOutletTests:51:12
|
||||
// CHECK: Punctuation: "-" [55:1 - 55:2] ObjCInterfaceDecl=IBOutletTests:51:12
|
||||
// CHECK: Punctuation: "(" [55:3 - 55:4] ObjCInterfaceDecl=IBOutletTests:51:12
|
||||
// CHECK: Identifier: "IBAction" [55:4 - 55:12] macro instantiation=IBAction
|
||||
// CHECK: Punctuation: ")" [55:12 - 55:13] ObjCInterfaceDecl=IBOutletTests:51:12
|
||||
// CHECK: Identifier: "actionMethod" [55:14 - 55:26] ObjCInterfaceDecl=IBOutletTests:51:12
|
||||
// CHECK: Punctuation: ":" [55:26 - 55:27] ObjCInterfaceDecl=IBOutletTests:51:12
|
||||
// CHECK: Punctuation: "(" [55:27 - 55:28] ObjCInterfaceDecl=IBOutletTests:51:12
|
||||
// CHECK: Identifier: "id" [55:28 - 55:30] ObjCInterfaceDecl=IBOutletTests:51:12
|
||||
// CHECK: Punctuation: ")" [55:30 - 55:31] ObjCInterfaceDecl=IBOutletTests:51:12
|
||||
// CHECK: Identifier: "arg" [55:31 - 55:34] ObjCInterfaceDecl=IBOutletTests:51:12
|
||||
// CHECK: Punctuation: ";" [55:34 - 55:35] ObjCInterfaceDecl=IBOutletTests:51:12
|
||||
// CHECK: Punctuation: "-" [55:1 - 55:2] ObjCInstanceMethodDecl=actionMethod::55:1
|
||||
// CHECK: Punctuation: "(" [55:3 - 55:4] ObjCInstanceMethodDecl=actionMethod::55:1
|
||||
// CHECK: Identifier: "IBAction" [55:4 - 55:12] macro instantiation=IBAction:146:9
|
||||
// CHECK: Punctuation: ")" [55:12 - 55:13] ObjCInstanceMethodDecl=actionMethod::55:1
|
||||
// CHECK: Identifier: "actionMethod" [55:14 - 55:26] ObjCInstanceMethodDecl=actionMethod::55:1
|
||||
// CHECK: Punctuation: ":" [55:26 - 55:27] ObjCInstanceMethodDecl=actionMethod::55:1
|
||||
// CHECK: Punctuation: "(" [55:27 - 55:28] ObjCInstanceMethodDecl=actionMethod::55:1
|
||||
// CHECK: Identifier: "id" [55:28 - 55:30] TypeRef=id:0:0
|
||||
// CHECK: Punctuation: ")" [55:30 - 55:31] ParmDecl=arg:55:31 (Definition)
|
||||
// CHECK: Identifier: "arg" [55:31 - 55:34] ParmDecl=arg:55:31 (Definition)
|
||||
// CHECK: Punctuation: ";" [55:34 - 55:35] ObjCInstanceMethodDecl=actionMethod::55:1
|
||||
// CHECK: Punctuation: "@" [56:1 - 56:2] ObjCPropertyDecl=aPropOutlet:56:26
|
||||
// CHECK: Keyword: "property" [56:2 - 56:10] ObjCPropertyDecl=aPropOutlet:56:26
|
||||
// CHECK: Identifier: "IBOutlet" [56:11 - 56:19] macro instantiation=IBOutlet
|
||||
|
@ -519,3 +524,27 @@ static Rdar8595462_A * Rdar8595462_staticVar;
|
|||
// CHECK-INSIDE_BLOCK: Identifier: "a" [128:18 - 128:19] VarDecl=a:128:18 (Definition)
|
||||
// CHECK-INSIDE_BLOCK: Punctuation: "=" [128:20 - 128:21] VarDecl=a:128:18 (Definition)
|
||||
// CHECK-INSIDE_BLOCK: Identifier: "self" [128:22 - 128:26] DeclRefExpr=self:0:0
|
||||
|
||||
// RUN: c-index-test -test-annotate-tokens=%s:134:1:137:1 %s -DIBOutlet='__attribute__((iboutlet))' -DIBAction='void)__attribute__((ibaction)' | FileCheck -check-prefix=CHECK-PROP-AFTER-METHOD %s
|
||||
// CHECK-PROP-AFTER-METHOD: Punctuation: "@" [134:1 - 134:2] ObjCInterfaceDecl=Rdar8062781:134:12
|
||||
// CHECK-PROP-AFTER-METHOD: Keyword: "interface" [134:2 - 134:11] ObjCInterfaceDecl=Rdar8062781:134:12
|
||||
// CHECK-PROP-AFTER-METHOD: Identifier: "Rdar8062781" [134:12 - 134:23] ObjCInterfaceDecl=Rdar8062781:134:12
|
||||
// CHECK-PROP-AFTER-METHOD: Punctuation: "+" [135:1 - 135:2] ObjCClassMethodDecl=getB:135:1
|
||||
// CHECK-PROP-AFTER-METHOD: Punctuation: "(" [135:3 - 135:4] ObjCClassMethodDecl=getB:135:1
|
||||
// CHECK-PROP-AFTER-METHOD: Identifier: "Foo" [135:4 - 135:7] ObjCClassRef=Foo:1:12
|
||||
// CHECK-PROP-AFTER-METHOD: Punctuation: "*" [135:7 - 135:8] ObjCClassMethodDecl=getB:135:1
|
||||
// CHECK-PROP-AFTER-METHOD: Punctuation: ")" [135:8 - 135:9] ObjCClassMethodDecl=getB:135:1
|
||||
// CHECK-PROP-AFTER-METHOD: Identifier: "getB" [135:9 - 135:13] ObjCClassMethodDecl=getB:135:1
|
||||
// CHECK-PROP-AFTER-METHOD: Punctuation: ";" [135:13 - 135:14] ObjCClassMethodDecl=getB:135:1
|
||||
// CHECK-PROP-AFTER-METHOD: Punctuation: "@" [136:1 - 136:2] ObjCPropertyDecl=blah:136:38
|
||||
// CHECK-PROP-AFTER-METHOD: Keyword: "property" [136:2 - 136:10] ObjCPropertyDecl=blah:136:38
|
||||
// CHECK-PROP-AFTER-METHOD: Punctuation: "(" [136:11 - 136:12] ObjCPropertyDecl=blah:136:38
|
||||
// CHECK-PROP-AFTER-METHOD: Identifier: "readonly" [136:12 - 136:20] ObjCPropertyDecl=blah:136:38
|
||||
// CHECK-PROP-AFTER-METHOD: Punctuation: "," [136:20 - 136:21] ObjCPropertyDecl=blah:136:38
|
||||
// CHECK-PROP-AFTER-METHOD: Identifier: "nonatomic" [136:22 - 136:31] ObjCPropertyDecl=blah:136:38
|
||||
// CHECK-PROP-AFTER-METHOD: Punctuation: ")" [136:31 - 136:32] ObjCPropertyDecl=blah:136:38
|
||||
// CHECK-PROP-AFTER-METHOD: Identifier: "Foo" [136:33 - 136:36] ObjCClassRef=Foo:1:12
|
||||
// CHECK-PROP-AFTER-METHOD: Punctuation: "*" [136:37 - 136:38] ObjCPropertyDecl=blah:136:38
|
||||
// CHECK-PROP-AFTER-METHOD: Identifier: "blah" [136:38 - 136:42] ObjCPropertyDecl=blah:136:38
|
||||
// CHECK-PROP-AFTER-METHOD: Punctuation: ";" [136:42 - 136:43] ObjCInterfaceDecl=Rdar8062781:134:12
|
||||
// CHECK-PROP-AFTER-METHOD: Punctuation: "@" [137:1 - 137:2] ObjCInterfaceDecl=Rdar8062781:134:12
|
||||
|
|
|
@ -95,9 +95,9 @@ int test_multi_declaration(void) {
|
|||
// CHECK: usrs.m c:objc(cs)Foo Extent=[25:1 - 32:5]
|
||||
// CHECK: usrs.m c:objc(cs)Foo@x Extent=[26:6 - 26:7]
|
||||
// CHECK: usrs.m c:objc(cs)Foo@y Extent=[27:6 - 27:7]
|
||||
// CHECK: usrs.m c:objc(cs)Foo(py)d1 Extent=[31:1 - 31:17]
|
||||
// CHECK: usrs.m c:objc(cs)Foo(im)godzilla Extent=[29:1 - 29:17]
|
||||
// CHECK: usrs.m c:objc(cs)Foo(cm)kingkong Extent=[30:1 - 30:17]
|
||||
// CHECK: usrs.m c:objc(cs)Foo(py)d1 Extent=[31:1 - 31:17]
|
||||
// CHECK: usrs.m c:objc(cs)Foo(im)d1 Extent=[31:15 - 31:17]
|
||||
// CHECK: usrs.m c:objc(cs)Foo(im)setD1: Extent=[31:15 - 31:17]
|
||||
// CHECK: usrs.m c:usrs.m@352objc(cs)Foo(im)setD1:@d1 Extent=[31:15 - 31:17]
|
||||
|
@ -160,11 +160,11 @@ int test_multi_declaration(void) {
|
|||
// CHECK-source: usrs.m:26:3: TypeRef=id:0:0 Extent=[26:3 - 26:5]
|
||||
// CHECK-source: usrs.m:27:6: ObjCIvarDecl=y:27:6 (Definition) Extent=[27:6 - 27:7]
|
||||
// CHECK-source: usrs.m:27:3: TypeRef=id:0:0 Extent=[27:3 - 27:5]
|
||||
// CHECK-source: usrs.m:31:15: ObjCPropertyDecl=d1:31:15 Extent=[31:1 - 31:17]
|
||||
// CHECK-source: usrs.m:29:1: ObjCInstanceMethodDecl=godzilla:29:1 Extent=[29:1 - 29:17]
|
||||
// CHECK-source: usrs.m:29:4: TypeRef=id:0:0 Extent=[29:4 - 29:6]
|
||||
// CHECK-source: usrs.m:30:1: ObjCClassMethodDecl=kingkong:30:1 Extent=[30:1 - 30:17]
|
||||
// CHECK-source: usrs.m:30:4: TypeRef=id:0:0 Extent=[30:4 - 30:6]
|
||||
// CHECK-source: usrs.m:31:15: ObjCPropertyDecl=d1:31:15 Extent=[31:1 - 31:17]
|
||||
// CHECK-source: usrs.m:31:15: ObjCInstanceMethodDecl=d1:31:15 Extent=[31:15 - 31:17]
|
||||
// CHECK-source: usrs.m:31:15: ObjCInstanceMethodDecl=setD1::31:15 Extent=[31:15 - 31:17]
|
||||
// CHECK-source: usrs.m:31:15: ParmDecl=d1:31:15 (Definition) Extent=[31:15 - 31:17]
|
||||
|
|
Loading…
Reference in New Issue