diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2011-02-09 22:20:01 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2011-02-09 22:20:01 +0000 |
commit | 7f53253223b29d77f1e9c5c0ce93a19932761b77 (patch) | |
tree | 241f0561678ba7020b09d3088260ca62e378b2e5 | |
parent | bf36e25224b959595af84337339103ebc542ff8c (diff) |
Fix scoping of method declarations and issue
warning when same parameter name used multiple times.
// rdar://8877730
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125229 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticCommonKinds.td | 1 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 1 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 19 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 23 | ||||
-rw-r--r-- | test/Parser/objc-forcollection-neg-2.m | 2 | ||||
-rw-r--r-- | test/Parser/objc-forcollection-neg.m | 1 | ||||
-rw-r--r-- | test/Parser/objc-foreach-syntax.m | 3 | ||||
-rw-r--r-- | test/SemaObjC/method-prototype-scope.m | 38 |
8 files changed, 77 insertions, 11 deletions
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index 49504e6e22..85c64c5cef 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -44,6 +44,7 @@ def err_expected_colon_after_setter_name : Error< def ext_no_declarators : ExtWarn<"declaration does not declare anything">, InGroup<MissingDeclarations>; def err_param_redefinition : Error<"redefinition of parameter %0">; +def warn_method_param_redefinition : Warning<"redefinition of method parameter %0">; def err_invalid_storage_class_in_func_decl : Error< "invalid storage class specifier in function declarator">; def err_expected_namespace_name : Error<"expected namespace name">; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 8b24e925ed..4731ad8d27 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -4251,6 +4251,7 @@ public: }; Decl *ActOnMethodDeclaration( + Scope *S, SourceLocation BeginLoc, // location of the + or -. SourceLocation EndLoc, // location of the ; or {. tok::TokenKind MethodType, diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index af53d7d592..0aae43adb8 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -868,7 +868,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent); Decl *Result - = Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(), + = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), mType, IDecl, DSRet, ReturnType, Sel, 0, CParamInfo.data(), CParamInfo.size(), @@ -879,7 +879,9 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, llvm::SmallVector<IdentifierInfo *, 12> KeyIdents; llvm::SmallVector<Sema::ObjCArgInfo, 12> ArgInfos; - + ParseScope PrototypeScope(this, + Scope::FunctionPrototypeScope|Scope::DeclScope); + while (1) { Sema::ObjCArgInfo ArgInfo; @@ -976,18 +978,25 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // If attributes exist after the method, parse them. if (getLang().ObjC2) MaybeParseGNUAttributes(attrs); - - if (KeyIdents.size() == 0) + + if (KeyIdents.size() == 0) { + // Leave prototype scope. + PrototypeScope.Exit(); return 0; + } + Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(), &KeyIdents[0]); Decl *Result - = Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(), + = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), mType, IDecl, DSRet, ReturnType, Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), attrs.getList(), MethodImplKind, isVariadic); + // Leave prototype scope. + PrototypeScope.Exit(); + PD.complete(Result); return Result; } diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index a2f6b516be..a3d93ab85e 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1664,6 +1664,7 @@ bool containsInvalidMethodImplAttribute(const AttrVec &A) { } Decl *Sema::ActOnMethodDeclaration( + Scope *S, SourceLocation MethodLoc, SourceLocation EndLoc, tok::TokenKind MethodType, Decl *ClassDecl, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, @@ -1721,6 +1722,20 @@ Decl *Sema::ActOnMethodDeclaration( ArgType = adjustParameterType(ArgType); } + LookupResult R(*this, ArgInfo[i].Name, ArgInfo[i].NameLoc, + LookupOrdinaryName, ForRedeclaration); + LookupName(R, S); + if (R.isSingleResult()) { + NamedDecl *PrevDecl = R.getFoundDecl(); + if (S->isDeclScope(PrevDecl)) { + // FIXME. This should be an error; but will break projects. + Diag(ArgInfo[i].NameLoc, diag::warn_method_param_redefinition) + << ArgInfo[i].Name; + Diag(PrevDecl->getLocation(), + diag::note_previous_declaration); + } + } + ParmVarDecl* Param = ParmVarDecl::Create(Context, ObjCMethod, ArgInfo[i].NameLoc, ArgInfo[i].Name, ArgType, DI, @@ -1739,9 +1754,12 @@ Decl *Sema::ActOnMethodDeclaration( // Apply the attributes to the parameter. ProcessDeclAttributeList(TUScope, Param, ArgInfo[i].ArgAttrs); + S->AddDecl(Param); + IdResolver.AddDecl(Param); + Params.push_back(Param); } - + for (unsigned i = 0, e = CNumArgs; i != e; ++i) { ParmVarDecl *Param = cast<ParmVarDecl>(CParamInfo[i].Param); QualType ArgType = Param->getType(); @@ -1757,8 +1775,7 @@ Decl *Sema::ActOnMethodDeclaration( Param->setInvalidDecl(); } Param->setDeclContext(ObjCMethod); - if (Param->getDeclName()) - IdResolver.RemoveDecl(Param); + Params.push_back(Param); } diff --git a/test/Parser/objc-forcollection-neg-2.m b/test/Parser/objc-forcollection-neg-2.m index e02c51c1ba..6aa74c9c0b 100644 --- a/test/Parser/objc-forcollection-neg-2.m +++ b/test/Parser/objc-forcollection-neg-2.m @@ -1,11 +1,11 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s typedef struct objc_class *Class; +struct __objcFastEnumerationState; typedef struct objc_object { Class isa; } *id; - @protocol P @end @interface MyList diff --git a/test/Parser/objc-forcollection-neg.m b/test/Parser/objc-forcollection-neg.m index 0ba093efa0..d896c35f3f 100644 --- a/test/Parser/objc-forcollection-neg.m +++ b/test/Parser/objc-forcollection-neg.m @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s +struct __objcFastEnumerationState; typedef struct objc_class *Class; typedef struct objc_object { Class isa; diff --git a/test/Parser/objc-foreach-syntax.m b/test/Parser/objc-foreach-syntax.m index 943540ef1f..cc82725b17 100644 --- a/test/Parser/objc-foreach-syntax.m +++ b/test/Parser/objc-foreach-syntax.m @@ -1,7 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s - - +struct __objcFastEnumerationState; @implementation MyList // expected-warning {{cannot find interface declaration for 'MyList'}} - (unsigned int)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state objects: (id *)items count:(unsigned int)stackcount { diff --git a/test/SemaObjC/method-prototype-scope.m b/test/SemaObjC/method-prototype-scope.m new file mode 100644 index 0000000000..2184172f35 --- /dev/null +++ b/test/SemaObjC/method-prototype-scope.m @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// rdar://8877730 + +int object; + +@class NSString, NSArray; + +@interface Test +- Func:(int)XXXX, id object; + +- doSomethingElseWith:(id)object; + +- (NSString *)doSomethingWith:(NSString *)object and:(NSArray *)object; // expected-warning {{redefinition of method parameter 'object'}} \ + // expected-note {{previous declaration is here}} +@end + +@implementation Test + +- (NSString *)doSomethingWith:(NSString *)object and:(NSArray *)object // expected-warning {{redefinition of method parameter 'object'}} \ + // expected-note {{previous declaration is here}} +{ + return object; // expected-warning {{incompatible pointer types returning 'NSArray *' from a function with result type 'NSString *'}} +} + +- Func:(int)XXXX, id object { return object; } + +- doSomethingElseWith:(id)object { return object; } + +@end + +struct P; + +@interface Test1 +- doSomethingWith:(struct S *)object and:(struct P *)obj; // expected-warning {{declaration of 'struct S' will not be visible outside of this function}} +@end + +int obj; |