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

llvm-svn: 55215
This commit is contained in:
Chris Lattner 2008-08-23 01:48:03 +00:00
parent 95d1056831
commit 2ebb178f8b
3 changed files with 41 additions and 14 deletions

View File

@ -322,8 +322,8 @@ DIAG(err_parse_error, ERROR,
"parse error")
DIAG(err_expected_expression, ERROR,
"expected expression")
DIAG(err_invalid_receiver_to_message, ERROR,
"invalid receiver to message expression")
DIAG(err_expected_type, ERROR,
"expected a type")
DIAG(err_expected_external_declaration, ERROR,
"expected external declaration")
DIAG(err_expected_ident, ERROR,
@ -386,6 +386,8 @@ DIAG(err_expected_string_literal, ERROR,
"expected string literal")
DIAG(err_expected_asm_operand, ERROR,
"expected string literal or '[' for asm operand")
DIAG(err_expected_selector_for_method, ERROR,
"expected selector for Objective-C method")
DIAG(err_unexpected_at, ERROR,
"unexpected '@' in program")
@ -409,6 +411,8 @@ DIAG(warn_objc_protocol_qualifier_missing_id, WARNING,
DIAG(warn_objc_array_of_interfaces, WARNING,
"array of interface '%0' should probably be an array of pointers")
DIAG(err_invalid_receiver_to_message, ERROR,
"invalid receiver to message expression")
DIAG(err_objc_illegal_visibility_spec, ERROR,
"illegal visibility specification")
DIAG(err_objc_illegal_interface_qual, ERROR,

View File

@ -561,6 +561,7 @@ Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) {
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 @@ Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) {
// 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 @@ Parser::DeclTy *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
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 @@ Parser::DeclTy *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
}
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);

View File

@ -1,4 +1,4 @@
// RUN: clang -fsyntax-only %s
// RUN: clang -fsyntax-only -verify %s
@interface foo
- (int)meth;
@ -8,3 +8,14 @@
- (int) meth { return [self meth]; }
@end
// PR2708
@interface MyClass
+- (void)myMethod; // expected-error {{expected selector for Objective-C method}}
- (vid)myMethod2; // expected-error {{expected a type}}
@end
@implementation MyClass
- (void)myMethod { }
- (void)myMethod2 { }
@end