зеркало из 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_FRONTEND = DIAG_START_DRIVER + 100,
|
||||||
DIAG_START_LEX = DIAG_START_FRONTEND + 120,
|
DIAG_START_LEX = DIAG_START_FRONTEND + 120,
|
||||||
DIAG_START_PARSE = DIAG_START_LEX + 300,
|
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_SEMA = DIAG_START_AST + 100,
|
||||||
DIAG_START_ANALYSIS = DIAG_START_SEMA + 3000,
|
DIAG_START_ANALYSIS = DIAG_START_SEMA + 3000,
|
||||||
DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
|
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 '+'">;
|
"method type specifier must start with '-' or '+'">;
|
||||||
def err_objc_no_attributes_on_category : Error<
|
def err_objc_no_attributes_on_category : Error<
|
||||||
"attributes may not be specified on a category">;
|
"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<
|
def warn_objc_protocol_qualifier_missing_id : Warning<
|
||||||
"protocol qualifiers without 'id' is archaic">;
|
"protocol qualifiers without 'id' is archaic">;
|
||||||
def err_objc_unknown_at : Error<"expected an Objective-C directive after '@'">;
|
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<
|
def err_missing_proto_definition : Error<
|
||||||
"cannot find definition of 'Protocol'">;
|
"cannot find definition of 'Protocol'">;
|
||||||
def err_missing_class_definition : Error<"cannot find definition of 'Class'">;
|
def err_missing_class_definition : Error<"cannot find definition of 'Class'">;
|
||||||
def err_expected_implementation : Error<
|
def err_expected_objc_container : Error<
|
||||||
"@end must appear in an @implementation context">;
|
"'@end' must appear in an Objective-C context">;
|
||||||
def error_property_ivar_decl : Error<
|
def error_property_ivar_decl : Error<
|
||||||
"property synthesize requires specification of an ivar">;
|
"property synthesize requires specification of an ivar">;
|
||||||
def err_synthesized_property_name : Error<
|
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 note_method_declared_at : Note<"method declared here">;
|
||||||
def err_setter_type_void : Error<"type of setter must be void">;
|
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_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 :
|
def err_objc_var_decl_inclass :
|
||||||
Error<"cannot declare variable inside @interface or @protocol">;
|
Error<"cannot declare variable inside @interface or @protocol">;
|
||||||
def error_missing_method_context : Error<
|
def error_missing_method_context : Error<
|
||||||
|
|
|
@ -716,6 +716,7 @@ public:
|
||||||
private:
|
private:
|
||||||
void SuggestParentheses(SourceLocation Loc, unsigned DK,
|
void SuggestParentheses(SourceLocation Loc, unsigned DK,
|
||||||
SourceRange ParenRange);
|
SourceRange ParenRange);
|
||||||
|
void CheckNestedObjCContexts(SourceLocation AtLoc);
|
||||||
|
|
||||||
/// SkipUntil - Read tokens until we get to the specified token, then consume
|
/// SkipUntil - Read tokens until we get to the specified token, then consume
|
||||||
/// it (unless DontConsume is true). Because we cannot guarantee that the
|
/// it (unless DontConsume is true). Because we cannot guarantee that the
|
||||||
|
@ -1204,7 +1205,7 @@ private:
|
||||||
// Objective-C External Declarations
|
// Objective-C External Declarations
|
||||||
Parser::DeclGroupPtrTy ParseObjCAtDirectives();
|
Parser::DeclGroupPtrTy ParseObjCAtDirectives();
|
||||||
Parser::DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc);
|
Parser::DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc);
|
||||||
Decl *ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
|
Decl *ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
|
||||||
ParsedAttributes &prefixAttrs);
|
ParsedAttributes &prefixAttrs);
|
||||||
void ParseObjCClassInstanceVariables(Decl *interfaceDecl,
|
void ParseObjCClassInstanceVariables(Decl *interfaceDecl,
|
||||||
tok::ObjCKeywordKind visibility,
|
tok::ObjCKeywordKind visibility,
|
||||||
|
@ -1225,7 +1226,7 @@ private:
|
||||||
typedef SmallVector<LexedMethod*, 2> LateParsedObjCMethodContainer;
|
typedef SmallVector<LexedMethod*, 2> LateParsedObjCMethodContainer;
|
||||||
LateParsedObjCMethodContainer LateParsedObjCMethods;
|
LateParsedObjCMethodContainer LateParsedObjCMethods;
|
||||||
|
|
||||||
Decl *ParseObjCAtImplementationDeclaration(SourceLocation atLoc);
|
Decl *ParseObjCAtImplementationDeclaration(SourceLocation AtLoc);
|
||||||
DeclGroupPtrTy ParseObjCAtEndDeclaration(SourceRange atEnd);
|
DeclGroupPtrTy ParseObjCAtEndDeclaration(SourceRange atEnd);
|
||||||
Decl *ParseObjCAtAliasDeclaration(SourceLocation atLoc);
|
Decl *ParseObjCAtAliasDeclaration(SourceLocation atLoc);
|
||||||
Decl *ParseObjCPropertySynthesize(SourceLocation atLoc);
|
Decl *ParseObjCPropertySynthesize(SourceLocation atLoc);
|
||||||
|
|
|
@ -5173,6 +5173,17 @@ public:
|
||||||
const MultiLevelTemplateArgumentList &TemplateArgs);
|
const MultiLevelTemplateArgumentList &TemplateArgs);
|
||||||
|
|
||||||
// Objective-C declarations.
|
// 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,
|
Decl *ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
||||||
IdentifierInfo *ClassName,
|
IdentifierInfo *ClassName,
|
||||||
SourceLocation ClassLoc,
|
SourceLocation ClassLoc,
|
||||||
|
@ -5275,10 +5286,10 @@ public:
|
||||||
void MatchOneProtocolPropertiesInClass(Decl *CDecl,
|
void MatchOneProtocolPropertiesInClass(Decl *CDecl,
|
||||||
ObjCProtocolDecl *PDecl);
|
ObjCProtocolDecl *PDecl);
|
||||||
|
|
||||||
void ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
Decl *ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
||||||
Decl **allMethods = 0, unsigned allNum = 0,
|
Decl **allMethods = 0, unsigned allNum = 0,
|
||||||
Decl **allProperties = 0, unsigned pNum = 0,
|
Decl **allProperties = 0, unsigned pNum = 0,
|
||||||
DeclGroupPtrTy *allTUVars = 0, unsigned tuvNum = 0);
|
DeclGroupPtrTy *allTUVars = 0, unsigned tuvNum = 0);
|
||||||
|
|
||||||
Decl *ActOnProperty(Scope *S, SourceLocation AtLoc,
|
Decl *ActOnProperty(Scope *S, SourceLocation AtLoc,
|
||||||
FieldDeclarator &FD, ObjCDeclSpec &ODS,
|
FieldDeclarator &FD, ObjCDeclSpec &ODS,
|
||||||
|
|
|
@ -113,6 +113,23 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
|
||||||
ClassNames.size());
|
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-interface:
|
||||||
/// objc-class-interface-attributes[opt] objc-class-interface
|
/// objc-class-interface-attributes[opt] objc-class-interface
|
||||||
|
@ -141,10 +158,11 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
|
||||||
/// __attribute__((unavailable))
|
/// __attribute__((unavailable))
|
||||||
/// __attribute__((objc_exception)) - used by NSException on 64-bit
|
/// __attribute__((objc_exception)) - used by NSException on 64-bit
|
||||||
///
|
///
|
||||||
Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
|
Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
|
||||||
ParsedAttributes &attrs) {
|
ParsedAttributes &attrs) {
|
||||||
assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
|
assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
|
||||||
"ParseObjCAtInterfaceDeclaration(): Expected @interface");
|
"ParseObjCAtInterfaceDeclaration(): Expected @interface");
|
||||||
|
CheckNestedObjCContexts(AtLoc);
|
||||||
ConsumeToken(); // the "interface" identifier
|
ConsumeToken(); // the "interface" identifier
|
||||||
|
|
||||||
// Code completion after '@interface'.
|
// Code completion after '@interface'.
|
||||||
|
@ -205,7 +223,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Decl *CategoryType =
|
Decl *CategoryType =
|
||||||
Actions.ActOnStartCategoryInterface(atLoc,
|
Actions.ActOnStartCategoryInterface(AtLoc,
|
||||||
nameId, nameLoc,
|
nameId, nameLoc,
|
||||||
categoryId, categoryLoc,
|
categoryId, categoryLoc,
|
||||||
ProtocolRefs.data(),
|
ProtocolRefs.data(),
|
||||||
|
@ -214,7 +232,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
|
||||||
EndProtoLoc);
|
EndProtoLoc);
|
||||||
|
|
||||||
if (Tok.is(tok::l_brace))
|
if (Tok.is(tok::l_brace))
|
||||||
ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, atLoc);
|
ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, AtLoc);
|
||||||
|
|
||||||
ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType);
|
ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType);
|
||||||
return CategoryType;
|
return CategoryType;
|
||||||
|
@ -250,14 +268,14 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Decl *ClsType =
|
Decl *ClsType =
|
||||||
Actions.ActOnStartClassInterface(atLoc, nameId, nameLoc,
|
Actions.ActOnStartClassInterface(AtLoc, nameId, nameLoc,
|
||||||
superClassId, superClassLoc,
|
superClassId, superClassLoc,
|
||||||
ProtocolRefs.data(), ProtocolRefs.size(),
|
ProtocolRefs.data(), ProtocolRefs.size(),
|
||||||
ProtocolLocs.data(),
|
ProtocolLocs.data(),
|
||||||
EndProtoLoc, attrs.getList());
|
EndProtoLoc, attrs.getList());
|
||||||
|
|
||||||
if (Tok.is(tok::l_brace))
|
if (Tok.is(tok::l_brace))
|
||||||
ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, atLoc);
|
ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc);
|
||||||
|
|
||||||
ParseObjCInterfaceDeclList(tok::objc_interface, ClsType);
|
ParseObjCInterfaceDeclList(tok::objc_interface, ClsType);
|
||||||
return ClsType;
|
return ClsType;
|
||||||
|
@ -425,7 +443,10 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
|
||||||
|
|
||||||
case tok::objc_implementation:
|
case tok::objc_implementation:
|
||||||
case tok::objc_interface:
|
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();
|
ConsumeToken();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -465,10 +486,16 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
|
||||||
if (Tok.is(tok::code_completion)) {
|
if (Tok.is(tok::code_completion)) {
|
||||||
Actions.CodeCompleteObjCAtDirective(getCurScope());
|
Actions.CodeCompleteObjCAtDirective(getCurScope());
|
||||||
return cutOffParsing();
|
return cutOffParsing();
|
||||||
} else if (Tok.isObjCAtKeyword(tok::objc_end))
|
} else if (Tok.isObjCAtKeyword(tok::objc_end)) {
|
||||||
ConsumeToken(); // the "end" identifier
|
ConsumeToken(); // the "end" identifier
|
||||||
else
|
} else {
|
||||||
Diag(Tok, diag::err_objc_missing_end);
|
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.
|
// Insert collected methods declarations into the @interface object.
|
||||||
// This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
|
// This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
|
||||||
|
@ -1316,6 +1343,7 @@ Decl *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
|
||||||
ParsedAttributes &attrs) {
|
ParsedAttributes &attrs) {
|
||||||
assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
|
assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
|
||||||
"ParseObjCAtProtocolDeclaration(): Expected @protocol");
|
"ParseObjCAtProtocolDeclaration(): Expected @protocol");
|
||||||
|
CheckNestedObjCContexts(AtLoc);
|
||||||
ConsumeToken(); // the "protocol" identifier
|
ConsumeToken(); // the "protocol" identifier
|
||||||
|
|
||||||
if (Tok.is(tok::code_completion)) {
|
if (Tok.is(tok::code_completion)) {
|
||||||
|
@ -1399,10 +1427,10 @@ Decl *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
|
||||||
///
|
///
|
||||||
/// objc-category-implementation-prologue:
|
/// objc-category-implementation-prologue:
|
||||||
/// @implementation identifier ( identifier )
|
/// @implementation identifier ( identifier )
|
||||||
Decl *Parser::ParseObjCAtImplementationDeclaration(
|
Decl *Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
|
||||||
SourceLocation atLoc) {
|
|
||||||
assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
|
assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
|
||||||
"ParseObjCAtImplementationDeclaration(): Expected @implementation");
|
"ParseObjCAtImplementationDeclaration(): Expected @implementation");
|
||||||
|
CheckNestedObjCContexts(AtLoc);
|
||||||
ConsumeToken(); // the "implementation" identifier
|
ConsumeToken(); // the "implementation" identifier
|
||||||
|
|
||||||
// Code completion after '@implementation'.
|
// Code completion after '@implementation'.
|
||||||
|
@ -1446,7 +1474,7 @@ Decl *Parser::ParseObjCAtImplementationDeclaration(
|
||||||
}
|
}
|
||||||
rparenLoc = ConsumeParen();
|
rparenLoc = ConsumeParen();
|
||||||
Decl *ImplCatType = Actions.ActOnStartCategoryImplementation(
|
Decl *ImplCatType = Actions.ActOnStartCategoryImplementation(
|
||||||
atLoc, nameId, nameLoc, categoryId,
|
AtLoc, nameId, nameLoc, categoryId,
|
||||||
categoryLoc);
|
categoryLoc);
|
||||||
|
|
||||||
ObjCImpDecl = ImplCatType;
|
ObjCImpDecl = ImplCatType;
|
||||||
|
@ -1467,11 +1495,11 @@ Decl *Parser::ParseObjCAtImplementationDeclaration(
|
||||||
superClassLoc = ConsumeToken(); // Consume super class name
|
superClassLoc = ConsumeToken(); // Consume super class name
|
||||||
}
|
}
|
||||||
Decl *ImplClsType = Actions.ActOnStartClassImplementation(
|
Decl *ImplClsType = Actions.ActOnStartClassImplementation(
|
||||||
atLoc, nameId, nameLoc,
|
AtLoc, nameId, nameLoc,
|
||||||
superClassId, superClassLoc);
|
superClassId, superClassLoc);
|
||||||
|
|
||||||
if (Tok.is(tok::l_brace)) // we have ivars
|
if (Tok.is(tok::l_brace)) // we have ivars
|
||||||
ParseObjCClassInstanceVariables(ImplClsType, tok::objc_private, atLoc);
|
ParseObjCClassInstanceVariables(ImplClsType, tok::objc_private, AtLoc);
|
||||||
|
|
||||||
ObjCImpDecl = ImplClsType;
|
ObjCImpDecl = ImplClsType;
|
||||||
PendingObjCImpDecl.push_back(ObjCImpDecl);
|
PendingObjCImpDecl.push_back(ObjCImpDecl);
|
||||||
|
@ -1498,7 +1526,7 @@ Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// missing @implementation
|
// missing @implementation
|
||||||
Diag(atEnd.getBegin(), diag::err_expected_implementation);
|
Diag(atEnd.getBegin(), diag::err_expected_objc_container);
|
||||||
|
|
||||||
clearLateParsedObjCMethods();
|
clearLateParsedObjCMethods();
|
||||||
ObjCImpDecl = 0;
|
ObjCImpDecl = 0;
|
||||||
|
@ -1510,8 +1538,15 @@ Parser::DeclGroupPtrTy Parser::FinishPendingObjCActions() {
|
||||||
Actions.DiagnoseUseOfUnimplementedSelectors();
|
Actions.DiagnoseUseOfUnimplementedSelectors();
|
||||||
if (PendingObjCImpDecl.empty())
|
if (PendingObjCImpDecl.empty())
|
||||||
return Actions.ConvertDeclToDeclGroup(0);
|
return Actions.ConvertDeclToDeclGroup(0);
|
||||||
|
|
||||||
Decl *ImpDecl = PendingObjCImpDecl.pop_back_val();
|
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);
|
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
|
// Note: For class/category implemenations, allMethods/allProperties is
|
||||||
// always null.
|
// always null.
|
||||||
void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
||||||
Decl **allMethods, unsigned allNum,
|
Decl **allMethods, unsigned allNum,
|
||||||
Decl **allProperties, unsigned pNum,
|
Decl **allProperties, unsigned pNum,
|
||||||
DeclGroupPtrTy *allTUVars, unsigned tuvNum) {
|
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);
|
ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
|
||||||
Decl *ClassDecl = cast<Decl>(OCD);
|
Decl *ClassDecl = cast<Decl>(OCD);
|
||||||
|
|
||||||
|
@ -2165,15 +2189,6 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
||||||
|| isa<ObjCProtocolDecl>(ClassDecl);
|
|| isa<ObjCProtocolDecl>(ClassDecl);
|
||||||
bool checkIdenticalMethods = isa<ObjCImplementationDecl>(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.
|
// FIXME: Remove these and use the ObjCContainerDecl/DeclContext.
|
||||||
llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap;
|
llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap;
|
||||||
llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap;
|
llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap;
|
||||||
|
@ -2335,6 +2350,8 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
||||||
(*I)->setTopLevelDeclInObjCContainer();
|
(*I)->setTopLevelDeclInObjCContainer();
|
||||||
Consumer.HandleTopLevelDeclInObjCContainer(DG);
|
Consumer.HandleTopLevelDeclInObjCContainer(DG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ClassDecl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,4 +4,4 @@
|
||||||
@interface Rdar8452791 () - (void)rdar8452791;
|
@interface Rdar8452791 () - (void)rdar8452791;
|
||||||
|
|
||||||
// CHECK: error: cannot find interface declaration for '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
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||||
// rdar: //7824372
|
// rdar: //7824372
|
||||||
|
|
||||||
@interface A
|
@interface A // expected-note {{class started here}}
|
||||||
-(void) im0;
|
-(void) im0;
|
||||||
|
|
||||||
@implementation A // expected-error {{missing @end}}
|
@implementation A // expected-error {{missing '@end'}}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface B {
|
@interface B { // expected-note {{class started here}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@implementation B // expected-error {{missing @end}}
|
@implementation B // expected-error {{missing '@end'}}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface C
|
@interface C // expected-note 2 {{class started here}}
|
||||||
@property int P;
|
@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
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||||
// rdar://8283484
|
// rdar://8283484
|
||||||
@interface blah {
|
@interface blah { // expected-note {{class started here}}
|
||||||
@private
|
@private
|
||||||
}
|
}
|
||||||
// since I forgot the @end here it should say something
|
// 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
|
@end // and Unknown type name 'end' here
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
// 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 '@'}}
|
@ 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
|
// 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
|
// rdar://6480479
|
||||||
@interface A
|
@interface A // expected-note {{class started here}}
|
||||||
}; // expected-error {{missing @end}} \
|
}; // expected-error {{missing '@end'}} \
|
||||||
// expected-error {{expected external declaration}} \
|
// expected-error {{expected external declaration}} \
|
||||||
// expected-warning{{extra ';' outside of a function}}
|
// expected-warning{{extra ';' outside of a function}}
|
||||||
|
|
||||||
|
|
|
@ -3,20 +3,20 @@
|
||||||
@interface I0
|
@interface I0
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation I0 // expected-error {{'@end' is missing in implementation context}}
|
@implementation I0 // expected-note {{implementation started here}}
|
||||||
- meth { return 0; }
|
- meth { return 0; }
|
||||||
|
|
||||||
@interface I1 : I0
|
@interface I1 : I0 // expected-error {{missing '@end'}}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation I1 // expected-error {{'@end' is missing in implementation context}}
|
@implementation I1 // expected-note {{implementation started here}}
|
||||||
-(void) im0 { self = [super init]; }
|
-(void) im0 { self = [super init]; }
|
||||||
|
|
||||||
@interface I2 : I0
|
@interface I2 : I0 // expected-error {{missing '@end'}}
|
||||||
- I2meth;
|
- I2meth;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation I2 // expected-error {{'@end' is missing in implementation context}}
|
@implementation I2 // expected-note {{implementation started here}}
|
||||||
- I2meth { return 0; }
|
- 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}}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче