diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2011-08-19 18:02:47 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2011-08-19 18:02:47 +0000 |
commit | e6f07f538fd0eddd6c087fcc01d4e4ff19129c71 (patch) | |
tree | d48b4f4bd3d46b513a2ad7613d7146ece6e97952 | |
parent | 3dbf2f5f00cfc8b25318c119c0d39f4a49d15ebe (diff) |
Revers r138040. Need to look at a few buildbot failures.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138049 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/DeclBase.h | 5 | ||||
-rw-r--r-- | include/clang/Parse/Parser.h | 10 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 33 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 110 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 11 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 37 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 34 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 24 | ||||
-rw-r--r-- | lib/Sema/SemaObjCProperty.cpp | 27 | ||||
-rw-r--r-- | test/Index/rdar-8288645-invalid-code.mm | 1 |
11 files changed, 128 insertions, 165 deletions
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index dfe43f4086..8355e36c75 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -893,11 +893,6 @@ public: return DeclKind == Decl::Block; } - bool isObjCContainer() const { - return (DeclKind >= (int)Decl::ObjCCategory && - DeclKind <= (int)Decl::ObjCProtocol); - } - bool isFunctionOrMethod() const { switch (DeclKind) { case Decl::Block: diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 00917c64ae..fc5d11cb6a 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -186,8 +186,6 @@ public: const Token &getCurToken() const { return Tok; } Scope *getCurScope() const { return Actions.getCurScope(); } - - Decl *getObjCDeclContext() const { return Actions.getObjCDeclContext(); } // Type forwarding. All of these are statically 'void*', but they may all be // different actual classes based on the actions in place. @@ -1056,7 +1054,8 @@ private: SourceLocation &LAngleLoc, SourceLocation &EndProtoLoc); bool ParseObjCProtocolQualifiers(DeclSpec &DS); - void ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey); + void ParseObjCInterfaceDeclList(Decl *interfaceDecl, + tok::ObjCKeywordKind contextKey); Decl *ParseObjCAtProtocolDeclaration(SourceLocation atLoc, ParsedAttributes &prefixAttrs); @@ -1087,13 +1086,14 @@ private: ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, ObjCTypeNameContext Context); void ParseObjCMethodRequirement(); - Decl *ParseObjCMethodPrototype( + Decl *ParseObjCMethodPrototype(Decl *classOrCat, tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword, bool MethodDefinition = true); Decl *ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType, + Decl *classDecl, tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword, bool MethodDefinition=true); - void ParseObjCPropertyAttribute(ObjCDeclSpec &DS); + void ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl); Decl *ParseObjCMethodDefinition(); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 4bb014b88a..520afbc5d2 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1154,9 +1154,9 @@ public: bool CheckNontrivialField(FieldDecl *FD); void DiagnoseNontrivial(const RecordType* Record, CXXSpecialMember mem); CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD); - void ActOnLastBitfield(SourceLocation DeclStart, + void ActOnLastBitfield(SourceLocation DeclStart, Decl *IntfDecl, SmallVectorImpl<Decl *> &AllIvarDecls); - Decl *ActOnIvar(Scope *S, SourceLocation DeclStart, + Decl *ActOnIvar(Scope *S, SourceLocation DeclStart, Decl *IntfDecl, Declarator &D, Expr *BitfieldWidth, tok::ObjCKeywordKind visibility); @@ -1171,8 +1171,6 @@ public: /// struct, or union). void ActOnTagStartDefinition(Scope *S, Decl *TagDecl); - void ActOnObjCContainerStartDefinition(Decl *IDecl); - /// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a /// C++ record definition's base-specifiers clause and are starting its /// member declarations. @@ -1185,8 +1183,6 @@ public: void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl, SourceLocation RBraceLoc); - void ActOnObjCContainerFinishDefinition(Decl *IDecl); - /// ActOnTagDefinitionError - Invoked when there was an unrecoverable /// error parsing the definition of a tag. void ActOnTagDefinitionError(Scope *S, Decl *TagDecl); @@ -1849,6 +1845,7 @@ public: /// Called by ActOnProperty to handle @property declarations in //// class extensions. Decl *HandlePropertyInClassExtension(Scope *S, + ObjCCategoryDecl *CDecl, SourceLocation AtLoc, FieldDeclarator &FD, Selector GetterSel, @@ -5047,7 +5044,7 @@ public: void MatchOneProtocolPropertiesInClass(Decl *CDecl, ObjCProtocolDecl *PDecl); - void ActOnAtEnd(Scope *S, SourceRange AtEnd, + void ActOnAtEnd(Scope *S, SourceRange AtEnd, Decl *classDecl, Decl **allMethods = 0, unsigned allNum = 0, Decl **allProperties = 0, unsigned pNum = 0, DeclGroupPtrTy *allTUVars = 0, unsigned tuvNum = 0); @@ -5055,6 +5052,7 @@ public: Decl *ActOnProperty(Scope *S, SourceLocation AtLoc, FieldDeclarator &FD, ObjCDeclSpec &ODS, Selector GetterSel, Selector SetterSel, + Decl *ClassCategory, bool *OverridingProperty, tok::ObjCKeywordKind MethodImplKind, DeclContext *lexicalDC = 0); @@ -5062,7 +5060,7 @@ public: Decl *ActOnPropertyImplDecl(Scope *S, SourceLocation AtLoc, SourceLocation PropertyLoc, - bool ImplKind, + bool ImplKind,Decl *ClassImplDecl, IdentifierInfo *PropertyId, IdentifierInfo *PropertyIvar, SourceLocation PropertyIvarLoc); @@ -5093,7 +5091,7 @@ public: SourceLocation BeginLoc, // location of the + or -. SourceLocation EndLoc, // location of the ; or {. tok::TokenKind MethodType, - ObjCDeclSpec &ReturnQT, ParsedType ReturnType, + Decl *ClassDecl, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, SourceLocation SelectorStartLoc, Selector Sel, // optional arguments. The number of types/arguments is obtained // from the Sel.getNumArgs(). @@ -5839,13 +5837,14 @@ public: CXXCtorInitializer** Initializers, unsigned NumInitializers); - void CodeCompleteObjCAtDirective(Scope *S); + void CodeCompleteObjCAtDirective(Scope *S, Decl *ObjCImpDecl, + bool InInterface); void CodeCompleteObjCAtVisibility(Scope *S); void CodeCompleteObjCAtStatement(Scope *S); void CodeCompleteObjCAtExpression(Scope *S); void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS); - void CodeCompleteObjCPropertyGetter(Scope *S); - void CodeCompleteObjCPropertySetter(Scope *S); + void CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl); + void CodeCompleteObjCPropertySetter(Scope *S, Decl *ClassDecl); void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, bool IsParameter); void CodeCompleteObjCMessageReceiver(Scope *S); @@ -5882,12 +5881,14 @@ public: void CodeCompleteObjCImplementationCategory(Scope *S, IdentifierInfo *ClassName, SourceLocation ClassNameLoc); - void CodeCompleteObjCPropertyDefinition(Scope *S); + void CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl); void CodeCompleteObjCPropertySynthesizeIvar(Scope *S, - IdentifierInfo *PropertyName); + IdentifierInfo *PropertyName, + Decl *ObjCImpDecl); void CodeCompleteObjCMethodDecl(Scope *S, bool IsInstanceMethod, - ParsedType ReturnType); + ParsedType ReturnType, + Decl *IDecl); void CodeCompleteObjCMethodDeclSelector(Scope *S, bool IsInstanceMethod, bool AtParameterName, @@ -6004,8 +6005,6 @@ public: /// itself and in routines directly invoked from the parser and *never* from /// template substitution or instantiation. Scope *getCurScope() const { return CurScope; } - - Decl *getObjCDeclContext() const; }; /// \brief RAII object that enters a new expression evaluation context. diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 2316590afe..9023b34fa9 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2319,7 +2319,6 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, /// void Parser:: ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) { - if (Tok.is(tok::kw___extension__)) { // __extension__ silences extension warnings in the subexpression. ExtensionRAIIObject O(Diags); // Use RAII to do this. diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index e2f8d1f3e6..c8b2a09d5e 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -33,7 +33,7 @@ Decl *Parser::ParseObjCAtDirectives() { SourceLocation AtLoc = ConsumeToken(); // the "@" if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCAtDirective(getCurScope()); + Actions.CodeCompleteObjCAtDirective(getCurScope(), ObjCImpDecl, false); ConsumeCodeCompletionToken(); } @@ -195,13 +195,11 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, ProtocolRefs.size(), ProtocolLocs.data(), EndProtoLoc); - if (Tok.is(tok::l_brace)) - ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, atLoc); - - Actions.ActOnObjCContainerStartDefinition(CategoryType); - ParseObjCInterfaceDeclList(tok::objc_not_keyword); - Actions.ActOnObjCContainerFinishDefinition(CategoryType); + ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, + atLoc); + + ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword); return CategoryType; } // Parse a class interface. @@ -243,9 +241,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, if (Tok.is(tok::l_brace)) ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, atLoc); - Actions.ActOnObjCContainerStartDefinition(ClsType); - ParseObjCInterfaceDeclList(tok::objc_interface); - Actions.ActOnObjCContainerFinishDefinition(ClsType); + ParseObjCInterfaceDeclList(ClsType, tok::objc_interface); return ClsType; } @@ -253,16 +249,17 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, /// it's used, but instead it's been lifted to here to support VS2005. struct Parser::ObjCPropertyCallback : FieldCallback { Parser &P; + Decl *IDecl; SmallVectorImpl<Decl *> &Props; ObjCDeclSpec &OCDS; SourceLocation AtLoc; tok::ObjCKeywordKind MethodImplKind; - ObjCPropertyCallback(Parser &P, + ObjCPropertyCallback(Parser &P, Decl *IDecl, SmallVectorImpl<Decl *> &Props, ObjCDeclSpec &OCDS, SourceLocation AtLoc, tok::ObjCKeywordKind MethodImplKind) : - P(P), Props(Props), OCDS(OCDS), AtLoc(AtLoc), + P(P), IDecl(IDecl), Props(Props), OCDS(OCDS), AtLoc(AtLoc), MethodImplKind(MethodImplKind) { } @@ -295,7 +292,7 @@ struct Parser::ObjCPropertyCallback : FieldCallback { bool isOverridingProperty = false; Decl *Property = P.Actions.ActOnProperty(P.getCurScope(), AtLoc, FD, OCDS, - GetterSel, SetterSel, + GetterSel, SetterSel, IDecl, &isOverridingProperty, MethodImplKind); if (!isOverridingProperty) @@ -317,7 +314,8 @@ struct Parser::ObjCPropertyCallback : FieldCallback { /// @required /// @optional /// -void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey) { +void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, + tok::ObjCKeywordKind contextKey) { SmallVector<Decl *, 32> allMethods; SmallVector<Decl *, 16> allProperties; SmallVector<DeclGroupPtrTy, 8> allTUVariables; @@ -329,7 +327,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey) { // If this is a method prototype, parse it. if (Tok.is(tok::minus) || Tok.is(tok::plus)) { Decl *methodPrototype = - ParseObjCMethodPrototype(MethodImplKind, false); + ParseObjCMethodPrototype(interfaceDecl, MethodImplKind, false); allMethods.push_back(methodPrototype); // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for // method definitions. @@ -341,6 +339,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey) { Diag(Tok, diag::err_expected_minus_or_plus); ParseObjCMethodDecl(Tok.getLocation(), tok::minus, + interfaceDecl, MethodImplKind, false); continue; } @@ -369,6 +368,9 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey) { // erroneous r_brace would cause an infinite loop if not handled here. if (Tok.is(tok::r_brace)) break; + + // FIXME: as the name implies, this rule allows function definitions. + // We could pass a flag or check for functions during semantic analysis. ParsedAttributes attrs(AttrFactory); allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(attrs)); continue; @@ -377,7 +379,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey) { // Otherwise, we have an @ directive, eat the @. SourceLocation AtLoc = ConsumeToken(); // the "@" if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCAtDirective(getCurScope()); + Actions.CodeCompleteObjCAtDirective(getCurScope(), ObjCImpDecl, true); ConsumeCodeCompletionToken(); break; } @@ -431,9 +433,9 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey) { ObjCDeclSpec OCDS; // Parse property attribute list, if any. if (Tok.is(tok::l_paren)) - ParseObjCPropertyAttribute(OCDS); + ParseObjCPropertyAttribute(OCDS, interfaceDecl); - ObjCPropertyCallback Callback(*this, allProperties, + ObjCPropertyCallback Callback(*this, interfaceDecl, allProperties, OCDS, AtLoc, MethodImplKind); // Parse all the comma separated declarators. @@ -448,7 +450,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey) { // We break out of the big loop in two cases: when we see @end or when we see // EOF. In the former case, eat the @end. In the later case, emit an error. if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCAtDirective(getCurScope()); + Actions.CodeCompleteObjCAtDirective(getCurScope(), ObjCImpDecl, true); ConsumeCodeCompletionToken(); } else if (Tok.isObjCAtKeyword(tok::objc_end)) ConsumeToken(); // the "end" identifier @@ -457,7 +459,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey) { // Insert collected methods declarations into the @interface object. // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit. - Actions.ActOnAtEnd(getCurScope(), AtEnd, + Actions.ActOnAtEnd(getCurScope(), AtEnd, interfaceDecl, allMethods.data(), allMethods.size(), allProperties.data(), allProperties.size(), allTUVariables.data(), allTUVariables.size()); @@ -483,7 +485,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey) { /// weak /// unsafe_unretained /// -void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { +void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl) { assert(Tok.getKind() == tok::l_paren); SourceLocation LHSLoc = ConsumeParen(); // consume '(' @@ -534,9 +536,9 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { if (Tok.is(tok::code_completion)) { if (IsSetter) - Actions.CodeCompleteObjCPropertySetter(getCurScope()); + Actions.CodeCompleteObjCPropertySetter(getCurScope(), ClassDecl); else - Actions.CodeCompleteObjCPropertyGetter(getCurScope()); + Actions.CodeCompleteObjCPropertyGetter(getCurScope(), ClassDecl); ConsumeCodeCompletionToken(); } @@ -588,13 +590,14 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { /// objc-method-attributes: [OBJC2] /// __attribute__((deprecated)) /// -Decl *Parser::ParseObjCMethodPrototype(tok::ObjCKeywordKind MethodImplKind, +Decl *Parser::ParseObjCMethodPrototype(Decl *IDecl, + tok::ObjCKeywordKind MethodImplKind, bool MethodDefinition) { assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-"); tok::TokenKind methodType = Tok.getKind(); SourceLocation mLoc = ConsumeToken(); - Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, MethodImplKind, + Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, IDecl,MethodImplKind, MethodDefinition); // Since this rule is used for both method declarations and definitions, // the caller is (optionally) responsible for consuming the ';'. @@ -832,13 +835,14 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, /// Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType, + Decl *IDecl, tok::ObjCKeywordKind MethodImplKind, bool MethodDefinition) { ParsingDeclRAIIObject PD(*this); if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, - /*ReturnType=*/ ParsedType()); + /*ReturnType=*/ ParsedType(), IDecl); ConsumeCodeCompletionToken(); } @@ -855,7 +859,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, - ReturnType); + ReturnType, IDecl); ConsumeCodeCompletionToken(); } @@ -881,7 +885,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent); Decl *Result = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), - mType, DSRet, ReturnType, + mType, IDecl, DSRet, ReturnType, selLoc, Sel, 0, CParamInfo.data(), CParamInfo.size(), methodAttrs.getList(), MethodImplKind, @@ -997,18 +1001,23 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, if (getLang().ObjC2) MaybeParseGNUAttributes(methodAttrs); - if (KeyIdents.size() == 0) + if (KeyIdents.size() == 0) { + // Leave prototype scope. + PrototypeScope.Exit(); return 0; + } Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(), &KeyIdents[0]); Decl *Result = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), - mType, DSRet, ReturnType, + mType, IDecl, DSRet, ReturnType, selLoc, Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), methodAttrs.getList(), MethodImplKind, isVariadic, MethodDefinition); + // Leave prototype scope. + PrototypeScope.Exit(); PD.complete(Result); return Result; @@ -1108,7 +1117,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, SourceLocation atLoc) { assert(Tok.is(tok::l_brace) && "expected {"); SmallVector<Decl *, 32> AllIvarDecls; - + ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope); SourceLocation LBraceLoc = ConsumeBrace(); // the "{" @@ -1166,13 +1175,11 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, } Decl *invoke(FieldDeclarator &FD) { - P.Actions.ActOnObjCContainerStartDefinition(IDecl); // Install the declarator into the interface decl. Decl *Field = P.Actions.ActOnIvar(P.getCurScope(), FD.D.getDeclSpec().getSourceRange().getBegin(), - FD.D, FD.BitfieldSize, visibility); - P.Actions.ActOnObjCContainerFinishDefinition(IDecl); + IDecl, FD.D, FD.BitfieldSize, visibility); if (Field) AllIvarDecls.push_back(Field); return Field; @@ -1192,7 +1199,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, } } SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc); - Actions.ActOnLastBitfield(RBraceLoc, AllIvarDecls); + Actions.ActOnLastBitfield(RBraceLoc, interfaceDecl, AllIvarDecls); // Call ActOnFields() even if we don't have any decls. This is useful // for code rewriting tools that need to be aware of the empty list. Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, @@ -1288,11 +1295,7 @@ Decl *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, ProtocolRefs.size(), ProtocolLocs.data(), EndProtoLoc, attrs.getList()); - - - Actions.ActOnObjCContainerStartDefinition(ProtoType); - ParseObjCInterfaceDeclList(tok::objc_protocol); - Actions.ActOnObjCContainerFinishDefinition(ProtoType); + ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol); return ProtoType; } @@ -1353,8 +1356,6 @@ Decl *Parser::ParseObjCAtImplementationDeclaration( Decl *ImplCatType = Actions.ActOnStartCategoryImplementation( atLoc, nameId, nameLoc, categoryId, categoryLoc); - - Actions.ActOnObjCContainerStartDefinition(ImplCatType); ObjCImpDecl = ImplCatType; PendingObjCImpDecl.push_back(ObjCImpDecl); return 0; @@ -1377,11 +1378,11 @@ Decl *Parser::ParseObjCAtImplementationDeclaration( superClassId, superClassLoc); if (Tok.is(tok::l_brace)) // we have ivars - ParseObjCClassInstanceVariables(ImplClsType, tok::objc_private, atLoc); - - Actions.ActOnObjCContainerStartDefinition(ImplClsType); + ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/, + tok::objc_private, atLoc); ObjCImpDecl = ImplClsType; PendingObjCImpDecl.push_back(ObjCImpDecl); + return 0; } @@ -1391,8 +1392,7 @@ Decl *Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) { Decl *Result = ObjCImpDecl; ConsumeToken(); // the "end" identifier if (ObjCImpDecl) { - Actions.ActOnAtEnd(getCurScope(), atEnd); - Actions.ActOnObjCContainerFinishDefinition(ObjCImpDecl); + Actions.ActOnAtEnd(getCurScope(), atEnd, ObjCImpDecl); ObjCImpDecl = 0; PendingObjCImpDecl.pop_back(); } @@ -1408,8 +1408,7 @@ Parser::DeclGroupPtrTy Parser::FinishPendingObjCActions() { if (PendingObjCImpDecl.empty()) return Actions.ConvertDeclToDeclGroup(0); Decl *ImpDecl = PendingObjCImpDecl.pop_back_val(); - Actions.ActOnAtEnd(getCurScope(), SourceRange()); - Actions.ActOnObjCContainerFinishDefinition(ImpDecl); + Actions.ActOnAtEnd(getCurScope(), SourceRange(), ImpDecl); return Actions.ConvertDeclToDeclGroup(ImpDecl); } @@ -1456,7 +1455,7 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { while (true) { if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCPropertyDefinition(getCurScope()); + Actions.CodeCompleteObjCPropertyDefinition(getCurScope(), ObjCImpDecl); ConsumeCodeCompletionToken(); } @@ -1475,7 +1474,8 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { ConsumeToken(); // consume '=' if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId); + Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId, + ObjCImpDecl); ConsumeCodeCompletionToken(); } @@ -1486,7 +1486,7 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { propertyIvar = Tok.getIdentifierInfo(); propertyIvarLoc = ConsumeToken(); // consume ivar-name } - Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, true, + Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, true, ObjCImpDecl, propertyId, propertyIvar, propertyIvarLoc); if (Tok.isNot(tok::comma)) break; @@ -1509,7 +1509,7 @@ Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { ConsumeToken(); // consume dynamic while (true) { if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCPropertyDefinition(getCurScope()); + Actions.CodeCompleteObjCPropertyDefinition(getCurScope(), ObjCImpDecl); ConsumeCodeCompletionToken(); } @@ -1521,7 +1521,7 @@ Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { IdentifierInfo *propertyId = Tok.getIdentifierInfo(); SourceLocation propertyLoc = ConsumeToken(); // consume property name - Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, false, + Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, false, ObjCImpDecl, propertyId, 0, SourceLocation()); if (Tok.isNot(tok::comma)) @@ -1739,7 +1739,7 @@ Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) { /// objc-method-def: objc-method-proto ';'[opt] '{' body '}' /// Decl *Parser::ParseObjCMethodDefinition() { - Decl *MDecl = ParseObjCMethodPrototype(); + Decl *MDecl = ParseObjCMethodPrototype(ObjCImpDecl); PrettyDeclStackTraceEntry CrashInfo(Actions, MDecl, Tok.getLocation(), "parsing Objective-C method"); diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index d7e7d4b081..5bb4165fbb 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -811,16 +811,7 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs, AccessSpecifier AS) { ParsingDeclSpec DS(*this); DS.takeAttributesFrom(attrs); - Decl *DC = getObjCDeclContext(); - if (DC) - // Must temporarily exit the objective-c container scope for - // parsing c constructs and re-enter objc container scope - // afterwards. - Actions.ActOnObjCContainerFinishDefinition(DC); - DeclGroupPtrTy resPtrTy = ParseDeclarationOrFunctionDefinition(DS, AS); - if (DC) - Actions.ActOnObjCContainerStartDefinition(DC); - return resPtrTy; + return ParseDeclarationOrFunctionDefinition(DS, AS); } /// ParseFunctionDefinition - We parsed and verified that the specified diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index ef54fbcad8..858a001d43 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -4141,14 +4141,15 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { Results.AddResult(Result(Builder.TakeString())); } -void Sema::CodeCompleteObjCAtDirective(Scope *S) { +void Sema::CodeCompleteObjCAtDirective(Scope *S, Decl *ObjCImpDecl, + bool InInterface) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); - if (isa<ObjCImplDecl>(CurContext)) + if (ObjCImpDecl) AddObjCImplementationResults(getLangOptions(), Results, false); - else if (CurContext->isObjCContainer()) + else if (InInterface) AddObjCInterfaceResults(getLangOptions(), Results, false); else AddObjCTopLevelResults(Results, false); @@ -4520,14 +4521,14 @@ static void AddObjCMethods(ObjCContainerDecl *Container, } -void Sema::CodeCompleteObjCPropertyGetter(Scope *S) { +void Sema::CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl) { typedef CodeCompletionResult Result; // Try to find the interface where getters might live. - ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext); + ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(ClassDecl); if (!Class) { if (ObjCCategoryDecl *Category - = dyn_cast_or_null<ObjCCategoryDecl>(CurContext)) + = dyn_cast_or_null<ObjCCategoryDecl>(ClassDecl)) Class = Category->getClassInterface(); if (!Class) @@ -4548,15 +4549,15 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S) { Results.data(),Results.size()); } -void Sema::CodeCompleteObjCPropertySetter(Scope *S) { +void Sema::CodeCompleteObjCPropertySetter(Scope *S, Decl *ObjCImplDecl) { typedef CodeCompletionResult Result; // Try to find the interface where setters might live. ObjCInterfaceDecl *Class - = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext); + = dyn_cast_or_null<ObjCInterfaceDecl>(ObjCImplDecl); if (!Class) { if (ObjCCategoryDecl *Category - = dyn_cast_or_null<ObjCCategoryDecl>(CurContext)) + = dyn_cast_or_null<ObjCCategoryDecl>(ObjCImplDecl)) Class = Category->getClassInterface(); if (!Class) @@ -5550,14 +5551,14 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S, Results.data(),Results.size()); } -void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { +void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompletionContext::CCC_Other); // Figure out where this @synthesize lives. ObjCContainerDecl *Container - = dyn_cast_or_null<ObjCContainerDecl>(CurContext); + = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl); if (!Container || (!isa<ObjCImplementationDecl>(Container) && !isa<ObjCCategoryImplDecl>(Container))) @@ -5590,14 +5591,15 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { } void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, - IdentifierInfo *PropertyName) { + IdentifierInfo *PropertyName, + Decl *ObjCImpDecl) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompletionContext::CCC_Other); // Figure out where this @synthesize lives. ObjCContainerDecl *Container - = dyn_cast_or_null<ObjCContainerDecl>(CurContext); + = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl); if (!Container || (!isa<ObjCImplementationDecl>(Container) && !isa<ObjCCategoryImplDecl>(Container))) @@ -6410,15 +6412,12 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, void Sema::CodeCompleteObjCMethodDecl(Scope *S, bool IsInstanceMethod, - ParsedType ReturnTy) { + ParsedType ReturnTy, + Decl *IDecl) { // Determine the return type of the method we're declaring, if // provided. QualType ReturnType = GetTypeFromParser(ReturnTy); - Decl *IDecl = 0; - if (CurContext->isObjCContainer()) { - ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext); - IDecl = cast<Decl>(OCD); - } + // Determine where we should start searching for methods. ObjCContainerDecl *SearchDecl = 0; bool IsInImplementation = false; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 26af6ef97d..b45b7ae5dc 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -737,6 +737,11 @@ DeclContext *Sema::getContainingDC(DeclContext *DC) { return DC; } + // ObjCMethodDecls are parsed (for some reason) outside the context + // of the class. + if (isa<ObjCMethodDecl>(DC)) + return DC->getLexicalParent()->getLexicalParent(); + return DC->getLexicalParent(); } @@ -7727,15 +7732,6 @@ void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) { PushDeclContext(S, Tag); } -void Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) { - assert(isa<ObjCContainerDecl>(IDecl) && - "ActOnObjCContainerStartDefinition - Not ObjCContainerDecl"); - DeclContext *OCD = cast<DeclContext>(IDecl); - assert(getContainingDC(OCD) == CurContext && - "The next DeclContext should be lexically contained in the current one."); - CurContext = OCD; -} - void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, SourceLocation FinalLoc, SourceLocation LBraceLoc) { @@ -7787,11 +7783,6 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD, Consumer.HandleTagDeclDefinition(Tag); } -void Sema::ActOnObjCContainerFinishDefinition(Decl *IDecl) { - // Exit this scope of this interface definition. - PopDeclContext(); -} - void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) { AdjustDeclIfTemplate(TagD); TagDecl *Tag = cast<TagDecl>(TagD); @@ -8336,6 +8327,7 @@ TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) { /// in order to create an IvarDecl object for it. Decl *Sema::ActOnIvar(Scope *S, SourceLocation DeclStart, + Decl *IntfDecl, Declarator &D, ExprTy *BitfieldWidth, tok::ObjCKeywordKind Visibility) { @@ -8378,7 +8370,7 @@ Decl *Sema::ActOnIvar(Scope *S, Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility) : ObjCIvarDecl::None; // Must set ivar's DeclContext to its enclosing interface. - ObjCContainerDecl *EnclosingDecl = cast<ObjCContainerDecl>(CurContext); + ObjCContainerDecl *EnclosingDecl = cast<ObjCContainerDecl>(IntfDecl); ObjCContainerDecl *EnclosingContext; if (ObjCImplementationDecl *IMPDecl = dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) { @@ -8440,7 +8432,7 @@ Decl *Sema::ActOnIvar(Scope *S, /// class and class extensions. For every class @interface and class /// extension @interface, if the last ivar is a bitfield of any type, /// then add an implicit `char :0` ivar to the end of that interface. -void Sema::ActOnLastBitfield(SourceLocation DeclLoc, +void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *EnclosingDecl, SmallVectorImpl<Decl *> &AllIvarDecls) { if (!LangOpts.ObjCNonFragileABI2 || AllIvarDecls.empty()) return; @@ -8454,9 +8446,9 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Ivar->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); if (BitFieldSize == 0) return; - ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CurContext); + ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(EnclosingDecl); if (!ID) { - if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(CurContext)) { + if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) { if (!CD->IsClassExtension()) return; } @@ -8468,7 +8460,7 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, llvm::APInt Zero(Context.getTypeSize(Context.IntTy), 0); Expr * BW = IntegerLiteral::Create(Context, Zero, Context.IntTy, DeclLoc); - Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(CurContext), + Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(EnclosingDecl), DeclLoc, DeclLoc, 0, Context.CharTy, Context.getTrivialTypeSourceInfo(Context.CharTy, @@ -9340,7 +9332,3 @@ void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name, std::pair<IdentifierInfo*,WeakInfo>(AliasName, W)); } } - -Decl *Sema::getObjCDeclContext() const { - return (dyn_cast_or_null<ObjCContainerDecl>(CurContext)); -} diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index d255a3686f..3c3c7cb232 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -2052,14 +2052,15 @@ void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, // Note: For class/category implemenations, allMethods/allProperties is // always null. void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, + Decl *ClassDecl, Decl **allMethods, unsigned allNum, Decl **allProperties, unsigned pNum, DeclGroupPtrTy *allTUVars, unsigned tuvNum) { - - if (!CurContext->isObjCContainer()) + // FIXME: If we don't have a ClassDecl, we have an error. We should consider + // always passing in a decl. If the decl has an error, isInvalidDecl() + // should be true. + if (!ClassDecl) return; - ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext); - Decl *ClassDecl = cast<Decl>(OCD); bool isInterfaceDeclKind = isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCCategoryDecl>(ClassDecl) @@ -2426,7 +2427,7 @@ private: Decl *Sema::ActOnMethodDeclaration( Scope *S, SourceLocation MethodLoc, SourceLocation EndLoc, - tok::TokenKind MethodType, + tok::TokenKind MethodType, Decl *ClassDecl, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, SourceLocation SelectorStartLoc, Selector Sel, @@ -2437,12 +2438,10 @@ Decl *Sema::ActOnMethodDeclaration( AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind, bool isVariadic, bool MethodDefinition) { // Make sure we can establish a context for the method. - if (!CurContext->isObjCContainer()) { + if (!ClassDecl) { Diag(MethodLoc, diag::error_missing_method_context); return 0; } - ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext); - Decl *ClassDecl = cast<Decl>(OCD); QualType resultDeclType; TypeSourceInfo *ResultTInfo = 0; @@ -2465,7 +2464,7 @@ Decl *Sema::ActOnMethodDeclaration( ObjCMethodDecl* ObjCMethod = ObjCMethodDecl::Create(Context, MethodLoc, EndLoc, Sel, resultDeclType, ResultTInfo, - CurContext, + cast<DeclContext>(ClassDecl), MethodType == tok::minus, isVariadic, /*isSynthesized=*/false, /*isImplicitlyDeclared=*/false, /*isDefined=*/false, @@ -2657,12 +2656,7 @@ Decl *Sema::ActOnMethodDeclaration( bool Sema::CheckObjCDeclScope(Decl *D) { if (isa<TranslationUnitDecl>(CurContext->getRedeclContext())) return false; - // Following is also an error. But it is caused my a missing @end - // and diagnostic is issued elsewere. - if (isa<ObjCContainerDecl>(CurContext->getRedeclContext())) { - return false; - } - + Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope); D->setInvalidDecl(); diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index a98c2c7d9a..9602c2bd5b 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -74,6 +74,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, ObjCDeclSpec &ODS, Selector GetterSel, Selector SetterSel, + Decl *ClassCategory, bool *isOverridingProperty, tok::ObjCKeywordKind MethodImplKind, DeclContext *lexicalDC) { @@ -100,11 +101,12 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, !(Attributes & ObjCDeclSpec::DQ_PR_weak))); // Proceed with constructing the ObjCPropertDecls. - ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(CurContext); + ObjCContainerDecl *ClassDecl = + cast<ObjCContainerDecl>(ClassCategory); if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) if (CDecl->IsClassExtension()) { - Decl *Res = HandlePropertyInClassExtension(S, AtLoc, + Decl *Res = HandlePropertyInClassExtension(S, CDecl, AtLoc, FD, GetterSel, SetterSel, isAssign, isReadWrite, Attributes, @@ -135,7 +137,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, } Decl * -Sema::HandlePropertyInClassExtension(Scope *S, +Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl, SourceLocation AtLoc, FieldDeclarator &FD, Selector GetterSel, Selector SetterSel, const bool isAssign, @@ -144,9 +146,9 @@ Sema::HandlePropertyInClassExtension(Scope *S, bool *isOverridingProperty, TypeSourceInfo *T, tok::ObjCKeywordKind MethodImplKind) { - ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(CurContext); + // Diagnose if this property is already in continuation class. - DeclContext *DC = CurContext; + DeclContext *DC = cast<DeclContext>(CDecl); IdentifierInfo *PropertyId = FD.D.getIdentifier(); ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface(); @@ -233,20 +235,14 @@ Sema::HandlePropertyInClassExtension(Scope *S, ProtocolPropertyODS. setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind) PIkind); - // Must re-establish the context from class extension to primary - // class context. - ActOnObjCContainerFinishDefinition(CDecl); - ActOnObjCContainerStartDefinition(CCPrimary); + Decl *ProtocolPtrTy = ActOnProperty(S, AtLoc, FD, ProtocolPropertyODS, PIDecl->getGetterName(), PIDecl->getSetterName(), - isOverridingProperty, + CCPrimary, isOverridingProperty, MethodImplKind, /* lexicalDC = */ CDecl); - // restore class extension context. - ActOnObjCContainerFinishDefinition(CCPrimary); - ActOnObjCContainerStartDefinition(CDecl); PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy); } PIDecl->makeitReadWriteAttribute(); @@ -511,11 +507,12 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, SourceLocation AtLoc, SourceLocation PropertyLoc, bool Synthesize, + Decl *ClassCatImpDecl, IdentifierInfo *PropertyId, IdentifierInfo *PropertyIvar, SourceLocation PropertyIvarLoc) { ObjCContainerDecl *ClassImpDecl = - cast_or_null<ObjCContainerDecl>(CurContext); + cast_or_null<ObjCContainerDecl>(ClassCatImpDecl); // Make sure we have a context for the property implementation declaration. if (!ClassImpDecl) { Diag(AtLoc, diag::error_missing_property_context); @@ -1283,7 +1280,7 @@ void Sema::DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl, // Saying that they are located at the @implementation isn't really going // to help users. ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(), - true, + true,IMPDecl, Prop->getIdentifier(), Prop->getIdentifier(), SourceLocation()); } diff --git a/test/Index/rdar-8288645-invalid-code.mm b/test/Index/rdar-8288645-invalid-code.mm index ec4564130a..74e2365edc 100644 --- a/test/Index/rdar-8288645-invalid-code.mm +++ b/test/Index/rdar-8288645-invalid-code.mm @@ -5,3 +5,4 @@ extern "C" { @implementation Foo - (id)initWithBar:(Baz<WozBar>)pepper { // CHECK: warning: cannot find interface declaration for 'Foo' +// CHECK: error: '@end' is missing in implementation context |