"'super' is only valid in a method body">;
def err_invalid_receiver_class_message : Error<
"receiver type %0 is not an Objective-C class">;
+def err_missing_open_square_message_send : Error<
+ "missing '[' at start of message send expression">;
def warn_bad_receiver_type : Warning<
"receiver type %0 is not 'id' or interface pointer, consider "
"casting it to 'id'">;
class Parser;
class PragmaUnusedHandler;
class ColonProtectionRAIIObject;
-
+ class InMessageExpressionRAIIObject;
+
/// PrettyStackTraceParserEntry - If a crash happens while the parser is active,
/// an entry is printed for it.
class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry {
class Parser : public CodeCompletionHandler {
friend class PragmaUnusedHandler;
friend class ColonProtectionRAIIObject;
+ friend class InMessageExpressionRAIIObject;
friend class ParenBraceBracketBalancer;
PrettyStackTraceParserEntry CrashInfo;
/// ColonProtectionRAIIObject RAII object.
bool ColonIsSacred;
+ /// \brief When true, we are directly inside an Ojective-C messsage
+ /// send expression.
+ ///
+ /// This is managed by the \c InMessageExpressionRAIIObject class, and
+ /// should not be set directly.
+ bool InMessageExpression;
+
/// The "depth" of the template parameters currently being parsed.
unsigned TemplateParameterDepth;
SourceLocation RParenLoc;
{
- // The inside of the parens don't need to be a colon protected scope.
+ // The inside of the parens don't need to be a colon protected scope, and
+ // isn't immediately a message send.
ColonProtectionRAIIObject X(*this, false);
-
+
Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
TypeOfCast, CastTy, RParenLoc);
if (Res.isInvalid())
SourceLocation Loc;
while (1) {
switch (Tok.getKind()) {
+ case tok::identifier:
+ // If we see identifier: after an expression, and we're not already in a
+ // message send, then this is probably a message send with a missing
+ // opening bracket '['.
+ if (getLang().ObjC1 && !InMessageExpression &&
+ NextToken().is(tok::colon)) {
+ LHS = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),
+ ParsedType(), LHS.get());
+ break;
+ }
+
+ // Fall through; this isn't a message send.
+
default: // Not a postfix-expression suffix.
return move(LHS);
case tok::l_square: { // postfix-expression: p-e '[' expression ']'
}
case tok::l_paren: { // p-e: p-e '(' argument-expression-list[opt] ')'
+ InMessageExpressionRAIIObject InMessage(*this, false);
+
ExprVector ArgExprs(Actions);
CommaLocsTy CommaLocs;
return ParseCXXAmbiguousParenExpression(ExprType, CastTy,
OpenLoc, RParenLoc);
- TypeResult Ty = ParseTypeName();
-
+ TypeResult Ty;
+
+ {
+ InMessageExpressionRAIIObject InMessage(*this, false);
+ Ty = ParseTypeName();
+ }
+
// Match the ')'.
if (Tok.is(tok::r_paren))
RParenLoc = ConsumeParen();
return ExprError();
} else if (TypeOfCast) {
// Parse the expression-list.
+ InMessageExpressionRAIIObject InMessage(*this, false);
+
ExprVector ArgExprs(Actions);
CommaLocsTy CommaLocs;
move_arg(ArgExprs), TypeOfCast);
}
} else {
+ InMessageExpressionRAIIObject InMessage(*this, false);
+
Result = ParseExpression();
ExprType = SimpleExpr;
if (!Result.isInvalid() && Tok.is(tok::r_paren))
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"
+#include "RAIIObjectsForParser.h"
#include "clang/Sema/Designator.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/SmallString.h"
// [foo ... bar] -> array designator
// [4][foo bar] -> obsolete GNU designation with objc message send.
//
+ InMessageExpressionRAIIObject InMessage(*this, true);
+
SourceLocation StartLoc = ConsumeBracket();
ExprResult Idx;
if (getLang().ObjC1 && getLang().CPlusPlus) {
// Send to 'super'.
if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&
- NextToken().isNot(tok::period) && getCurScope()->isInObjcMethodScope()) {
+ NextToken().isNot(tok::period) &&
+ getCurScope()->isInObjcMethodScope()) {
CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
ConsumeToken(),
/// initializer-list ',' designation[opt] initializer
///
ExprResult Parser::ParseBraceInitializer() {
+ InMessageExpressionRAIIObject InMessage(*this, false);
+
SourceLocation LBraceLoc = ConsumeBrace();
/// InitExprs - This is the actual list of expressions contained in the
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
+#include "RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Scope.h"
/// simple-type-specifier
/// typename-specifier
bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
+ InMessageExpressionRAIIObject InMessage(*this, true);
+
if (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope))
TryAnnotateTypeOrScopeToken();
return ExprError();
}
+ InMessageExpressionRAIIObject InMessage(*this, true);
+
if (getLang().CPlusPlus) {
// We completely separate the C and C++ cases because C++ requires
// more complicated (read: slower) parsing.
SourceLocation SuperLoc,
ParsedType ReceiverType,
ExprArg ReceiverExpr) {
+ InMessageExpressionRAIIObject InMessage(*this, true);
+
if (Tok.is(tok::code_completion)) {
if (SuperLoc.isValid())
Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, 0, 0);
PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),
Tok.getLocation(),
"in compound statement ('{}')");
-
+ InMessageExpressionRAIIObject InMessage(*this, false);
+
SourceLocation LBraceLoc = ConsumeBrace(); // eat the '{'.
// TODO: "__label__ X, Y, Z;" is the GNU "Local Label" extension. These are
Parser::Parser(Preprocessor &pp, Sema &actions)
: CrashInfo(*this), PP(pp), Actions(actions), Diags(PP.getDiagnostics()),
- GreaterThanIsOperator(true), ColonIsSacred(false),
- TemplateParameterDepth(0) {
+ GreaterThanIsOperator(true), ColonIsSacred(false),
+ InMessageExpression(false), TemplateParameterDepth(0) {
Tok.setKind(tok::eof);
Actions.CurScope = 0;
NumCachedScopes = 0;
}
};
+ class InMessageExpressionRAIIObject {
+ bool &InMessageExpression;
+ bool OldValue;
+
+ public:
+ InMessageExpressionRAIIObject(Parser &P, bool Value)
+ : InMessageExpression(P.InMessageExpression),
+ OldValue(P.InMessageExpression) {
+ InMessageExpression = Value;
+ }
+
+ ~InMessageExpressionRAIIObject() {
+ InMessageExpression = OldValue;
+ }
+ };
+
/// \brief RAII object that makes sure paren/bracket/brace count is correct
/// after declaration/statement parsing, even when there's a parsing error.
class ParenBraceBracketBalancer {
}
ExprResult Sema::ActOnSuperMessage(Scope *S,
- SourceLocation SuperLoc,
- Selector Sel,
- SourceLocation LBracLoc,
- SourceLocation SelectorLoc,
- SourceLocation RBracLoc,
- MultiExprArg Args) {
+ 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) {
///
/// \param Args The message arguments.
ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
- QualType ReceiverType,
- SourceLocation SuperLoc,
- Selector Sel,
- ObjCMethodDecl *Method,
- SourceLocation LBracLoc,
- SourceLocation RBracLoc,
- MultiExprArg ArgsIn) {
+ QualType ReceiverType,
+ SourceLocation SuperLoc,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ SourceLocation LBracLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg ArgsIn) {
+ SourceLocation Loc = SuperLoc.isValid()? SuperLoc
+ : ReceiverTypeInfo->getTypeLoc().getLocalSourceRange().getBegin();
+ if (LBracLoc.isInvalid()) {
+ Diag(Loc, diag::err_missing_open_square_message_send)
+ << FixItHint::CreateInsertion(Loc, "[");
+ LBracLoc = Loc;
+ }
+
if (ReceiverType->isDependentType()) {
// If the receiver type is dependent, we can't type-check anything
// at this point. Build a dependent expression.
Args, NumArgs, RBracLoc));
}
- SourceLocation Loc = SuperLoc.isValid()? SuperLoc
- : ReceiverTypeInfo->getTypeLoc().getLocalSourceRange().getBegin();
-
// Find the class to which we are sending this message.
ObjCInterfaceDecl *Class = 0;
const ObjCObjectType *ClassType = ReceiverType->getAs<ObjCObjectType>();
SourceLocation LBracLoc,
SourceLocation RBracLoc,
MultiExprArg ArgsIn) {
+ // The location of the receiver.
+ SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart();
+
+ if (LBracLoc.isInvalid()) {
+ Diag(Loc, diag::err_missing_open_square_message_send)
+ << FixItHint::CreateInsertion(Loc, "[");
+ LBracLoc = Loc;
+ }
+
// If we have a receiver expression, perform appropriate promotions
// and determine receiver type.
if (Receiver) {
ReceiverType = Receiver->getType();
}
- // The location of the receiver.
- SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart();
-
if (!Method) {
// Handle messages to id.
bool receiverIsId = ReceiverType->isObjCIdType();
--- /dev/null
+// Objective-C recovery
+// RUN: cp %s %t
+// RUN: %clang_cc1 -pedantic -Wall -fixit -x objective-c %t || true
+// RUN: %clang_cc1 -fsyntax-only -pedantic -Wall -Werror -x objective-c %t
+
+// Objective-C++ recovery
+// RUN: cp %s %t
+// RUN: %clang_cc1 -pedantic -Wall -fixit -x objective-c++ %t || true
+// RUN: %clang_cc1 -fsyntax-only -pedantic -Wall -Werror -x objective-c++ %t
+
+@interface A
+- (int)method1:(int)x second:(float)y;
++ (int)method2:(int)x second:(double)y;
+@end
+
+void f(A *a, int i, int j) {
+ a method1:5+2 second:+(3.14159)];
+ a method1:[a method1:3 second:j] second:i++]
+}