Fix rdar://6124613 a crash on invalid code.

llvm-svn: 54340
This commit is contained in:
Chris Lattner 2008-08-05 06:19:09 +00:00
parent 4983df37a7
commit 197a301669
4 changed files with 69 additions and 51 deletions

View File

@ -244,12 +244,12 @@ private:
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
// Diagnostic Emission and Error recovery. // Diagnostic Emission and Error recovery.
void Diag(SourceLocation Loc, unsigned DiagID, bool Diag(SourceLocation Loc, unsigned DiagID,
const std::string &Msg = std::string()); const std::string &Msg = std::string());
void Diag(SourceLocation Loc, unsigned DiagID, const SourceRange &R); bool Diag(SourceLocation Loc, unsigned DiagID, const SourceRange &R);
void Diag(const Token &Tok, unsigned DiagID, bool Diag(const Token &Tok, unsigned DiagID,
const std::string &M = std::string()) { const std::string &M = std::string()) {
Diag(Tok.getLocation(), DiagID, M); return Diag(Tok.getLocation(), DiagID, M);
} }
/// SkipUntil - Read tokens until we get to the specified token, then consume /// SkipUntil - Read tokens until we get to the specified token, then consume

View File

@ -1337,26 +1337,24 @@ Parser::StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
} }
Parser::ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { Parser::ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
switch (Tok.getKind()) { switch (Tok.getKind()) {
case tok::string_literal: // primary-expression: string-literal case tok::string_literal: // primary-expression: string-literal
case tok::wide_string_literal: case tok::wide_string_literal:
return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc)); return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));
default: default:
break; if (Tok.getIdentifierInfo() == 0)
} return Diag(AtLoc, diag::err_unexpected_at);
switch (Tok.getIdentifierInfo()->getObjCKeywordID()) { switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
case tok::objc_encode: case tok::objc_encode:
return ParsePostfixExpressionSuffix(ParseObjCEncodeExpression(AtLoc)); return ParsePostfixExpressionSuffix(ParseObjCEncodeExpression(AtLoc));
case tok::objc_protocol: case tok::objc_protocol:
return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc)); return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc));
case tok::objc_selector: case tok::objc_selector:
return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc)); return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc));
default: default:
Diag(AtLoc, diag::err_unexpected_at); return Diag(AtLoc, diag::err_unexpected_at);
SkipUntil(tok::semi); }
return true;
} }
} }
@ -1380,10 +1378,10 @@ Parser::ExprResult Parser::ParseObjCMessageExpression() {
ExprResult Res = ParseAssignmentExpression(); ExprResult Res = ParseAssignmentExpression();
if (Res.isInvalid) { if (Res.isInvalid) {
Diag(Tok, diag::err_invalid_receiver_to_message);
SkipUntil(tok::r_square); SkipUntil(tok::r_square);
return Res; return Res;
} }
return ParseObjCMessageExpressionBody(LBracLoc, 0, Res.Val); return ParseObjCMessageExpressionBody(LBracLoc, 0, Res.Val);
} }
@ -1426,16 +1424,24 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
if (Tok.isNot(tok::colon)) { if (Tok.isNot(tok::colon)) {
Diag(Tok, diag::err_expected_colon); Diag(Tok, diag::err_expected_colon);
SkipUntil(tok::semi); // We must manually skip to a ']', otherwise the expression skipper will
// stop at the ']' when it skips to the ';'. We want it to skip beyond
// the enclosing expression.
SkipUntil(tok::r_square);
return true; return true;
} }
ConsumeToken(); // Eat the ':'. ConsumeToken(); // Eat the ':'.
/// Parse the expression after ':' /// Parse the expression after ':'
ExprResult Res = ParseAssignmentExpression(); ExprResult Res = ParseAssignmentExpression();
if (Res.isInvalid) { if (Res.isInvalid) {
SkipUntil(tok::identifier); // We must manually skip to a ']', otherwise the expression skipper will
// stop at the ']' when it skips to the ';'. We want it to skip beyond
// the enclosing expression.
SkipUntil(tok::r_square);
return Res; return Res;
} }
// We have a valid expression. // We have a valid expression.
KeyExprs.push_back(Res.Val); KeyExprs.push_back(Res.Val);
@ -1451,23 +1457,35 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
/// Parse the expression after ',' /// Parse the expression after ','
ExprResult Res = ParseAssignmentExpression(); ExprResult Res = ParseAssignmentExpression();
if (Res.isInvalid) { if (Res.isInvalid) {
SkipUntil(tok::identifier); // We must manually skip to a ']', otherwise the expression skipper will
// stop at the ']' when it skips to the ';'. We want it to skip beyond
// the enclosing expression.
SkipUntil(tok::r_square);
return Res; return Res;
} }
// We have a valid expression. // We have a valid expression.
KeyExprs.push_back(Res.Val); KeyExprs.push_back(Res.Val);
} }
} else if (!selIdent) { } else if (!selIdent) {
Diag(Tok, diag::err_expected_ident); // missing selector name. Diag(Tok, diag::err_expected_ident); // missing selector name.
SkipUntil(tok::semi);
// We must manually skip to a ']', otherwise the expression skipper will
// stop at the ']' when it skips to the ';'. We want it to skip beyond
// the enclosing expression.
SkipUntil(tok::r_square);
return true; return true;
} }
if (Tok.isNot(tok::r_square)) { if (Tok.isNot(tok::r_square)) {
Diag(Tok, diag::err_expected_rsquare); Diag(Tok, diag::err_expected_rsquare);
SkipUntil(tok::semi); // We must manually skip to a ']', otherwise the expression skipper will
// stop at the ']' when it skips to the ';'. We want it to skip beyond
// the enclosing expression.
SkipUntil(tok::r_square);
return true; return true;
} }
SourceLocation RBracLoc = ConsumeBracket(); // consume ']' SourceLocation RBracLoc = ConsumeBracket(); // consume ']'
unsigned nKeys = KeyIdents.size(); unsigned nKeys = KeyIdents.size();
@ -1527,10 +1545,8 @@ Parser::ExprResult Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
SourceLocation EncLoc = ConsumeToken(); SourceLocation EncLoc = ConsumeToken();
if (Tok.isNot(tok::l_paren)) { if (Tok.isNot(tok::l_paren))
Diag(Tok, diag::err_expected_lparen_after, "@encode"); return Diag(Tok, diag::err_expected_lparen_after, "@encode");
return true;
}
SourceLocation LParenLoc = ConsumeParen(); SourceLocation LParenLoc = ConsumeParen();
@ -1549,17 +1565,14 @@ Parser::ExprResult Parser::ParseObjCProtocolExpression(SourceLocation AtLoc)
{ {
SourceLocation ProtoLoc = ConsumeToken(); SourceLocation ProtoLoc = ConsumeToken();
if (Tok.isNot(tok::l_paren)) { if (Tok.isNot(tok::l_paren))
Diag(Tok, diag::err_expected_lparen_after, "@protocol"); return Diag(Tok, diag::err_expected_lparen_after, "@protocol");
return true;
}
SourceLocation LParenLoc = ConsumeParen(); SourceLocation LParenLoc = ConsumeParen();
if (Tok.isNot(tok::identifier)) { if (Tok.isNot(tok::identifier))
Diag(Tok, diag::err_expected_ident); return Diag(Tok, diag::err_expected_ident);
return true;
}
IdentifierInfo *protocolId = Tok.getIdentifierInfo(); IdentifierInfo *protocolId = Tok.getIdentifierInfo();
ConsumeToken(); ConsumeToken();
@ -1575,27 +1588,23 @@ Parser::ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc)
{ {
SourceLocation SelectorLoc = ConsumeToken(); SourceLocation SelectorLoc = ConsumeToken();
if (Tok.isNot(tok::l_paren)) { if (Tok.isNot(tok::l_paren))
Diag(Tok, diag::err_expected_lparen_after, "@selector"); return Diag(Tok, diag::err_expected_lparen_after, "@selector");
return 0;
}
llvm::SmallVector<IdentifierInfo *, 12> KeyIdents; llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
SourceLocation LParenLoc = ConsumeParen(); SourceLocation LParenLoc = ConsumeParen();
SourceLocation sLoc; SourceLocation sLoc;
IdentifierInfo *SelIdent = ParseObjCSelector(sLoc); IdentifierInfo *SelIdent = ParseObjCSelector(sLoc);
if (!SelIdent && Tok.isNot(tok::colon)) { if (!SelIdent && Tok.isNot(tok::colon))
Diag(Tok, diag::err_expected_ident); // missing selector name. return Diag(Tok, diag::err_expected_ident); // missing selector name.
return 0;
}
KeyIdents.push_back(SelIdent); KeyIdents.push_back(SelIdent);
unsigned nColons = 0; unsigned nColons = 0;
if (Tok.isNot(tok::r_paren)) { if (Tok.isNot(tok::r_paren)) {
while (1) { while (1) {
if (Tok.isNot(tok::colon)) { if (Tok.isNot(tok::colon))
Diag(Tok, diag::err_expected_colon); return Diag(Tok, diag::err_expected_colon);
break;
}
nColons++; nColons++;
ConsumeToken(); // Eat the ':'. ConsumeToken(); // Eat the ':'.
if (Tok.is(tok::r_paren)) if (Tok.is(tok::r_paren))

View File

@ -31,14 +31,16 @@ Parser::Parser(Preprocessor &pp, Action &actions)
Action::~Action() {} Action::~Action() {}
void Parser::Diag(SourceLocation Loc, unsigned DiagID, bool Parser::Diag(SourceLocation Loc, unsigned DiagID,
const std::string &Msg) { const std::string &Msg) {
Diags.Report(FullSourceLoc(Loc,PP.getSourceManager()), DiagID, &Msg, 1); Diags.Report(FullSourceLoc(Loc,PP.getSourceManager()), DiagID, &Msg, 1);
return true;
} }
void Parser::Diag(SourceLocation Loc, unsigned DiagID, const SourceRange &R) { bool Parser::Diag(SourceLocation Loc, unsigned DiagID, const SourceRange &R) {
Diags.Report(FullSourceLoc(Loc,PP.getSourceManager()), DiagID, 0, 0, Diags.Report(FullSourceLoc(Loc,PP.getSourceManager()), DiagID, 0, 0,
&R, 1); &R, 1);
return true;
} }

View File

@ -0,0 +1,7 @@
// RUN: clang %s -fsyntax-only -verify
// rdar://6124613
void test1() {
void *p = @1; // expected-error {{unexpected '@' in program}}
}