From: Fariborz Jahanian Date: Thu, 8 Apr 2010 00:30:06 +0000 (+0000) Subject: Patch to implement gcc's cstyle arguments in objc X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4f4fd92c6c64ecbc65507f63ddd09211f732622c;p=clang Patch to implement gcc's cstyle arguments in objc methods. wip. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100734 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 4122aff91f..e8901b85d1 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -2306,7 +2306,7 @@ public: TypeTy *ReturnType, // the method return type. Selector Sel, // a unique name for the method. ObjCArgInfo *ArgInfo, // ArgInfo: Has 'Sel.getNumArgs()' entries. - llvm::SmallVectorImpl &Cdecls, // c-style args + DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args AttributeList *MethodAttrList, // optional // tok::objc_not_keyword, tok::objc_optional, tok::objc_required tok::ObjCKeywordKind impKind, diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 155e352073..cd42aee255 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -823,7 +823,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc, return DeclPtrTy(); } - llvm::SmallVector CargNames; + llvm::SmallVector CParamInfo; if (Tok.isNot(tok::colon)) { // If attributes exist after the method, parse them. if (getLang().ObjC2 && Tok.is(tok::kw___attribute)) @@ -834,7 +834,9 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc, DeclPtrTy Result = Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(), mType, IDecl, DSRet, ReturnType, Sel, - 0, CargNames, MethodAttrs.get(), + 0, + CParamInfo.data(), CParamInfo.size(), + MethodAttrs.get(), MethodImplKind); PD.complete(Result); return Result; @@ -897,7 +899,13 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc, // Parse the declarator. Declarator ParmDecl(DS, Declarator::PrototypeContext); ParseDeclarator(ParmDecl); - CargNames.push_back(ParmDecl); + IdentifierInfo *ParmII = ParmDecl.getIdentifier(); + DeclPtrTy Param = Actions.ActOnParamDeclarator(CurScope, ParmDecl); + CParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, + ParmDecl.getIdentifierLoc(), + Param, + 0)); + } // FIXME: Add support for optional parmameter list... @@ -913,7 +921,8 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc, DeclPtrTy Result = Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(), mType, IDecl, DSRet, ReturnType, Sel, - &ArgInfos[0], CargNames, + &ArgInfos[0], + CParamInfo.data(), CParamInfo.size(), MethodAttrs.get(), MethodImplKind, isVariadic); PD.complete(Result); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index a6bcc4375e..45574b9d69 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -3822,7 +3822,7 @@ public: // optional arguments. The number of types/arguments is obtained // from the Sel.getNumArgs(). ObjCArgInfo *ArgInfo, - llvm::SmallVectorImpl &Cdecls, + DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind, bool isVariadic = false); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 0c47e63d99..b422c83162 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1495,7 +1495,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( // optional arguments. The number of types/arguments is obtained // from the Sel.getNumArgs(). ObjCArgInfo *ArgInfo, - llvm::SmallVectorImpl &Cdecls, + DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind, bool isVariadic) { Decl *ClassDecl = classDecl.getAs(); @@ -1568,7 +1568,26 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( Params.push_back(Param); } - ObjCMethod->setMethodParams(Context, Params.data(), Sel.getNumArgs()); + for (unsigned i = 0, e = CNumArgs; i != e; ++i) { + ParmVarDecl *Param = CParamInfo[i].Param.getAs(); + QualType ArgType = Param->getType(); + if (ArgType.isNull()) + ArgType = Context.getObjCIdType(); + else + // Perform the default array/function conversions (C99 6.7.5.3p[7,8]). + ArgType = adjustParameterType(ArgType); + if (ArgType->isObjCInterfaceType()) { + Diag(Param->getLocation(), + diag::err_object_cannot_be_passed_returned_by_value) + << 1 << ArgType; + Param->setInvalidDecl(); + } + Param->setDeclContext(ObjCMethod); + IdResolver.RemoveDecl(Param); + Params.push_back(Param); + } + + ObjCMethod->setMethodParams(Context, Params.data(), Params.size()); ObjCMethod->setObjCDeclQualifier( CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier())); const ObjCMethodDecl *PrevMethod = 0; diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index d5a22ca15f..99db910a90 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -182,7 +182,15 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, ReturnType = Method->getResultType(); unsigned NumNamedArgs = Sel.getNumArgs(); - assert(NumArgs >= NumNamedArgs && "Too few arguments for selector!"); + // Method might have more arguments than selector indicates. This is due + // to addition of c-style arguments in method. + if (Method->param_size() > Sel.getNumArgs()) + NumNamedArgs = Method->param_size(); + // FIXME. This need be cleaned up. + if (NumArgs < NumNamedArgs) { + Diag(lbrac, diag::err_typecheck_call_too_few_args) << 2; + return false; + } bool IsError = false; for (unsigned i = 0; i < NumNamedArgs; i++) { diff --git a/test/SemaObjC/objc-cstyle-args-in-methods.m b/test/SemaObjC/objc-cstyle-args-in-methods.m new file mode 100644 index 0000000000..9f752959e9 --- /dev/null +++ b/test/SemaObjC/objc-cstyle-args-in-methods.m @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +@interface Foo +- (id)test:(id)one, id two; +- (id)bad:(id)one, id two, double three; +@end + +@implementation Foo +- (id)test:(id )one, id two {return two; } +- (id)bad:(id)one, id two, double three { return two; } +@end + + +int main() { + Foo *foo; + [foo test:@"One", @"Two"]; + [foo bad:@"One", @"Two"]; // expected-error {{too few arguments to method call}} + [foo bad:@"One", @"Two", 3.14]; + [foo bad:@"One", @"Two", 3.14, @"Two"]; // expected-error {{too many arguments to method call}} +}