From: Fariborz Jahanian Date: Fri, 2 Apr 2010 23:15:40 +0000 (+0000) Subject: Improve diagnosing when a method type does not start with '-'|'+' X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=05511fa6349ef0820a778f8c840d0b64e05e9aee;p=clang Improve diagnosing when a method type does not start with '-'|'+' when parsing. Fixes radar 7822196. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100248 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index facf15f52e..3e0956fb94 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -182,6 +182,8 @@ def err_unexected_colon_in_nested_name_spec : Error< "unexpected ':' in nested name specifier">; /// Objective-C parser diagnostics +def err_expected_minus_or_plus : Error< + "method type specifier must start with '-' or '+'">; def err_objc_no_attributes_on_category : Error< "attributes may not be specified on a category">; def err_objc_missing_end : Error<"missing @end">; diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 9a3473f042..243be0ed45 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -142,12 +142,11 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration( // We have a class or category name - consume it. IdentifierInfo *nameId = Tok.getIdentifierInfo(); SourceLocation nameLoc = ConsumeToken(); - + bool Err = false; if (Tok.is(tok::l_paren)) { // we have a category. SourceLocation lparenLoc = ConsumeParen(); SourceLocation categoryLoc, rparenLoc; IdentifierInfo *categoryId = 0; - if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCInterfaceCategory(CurScope, nameId); ConsumeToken(); @@ -157,7 +156,14 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration( if (Tok.is(tok::identifier)) { categoryId = Tok.getIdentifierInfo(); categoryLoc = ConsumeToken(); - } else if (!getLang().ObjC2) { + } + else if (isKnownToBeTypeSpecifier(Tok)) { + // Fall thru after diagnosing for better error recovery. + Diag(Tok, diag::err_expected_minus_or_plus); + ConsumeToken(); + Err = true; + } + else if (!getLang().ObjC2) { Diag(Tok, diag::err_expected_ident); // missing category name. return DeclPtrTy(); } @@ -167,33 +173,34 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration( return DeclPtrTy(); } rparenLoc = ConsumeParen(); - - // Next, we need to check for any protocol references. - SourceLocation LAngleLoc, EndProtoLoc; - llvm::SmallVector ProtocolRefs; - llvm::SmallVector ProtocolLocs; - if (Tok.is(tok::less) && - ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, + if (!Err) { + // Next, we need to check for any protocol references. + SourceLocation LAngleLoc, EndProtoLoc; + llvm::SmallVector ProtocolRefs; + llvm::SmallVector ProtocolLocs; + if (Tok.is(tok::less) && + ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, LAngleLoc, EndProtoLoc)) - return DeclPtrTy(); + return DeclPtrTy(); - if (attrList) // categories don't support attributes. - Diag(Tok, diag::err_objc_no_attributes_on_category); - - DeclPtrTy CategoryType = - Actions.ActOnStartCategoryInterface(atLoc, - nameId, nameLoc, - categoryId, categoryLoc, - ProtocolRefs.data(), - ProtocolRefs.size(), - ProtocolLocs.data(), - EndProtoLoc); - if (Tok.is(tok::l_brace)) + if (attrList) // categories don't support attributes. + Diag(Tok, diag::err_objc_no_attributes_on_category); + + DeclPtrTy CategoryType = + Actions.ActOnStartCategoryInterface(atLoc, + nameId, nameLoc, + categoryId, categoryLoc, + ProtocolRefs.data(), + ProtocolRefs.size(), + ProtocolLocs.data(), + EndProtoLoc); + if (Tok.is(tok::l_brace)) ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, atLoc); - ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword); - return CategoryType; + ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword); + return CategoryType; + } } // Parse a class interface. IdentifierInfo *superClassId = 0; @@ -235,7 +242,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration( ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, atLoc); ParseObjCInterfaceDeclList(ClsType, tok::objc_interface); - return ClsType; + return Err ? DeclPtrTy() : ClsType; } /// The Objective-C property callback. This should be defined where @@ -328,7 +335,14 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, "", tok::semi); continue; } - + if (Tok.is(tok::l_paren)) { + Diag(Tok, diag::err_expected_minus_or_plus); + DeclPtrTy methodPrototype = ParseObjCMethodDecl(Tok.getLocation(), + tok::minus, + interfaceDecl, + MethodImplKind); + continue; + } // Ignore excess semicolons. if (Tok.is(tok::semi)) { ConsumeToken(); diff --git a/test/Parser/check-syntax-1.m b/test/Parser/check-syntax-1.m index a1999def59..085ff4cf67 100644 --- a/test/Parser/check-syntax-1.m +++ b/test/Parser/check-syntax-1.m @@ -9,3 +9,13 @@ typedef float CGFloat; // expected-error {{ expected ';' after method prototype}} @end +// rdar: // 7822196 +@interface A +(void) x; // expected-error {{method type specifier must start with '-' or '+'}} \ + // expected-warning {{type specifier missing, defaults to 'int' [-Wimplicit-int]}} \ + // expected-error {{cannot declare variable inside @interface or @protocol}} +(int)im; // expected-error {{method type specifier must start with '-' or '+'}} \ +- ok; +@end + +