Fix rdar://6124613 a crash on invalid code.
llvm-svn: 54340
This commit is contained in:
parent
4983df37a7
commit
197a301669
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
// RUN: clang %s -fsyntax-only -verify
|
||||||
|
|
||||||
|
// rdar://6124613
|
||||||
|
void test1() {
|
||||||
|
void *p = @1; // expected-error {{unexpected '@' in program}}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue