def warn_objc_protocol_qualifier_missing_id : Warning<
"protocol qualifiers without 'id' is archaic">;
def err_objc_unknown_at : Error<"expected an Objective-C directive after '@'">;
-
+def err_illegal_super_cast : Error<
+ "cannot cast 'super' (it isn't an expression)">;
+
def err_objc_illegal_visibility_spec : Error<
"illegal visibility specification">;
def err_objc_illegal_interface_qual : Error<"illegal interface qualifier">;
"no super class declared in @interface for %0">;
def err_invalid_receiver_to_message : Error<
"invalid receiver to message expression">;
+def err_invalid_receiver_to_message_super : Error<
+ "'super' not valid when not in a method">;
def warn_bad_receiver_type : Warning<
"receiver type %0 is not 'id' or interface pointer, consider "
"casting it to 'id'">;
"@catch parameter is not a pointer to an interface type">;
def err_illegal_qualifiers_on_catch_parm : Error<
"illegal qualifiers on @catch parameter">;
-def err_illegal_super_cast : Error<
- "cannot cast 'super' (it isn't an expression)">;
def warn_setter_getter_impl_required : Warning<
"property %0 requires method %1 to be defined - "
"use @synthesize, @dynamic or provide a method implementation">;
return DeclPtrTy();
}
- virtual OwningExprResult ActOnClassPropertyRefExpr(
- IdentifierInfo &receiverName,
- IdentifierInfo &propertyName,
- SourceLocation &receiverNameLoc,
- SourceLocation &propertyNameLoc) {
+ virtual OwningExprResult
+ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
+ IdentifierInfo &propertyName,
+ SourceLocation receiverNameLoc,
+ SourceLocation propertyNameLoc) {
return ExprEmpty();
}
//===--------------------------------------------------------------------===//
// Objective-C Expressions
-
- bool isTokObjCMessageIdentifierReceiver() const {
- if (!Tok.is(tok::identifier))
- return false;
-
- IdentifierInfo *II = Tok.getIdentifierInfo();
- if (Actions.getTypeName(*II, Tok.getLocation(), CurScope))
- return true;
-
- return II == Ident_super;
- }
-
OwningExprResult ParseObjCAtExpression(SourceLocation AtLocation);
OwningExprResult ParseObjCStringLiteral(SourceLocation AtLoc);
OwningExprResult ParseObjCEncodeExpression(SourceLocation AtLoc);
IdentifierInfo &II = *Tok.getIdentifierInfo();
SourceLocation ILoc = ConsumeToken();
- // Support 'Class.property' notation. We don't use
- // isTokObjCMessageIdentifierReceiver(), since it allows 'super' (which is
- // inappropriate here).
+ // Support 'Class.property' and 'super.property' notation.
if (getLang().ObjC1 && Tok.is(tok::period) &&
- Actions.getTypeName(II, ILoc, CurScope)) {
+ (Actions.getTypeName(II, ILoc, CurScope) || II.isStr("super"))) {
SourceLocation DotLoc = ConsumeToken();
if (Tok.isNot(tok::identifier)) {
// returns the parsed type to the callee.
return OwningExprResult(Actions);
}
+
+
+ // Reject the cast of super idiom in ObjC.
+ if (Tok.is(tok::identifier) && getLang().ObjC1 &&
+ Tok.getIdentifierInfo()->isStr("super")) {
+ Diag(Tok.getLocation(), diag::err_illegal_super_cast)
+ << SourceRange(OpenLoc, RParenLoc);
+ return ExprError();
+ }
// Parse the cast-expression that follows it next.
// TODO: For cast expression with CastTy.
//
SourceLocation StartLoc = ConsumeBracket();
- // If Objective-C is enabled and this is a typename or other identifier
- // receiver, parse this as a message send expression.
- if (getLang().ObjC1 && isTokObjCMessageIdentifierReceiver()) {
- // If we have exactly one array designator, this used the GNU
- // 'designation: array-designator' extension, otherwise there should be no
- // designators at all!
- if (Desig.getNumDesignators() == 1 &&
- (Desig.getDesignator(0).isArrayDesignator() ||
- Desig.getDesignator(0).isArrayRangeDesignator()))
- Diag(StartLoc, diag::ext_gnu_missing_equal_designator);
- else if (Desig.getNumDesignators() > 0)
- Diag(Tok, diag::err_expected_equal_designator);
-
- IdentifierInfo *Name = Tok.getIdentifierInfo();
- SourceLocation NameLoc = ConsumeToken();
- return ParseAssignmentExprWithObjCMessageExprStart(
- StartLoc, NameLoc, Name, ExprArg(Actions));
+ // If Objective-C is enabled and this is a typename (class message send) or
+ // 'super', parse this as a message send expression.
+ if (getLang().ObjC1 && Tok.is(tok::identifier)) {
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+
+ if (II == Ident_super || Actions.getTypeName(*II, Tok.getLocation(),
+ CurScope)) {
+ // If we have exactly one array designator, this used the GNU
+ // 'designation: array-designator' extension, otherwise there should be no
+ // designators at all!
+ if (Desig.getNumDesignators() == 1 &&
+ (Desig.getDesignator(0).isArrayDesignator() ||
+ Desig.getDesignator(0).isArrayRangeDesignator()))
+ Diag(StartLoc, diag::ext_gnu_missing_equal_designator);
+ else if (Desig.getNumDesignators() > 0)
+ Diag(Tok, diag::err_expected_equal_designator);
+
+ SourceLocation NameLoc = ConsumeToken();
+ return ParseAssignmentExprWithObjCMessageExprStart(
+ StartLoc, NameLoc, II, ExprArg(Actions));
+ }
}
// Note that we parse this as an assignment expression, not a constant
/// '[' objc-receiver objc-message-args ']'
///
/// objc-receiver:
+/// 'super'
/// expression
/// class-name
/// type-name
assert(Tok.is(tok::l_square) && "'[' expected");
SourceLocation LBracLoc = ConsumeBracket(); // consume '['
- // Parse receiver
- if (isTokObjCMessageIdentifierReceiver()) {
- IdentifierInfo *ReceiverName = Tok.getIdentifierInfo();
- if (ReceiverName != Ident_super || GetLookAheadToken(1).isNot(tok::period)) {
+ if (Tok.is(tok::identifier)) {
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+
+ // If this is '[' 'super', then this is a magic superclass message.
+ // We parse '[' 'super' '.' 'foo' as an expression?
+ // FIXME: Not in ParseInit.cpp?
+ if ((II == Ident_super && GetLookAheadToken(1).isNot(tok::period)) ||
+ // Check to see if this is a typename. If so, it is a class message.
+ Actions.getTypeName(*II, Tok.getLocation(), CurScope)) {
SourceLocation NameLoc = ConsumeToken();
- return ParseObjCMessageExpressionBody(LBracLoc, NameLoc, ReceiverName,
+ return ParseObjCMessageExpressionBody(LBracLoc, NameLoc, II,
ExprArg(Actions));
}
}
-
+
+ // Otherwise, an arbitrary expression can be the receiver of a send.
OwningExprResult Res(ParseExpression());
if (Res.isInvalid()) {
SkipUntil(tok::r_square);
ObjCMethodDecl *LookupPrivateInstanceMethod(Selector Sel,
ObjCInterfaceDecl *ClassDecl);
- Action::OwningExprResult
+ OwningExprResult
HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
Expr *BaseExpr,
DeclarationName MemberName,
SourceLocation MemberLoc);
- virtual OwningExprResult ActOnClassPropertyRefExpr(
- IdentifierInfo &receiverName,
- IdentifierInfo &propertyName,
- SourceLocation &receiverNameLoc,
- SourceLocation &propertyNameLoc);
+ virtual OwningExprResult
+ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
+ IdentifierInfo &propertyName,
+ SourceLocation receiverNameLoc,
+ SourceLocation propertyNameLoc);
// ActOnClassMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions
/// Returns a null sentinel to indicate trivial success.
Sema::OwningExprResult
Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
- IdentifierInfo *II,
- bool AllowBuiltinCreation) {
+ IdentifierInfo *II, bool AllowBuiltinCreation) {
SourceLocation Loc = Lookup.getNameLoc();
+ // FIXME: Stop re-evaluating "getCurMethodDecl".
+
// There are two cases to handle here. 1) scoped lookup could have failed,
// in which case we should look for an ivar. 2) scoped lookup could have
// found a decl, but that decl is outside the current instance method (i.e.
}
}
- // Needed to implement property "super.method" notation.
- if (Lookup.empty() && II->isStr("super")) {
- QualType T;
-
- if (getCurMethodDecl()->isInstanceMethod())
- T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType(
- getCurMethodDecl()->getClassInterface()));
- else
- T = Context.getObjCClassType();
- return Owned(new (Context) ObjCSuperExpr(Loc, T));
- }
if (Lookup.empty() && II && AllowBuiltinCreation) {
// FIXME. Consolidate this with similar code in LookupName.
if (unsigned BuiltinID = II->getBuiltinID()) {
return ExprError(Diag(MemberLoc, diag::err_property_not_found)
<< MemberName << BaseType);
}
+
// Handle Objective-C property access, which is "Obj.property" where Obj is a
// pointer to a (potentially qualified) interface type.
if (!IsArrow)
if (castExpr->getType()->isVectorType())
return CheckVectorCast(TyR, castExpr->getType(), castType, Kind);
- if (getLangOptions().ObjC1 && isa<ObjCSuperExpr>(castExpr))
- return Diag(castExpr->getLocStart(), diag::err_illegal_super_cast) << TyR;
-
if (isa<ObjCSelectorExpr>(castExpr))
return Diag(castExpr->getLocStart(), diag::err_cast_selector_expr);
-Action::OwningExprResult Sema::ActOnClassPropertyRefExpr(
- IdentifierInfo &receiverName,
- IdentifierInfo &propertyName,
- SourceLocation &receiverNameLoc,
- SourceLocation &propertyNameLoc) {
+Action::OwningExprResult Sema::
+ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
+ IdentifierInfo &propertyName,
+ SourceLocation receiverNameLoc,
+ SourceLocation propertyNameLoc) {
IdentifierInfo *receiverNamePtr = &receiverName;
ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr);
- if (!IFace) {
- Diag(receiverNameLoc, diag::err_expected_ident_or_lparen);
- return ExprError();
+ if (IFace == 0) {
+ // If the "receiver" is 'super' in a method, handle it as an expression-like
+ // property reference.
+ if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
+ if (receiverNamePtr->isStr("super")) {
+ if (CurMethod->isInstanceMethod()) {
+ QualType T =
+ Context.getObjCInterfaceType(CurMethod->getClassInterface());
+ T = Context.getObjCObjectPointerType(T);
+ Expr *SuperExpr = new (Context) ObjCSuperExpr(receiverNameLoc, T);
+
+ return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(),
+ SuperExpr, &propertyName,
+ propertyNameLoc);
+ }
+
+ // Otherwise, if this is a class method, try dispatching to our
+ // superclass.
+ IFace = CurMethod->getClassInterface()->getSuperClass();
+ }
+
+ if (IFace == 0) {
+ Diag(receiverNameLoc, diag::err_expected_ident_or_lparen);
+ return ExprError();
+ }
}
- // Search for a declared property first.
+ // Search for a declared property first.
Selector Sel = PP.getSelectorTable().getNullarySelector(&propertyName);
ObjCMethodDecl *Getter = IFace->lookupClassMethod(Sel);
// 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) {
+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);
bool isSuper = false;
if (receiverName->isStr("super")) {
- if (getCurMethodDecl()) {
+ if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
isSuper = true;
- ObjCInterfaceDecl *OID = getCurMethodDecl()->getClassInterface();
+ ObjCInterfaceDecl *OID = CurMethod->getClassInterface();
if (!OID)
return Diag(lbrac, diag::error_no_super_class_message)
- << getCurMethodDecl()->getDeclName();
+ << CurMethod->getDeclName();
ClassDecl = OID->getSuperClass();
if (!ClassDecl)
return Diag(lbrac, diag::error_no_super_class) << OID->getDeclName();
- if (getCurMethodDecl()->isInstanceMethod()) {
+ if (CurMethod->isInstanceMethod()) {
QualType superTy = Context.getObjCInterfaceType(ClassDecl);
superTy = Context.getObjCObjectPointerType(superTy);
ExprResult ReceiverExpr = new (Context) ObjCSuperExpr(SourceLocation(),
} else {
// 'super' has been used outside a method context. If a variable named
// 'super' has been declared, redirect. If not, produce a diagnostic.
+
+ // FIXME:
+ // FIXME: This should be handled in the parser!
+ // FIXME:
+
NamedDecl *SuperDecl
= LookupSingleName(S, receiverName, LookupOrdinaryName);
ValueDecl *VD = dyn_cast_or_null<ValueDecl>(SuperDecl);
return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac,
selectorLoc, rbrac, Args, NumArgs);
}
- else if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(SuperDecl)) {
- const ObjCInterfaceType *OCIT;
- OCIT = OCTD->getUnderlyingType()->getAs<ObjCInterfaceType>();
- if (!OCIT) {
- Diag(receiverLoc, diag::err_invalid_receiver_to_message);
- return true;
- }
- ClassDecl = OCIT->getDecl();
- }
- else
- return Diag(receiverLoc, diag::err_undeclared_var_use) << receiverName;
+ ClassDecl = getObjCInterfaceDecl(receiverName, receiverLoc);
}
} else
ClassDecl = getObjCInterfaceDecl(receiverName, receiverLoc);
ClassDecl = OCIT->getDecl();
if (!ClassDecl) {
- Diag(receiverLoc, diag::err_invalid_receiver_to_message);
+ // 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;
}
}
QualType ReceiverCType =
Context.getCanonicalType(RExpr->getType()).getUnqualifiedType();
+#if 0
// Handle messages to 'super'.
if (isa<ObjCSuperExpr>(RExpr)) {
ObjCMethodDecl *Method = 0;
Method, lbrac, rbrac,
ArgExprs, NumArgs);
}
+#endif
// Handle messages to id.
if (ReceiverCType->isObjCIdType() || ReceiverCType->isBlockPointerType() ||
@interface A
}; // expected-error {{missing @end}} expected-error {{expected external declaration}}
+
+
+
+// PR6811
+// 'super' isn't an expression, it is a magic context-sensitive keyword.
+@interface A2 {
+ id isa;
+}
+- (void)a;
+@end
+
+@interface B2 : A2 @end
+@implementation B2
+- (void)a
+{
+ [(super) a]; // expected-error {{use of undeclared identifier 'super'}}
+}
+@end
- (int) instance_func1
{
int i = (size_t)[self instance_func0]; // expected-warning {{method '-instance_func0' not found (return type defaults to 'id'))}}
- return i + (size_t)[super instance_func0]; // expected-warning {{method '-instance_func0' not found (return type defaults to 'id')}}
+ return i + (size_t)[super instance_func0]; // expected-warning {{'Object' may not respond to 'instance_func0')}}
}
- (int) instance_func2
{
@implementation B
- (void)instanceMethod {
- [super iMethod]; // expected-warning{{method '-iMethod' not found (return type defaults to 'id')}}
+ [super iMethod]; // expected-warning{{'A' may not respond to 'iMethod')}}
}
+ classMethod {
expected-warning {{method '-m' not found (return type defaults to 'id')}}
}
void f1(int puper) {
- [super m]; // expected-error{{use of undeclared identifier 'super'}}
+ [super m]; // expected-error{{'super' not valid when not in a method}}
}
// radar 7400691
typedef Foo super;
+typedef Foo FooTD;
+
void test() {
+ [FooTD cMethod];
[super cMethod];
}