diff options
author | Steve Naroff <snaroff@apple.com> | 2008-11-19 15:54:23 +0000 |
---|---|---|
committer | Steve Naroff <snaroff@apple.com> | 2008-11-19 15:54:23 +0000 |
commit | 5cb93b8bf009c4b0ae09b71ba85f54b2a7ea8022 (patch) | |
tree | 94dac43df0a39c26d55980ad047066292ea716f8 /lib/Sema/SemaExprObjC.cpp | |
parent | 74253736184c0717a0649922551bf9d8b6815651 (diff) |
Fix <rdar://problem/6150376> [sema] crash on invalid message send.
The core fix in Sema::ActOnClassMessage(). All the other changes have to do with passing down the SourceLocation for the receiver (to properly position the cursor when producing an error diagnostic).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59639 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExprObjC.cpp')
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 51 |
1 files changed, 34 insertions, 17 deletions
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 8bacea14bf..786d74c950 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -176,7 +176,8 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, Sema::ExprResult Sema::ActOnClassMessage( Scope *S, IdentifierInfo *receiverName, Selector Sel, - SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args, unsigned NumArgs) + SourceLocation lbrac, SourceLocation receiverLoc, SourceLocation rbrac, + ExprTy **Args, unsigned NumArgs) { assert(receiverName && "missing receiver class name"); @@ -184,22 +185,38 @@ Sema::ExprResult Sema::ActOnClassMessage( ObjCInterfaceDecl* ClassDecl = 0; bool isSuper = false; - if (receiverName == SuperID && getCurMethodDecl()) { - isSuper = true; - ClassDecl = getCurMethodDecl()->getClassInterface()->getSuperClass(); - if (!ClassDecl) - return Diag(lbrac, diag::error_no_super_class) - << getCurMethodDecl()->getClassInterface()->getName(); - if (getCurMethodDecl()->isInstance()) { - QualType superTy = Context.getObjCInterfaceType(ClassDecl); - superTy = Context.getPointerType(superTy); - ExprResult ReceiverExpr = new ObjCSuperExpr(SourceLocation(), superTy); - // We are really in an instance method, redirect. - return ActOnInstanceMessage(ReceiverExpr.Val, Sel, lbrac, rbrac, - Args, NumArgs); - } - // We are sending a message to 'super' within a class method. Do nothing, - // the receiver will pass through as 'super' (how convenient:-). + if (receiverName == SuperID) { + if (getCurMethodDecl()) { + isSuper = true; + ClassDecl = getCurMethodDecl()->getClassInterface()->getSuperClass(); + if (!ClassDecl) + return Diag(lbrac, diag::error_no_super_class, + getCurMethodDecl()->getClassInterface()->getName()); + if (getCurMethodDecl()->isInstance()) { + QualType superTy = Context.getObjCInterfaceType(ClassDecl); + superTy = Context.getPointerType(superTy); + ExprResult ReceiverExpr = new ObjCSuperExpr(SourceLocation(), superTy); + // We are really in an instance method, redirect. + return ActOnInstanceMessage(ReceiverExpr.Val, Sel, lbrac, rbrac, + Args, NumArgs); + } + // We are sending a message to 'super' within a class method. Do nothing, + // the receiver will pass through as 'super' (how convenient:-). + } else { + // 'super' has been used outside a method context. If a variable named + // 'super' has been declared, redirect. If not, produce a diagnostic. + Decl *SuperDecl = LookupDecl(receiverName, Decl::IDNS_Ordinary, S, false); + ValueDecl *VD = dyn_cast_or_null<ValueDecl>(SuperDecl); + if (VD) { + ExprResult ReceiverExpr = new DeclRefExpr(VD, VD->getType(), + receiverLoc); + // We are really in an instance method, redirect. + return ActOnInstanceMessage(ReceiverExpr.Val, Sel, lbrac, rbrac, + Args, NumArgs); + } + return Diag(receiverLoc, diag::err_undeclared_var_use, + receiverName->getName()); + } } else ClassDecl = getObjCInterfaceDecl(receiverName); |