зеркало из https://github.com/microsoft/clang-1.git
Extend warnings for missing '@end'.
Fixes PR2709. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145928 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
26b45d8608
Коммит
d64251fd56
|
@ -35,7 +35,7 @@ namespace clang {
|
|||
DIAG_START_FRONTEND = DIAG_START_DRIVER + 100,
|
||||
DIAG_START_LEX = DIAG_START_FRONTEND + 120,
|
||||
DIAG_START_PARSE = DIAG_START_LEX + 300,
|
||||
DIAG_START_AST = DIAG_START_PARSE + 300,
|
||||
DIAG_START_AST = DIAG_START_PARSE + 350,
|
||||
DIAG_START_SEMA = DIAG_START_AST + 100,
|
||||
DIAG_START_ANALYSIS = DIAG_START_SEMA + 3000,
|
||||
DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
|
||||
|
|
|
@ -313,7 +313,10 @@ 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">;
|
||||
def err_objc_missing_end : Error<"missing '@end'">;
|
||||
def note_objc_container_start : Note<
|
||||
"%select{class|protocol|category|class extension|implementation"
|
||||
"|category implementation}0 started here">;
|
||||
def warn_objc_protocol_qualifier_missing_id : Warning<
|
||||
"protocol qualifiers without 'id' is archaic">;
|
||||
def err_objc_unknown_at : Error<"expected an Objective-C directive after '@'">;
|
||||
|
@ -352,8 +355,8 @@ def err_missing_id_definition : Error<"cannot find definition of 'id'">;
|
|||
def err_missing_proto_definition : Error<
|
||||
"cannot find definition of 'Protocol'">;
|
||||
def err_missing_class_definition : Error<"cannot find definition of 'Class'">;
|
||||
def err_expected_implementation : Error<
|
||||
"@end must appear in an @implementation context">;
|
||||
def err_expected_objc_container : Error<
|
||||
"'@end' must appear in an Objective-C context">;
|
||||
def error_property_ivar_decl : Error<
|
||||
"property synthesize requires specification of an ivar">;
|
||||
def err_synthesized_property_name : Error<
|
||||
|
|
|
@ -488,7 +488,6 @@ def note_declared_at : Note<"declared here">;
|
|||
def note_method_declared_at : Note<"method declared here">;
|
||||
def err_setter_type_void : Error<"type of setter must be void">;
|
||||
def err_duplicate_method_decl : Error<"duplicate declaration of method %0">;
|
||||
def err_missing_atend : Error<"'@end' is missing in implementation context">;
|
||||
def err_objc_var_decl_inclass :
|
||||
Error<"cannot declare variable inside @interface or @protocol">;
|
||||
def error_missing_method_context : Error<
|
||||
|
|
|
@ -716,6 +716,7 @@ public:
|
|||
private:
|
||||
void SuggestParentheses(SourceLocation Loc, unsigned DK,
|
||||
SourceRange ParenRange);
|
||||
void CheckNestedObjCContexts(SourceLocation AtLoc);
|
||||
|
||||
/// SkipUntil - Read tokens until we get to the specified token, then consume
|
||||
/// it (unless DontConsume is true). Because we cannot guarantee that the
|
||||
|
@ -1204,7 +1205,7 @@ private:
|
|||
// Objective-C External Declarations
|
||||
Parser::DeclGroupPtrTy ParseObjCAtDirectives();
|
||||
Parser::DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc);
|
||||
Decl *ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
|
||||
Decl *ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
|
||||
ParsedAttributes &prefixAttrs);
|
||||
void ParseObjCClassInstanceVariables(Decl *interfaceDecl,
|
||||
tok::ObjCKeywordKind visibility,
|
||||
|
@ -1225,7 +1226,7 @@ private:
|
|||
typedef SmallVector<LexedMethod*, 2> LateParsedObjCMethodContainer;
|
||||
LateParsedObjCMethodContainer LateParsedObjCMethods;
|
||||
|
||||
Decl *ParseObjCAtImplementationDeclaration(SourceLocation atLoc);
|
||||
Decl *ParseObjCAtImplementationDeclaration(SourceLocation AtLoc);
|
||||
DeclGroupPtrTy ParseObjCAtEndDeclaration(SourceRange atEnd);
|
||||
Decl *ParseObjCAtAliasDeclaration(SourceLocation atLoc);
|
||||
Decl *ParseObjCPropertySynthesize(SourceLocation atLoc);
|
||||
|
|
|
@ -5173,6 +5173,17 @@ public:
|
|||
const MultiLevelTemplateArgumentList &TemplateArgs);
|
||||
|
||||
// Objective-C declarations.
|
||||
enum ObjCContainerKind {
|
||||
OCK_None = -1,
|
||||
OCK_Interface = 0,
|
||||
OCK_Protocol,
|
||||
OCK_Category,
|
||||
OCK_ClassExtension,
|
||||
OCK_Implementation,
|
||||
OCK_CategoryImplementation
|
||||
};
|
||||
ObjCContainerKind getObjCContainerKind() const;
|
||||
|
||||
Decl *ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
||||
IdentifierInfo *ClassName,
|
||||
SourceLocation ClassLoc,
|
||||
|
@ -5275,10 +5286,10 @@ public:
|
|||
void MatchOneProtocolPropertiesInClass(Decl *CDecl,
|
||||
ObjCProtocolDecl *PDecl);
|
||||
|
||||
void ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
||||
Decl **allMethods = 0, unsigned allNum = 0,
|
||||
Decl **allProperties = 0, unsigned pNum = 0,
|
||||
DeclGroupPtrTy *allTUVars = 0, unsigned tuvNum = 0);
|
||||
Decl *ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
||||
Decl **allMethods = 0, unsigned allNum = 0,
|
||||
Decl **allProperties = 0, unsigned pNum = 0,
|
||||
DeclGroupPtrTy *allTUVars = 0, unsigned tuvNum = 0);
|
||||
|
||||
Decl *ActOnProperty(Scope *S, SourceLocation AtLoc,
|
||||
FieldDeclarator &FD, ObjCDeclSpec &ODS,
|
||||
|
|
|
@ -113,6 +113,23 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
|
|||
ClassNames.size());
|
||||
}
|
||||
|
||||
void Parser::CheckNestedObjCContexts(SourceLocation AtLoc)
|
||||
{
|
||||
Sema::ObjCContainerKind ock = Actions.getObjCContainerKind();
|
||||
if (ock == Sema::OCK_None)
|
||||
return;
|
||||
|
||||
Decl *Decl = Actions.ActOnAtEnd(getCurScope(), AtLoc);
|
||||
Diag(AtLoc, diag::err_objc_missing_end)
|
||||
<< FixItHint::CreateInsertion(AtLoc, "@end\n");
|
||||
if (Decl)
|
||||
Diag(Decl->getLocStart(), diag::note_objc_container_start)
|
||||
<< (int) ock;
|
||||
if (!PendingObjCImpDecl.empty())
|
||||
PendingObjCImpDecl.pop_back();
|
||||
ObjCImpDecl = 0;
|
||||
}
|
||||
|
||||
///
|
||||
/// objc-interface:
|
||||
/// objc-class-interface-attributes[opt] objc-class-interface
|
||||
|
@ -141,10 +158,11 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
|
|||
/// __attribute__((unavailable))
|
||||
/// __attribute__((objc_exception)) - used by NSException on 64-bit
|
||||
///
|
||||
Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
|
||||
Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
|
||||
ParsedAttributes &attrs) {
|
||||
assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
|
||||
"ParseObjCAtInterfaceDeclaration(): Expected @interface");
|
||||
CheckNestedObjCContexts(AtLoc);
|
||||
ConsumeToken(); // the "interface" identifier
|
||||
|
||||
// Code completion after '@interface'.
|
||||
|
@ -205,7 +223,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
|
|||
return 0;
|
||||
|
||||
Decl *CategoryType =
|
||||
Actions.ActOnStartCategoryInterface(atLoc,
|
||||
Actions.ActOnStartCategoryInterface(AtLoc,
|
||||
nameId, nameLoc,
|
||||
categoryId, categoryLoc,
|
||||
ProtocolRefs.data(),
|
||||
|
@ -214,7 +232,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
|
|||
EndProtoLoc);
|
||||
|
||||
if (Tok.is(tok::l_brace))
|
||||
ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, atLoc);
|
||||
ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, AtLoc);
|
||||
|
||||
ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType);
|
||||
return CategoryType;
|
||||
|
@ -250,14 +268,14 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
|
|||
return 0;
|
||||
|
||||
Decl *ClsType =
|
||||
Actions.ActOnStartClassInterface(atLoc, nameId, nameLoc,
|
||||
Actions.ActOnStartClassInterface(AtLoc, nameId, nameLoc,
|
||||
superClassId, superClassLoc,
|
||||
ProtocolRefs.data(), ProtocolRefs.size(),
|
||||
ProtocolLocs.data(),
|
||||
EndProtoLoc, attrs.getList());
|
||||
|
||||
if (Tok.is(tok::l_brace))
|
||||
ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, atLoc);
|
||||
ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc);
|
||||
|
||||
ParseObjCInterfaceDeclList(tok::objc_interface, ClsType);
|
||||
return ClsType;
|
||||
|
@ -425,7 +443,10 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
|
|||
|
||||
case tok::objc_implementation:
|
||||
case tok::objc_interface:
|
||||
Diag(Tok, diag::err_objc_missing_end);
|
||||
Diag(AtLoc, diag::err_objc_missing_end)
|
||||
<< FixItHint::CreateInsertion(AtLoc, "@end\n");
|
||||
Diag(CDecl->getLocStart(), diag::note_objc_container_start)
|
||||
<< (int) Actions.getObjCContainerKind();
|
||||
ConsumeToken();
|
||||
break;
|
||||
|
||||
|
@ -465,10 +486,16 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
|
|||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCAtDirective(getCurScope());
|
||||
return cutOffParsing();
|
||||
} else if (Tok.isObjCAtKeyword(tok::objc_end))
|
||||
} else if (Tok.isObjCAtKeyword(tok::objc_end)) {
|
||||
ConsumeToken(); // the "end" identifier
|
||||
else
|
||||
Diag(Tok, diag::err_objc_missing_end);
|
||||
} else {
|
||||
Diag(Tok, diag::err_objc_missing_end)
|
||||
<< FixItHint::CreateInsertion(Tok.getLocation(), "\n@end\n");
|
||||
Diag(CDecl->getLocStart(), diag::note_objc_container_start)
|
||||
<< (int) Actions.getObjCContainerKind();
|
||||
AtEnd.setBegin(Tok.getLocation());
|
||||
AtEnd.setEnd(Tok.getLocation());
|
||||
}
|
||||
|
||||
// Insert collected methods declarations into the @interface object.
|
||||
// This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
|
||||
|
@ -1316,6 +1343,7 @@ Decl *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
|
|||
ParsedAttributes &attrs) {
|
||||
assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
|
||||
"ParseObjCAtProtocolDeclaration(): Expected @protocol");
|
||||
CheckNestedObjCContexts(AtLoc);
|
||||
ConsumeToken(); // the "protocol" identifier
|
||||
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
|
@ -1399,10 +1427,10 @@ Decl *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
|
|||
///
|
||||
/// objc-category-implementation-prologue:
|
||||
/// @implementation identifier ( identifier )
|
||||
Decl *Parser::ParseObjCAtImplementationDeclaration(
|
||||
SourceLocation atLoc) {
|
||||
Decl *Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
|
||||
assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
|
||||
"ParseObjCAtImplementationDeclaration(): Expected @implementation");
|
||||
CheckNestedObjCContexts(AtLoc);
|
||||
ConsumeToken(); // the "implementation" identifier
|
||||
|
||||
// Code completion after '@implementation'.
|
||||
|
@ -1446,7 +1474,7 @@ Decl *Parser::ParseObjCAtImplementationDeclaration(
|
|||
}
|
||||
rparenLoc = ConsumeParen();
|
||||
Decl *ImplCatType = Actions.ActOnStartCategoryImplementation(
|
||||
atLoc, nameId, nameLoc, categoryId,
|
||||
AtLoc, nameId, nameLoc, categoryId,
|
||||
categoryLoc);
|
||||
|
||||
ObjCImpDecl = ImplCatType;
|
||||
|
@ -1467,11 +1495,11 @@ Decl *Parser::ParseObjCAtImplementationDeclaration(
|
|||
superClassLoc = ConsumeToken(); // Consume super class name
|
||||
}
|
||||
Decl *ImplClsType = Actions.ActOnStartClassImplementation(
|
||||
atLoc, nameId, nameLoc,
|
||||
AtLoc, nameId, nameLoc,
|
||||
superClassId, superClassLoc);
|
||||
|
||||
if (Tok.is(tok::l_brace)) // we have ivars
|
||||
ParseObjCClassInstanceVariables(ImplClsType, tok::objc_private, atLoc);
|
||||
ParseObjCClassInstanceVariables(ImplClsType, tok::objc_private, AtLoc);
|
||||
|
||||
ObjCImpDecl = ImplClsType;
|
||||
PendingObjCImpDecl.push_back(ObjCImpDecl);
|
||||
|
@ -1498,7 +1526,7 @@ Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
|
|||
}
|
||||
else
|
||||
// missing @implementation
|
||||
Diag(atEnd.getBegin(), diag::err_expected_implementation);
|
||||
Diag(atEnd.getBegin(), diag::err_expected_objc_container);
|
||||
|
||||
clearLateParsedObjCMethods();
|
||||
ObjCImpDecl = 0;
|
||||
|
@ -1510,8 +1538,15 @@ Parser::DeclGroupPtrTy Parser::FinishPendingObjCActions() {
|
|||
Actions.DiagnoseUseOfUnimplementedSelectors();
|
||||
if (PendingObjCImpDecl.empty())
|
||||
return Actions.ConvertDeclToDeclGroup(0);
|
||||
|
||||
Decl *ImpDecl = PendingObjCImpDecl.pop_back_val();
|
||||
Actions.ActOnAtEnd(getCurScope(), SourceRange());
|
||||
Actions.ActOnAtEnd(getCurScope(), SourceRange(Tok.getLocation()));
|
||||
Diag(Tok, diag::err_objc_missing_end)
|
||||
<< FixItHint::CreateInsertion(Tok.getLocation(), "\n@end\n");
|
||||
if (ImpDecl)
|
||||
Diag(ImpDecl->getLocStart(), diag::note_objc_container_start)
|
||||
<< Sema::OCK_Implementation;
|
||||
|
||||
return Actions.ConvertDeclToDeclGroup(ImpDecl);
|
||||
}
|
||||
|
||||
|
|
|
@ -2148,15 +2148,39 @@ void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID,
|
|||
}
|
||||
}
|
||||
|
||||
Sema::ObjCContainerKind Sema::getObjCContainerKind() const {
|
||||
switch (CurContext->getDeclKind()) {
|
||||
case Decl::ObjCInterface:
|
||||
return Sema::OCK_Interface;
|
||||
case Decl::ObjCProtocol:
|
||||
return Sema::OCK_Protocol;
|
||||
case Decl::ObjCCategory:
|
||||
if (dyn_cast<ObjCCategoryDecl>(CurContext)->IsClassExtension())
|
||||
return Sema::OCK_ClassExtension;
|
||||
else
|
||||
return Sema::OCK_Category;
|
||||
case Decl::ObjCImplementation:
|
||||
return Sema::OCK_Implementation;
|
||||
case Decl::ObjCCategoryImpl:
|
||||
return Sema::OCK_CategoryImplementation;
|
||||
|
||||
default:
|
||||
return Sema::OCK_None;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: For class/category implemenations, allMethods/allProperties is
|
||||
// always null.
|
||||
void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
||||
Decl **allMethods, unsigned allNum,
|
||||
Decl **allProperties, unsigned pNum,
|
||||
DeclGroupPtrTy *allTUVars, unsigned tuvNum) {
|
||||
Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
||||
Decl **allMethods, unsigned allNum,
|
||||
Decl **allProperties, unsigned pNum,
|
||||
DeclGroupPtrTy *allTUVars, unsigned tuvNum) {
|
||||
|
||||
if (getObjCContainerKind() == Sema::OCK_None)
|
||||
return 0;
|
||||
|
||||
assert(AtEnd.isValid() && "Invalid location for '@end'");
|
||||
|
||||
if (!CurContext->isObjCContainer())
|
||||
return;
|
||||
ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
|
||||
Decl *ClassDecl = cast<Decl>(OCD);
|
||||
|
||||
|
@ -2165,15 +2189,6 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
|||
|| isa<ObjCProtocolDecl>(ClassDecl);
|
||||
bool checkIdenticalMethods = isa<ObjCImplementationDecl>(ClassDecl);
|
||||
|
||||
if (!isInterfaceDeclKind && AtEnd.isInvalid()) {
|
||||
// FIXME: This is wrong. We shouldn't be pretending that there is
|
||||
// an '@end' in the declaration.
|
||||
SourceLocation L = OCD->getAtStartLoc();
|
||||
AtEnd.setBegin(L);
|
||||
AtEnd.setEnd(L);
|
||||
Diag(L, diag::err_missing_atend);
|
||||
}
|
||||
|
||||
// FIXME: Remove these and use the ObjCContainerDecl/DeclContext.
|
||||
llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap;
|
||||
llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap;
|
||||
|
@ -2335,6 +2350,8 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
|||
(*I)->setTopLevelDeclInObjCContainer();
|
||||
Consumer.HandleTopLevelDeclInObjCContainer(DG);
|
||||
}
|
||||
|
||||
return ClassDecl;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
@interface Rdar8452791 () - (void)rdar8452791;
|
||||
|
||||
// CHECK: error: cannot find interface declaration for 'Rdar8452791'
|
||||
// CHECK: missing @end
|
||||
// CHECK: missing '@end'
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
// rdar: //7824372
|
||||
|
||||
@interface A
|
||||
@interface A // expected-note {{class started here}}
|
||||
-(void) im0;
|
||||
|
||||
@implementation A // expected-error {{missing @end}}
|
||||
@implementation A // expected-error {{missing '@end'}}
|
||||
@end
|
||||
|
||||
@interface B {
|
||||
@interface B { // expected-note {{class started here}}
|
||||
}
|
||||
|
||||
@implementation B // expected-error {{missing @end}}
|
||||
@implementation B // expected-error {{missing '@end'}}
|
||||
@end
|
||||
|
||||
@interface C
|
||||
@interface C // expected-note 2 {{class started here}}
|
||||
@property int P;
|
||||
|
||||
@implementation C // expected-error 2 {{missing @end}}
|
||||
@implementation C // expected-error 2 {{missing '@end'}}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
// rdar://8283484
|
||||
@interface blah {
|
||||
@interface blah { // expected-note {{class started here}}
|
||||
@private
|
||||
}
|
||||
// since I forgot the @end here it should say something
|
||||
|
||||
@interface blah // expected-error {{missing @end}}
|
||||
@interface blah // expected-error {{missing '@end'}}
|
||||
@end // and Unknown type name 'end' here
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
@interface AAA
|
||||
@interface AAA // expected-note {{class started here}}
|
||||
{
|
||||
}
|
||||
@ x// expected-error{{expected an Objective-C directive after '@'}}
|
||||
// expected-error{{missing @end}}
|
||||
// expected-error{{missing '@end'}}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
@end // expected-error {{@end must appear in an @implementation context}}
|
||||
@end // expected-error {{'@end' must appear in an Objective-C context}}
|
||||
|
|
|
@ -5,8 +5,8 @@ int @"s" = 5; // expected-error {{prefix attribute must be}}
|
|||
|
||||
|
||||
// rdar://6480479
|
||||
@interface A
|
||||
}; // expected-error {{missing @end}} \
|
||||
@interface A // expected-note {{class started here}}
|
||||
}; // expected-error {{missing '@end'}} \
|
||||
// expected-error {{expected external declaration}} \
|
||||
// expected-warning{{extra ';' outside of a function}}
|
||||
|
||||
|
|
|
@ -3,20 +3,20 @@
|
|||
@interface I0
|
||||
@end
|
||||
|
||||
@implementation I0 // expected-error {{'@end' is missing in implementation context}}
|
||||
@implementation I0 // expected-note {{implementation started here}}
|
||||
- meth { return 0; }
|
||||
|
||||
@interface I1 : I0
|
||||
@interface I1 : I0 // expected-error {{missing '@end'}}
|
||||
@end
|
||||
|
||||
@implementation I1 // expected-error {{'@end' is missing in implementation context}}
|
||||
@implementation I1 // expected-note {{implementation started here}}
|
||||
-(void) im0 { self = [super init]; }
|
||||
|
||||
@interface I2 : I0
|
||||
@interface I2 : I0 // expected-error {{missing '@end'}}
|
||||
- I2meth;
|
||||
@end
|
||||
|
||||
@implementation I2 // expected-error {{'@end' is missing in implementation context}}
|
||||
@implementation I2 // expected-note {{implementation started here}}
|
||||
- I2meth { return 0; }
|
||||
|
||||
@implementation I2(CAT) // expected-error {{'@end' is missing in implementation context}}
|
||||
@implementation I2(CAT) // expected-error 2 {{missing '@end'}} expected-note {{implementation started here}}
|
||||
|
|
Загрузка…
Ссылка в новой задаче