Fix a FIXME by not creating an invalid AST on erroneous input. Also
make diagnostic output in some other malformed cases significantly
more useful. This fixes PR2708
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55215 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 0079701..31e62d3 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -561,6 +561,7 @@
assert(Tok.is(tok::l_paren) && "expected (");
SourceLocation LParenLoc = ConsumeParen(), RParenLoc;
+ SourceLocation TypeStartLoc = Tok.getLocation();
TypeTy *Ty = 0;
// Parse type qualifiers, in, inout, etc.
@@ -571,9 +572,17 @@
// FIXME: back when Sema support is in place...
// assert(Ty && "Parser::ParseObjCTypeName(): missing type");
}
+
if (Tok.isNot(tok::r_paren)) {
- MatchRHSPunctuation(tok::r_paren, LParenLoc);
- return 0; // FIXME: decide how we want to handle this error...
+ // If we didn't eat any tokens, then this isn't a type.
+ if (Tok.getLocation() == TypeStartLoc) {
+ Diag(Tok.getLocation(), diag::err_expected_type);
+ SkipUntil(tok::r_brace);
+ } else {
+ // Otherwise, we found *something*, but didn't get a ')' in the right
+ // place. Emit an error then return what we have as the type.
+ MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ }
}
RParenLoc = ConsumeParen();
return Ty;
@@ -612,20 +621,24 @@
DeclTy *IDecl,
tok::ObjCKeywordKind MethodImplKind)
{
- // Parse the return type.
+ // Parse the return type if present.
TypeTy *ReturnType = 0;
ObjCDeclSpec DSRet;
if (Tok.is(tok::l_paren))
ReturnType = ParseObjCTypeName(DSRet);
+
SourceLocation selLoc;
IdentifierInfo *SelIdent = ParseObjCSelector(selLoc);
+
+ if (!SelIdent) { // missing selector name.
+ Diag(Tok.getLocation(), diag::err_expected_selector_for_method,
+ SourceRange(mLoc, Tok.getLocation()));
+ // Skip until we get a ; or {}.
+ SkipUntil(tok::r_brace);
+ return 0;
+ }
+
if (Tok.isNot(tok::colon)) {
- if (!SelIdent) {
- Diag(Tok, diag::err_expected_ident); // missing selector name.
- // FIXME: this creates a unary selector with a null identifier, is this
- // ok?? Maybe we should skip to the next semicolon or something.
- }
-
// If attributes exist after the method, parse them.
AttributeList *MethodAttrs = 0;
if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
@@ -653,9 +666,8 @@
}
ConsumeToken(); // Eat the ':'.
ObjCDeclSpec DSType;
- if (Tok.is(tok::l_paren)) { // Parse the argument type.
+ if (Tok.is(tok::l_paren)) // Parse the argument type.
TypeInfo = ParseObjCTypeName(DSType);
- }
else
TypeInfo = 0;
KeyTypes.push_back(TypeInfo);