diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 18 | ||||
-rw-r--r-- | lib/Parse/ParseInit.cpp | 55 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 104 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 63 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 114 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 477 |
6 files changed, 562 insertions, 269 deletions
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 27696c438f..ef35dcb3f6 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -268,11 +268,11 @@ Parser::OwningExprResult Parser::ParseAssignmentExpression() { /// expressions and other binary operators for these expressions as well. Parser::OwningExprResult Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc, - SourceLocation NameLoc, - IdentifierInfo *ReceiverName, + SourceLocation SuperLoc, + TypeTy *ReceiverType, ExprArg ReceiverExpr) { - OwningExprResult R(ParseObjCMessageExpressionBody(LBracLoc, NameLoc, - ReceiverName, + OwningExprResult R(ParseObjCMessageExpressionBody(LBracLoc, SuperLoc, + ReceiverType, move(ReceiverExpr))); if (R.isInvalid()) return move(R); R = ParsePostfixExpressionSuffix(move(R)); @@ -481,7 +481,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// [OBJC] '@encode' '(' type-name ')' /// [OBJC] objc-string-literal /// [C++] simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3] -/// [C++] typename-specifier '(' expression-list[opt] ')' [TODO] +/// [C++] typename-specifier '(' expression-list[opt] ')' [C++ 5.2.3] /// [C++] 'const_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] /// [C++] 'dynamic_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] /// [C++] 'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] @@ -501,14 +501,14 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// /// id-expression: [C++ 5.1] /// unqualified-id -/// qualified-id [TODO] +/// qualified-id /// /// unqualified-id: [C++ 5.1] /// identifier /// operator-function-id -/// conversion-function-id [TODO] -/// '~' class-name [TODO] -/// template-id [TODO] +/// conversion-function-id +/// '~' class-name +/// template-id /// /// new-expression: [C++ 5.3.4] /// '::'[opt] 'new' new-placement[opt] new-type-id diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp index 123908d25a..b0735b3cab 100644 --- a/lib/Parse/ParseInit.cpp +++ b/lib/Parse/ParseInit.cpp @@ -129,13 +129,16 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() { // send to 'super', parse this as a message send expression. if (getLang().ObjC1 && Tok.is(tok::identifier)) { IdentifierInfo *II = Tok.getIdentifierInfo(); - + SourceLocation IILoc = Tok.getLocation(); // Three cases. This is a message send to a type: [type foo] // This is a message send to super: [super foo] // This is a message sent to an expr: [super.bar foo] - if (Actions.getTypeName(*II, Tok.getLocation(), CurScope) || - (II == Ident_super && GetLookAheadToken(1).isNot(tok::period) && - CurScope->isInObjcMethodScope())) { + switch (Action::ObjCMessageKind Kind + = Actions.getObjCMessageKind(CurScope, II, IILoc, + II == Ident_super, + NextToken().is(tok::period))) { + case Action::ObjCSuperMessage: + case Action::ObjCClassMessage: { // If we have exactly one array designator, this used the GNU // 'designation: array-designator' extension, otherwise there should be no // designators at all! @@ -146,9 +149,47 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() { else if (Desig.getNumDesignators() > 0) Diag(Tok, diag::err_expected_equal_designator); - SourceLocation NameLoc = ConsumeToken(); - return ParseAssignmentExprWithObjCMessageExprStart( - StartLoc, NameLoc, II, ExprArg(Actions)); + if (Kind == Action::ObjCSuperMessage) + return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, + ConsumeToken(), + 0, + ExprArg(Actions)); + + // FIXME: This code is redundant with ParseObjCMessageExpr. + // Create the type that corresponds to the identifier (which + // names an Objective-C class). + TypeTy *Type = 0; + if (TypeTy *TyName = Actions.getTypeName(*II, IILoc, CurScope)) { + DeclSpec DS; + const char *PrevSpec = 0; + unsigned DiagID = 0; + if (!DS.SetTypeSpecType(DeclSpec::TST_typename, IILoc, PrevSpec, + DiagID, TyName)) { + DS.SetRangeEnd(IILoc); + Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); + TypeResult Ty = Actions.ActOnTypeName(CurScope, DeclaratorInfo); + if (!Ty.isInvalid()) + Type = Ty.get(); + } + } + + ConsumeToken(); // The identifier. + if (!Type) { + SkipUntil(tok::r_square); + return ExprError(); + } + + return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, + SourceLocation(), + Type, + ExprArg(Actions)); + } + + case Action::ObjCInstanceMessage: + // Fall through; we'll just parse the expression and + // (possibly) treat this like an Objective-C message send + // later. + break; } } diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 057907d112..56937a66cd 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -1714,7 +1714,7 @@ Parser::OwningExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { /// objc-message-expr: /// '[' objc-receiver objc-message-args ']' /// -/// objc-receiver: +/// objc-receiver: [C] /// 'super' /// expression /// class-name @@ -1730,11 +1730,39 @@ Parser::OwningExprResult Parser::ParseObjCMessageExpression() { Name == Ident_super, NextToken().is(tok::period))) { case Action::ObjCSuperMessage: - case Action::ObjCClassMessage: - return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), Name, + return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), 0, ExprArg(Actions)); + + case Action::ObjCClassMessage: { + // Create the type that corresponds to the identifier (which + // names an Objective-C class). + TypeTy *Type = 0; + if (TypeTy *TyName = Actions.getTypeName(*Name, NameLoc, CurScope)) { + DeclSpec DS; + const char *PrevSpec = 0; + unsigned DiagID = 0; + if (!DS.SetTypeSpecType(DeclSpec::TST_typename, NameLoc, PrevSpec, + DiagID, TyName)) { + DS.SetRangeEnd(NameLoc); + Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); + TypeResult Ty = Actions.ActOnTypeName(CurScope, DeclaratorInfo); + if (!Ty.isInvalid()) + Type = Ty.get(); + } + } + + ConsumeToken(); // The identifier. + if (!Type) { + SkipUntil(tok::r_square); + return ExprError(); + } + + return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), Type, + ExprArg(Actions)); + } case Action::ObjCInstanceMessage: + // Fall through to parse an expression. break; } } @@ -1746,12 +1774,29 @@ Parser::OwningExprResult Parser::ParseObjCMessageExpression() { return move(Res); } - return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), - 0, move(Res)); + return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), 0, + move(Res)); } -/// ParseObjCMessageExpressionBody - Having parsed "'[' objc-receiver", parse -/// the rest of a message expression. +/// \brief Parse the remainder of an Objective-C message following the +/// '[' objc-receiver. +/// +/// This routine handles sends to super, class messages (sent to a +/// class name), and instance messages (sent to an object), and the +/// target is represented by \p SuperLoc, \p ReceiverType, or \p +/// ReceiverExpr, respectively. Only one of these parameters may have +/// a valid value. +/// +/// \param LBracLoc The location of the opening '['. +/// +/// \param SuperLoc If this is a send to 'super', the location of the +/// 'super' keyword that indicates a send to the superclass. +/// +/// \param ReceiverType If this is a class message, the type of the +/// class we are sending a message to. +/// +/// \param ReceiverExpr If this is an instance message, the expression +/// used to compute the receiver object. /// /// objc-message-args: /// objc-selector @@ -1773,13 +1818,14 @@ Parser::OwningExprResult Parser::ParseObjCMessageExpression() { /// Parser::OwningExprResult Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, - SourceLocation NameLoc, - IdentifierInfo *ReceiverName, + SourceLocation SuperLoc, + TypeTy *ReceiverType, ExprArg ReceiverExpr) { if (Tok.is(tok::code_completion)) { - if (ReceiverName) - Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverName, NameLoc, - 0, 0); + if (SuperLoc.isValid()) + Actions.CodeCompleteObjCSuperMessage(CurScope, SuperLoc, 0, 0); + else if (ReceiverType) + Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverType, 0, 0); else Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get(), 0, 0); @@ -1825,8 +1871,12 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, // Code completion after each argument. if (Tok.is(tok::code_completion)) { - if (ReceiverName) - Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverName, NameLoc, + if (SuperLoc.isValid()) + Actions.CodeCompleteObjCSuperMessage(CurScope, SuperLoc, + KeyIdents.data(), + KeyIdents.size()); + else if (ReceiverType) + Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverType, KeyIdents.data(), KeyIdents.size()); else @@ -1887,15 +1937,23 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, KeyIdents.push_back(selIdent); Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]); - // We've just parsed a keyword message. - if (ReceiverName) - return Owned(Actions.ActOnClassMessage(CurScope, ReceiverName, Sel, - LBracLoc, NameLoc, SelectorLoc, - RBracLoc, - KeyExprs.take(), KeyExprs.size())); - return Owned(Actions.ActOnInstanceMessage(ReceiverExpr.release(), Sel, - LBracLoc, SelectorLoc, RBracLoc, - KeyExprs.take(), KeyExprs.size())); + if (SuperLoc.isValid()) + return Actions.ActOnSuperMessage(CurScope, SuperLoc, Sel, + LBracLoc, SelectorLoc, RBracLoc, + Action::MultiExprArg(Actions, + KeyExprs.take(), + KeyExprs.size())); + else if (ReceiverType) + return Actions.ActOnClassMessage(CurScope, ReceiverType, Sel, + LBracLoc, SelectorLoc, RBracLoc, + Action::MultiExprArg(Actions, + KeyExprs.take(), + KeyExprs.size())); + return Actions.ActOnInstanceMessage(CurScope, move(ReceiverExpr), Sel, + LBracLoc, SelectorLoc, RBracLoc, + Action::MultiExprArg(Actions, + KeyExprs.take(), + KeyExprs.size())); } Parser::OwningExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) { diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 1506d8c2dc..a7e402dfcb 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -3872,22 +3872,47 @@ public: bool IsSuper, bool HasTrailingDot); - // ActOnClassMessage - used for both unary and keyword messages. - // ArgExprs is optional - if it is present, the number of expressions - // is obtained from NumArgs. - virtual ExprResult ActOnClassMessage( - Scope *S, - IdentifierInfo *receivingClassName, Selector Sel, SourceLocation lbrac, - SourceLocation receiverLoc, SourceLocation selectorLoc,SourceLocation rbrac, - ExprTy **ArgExprs, unsigned NumArgs); - - // ActOnInstanceMessage - used for both unary and keyword messages. - // ArgExprs is optional - if it is present, the number of expressions - // is obtained from NumArgs. - virtual ExprResult ActOnInstanceMessage( - ExprTy *receiver, Selector Sel, - SourceLocation lbrac, SourceLocation receiverLoc, SourceLocation rbrac, - ExprTy **ArgExprs, unsigned NumArgs); + virtual OwningExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args); + + OwningExprResult BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, + QualType ReceiverType, + SourceLocation SuperLoc, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args); + + virtual OwningExprResult ActOnClassMessage(Scope *S, + TypeTy *Receiver, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args); + + OwningExprResult BuildInstanceMessage(ExprArg Receiver, + QualType ReceiverType, + SourceLocation SuperLoc, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args); + + virtual OwningExprResult ActOnInstanceMessage(Scope *S, + ExprArg Receiver, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args); + /// ActOnPragmaPack - Called on well formed #pragma pack(...). virtual void ActOnPragmaPack(PragmaPackKind Kind, @@ -4301,8 +4326,10 @@ public: DeclPtrTy *Methods, unsigned NumMethods); - virtual void CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName, - SourceLocation FNameLoc, + virtual void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, + IdentifierInfo **SelIdents, + unsigned NumSelIdents); + virtual void CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver, IdentifierInfo **SelIdents, unsigned NumSelIdents); virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index cb60f0aba1..e71f8c84eb 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -2947,62 +2947,82 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { .Default(0); } -void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName, - SourceLocation FNameLoc, +void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, IdentifierInfo **SelIdents, unsigned NumSelIdents) { - typedef CodeCompleteConsumer::Result Result; ObjCInterfaceDecl *CDecl = 0; + if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { + // Figure out which interface we're in. + CDecl = CurMethod->getClassInterface(); + if (!CDecl) + return; + + // Find the superclass of this class. + CDecl = CDecl->getSuperClass(); + if (!CDecl) + return; - if (FName->isStr("super")) { - // We're sending a message to "super". - if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { - // Figure out which interface we're in. - CDecl = CurMethod->getClassInterface(); - if (!CDecl) - return; - - // Find the superclass of this class. - CDecl = CDecl->getSuperClass(); - if (!CDecl) - return; + if (CurMethod->isInstanceMethod()) { + // We are inside an instance method, which means that the message + // send [super ...] is actually calling an instance method on the + // current object. Build the super expression and handle this like + // an instance method. + QualType SuperTy = Context.getObjCInterfaceType(CDecl); + SuperTy = Context.getObjCObjectPointerType(SuperTy); + OwningExprResult Super + = Owned(new (Context) ObjCSuperExpr(SuperLoc, SuperTy)); + return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(), + SelIdents, NumSelIdents); + } - if (CurMethod->isInstanceMethod()) { - // We are inside an instance method, which means that the message - // send [super ...] is actually calling an instance method on the - // current object. Build the super expression and handle this like - // an instance method. - QualType SuperTy = Context.getObjCInterfaceType(CDecl); - SuperTy = Context.getObjCObjectPointerType(SuperTy); - OwningExprResult Super - = Owned(new (Context) ObjCSuperExpr(FNameLoc, SuperTy)); - return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(), - SelIdents, NumSelIdents); - } + // Fall through to send to the superclass in CDecl. + } else { + // "super" may be the name of a type or variable. Figure out which + // it is. + IdentifierInfo *Super = &Context.Idents.get("super"); + NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, + LookupOrdinaryName); + if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) { + // "super" names an interface. Use it. + } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) { + if (const ObjCInterfaceType *Iface + = Context.getTypeDeclType(TD)->getAs<ObjCInterfaceType>()) + CDecl = Iface->getDecl(); + } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) { + // "super" names an unresolved type; we can't be more specific. + } else { + // Assume that "super" names some kind of value and parse that way. + CXXScopeSpec SS; + UnqualifiedId id; + id.setIdentifier(Super, SuperLoc); + OwningExprResult SuperExpr = ActOnIdExpression(S, SS, id, false, false); + return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(), + SelIdents, NumSelIdents); + } - // Okay, we're calling a factory method in our superclass. - } + // Fall through } + TypeTy *Receiver = 0; + if (CDecl) + Receiver = Context.getObjCInterfaceType(CDecl).getAsOpaquePtr(); + return CodeCompleteObjCClassMessage(S, Receiver, SelIdents, + NumSelIdents); +} + +void Sema::CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents) { + typedef CodeCompleteConsumer::Result Result; + ObjCInterfaceDecl *CDecl = 0; + // If the given name refers to an interface type, retrieve the // corresponding declaration. - if (!CDecl) - if (TypeTy *Ty = getTypeName(*FName, FNameLoc, S, 0, false)) { - QualType T = GetTypeFromParser(Ty, 0); - if (!T.isNull()) - if (const ObjCInterfaceType *Interface = T->getAs<ObjCInterfaceType>()) - CDecl = Interface->getDecl(); - } - - if (!CDecl && FName->isStr("super")) { - // "super" may be the name of a variable, in which case we are - // probably calling an instance method. - CXXScopeSpec SS; - UnqualifiedId id; - id.setIdentifier(FName, FNameLoc); - OwningExprResult Super = ActOnIdExpression(S, SS, id, false, false); - return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(), - SelIdents, NumSelIdents); + if (Receiver) { + QualType T = GetTypeFromParser(Receiver, 0); + if (!T.isNull()) + if (const ObjCInterfaceType *Interface = T->getAs<ObjCInterfaceType>()) + CDecl = Interface->getDecl(); } // Add all of the factory methods in this Objective-C class, its protocols, @@ -3013,7 +3033,7 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName, if (CDecl) AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents, CurContext, Results); - else if (FName->isStr("id")) { + else { // We're messaging "id" as a type; provide all class/factory methods. // If we have an external source, load the entire class method diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 6be1e1923a..d284100859 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/TypeLoc.h" #include "llvm/ADT/SmallString.h" #include "clang/Lex/Preprocessor.h" @@ -186,7 +187,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, return false; } - ReturnType = Method->getResultType(); + ReturnType = Method->getResultType().getNonReferenceType(); unsigned NumNamedArgs = Sel.getNumArgs(); // Method might have more arguments than selector indicates. This is due @@ -245,6 +246,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, } } + DiagnoseSentinelCalls(Method, lbrac, Args, NumArgs); return IsError; } @@ -585,153 +587,274 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, return ObjCInstanceMessage; } -// ActOnClassMessage - used for both unary and keyword messages. -// ArgExprs is optional - if it is present, the number of expressions -// is obtained from Sel.getNumArgs(). -Sema::ExprResult Sema:: -ActOnClassMessage(Scope *S, IdentifierInfo *receiverName, Selector Sel, - SourceLocation lbrac, SourceLocation receiverLoc, - SourceLocation selectorLoc, SourceLocation rbrac, - ExprTy **Args, unsigned NumArgs) { - assert(receiverName && "missing receiver class name"); - - Expr **ArgExprs = reinterpret_cast<Expr **>(Args); - ObjCInterfaceDecl *ClassDecl = 0; - bool isSuper = false; - - // Special case a message to super, which can be either a class message or an - // instance message, depending on what CurMethodDecl is. - if (receiverName->isStr("super")) { - if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { - ObjCInterfaceDecl *OID = CurMethod->getClassInterface(); - if (!OID) - return Diag(lbrac, diag::error_no_super_class_message) - << CurMethod->getDeclName(); - ClassDecl = OID->getSuperClass(); - if (ClassDecl == 0) - return Diag(lbrac, diag::error_no_super_class) << OID->getDeclName(); - if (CurMethod->isInstanceMethod()) { - QualType superTy = Context.getObjCInterfaceType(ClassDecl); - superTy = Context.getObjCObjectPointerType(superTy); - ExprResult ReceiverExpr = new (Context) ObjCSuperExpr(SourceLocation(), - superTy); - // We are really in an instance method, redirect. - return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac, - selectorLoc, rbrac, Args, NumArgs); - } - - // Otherwise, if this is a class method, try dispatching to our - // superclass, which is in ClassDecl. - isSuper = true; +Sema::OwningExprResult Sema::ActOnSuperMessage(Scope *S, + SourceLocation SuperLoc, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args) { + // Determine whether we are inside a method or not. + ObjCMethodDecl *Method = getCurMethodDecl(); + if (Method) { + ObjCInterfaceDecl *Class = Method->getClassInterface(); + if (!Class) { + Diag(SuperLoc, diag::error_no_super_class_message) + << Method->getDeclName(); + return ExprError(); } + + if (ObjCInterfaceDecl *Super = Class->getSuperClass()) { + // We are in a method whose class has a superclass, so 'super' + // is acting as a keyword. + if (Method->isInstanceMethod()) { + // Since we are in an instance method, this is an instance + // message to the superclass instance. + QualType SuperTy = Context.getObjCInterfaceType(Super); + SuperTy = Context.getObjCObjectPointerType(SuperTy); + return BuildInstanceMessage(ExprArg(*this), SuperTy, SuperLoc, + Sel, LBracLoc, SelectorLoc, RBracLoc, + move(Args)); + } + + // Since we are in a class method, this is a class message to + // the superclass. + return BuildClassMessage(/*ReceiverTypeInfo=*/0, + Context.getObjCInterfaceType(Super), + SuperLoc, Sel, LBracLoc, SelectorLoc, + RBracLoc, move(Args)); + } + + // The current class does not have a superclass. + Diag(SuperLoc, diag::error_no_super_class) << Class->getIdentifier(); + return ExprError(); } + + Diag(SuperLoc, diag::err_invalid_receiver_to_message_super); + return ExprError(); + +#if 0 + // We are not inside a method, or the method is in a class that has + // no superclass, so perform normal name lookup on "super". + IdentifierInfo &SuperId = Context.Idents.get("super"); + NamedDecl *Super = LookupSingleName(S, &SuperId, SuperLoc, + LookupOrdinaryName); + if (!Super) { + Diag(SuperLoc, diag::err_undeclared_var_use) << &SuperId; + return ExprError(); + } + + if (isa<TypeDecl>(Super) || isa<ObjCInterfaceDecl>(Super)) { + // Name lookup found a type named 'super'; create a class message + // sending to it. + QualType SuperType = + isa<TypeDecl>(Super)? Context.getTypeDeclType(cast<TypeDecl>(Super)) + : Context.getObjCInterfaceType(cast<ObjCInterfaceDecl>(Super)); + TypeSourceInfo *SuperTypeInfo + = Context.getTrivialTypeSourceInfo(SuperType, SuperLoc); + return BuildClassMessage(SuperTypeInfo, SuperType, + /*SuperLoc=*/SourceLocation(), + Sel, LBracLoc, SelectorLoc, RBracLoc, + move(Args)); + } + + // Assume that "super" is the name of a value of some + // sort. Type-check it as an id-expression. + CXXScopeSpec SS; + UnqualifiedId Id; + Id.setIdentifier(&SuperId, SuperLoc); + OwningExprResult Receiver = ActOnIdExpression(S, SS, Id, false, false); + if (Receiver.isInvalid() || !Receiver.get()) + return ExprError(); + + Expr *ReceiverExpr = static_cast<Expr *>(Receiver.get()); + return BuildInstanceMessage(move(Receiver), ReceiverExpr->getType(), + /*SuperLoc=*/SourceLocation(), + Sel, LBracLoc, SelectorLoc, RBracLoc, + move(Args)); +#endif +} + +/// \brief Build an Objective-C class message expression. +/// +/// This routine takes care of both normal class messages and +/// class messages to the superclass. +/// +/// \param ReceiverTypeInfo Type source information that describes the +/// receiver of this message. This may be NULL, in which case we are +/// sending to the superclass and \p SuperLoc must be a valid source +/// location. + +/// \param ReceiverType The type of the object receiving the +/// message. When \p ReceiverTypeInfo is non-NULL, this is the same +/// type as that refers to. For a superclass send, this is the type of +/// the superclass. +/// +/// \param SuperLoc The location of the "super" keyword in a +/// superclass message. +/// +/// \param Sel The selector to which the message is being sent. +/// +/// \param LBracLoc The location of the opening square bracket ']'. +/// +/// \param SelectorLoc The location of the first identifier in the selector. +/// +/// \param RBrac The location of the closing square bracket ']'. +/// +/// \param Args The message arguments. +Sema::OwningExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, + QualType ReceiverType, + SourceLocation SuperLoc, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg ArgsIn) { + assert(!ReceiverType->isDependentType() && + "Dependent class messages not yet implemented"); - if (ClassDecl == 0) - ClassDecl = getObjCInterfaceDecl(receiverName, receiverLoc, true); - - // The following code allows for the following GCC-ism: - // - // typedef XCElementDisplayRect XCElementGraphicsRect; - // - // @implementation XCRASlice - // - whatever { // Note that XCElementGraphicsRect is a typedef name. - // _sGraphicsDelegate =[[XCElementGraphicsRect alloc] init]; - // } - // - // If necessary, the following lookup could move to getObjCInterfaceDecl(). - if (!ClassDecl) { - NamedDecl *IDecl - = LookupSingleName(TUScope, receiverName, receiverLoc, - LookupOrdinaryName); - if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(IDecl)) - if (const ObjCInterfaceType *OCIT - = OCTD->getUnderlyingType()->getAs<ObjCInterfaceType>()) - ClassDecl = OCIT->getDecl(); - - if (!ClassDecl) { - // Give a better error message for invalid use of super. - if (receiverName->isStr("super")) - Diag(receiverLoc, diag::err_invalid_receiver_to_message_super); - else - Diag(receiverLoc, diag::err_invalid_receiver_to_message); - return true; - } + SourceLocation Loc = SuperLoc.isValid()? SuperLoc + : ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin(); + + // Find the class to which we are sending this message. + ObjCInterfaceDecl *Class = 0; + if (const ObjCInterfaceType *ClassType + = ReceiverType->getAs<ObjCInterfaceType>()) + Class = ClassType->getDecl(); + else { + Diag(Loc, diag::err_invalid_receiver_class_message) + << ReceiverType; + return ExprError(); } - assert(ClassDecl && "missing interface declaration"); + assert(Class && "We don't know which class we're messaging?"); + + // Find the method we are messaging. ObjCMethodDecl *Method = 0; - QualType returnType; - if (ClassDecl->isForwardDecl()) { - // A forward class used in messaging is tread as a 'Class' - Diag(lbrac, diag::warn_receiver_forward_class) << ClassDecl->getDeclName(); - Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac,rbrac)); + if (Class->isForwardDecl()) { + // A forward class used in messaging is treated as a 'Class' + Diag(Loc, diag::warn_receiver_forward_class) << Class->getDeclName(); + Method = LookupFactoryMethodInGlobalPool(Sel, + SourceRange(LBracLoc, RBracLoc)); if (Method) Diag(Method->getLocation(), diag::note_method_sent_forward_class) << Method->getDeclName(); } if (!Method) - Method = ClassDecl->lookupClassMethod(Sel); + Method = Class->lookupClassMethod(Sel); // If we have an implementation in scope, check "private" methods. if (!Method) - Method = LookupPrivateClassMethod(Sel, ClassDecl); + Method = LookupPrivateClassMethod(Sel, Class); - if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) - return true; + if (Method && DiagnoseUseOfDecl(Method, Loc)) + return ExprError(); - if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, true, - lbrac, rbrac, returnType)) - return true; + // Check the argument types and determine the result type. + QualType ReturnType; + unsigned NumArgs = ArgsIn.size(); + Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release()); + if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, true, + LBracLoc, RBracLoc, ReturnType)) { + for (unsigned I = 0; I != NumArgs; ++I) + Args[I]->Destroy(Context); + return ExprError(); + } - returnType = returnType.getNonReferenceType(); + // Construct the appropriate ObjCMessageExpr. + if (SuperLoc.isValid()) + return Owned(ObjCMessageExpr::Create(Context, ReturnType, LBracLoc, + SuperLoc, /*IsInstanceSuper=*/false, + ReceiverType, Sel, Method, Args, + NumArgs, RBracLoc)); - QualType ReceiverType = Context.getObjCInterfaceType(ClassDecl); - if (isSuper) - return ObjCMessageExpr::Create(Context, returnType, lbrac, receiverLoc, - /*IsInstanceSuper=*/false,ReceiverType, - Sel, Method, ArgExprs, NumArgs, rbrac); - - // If we have the ObjCInterfaceDecl* for the class that is receiving the - // message, use that to construct the ObjCMessageExpr. Otherwise pass on the - // IdentifierInfo* for the class. - TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(ReceiverType, - receiverLoc); - return ObjCMessageExpr::Create(Context, returnType, lbrac, TSInfo, Sel, - Method, ArgExprs, NumArgs, rbrac); + return Owned(ObjCMessageExpr::Create(Context, ReturnType, LBracLoc, + ReceiverTypeInfo, Sel, Method, Args, + NumArgs, RBracLoc)); } -// ActOnInstanceMessage - used for both unary and keyword messages. +// ActOnClassMessage - used for both unary and keyword messages. // ArgExprs is optional - if it is present, the number of expressions // is obtained from Sel.getNumArgs(). -Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, - SourceLocation lbrac, - SourceLocation receiverLoc, - SourceLocation rbrac, - ExprTy **Args, unsigned NumArgs) { - assert(receiver && "missing receiver expression"); |