Restore patch I reversed in r138040. Known buildbot

failures are resolved.

llvm-svn: 138234
This commit is contained in:
Fariborz Jahanian 2011-08-22 15:54:49 +00:00
parent b40654e21d
commit 8d382dc781
14 changed files with 230 additions and 141 deletions

View File

@ -893,6 +893,11 @@ public:
return DeclKind == Decl::Block; return DeclKind == Decl::Block;
} }
bool isObjCContainer() const {
return (DeclKind >= (int)Decl::ObjCCategory &&
DeclKind <= (int)Decl::ObjCProtocol);
}
bool isFunctionOrMethod() const { bool isFunctionOrMethod() const {
switch (DeclKind) { switch (DeclKind) {
case Decl::Block: case Decl::Block:

View File

@ -186,6 +186,8 @@ public:
const Token &getCurToken() const { return Tok; } const Token &getCurToken() const { return Tok; }
Scope *getCurScope() const { return Actions.getCurScope(); } 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 // Type forwarding. All of these are statically 'void*', but they may all be
// different actual classes based on the actions in place. // different actual classes based on the actions in place.
@ -1054,8 +1056,7 @@ private:
SourceLocation &LAngleLoc, SourceLocation &LAngleLoc,
SourceLocation &EndProtoLoc); SourceLocation &EndProtoLoc);
bool ParseObjCProtocolQualifiers(DeclSpec &DS); bool ParseObjCProtocolQualifiers(DeclSpec &DS);
void ParseObjCInterfaceDeclList(Decl *interfaceDecl, void ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey);
tok::ObjCKeywordKind contextKey);
Decl *ParseObjCAtProtocolDeclaration(SourceLocation atLoc, Decl *ParseObjCAtProtocolDeclaration(SourceLocation atLoc,
ParsedAttributes &prefixAttrs); ParsedAttributes &prefixAttrs);
@ -1086,14 +1087,13 @@ private:
ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, ObjCTypeNameContext Context); ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, ObjCTypeNameContext Context);
void ParseObjCMethodRequirement(); void ParseObjCMethodRequirement();
Decl *ParseObjCMethodPrototype(Decl *classOrCat, Decl *ParseObjCMethodPrototype(
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword, tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword,
bool MethodDefinition = true); bool MethodDefinition = true);
Decl *ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType, Decl *ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType,
Decl *classDecl,
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword, tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword,
bool MethodDefinition=true); bool MethodDefinition=true);
void ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl); void ParseObjCPropertyAttribute(ObjCDeclSpec &DS);
Decl *ParseObjCMethodDefinition(); Decl *ParseObjCMethodDefinition();

View File

@ -1154,9 +1154,9 @@ public:
bool CheckNontrivialField(FieldDecl *FD); bool CheckNontrivialField(FieldDecl *FD);
void DiagnoseNontrivial(const RecordType* Record, CXXSpecialMember mem); void DiagnoseNontrivial(const RecordType* Record, CXXSpecialMember mem);
CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD); CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD);
void ActOnLastBitfield(SourceLocation DeclStart, Decl *IntfDecl, void ActOnLastBitfield(SourceLocation DeclStart,
SmallVectorImpl<Decl *> &AllIvarDecls); SmallVectorImpl<Decl *> &AllIvarDecls);
Decl *ActOnIvar(Scope *S, SourceLocation DeclStart, Decl *IntfDecl, Decl *ActOnIvar(Scope *S, SourceLocation DeclStart,
Declarator &D, Expr *BitfieldWidth, Declarator &D, Expr *BitfieldWidth,
tok::ObjCKeywordKind visibility); tok::ObjCKeywordKind visibility);
@ -1171,6 +1171,8 @@ public:
/// struct, or union). /// struct, or union).
void ActOnTagStartDefinition(Scope *S, Decl *TagDecl); void ActOnTagStartDefinition(Scope *S, Decl *TagDecl);
void ActOnObjCContainerStartDefinition(Decl *IDecl);
/// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a /// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a
/// C++ record definition's base-specifiers clause and are starting its /// C++ record definition's base-specifiers clause and are starting its
/// member declarations. /// member declarations.
@ -1183,6 +1185,8 @@ public:
void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl, void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl,
SourceLocation RBraceLoc); SourceLocation RBraceLoc);
void ActOnObjCContainerFinishDefinition(Decl *IDecl);
/// ActOnTagDefinitionError - Invoked when there was an unrecoverable /// ActOnTagDefinitionError - Invoked when there was an unrecoverable
/// error parsing the definition of a tag. /// error parsing the definition of a tag.
void ActOnTagDefinitionError(Scope *S, Decl *TagDecl); void ActOnTagDefinitionError(Scope *S, Decl *TagDecl);
@ -1845,7 +1849,6 @@ public:
/// Called by ActOnProperty to handle @property declarations in /// Called by ActOnProperty to handle @property declarations in
//// class extensions. //// class extensions.
Decl *HandlePropertyInClassExtension(Scope *S, Decl *HandlePropertyInClassExtension(Scope *S,
ObjCCategoryDecl *CDecl,
SourceLocation AtLoc, SourceLocation AtLoc,
FieldDeclarator &FD, FieldDeclarator &FD,
Selector GetterSel, Selector GetterSel,
@ -5044,7 +5047,7 @@ public:
void MatchOneProtocolPropertiesInClass(Decl *CDecl, void MatchOneProtocolPropertiesInClass(Decl *CDecl,
ObjCProtocolDecl *PDecl); ObjCProtocolDecl *PDecl);
void ActOnAtEnd(Scope *S, SourceRange AtEnd, Decl *classDecl, void 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);
@ -5052,7 +5055,6 @@ public:
Decl *ActOnProperty(Scope *S, SourceLocation AtLoc, Decl *ActOnProperty(Scope *S, SourceLocation AtLoc,
FieldDeclarator &FD, ObjCDeclSpec &ODS, FieldDeclarator &FD, ObjCDeclSpec &ODS,
Selector GetterSel, Selector SetterSel, Selector GetterSel, Selector SetterSel,
Decl *ClassCategory,
bool *OverridingProperty, bool *OverridingProperty,
tok::ObjCKeywordKind MethodImplKind, tok::ObjCKeywordKind MethodImplKind,
DeclContext *lexicalDC = 0); DeclContext *lexicalDC = 0);
@ -5060,7 +5062,7 @@ public:
Decl *ActOnPropertyImplDecl(Scope *S, Decl *ActOnPropertyImplDecl(Scope *S,
SourceLocation AtLoc, SourceLocation AtLoc,
SourceLocation PropertyLoc, SourceLocation PropertyLoc,
bool ImplKind,Decl *ClassImplDecl, bool ImplKind,
IdentifierInfo *PropertyId, IdentifierInfo *PropertyId,
IdentifierInfo *PropertyIvar, IdentifierInfo *PropertyIvar,
SourceLocation PropertyIvarLoc); SourceLocation PropertyIvarLoc);
@ -5091,7 +5093,7 @@ public:
SourceLocation BeginLoc, // location of the + or -. SourceLocation BeginLoc, // location of the + or -.
SourceLocation EndLoc, // location of the ; or {. SourceLocation EndLoc, // location of the ; or {.
tok::TokenKind MethodType, tok::TokenKind MethodType,
Decl *ClassDecl, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
SourceLocation SelectorStartLoc, Selector Sel, SourceLocation SelectorStartLoc, Selector Sel,
// optional arguments. The number of types/arguments is obtained // optional arguments. The number of types/arguments is obtained
// from the Sel.getNumArgs(). // from the Sel.getNumArgs().
@ -5837,14 +5839,13 @@ public:
CXXCtorInitializer** Initializers, CXXCtorInitializer** Initializers,
unsigned NumInitializers); unsigned NumInitializers);
void CodeCompleteObjCAtDirective(Scope *S, Decl *ObjCImpDecl, void CodeCompleteObjCAtDirective(Scope *S);
bool InInterface);
void CodeCompleteObjCAtVisibility(Scope *S); void CodeCompleteObjCAtVisibility(Scope *S);
void CodeCompleteObjCAtStatement(Scope *S); void CodeCompleteObjCAtStatement(Scope *S);
void CodeCompleteObjCAtExpression(Scope *S); void CodeCompleteObjCAtExpression(Scope *S);
void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS); void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS);
void CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl); void CodeCompleteObjCPropertyGetter(Scope *S);
void CodeCompleteObjCPropertySetter(Scope *S, Decl *ClassDecl); void CodeCompleteObjCPropertySetter(Scope *S);
void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
bool IsParameter); bool IsParameter);
void CodeCompleteObjCMessageReceiver(Scope *S); void CodeCompleteObjCMessageReceiver(Scope *S);
@ -5881,14 +5882,12 @@ public:
void CodeCompleteObjCImplementationCategory(Scope *S, void CodeCompleteObjCImplementationCategory(Scope *S,
IdentifierInfo *ClassName, IdentifierInfo *ClassName,
SourceLocation ClassNameLoc); SourceLocation ClassNameLoc);
void CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl); void CodeCompleteObjCPropertyDefinition(Scope *S);
void CodeCompleteObjCPropertySynthesizeIvar(Scope *S, void CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
IdentifierInfo *PropertyName, IdentifierInfo *PropertyName);
Decl *ObjCImpDecl);
void CodeCompleteObjCMethodDecl(Scope *S, void CodeCompleteObjCMethodDecl(Scope *S,
bool IsInstanceMethod, bool IsInstanceMethod,
ParsedType ReturnType, ParsedType ReturnType);
Decl *IDecl);
void CodeCompleteObjCMethodDeclSelector(Scope *S, void CodeCompleteObjCMethodDeclSelector(Scope *S,
bool IsInstanceMethod, bool IsInstanceMethod,
bool AtParameterName, bool AtParameterName,
@ -6005,6 +6004,8 @@ public:
/// itself and in routines directly invoked from the parser and *never* from /// itself and in routines directly invoked from the parser and *never* from
/// template substitution or instantiation. /// template substitution or instantiation.
Scope *getCurScope() const { return CurScope; } Scope *getCurScope() const { return CurScope; }
Decl *getObjCDeclContext() const;
}; };
/// \brief RAII object that enters a new expression evaluation context. /// \brief RAII object that enters a new expression evaluation context.

View File

@ -2319,6 +2319,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
/// ///
void Parser:: void Parser::
ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) { ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
if (Tok.is(tok::kw___extension__)) { if (Tok.is(tok::kw___extension__)) {
// __extension__ silences extension warnings in the subexpression. // __extension__ silences extension warnings in the subexpression.
ExtensionRAIIObject O(Diags); // Use RAII to do this. ExtensionRAIIObject O(Diags); // Use RAII to do this.

View File

@ -52,7 +52,10 @@ Decl *Parser::ParseNamespace(unsigned Context,
SourceLocation InlineLoc) { SourceLocation InlineLoc) {
assert(Tok.is(tok::kw_namespace) && "Not a namespace!"); assert(Tok.is(tok::kw_namespace) && "Not a namespace!");
SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'. SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'.
Decl *DC = getObjCDeclContext();
if (DC)
Actions.ActOnObjCContainerFinishDefinition(DC);
if (Tok.is(tok::code_completion)) { if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteNamespaceDecl(getCurScope()); Actions.CodeCompleteNamespaceDecl(getCurScope());
ConsumeCodeCompletionToken(); ConsumeCodeCompletionToken();
@ -89,8 +92,10 @@ Decl *Parser::ParseNamespace(unsigned Context,
if (InlineLoc.isValid()) if (InlineLoc.isValid())
Diag(InlineLoc, diag::err_inline_namespace_alias) Diag(InlineLoc, diag::err_inline_namespace_alias)
<< FixItHint::CreateRemoval(InlineLoc); << FixItHint::CreateRemoval(InlineLoc);
Decl *Res = ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);
return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd); if (DC)
Actions.ActOnObjCContainerStartDefinition(DC);
return Res;
} }
@ -101,6 +106,8 @@ Decl *Parser::ParseNamespace(unsigned Context,
} }
Diag(Tok, Ident ? diag::err_expected_lbrace : Diag(Tok, Ident ? diag::err_expected_lbrace :
diag::err_expected_ident_lbrace); diag::err_expected_ident_lbrace);
if (DC)
Actions.ActOnObjCContainerStartDefinition(DC);
return 0; return 0;
} }
@ -115,6 +122,8 @@ Decl *Parser::ParseNamespace(unsigned Context,
} }
Diag(LBrace, diag::err_namespace_nonnamespace_scope); Diag(LBrace, diag::err_namespace_nonnamespace_scope);
SkipUntil(tok::r_brace, false); SkipUntil(tok::r_brace, false);
if (DC)
Actions.ActOnObjCContainerStartDefinition(DC);
return 0; return 0;
} }
@ -173,6 +182,8 @@ Decl *Parser::ParseNamespace(unsigned Context,
Actions.ActOnFinishNamespaceDef(NamespcDecl, RBraceLoc); Actions.ActOnFinishNamespaceDef(NamespcDecl, RBraceLoc);
DeclEnd = RBraceLoc; DeclEnd = RBraceLoc;
if (DC)
Actions.ActOnObjCContainerStartDefinition(DC);
return NamespcDecl; return NamespcDecl;
} }
@ -317,7 +328,9 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
ParsedAttributesWithRange &attrs, ParsedAttributesWithRange &attrs,
Decl **OwnedType) { Decl **OwnedType) {
assert(Tok.is(tok::kw_using) && "Not using token"); assert(Tok.is(tok::kw_using) && "Not using token");
Decl *DC = getObjCDeclContext();
if (DC)
Actions.ActOnObjCContainerFinishDefinition(DC);
// Eat 'using'. // Eat 'using'.
SourceLocation UsingLoc = ConsumeToken(); SourceLocation UsingLoc = ConsumeToken();
@ -335,7 +348,10 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
<< R << FixItHint::CreateRemoval(R); << R << FixItHint::CreateRemoval(R);
} }
return ParseUsingDirective(Context, UsingLoc, DeclEnd, attrs); Decl *Res = ParseUsingDirective(Context, UsingLoc, DeclEnd, attrs);
if (DC)
Actions.ActOnObjCContainerStartDefinition(DC);
return Res;
} }
// Otherwise, it must be a using-declaration or an alias-declaration. // Otherwise, it must be a using-declaration or an alias-declaration.
@ -343,8 +359,11 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
// Using declarations can't have attributes. // Using declarations can't have attributes.
ProhibitAttributes(attrs); ProhibitAttributes(attrs);
return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd, Decl *Res = ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd,
AS_none, OwnedType); AS_none, OwnedType);
if (DC)
Actions.ActOnObjCContainerStartDefinition(DC);
return Res;
} }
/// ParseUsingDirective - Parse C++ using-directive, assumes /// ParseUsingDirective - Parse C++ using-directive, assumes

View File

@ -33,7 +33,7 @@ Decl *Parser::ParseObjCAtDirectives() {
SourceLocation AtLoc = ConsumeToken(); // the "@" SourceLocation AtLoc = ConsumeToken(); // the "@"
if (Tok.is(tok::code_completion)) { if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCAtDirective(getCurScope(), ObjCImpDecl, false); Actions.CodeCompleteObjCAtDirective(getCurScope());
ConsumeCodeCompletionToken(); ConsumeCodeCompletionToken();
} }
@ -195,11 +195,13 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
ProtocolRefs.size(), ProtocolRefs.size(),
ProtocolLocs.data(), ProtocolLocs.data(),
EndProtoLoc); EndProtoLoc);
if (Tok.is(tok::l_brace))
ParseObjCClassInstanceVariables(CategoryType, tok::objc_private,
atLoc);
ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword); if (Tok.is(tok::l_brace))
ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, atLoc);
Actions.ActOnObjCContainerStartDefinition(CategoryType);
ParseObjCInterfaceDeclList(tok::objc_not_keyword);
Actions.ActOnObjCContainerFinishDefinition(CategoryType);
return CategoryType; return CategoryType;
} }
// Parse a class interface. // Parse a class interface.
@ -241,7 +243,9 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
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(ClsType, tok::objc_interface); Actions.ActOnObjCContainerStartDefinition(ClsType);
ParseObjCInterfaceDeclList(tok::objc_interface);
Actions.ActOnObjCContainerFinishDefinition(ClsType);
return ClsType; return ClsType;
} }
@ -249,17 +253,16 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
/// it's used, but instead it's been lifted to here to support VS2005. /// it's used, but instead it's been lifted to here to support VS2005.
struct Parser::ObjCPropertyCallback : FieldCallback { struct Parser::ObjCPropertyCallback : FieldCallback {
Parser &P; Parser &P;
Decl *IDecl;
SmallVectorImpl<Decl *> &Props; SmallVectorImpl<Decl *> &Props;
ObjCDeclSpec &OCDS; ObjCDeclSpec &OCDS;
SourceLocation AtLoc; SourceLocation AtLoc;
tok::ObjCKeywordKind MethodImplKind; tok::ObjCKeywordKind MethodImplKind;
ObjCPropertyCallback(Parser &P, Decl *IDecl, ObjCPropertyCallback(Parser &P,
SmallVectorImpl<Decl *> &Props, SmallVectorImpl<Decl *> &Props,
ObjCDeclSpec &OCDS, SourceLocation AtLoc, ObjCDeclSpec &OCDS, SourceLocation AtLoc,
tok::ObjCKeywordKind MethodImplKind) : tok::ObjCKeywordKind MethodImplKind) :
P(P), IDecl(IDecl), Props(Props), OCDS(OCDS), AtLoc(AtLoc), P(P), Props(Props), OCDS(OCDS), AtLoc(AtLoc),
MethodImplKind(MethodImplKind) { MethodImplKind(MethodImplKind) {
} }
@ -292,7 +295,7 @@ struct Parser::ObjCPropertyCallback : FieldCallback {
bool isOverridingProperty = false; bool isOverridingProperty = false;
Decl *Property = Decl *Property =
P.Actions.ActOnProperty(P.getCurScope(), AtLoc, FD, OCDS, P.Actions.ActOnProperty(P.getCurScope(), AtLoc, FD, OCDS,
GetterSel, SetterSel, IDecl, GetterSel, SetterSel,
&isOverridingProperty, &isOverridingProperty,
MethodImplKind); MethodImplKind);
if (!isOverridingProperty) if (!isOverridingProperty)
@ -314,8 +317,7 @@ struct Parser::ObjCPropertyCallback : FieldCallback {
/// @required /// @required
/// @optional /// @optional
/// ///
void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey) {
tok::ObjCKeywordKind contextKey) {
SmallVector<Decl *, 32> allMethods; SmallVector<Decl *, 32> allMethods;
SmallVector<Decl *, 16> allProperties; SmallVector<Decl *, 16> allProperties;
SmallVector<DeclGroupPtrTy, 8> allTUVariables; SmallVector<DeclGroupPtrTy, 8> allTUVariables;
@ -327,7 +329,7 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl,
// If this is a method prototype, parse it. // If this is a method prototype, parse it.
if (Tok.is(tok::minus) || Tok.is(tok::plus)) { if (Tok.is(tok::minus) || Tok.is(tok::plus)) {
Decl *methodPrototype = Decl *methodPrototype =
ParseObjCMethodPrototype(interfaceDecl, MethodImplKind, false); ParseObjCMethodPrototype(MethodImplKind, false);
allMethods.push_back(methodPrototype); allMethods.push_back(methodPrototype);
// Consume the ';' here, since ParseObjCMethodPrototype() is re-used for // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for
// method definitions. // method definitions.
@ -339,7 +341,6 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl,
Diag(Tok, diag::err_expected_minus_or_plus); Diag(Tok, diag::err_expected_minus_or_plus);
ParseObjCMethodDecl(Tok.getLocation(), ParseObjCMethodDecl(Tok.getLocation(),
tok::minus, tok::minus,
interfaceDecl,
MethodImplKind, false); MethodImplKind, false);
continue; continue;
} }
@ -368,9 +369,6 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl,
// erroneous r_brace would cause an infinite loop if not handled here. // erroneous r_brace would cause an infinite loop if not handled here.
if (Tok.is(tok::r_brace)) if (Tok.is(tok::r_brace))
break; 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); ParsedAttributes attrs(AttrFactory);
allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(attrs)); allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(attrs));
continue; continue;
@ -379,7 +377,7 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl,
// Otherwise, we have an @ directive, eat the @. // Otherwise, we have an @ directive, eat the @.
SourceLocation AtLoc = ConsumeToken(); // the "@" SourceLocation AtLoc = ConsumeToken(); // the "@"
if (Tok.is(tok::code_completion)) { if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCAtDirective(getCurScope(), ObjCImpDecl, true); Actions.CodeCompleteObjCAtDirective(getCurScope());
ConsumeCodeCompletionToken(); ConsumeCodeCompletionToken();
break; break;
} }
@ -433,9 +431,9 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl,
ObjCDeclSpec OCDS; ObjCDeclSpec OCDS;
// Parse property attribute list, if any. // Parse property attribute list, if any.
if (Tok.is(tok::l_paren)) if (Tok.is(tok::l_paren))
ParseObjCPropertyAttribute(OCDS, interfaceDecl); ParseObjCPropertyAttribute(OCDS);
ObjCPropertyCallback Callback(*this, interfaceDecl, allProperties, ObjCPropertyCallback Callback(*this, allProperties,
OCDS, AtLoc, MethodImplKind); OCDS, AtLoc, MethodImplKind);
// Parse all the comma separated declarators. // Parse all the comma separated declarators.
@ -450,7 +448,7 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl,
// We break out of the big loop in two cases: when we see @end or when we see // 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. // EOF. In the former case, eat the @end. In the later case, emit an error.
if (Tok.is(tok::code_completion)) { if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCAtDirective(getCurScope(), ObjCImpDecl, true); Actions.CodeCompleteObjCAtDirective(getCurScope());
ConsumeCodeCompletionToken(); ConsumeCodeCompletionToken();
} else if (Tok.isObjCAtKeyword(tok::objc_end)) } else if (Tok.isObjCAtKeyword(tok::objc_end))
ConsumeToken(); // the "end" identifier ConsumeToken(); // the "end" identifier
@ -459,7 +457,7 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl,
// 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.
Actions.ActOnAtEnd(getCurScope(), AtEnd, interfaceDecl, Actions.ActOnAtEnd(getCurScope(), AtEnd,
allMethods.data(), allMethods.size(), allMethods.data(), allMethods.size(),
allProperties.data(), allProperties.size(), allProperties.data(), allProperties.size(),
allTUVariables.data(), allTUVariables.size()); allTUVariables.data(), allTUVariables.size());
@ -485,7 +483,7 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl,
/// weak /// weak
/// unsafe_unretained /// unsafe_unretained
/// ///
void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl) { void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
assert(Tok.getKind() == tok::l_paren); assert(Tok.getKind() == tok::l_paren);
SourceLocation LHSLoc = ConsumeParen(); // consume '(' SourceLocation LHSLoc = ConsumeParen(); // consume '('
@ -536,9 +534,9 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl) {
if (Tok.is(tok::code_completion)) { if (Tok.is(tok::code_completion)) {
if (IsSetter) if (IsSetter)
Actions.CodeCompleteObjCPropertySetter(getCurScope(), ClassDecl); Actions.CodeCompleteObjCPropertySetter(getCurScope());
else else
Actions.CodeCompleteObjCPropertyGetter(getCurScope(), ClassDecl); Actions.CodeCompleteObjCPropertyGetter(getCurScope());
ConsumeCodeCompletionToken(); ConsumeCodeCompletionToken();
} }
@ -590,14 +588,13 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl) {
/// objc-method-attributes: [OBJC2] /// objc-method-attributes: [OBJC2]
/// __attribute__((deprecated)) /// __attribute__((deprecated))
/// ///
Decl *Parser::ParseObjCMethodPrototype(Decl *IDecl, Decl *Parser::ParseObjCMethodPrototype(tok::ObjCKeywordKind MethodImplKind,
tok::ObjCKeywordKind MethodImplKind,
bool MethodDefinition) { bool MethodDefinition) {
assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-"); assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-");
tok::TokenKind methodType = Tok.getKind(); tok::TokenKind methodType = Tok.getKind();
SourceLocation mLoc = ConsumeToken(); SourceLocation mLoc = ConsumeToken();
Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, IDecl,MethodImplKind, Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, MethodImplKind,
MethodDefinition); MethodDefinition);
// Since this rule is used for both method declarations and definitions, // Since this rule is used for both method declarations and definitions,
// the caller is (optionally) responsible for consuming the ';'. // the caller is (optionally) responsible for consuming the ';'.
@ -779,7 +776,9 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
SourceLocation LParenLoc = ConsumeParen(); SourceLocation LParenLoc = ConsumeParen();
SourceLocation TypeStartLoc = Tok.getLocation(); SourceLocation TypeStartLoc = Tok.getLocation();
Decl *DC = getObjCDeclContext();
if (DC)
Actions.ActOnObjCContainerFinishDefinition(DC);
// Parse type qualifiers, in, inout, etc. // Parse type qualifiers, in, inout, etc.
ParseObjCTypeQualifierList(DS, Context); ParseObjCTypeQualifierList(DS, Context);
@ -802,6 +801,8 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
// place. Emit an error then return what we have as the type. // place. Emit an error then return what we have as the type.
MatchRHSPunctuation(tok::r_paren, LParenLoc); MatchRHSPunctuation(tok::r_paren, LParenLoc);
} }
if (DC)
Actions.ActOnObjCContainerStartDefinition(DC);
return Ty; return Ty;
} }
@ -835,14 +836,13 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
/// ///
Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
tok::TokenKind mType, tok::TokenKind mType,
Decl *IDecl,
tok::ObjCKeywordKind MethodImplKind, tok::ObjCKeywordKind MethodImplKind,
bool MethodDefinition) { bool MethodDefinition) {
ParsingDeclRAIIObject PD(*this); ParsingDeclRAIIObject PD(*this);
if (Tok.is(tok::code_completion)) { if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
/*ReturnType=*/ ParsedType(), IDecl); /*ReturnType=*/ ParsedType());
ConsumeCodeCompletionToken(); ConsumeCodeCompletionToken();
} }
@ -859,7 +859,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
if (Tok.is(tok::code_completion)) { if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
ReturnType, IDecl); ReturnType);
ConsumeCodeCompletionToken(); ConsumeCodeCompletionToken();
} }
@ -885,7 +885,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent); Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
Decl *Result Decl *Result
= Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(),
mType, IDecl, DSRet, ReturnType, mType, DSRet, ReturnType,
selLoc, Sel, 0, selLoc, Sel, 0,
CParamInfo.data(), CParamInfo.size(), CParamInfo.data(), CParamInfo.size(),
methodAttrs.getList(), MethodImplKind, methodAttrs.getList(), MethodImplKind,
@ -1001,23 +1001,18 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
if (getLang().ObjC2) if (getLang().ObjC2)
MaybeParseGNUAttributes(methodAttrs); MaybeParseGNUAttributes(methodAttrs);
if (KeyIdents.size() == 0) { if (KeyIdents.size() == 0)
// Leave prototype scope.
PrototypeScope.Exit();
return 0; return 0;
}
Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(), Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
&KeyIdents[0]); &KeyIdents[0]);
Decl *Result Decl *Result
= Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(),
mType, IDecl, DSRet, ReturnType, mType, DSRet, ReturnType,
selLoc, Sel, &ArgInfos[0], selLoc, Sel, &ArgInfos[0],
CParamInfo.data(), CParamInfo.size(), CParamInfo.data(), CParamInfo.size(),
methodAttrs.getList(), methodAttrs.getList(),
MethodImplKind, isVariadic, MethodDefinition); MethodImplKind, isVariadic, MethodDefinition);
// Leave prototype scope.
PrototypeScope.Exit();
PD.complete(Result); PD.complete(Result);
return Result; return Result;
@ -1117,7 +1112,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
SourceLocation atLoc) { SourceLocation atLoc) {
assert(Tok.is(tok::l_brace) && "expected {"); assert(Tok.is(tok::l_brace) && "expected {");
SmallVector<Decl *, 32> AllIvarDecls; SmallVector<Decl *, 32> AllIvarDecls;
ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope); ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
SourceLocation LBraceLoc = ConsumeBrace(); // the "{" SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
@ -1175,11 +1170,13 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
} }
Decl *invoke(FieldDeclarator &FD) { Decl *invoke(FieldDeclarator &FD) {
P.Actions.ActOnObjCContainerStartDefinition(IDecl);
// Install the declarator into the interface decl. // Install the declarator into the interface decl.
Decl *Field Decl *Field
= P.Actions.ActOnIvar(P.getCurScope(), = P.Actions.ActOnIvar(P.getCurScope(),
FD.D.getDeclSpec().getSourceRange().getBegin(), FD.D.getDeclSpec().getSourceRange().getBegin(),
IDecl, FD.D, FD.BitfieldSize, visibility); FD.D, FD.BitfieldSize, visibility);
P.Actions.ActOnObjCContainerFinishDefinition(IDecl);
if (Field) if (Field)
AllIvarDecls.push_back(Field); AllIvarDecls.push_back(Field);
return Field; return Field;
@ -1199,7 +1196,9 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
} }
} }
SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc); SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
Actions.ActOnLastBitfield(RBraceLoc, interfaceDecl, AllIvarDecls); Actions.ActOnObjCContainerStartDefinition(interfaceDecl);
Actions.ActOnLastBitfield(RBraceLoc, AllIvarDecls);
Actions.ActOnObjCContainerFinishDefinition(interfaceDecl);
// Call ActOnFields() even if we don't have any decls. This is useful // 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. // for code rewriting tools that need to be aware of the empty list.
Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl,
@ -1295,7 +1294,11 @@ Decl *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
ProtocolRefs.size(), ProtocolRefs.size(),
ProtocolLocs.data(), ProtocolLocs.data(),
EndProtoLoc, attrs.getList()); EndProtoLoc, attrs.getList());
ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol);
Actions.ActOnObjCContainerStartDefinition(ProtoType);
ParseObjCInterfaceDeclList(tok::objc_protocol);
Actions.ActOnObjCContainerFinishDefinition(ProtoType);
return ProtoType; return ProtoType;
} }
@ -1356,6 +1359,8 @@ Decl *Parser::ParseObjCAtImplementationDeclaration(
Decl *ImplCatType = Actions.ActOnStartCategoryImplementation( Decl *ImplCatType = Actions.ActOnStartCategoryImplementation(
atLoc, nameId, nameLoc, categoryId, atLoc, nameId, nameLoc, categoryId,
categoryLoc); categoryLoc);
Actions.ActOnObjCContainerStartDefinition(ImplCatType);
ObjCImpDecl = ImplCatType; ObjCImpDecl = ImplCatType;
PendingObjCImpDecl.push_back(ObjCImpDecl); PendingObjCImpDecl.push_back(ObjCImpDecl);
return 0; return 0;
@ -1378,11 +1383,11 @@ Decl *Parser::ParseObjCAtImplementationDeclaration(
superClassId, superClassLoc); superClassId, superClassLoc);
if (Tok.is(tok::l_brace)) // we have ivars if (Tok.is(tok::l_brace)) // we have ivars
ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/, ParseObjCClassInstanceVariables(ImplClsType, tok::objc_private, atLoc);
tok::objc_private, atLoc);
Actions.ActOnObjCContainerStartDefinition(ImplClsType);
ObjCImpDecl = ImplClsType; ObjCImpDecl = ImplClsType;
PendingObjCImpDecl.push_back(ObjCImpDecl); PendingObjCImpDecl.push_back(ObjCImpDecl);
return 0; return 0;
} }
@ -1392,7 +1397,8 @@ Decl *Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
Decl *Result = ObjCImpDecl; Decl *Result = ObjCImpDecl;
ConsumeToken(); // the "end" identifier ConsumeToken(); // the "end" identifier
if (ObjCImpDecl) { if (ObjCImpDecl) {
Actions.ActOnAtEnd(getCurScope(), atEnd, ObjCImpDecl); Actions.ActOnAtEnd(getCurScope(), atEnd);
Actions.ActOnObjCContainerFinishDefinition(ObjCImpDecl);
ObjCImpDecl = 0; ObjCImpDecl = 0;
PendingObjCImpDecl.pop_back(); PendingObjCImpDecl.pop_back();
} }
@ -1408,7 +1414,8 @@ Parser::DeclGroupPtrTy Parser::FinishPendingObjCActions() {
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(), ImpDecl); Actions.ActOnAtEnd(getCurScope(), SourceRange());
Actions.ActOnObjCContainerFinishDefinition(ImpDecl);
return Actions.ConvertDeclToDeclGroup(ImpDecl); return Actions.ConvertDeclToDeclGroup(ImpDecl);
} }
@ -1455,7 +1462,7 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
while (true) { while (true) {
if (Tok.is(tok::code_completion)) { if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertyDefinition(getCurScope(), ObjCImpDecl); Actions.CodeCompleteObjCPropertyDefinition(getCurScope());
ConsumeCodeCompletionToken(); ConsumeCodeCompletionToken();
} }
@ -1474,8 +1481,7 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
ConsumeToken(); // consume '=' ConsumeToken(); // consume '='
if (Tok.is(tok::code_completion)) { if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId, Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId);
ObjCImpDecl);
ConsumeCodeCompletionToken(); ConsumeCodeCompletionToken();
} }
@ -1486,7 +1492,7 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
propertyIvar = Tok.getIdentifierInfo(); propertyIvar = Tok.getIdentifierInfo();
propertyIvarLoc = ConsumeToken(); // consume ivar-name propertyIvarLoc = ConsumeToken(); // consume ivar-name
} }
Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, true, ObjCImpDecl, Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, true,
propertyId, propertyIvar, propertyIvarLoc); propertyId, propertyIvar, propertyIvarLoc);
if (Tok.isNot(tok::comma)) if (Tok.isNot(tok::comma))
break; break;
@ -1509,7 +1515,7 @@ Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
ConsumeToken(); // consume dynamic ConsumeToken(); // consume dynamic
while (true) { while (true) {
if (Tok.is(tok::code_completion)) { if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertyDefinition(getCurScope(), ObjCImpDecl); Actions.CodeCompleteObjCPropertyDefinition(getCurScope());
ConsumeCodeCompletionToken(); ConsumeCodeCompletionToken();
} }
@ -1521,7 +1527,7 @@ Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
IdentifierInfo *propertyId = Tok.getIdentifierInfo(); IdentifierInfo *propertyId = Tok.getIdentifierInfo();
SourceLocation propertyLoc = ConsumeToken(); // consume property name SourceLocation propertyLoc = ConsumeToken(); // consume property name
Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, false, ObjCImpDecl, Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, false,
propertyId, 0, SourceLocation()); propertyId, 0, SourceLocation());
if (Tok.isNot(tok::comma)) if (Tok.isNot(tok::comma))
@ -1739,7 +1745,7 @@ Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) {
/// objc-method-def: objc-method-proto ';'[opt] '{' body '}' /// objc-method-def: objc-method-proto ';'[opt] '{' body '}'
/// ///
Decl *Parser::ParseObjCMethodDefinition() { Decl *Parser::ParseObjCMethodDefinition() {
Decl *MDecl = ParseObjCMethodPrototype(ObjCImpDecl); Decl *MDecl = ParseObjCMethodPrototype();
PrettyDeclStackTraceEntry CrashInfo(Actions, MDecl, Tok.getLocation(), PrettyDeclStackTraceEntry CrashInfo(Actions, MDecl, Tok.getLocation(),
"parsing Objective-C method"); "parsing Objective-C method");

View File

@ -27,11 +27,20 @@ Decl *
Parser::ParseDeclarationStartingWithTemplate(unsigned Context, Parser::ParseDeclarationStartingWithTemplate(unsigned Context,
SourceLocation &DeclEnd, SourceLocation &DeclEnd,
AccessSpecifier AS) { AccessSpecifier AS) {
if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) Decl *DC = getObjCDeclContext();
return ParseExplicitInstantiation(SourceLocation(), ConsumeToken(), if (DC)
DeclEnd); Actions.ActOnObjCContainerFinishDefinition(DC);
if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) {
return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS); Decl *Res = ParseExplicitInstantiation(SourceLocation(), ConsumeToken(),
DeclEnd);
if (DC)
Actions.ActOnObjCContainerStartDefinition(DC);
return Res;
}
Decl *Res = ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS);
if (DC)
Actions.ActOnObjCContainerStartDefinition(DC);
return Res;
} }
/// \brief RAII class that manages the template parameter depth. /// \brief RAII class that manages the template parameter depth.

View File

@ -811,7 +811,16 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs,
AccessSpecifier AS) { AccessSpecifier AS) {
ParsingDeclSpec DS(*this); ParsingDeclSpec DS(*this);
DS.takeAttributesFrom(attrs); DS.takeAttributesFrom(attrs);
return ParseDeclarationOrFunctionDefinition(DS, AS); 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;
} }
/// ParseFunctionDefinition - We parsed and verified that the specified /// ParseFunctionDefinition - We parsed and verified that the specified

View File

@ -4141,15 +4141,14 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
Results.AddResult(Result(Builder.TakeString())); Results.AddResult(Result(Builder.TakeString()));
} }
void Sema::CodeCompleteObjCAtDirective(Scope *S, Decl *ObjCImpDecl, void Sema::CodeCompleteObjCAtDirective(Scope *S) {
bool InInterface) {
typedef CodeCompletionResult Result; typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(), ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompletionContext::CCC_Other); CodeCompletionContext::CCC_Other);
Results.EnterNewScope(); Results.EnterNewScope();
if (ObjCImpDecl) if (isa<ObjCImplDecl>(CurContext))
AddObjCImplementationResults(getLangOptions(), Results, false); AddObjCImplementationResults(getLangOptions(), Results, false);
else if (InInterface) else if (CurContext->isObjCContainer())
AddObjCInterfaceResults(getLangOptions(), Results, false); AddObjCInterfaceResults(getLangOptions(), Results, false);
else else
AddObjCTopLevelResults(Results, false); AddObjCTopLevelResults(Results, false);
@ -4521,14 +4520,14 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
} }
void Sema::CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl) { void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
typedef CodeCompletionResult Result; typedef CodeCompletionResult Result;
// Try to find the interface where getters might live. // Try to find the interface where getters might live.
ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(ClassDecl); ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
if (!Class) { if (!Class) {
if (ObjCCategoryDecl *Category if (ObjCCategoryDecl *Category
= dyn_cast_or_null<ObjCCategoryDecl>(ClassDecl)) = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Class = Category->getClassInterface(); Class = Category->getClassInterface();
if (!Class) if (!Class)
@ -4549,15 +4548,15 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl) {
Results.data(),Results.size()); Results.data(),Results.size());
} }
void Sema::CodeCompleteObjCPropertySetter(Scope *S, Decl *ObjCImplDecl) { void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
typedef CodeCompletionResult Result; typedef CodeCompletionResult Result;
// Try to find the interface where setters might live. // Try to find the interface where setters might live.
ObjCInterfaceDecl *Class ObjCInterfaceDecl *Class
= dyn_cast_or_null<ObjCInterfaceDecl>(ObjCImplDecl); = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
if (!Class) { if (!Class) {
if (ObjCCategoryDecl *Category if (ObjCCategoryDecl *Category
= dyn_cast_or_null<ObjCCategoryDecl>(ObjCImplDecl)) = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Class = Category->getClassInterface(); Class = Category->getClassInterface();
if (!Class) if (!Class)
@ -5551,14 +5550,14 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Results.data(),Results.size()); Results.data(),Results.size());
} }
void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl) { void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
typedef CodeCompletionResult Result; typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(), ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompletionContext::CCC_Other); CodeCompletionContext::CCC_Other);
// Figure out where this @synthesize lives. // Figure out where this @synthesize lives.
ObjCContainerDecl *Container ObjCContainerDecl *Container
= dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl); = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
if (!Container || if (!Container ||
(!isa<ObjCImplementationDecl>(Container) && (!isa<ObjCImplementationDecl>(Container) &&
!isa<ObjCCategoryImplDecl>(Container))) !isa<ObjCCategoryImplDecl>(Container)))
@ -5591,15 +5590,14 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl) {
} }
void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
IdentifierInfo *PropertyName, IdentifierInfo *PropertyName) {
Decl *ObjCImpDecl) {
typedef CodeCompletionResult Result; typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(), ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompletionContext::CCC_Other); CodeCompletionContext::CCC_Other);
// Figure out where this @synthesize lives. // Figure out where this @synthesize lives.
ObjCContainerDecl *Container ObjCContainerDecl *Container
= dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl); = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
if (!Container || if (!Container ||
(!isa<ObjCImplementationDecl>(Container) && (!isa<ObjCImplementationDecl>(Container) &&
!isa<ObjCCategoryImplDecl>(Container))) !isa<ObjCCategoryImplDecl>(Container)))
@ -6412,12 +6410,15 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
void Sema::CodeCompleteObjCMethodDecl(Scope *S, void Sema::CodeCompleteObjCMethodDecl(Scope *S,
bool IsInstanceMethod, bool IsInstanceMethod,
ParsedType ReturnTy, ParsedType ReturnTy) {
Decl *IDecl) {
// Determine the return type of the method we're declaring, if // Determine the return type of the method we're declaring, if
// provided. // provided.
QualType ReturnType = GetTypeFromParser(ReturnTy); 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. // Determine where we should start searching for methods.
ObjCContainerDecl *SearchDecl = 0; ObjCContainerDecl *SearchDecl = 0;
bool IsInImplementation = false; bool IsInImplementation = false;

View File

@ -737,11 +737,6 @@ DeclContext *Sema::getContainingDC(DeclContext *DC) {
return 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(); return DC->getLexicalParent();
} }
@ -7732,6 +7727,15 @@ void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) {
PushDeclContext(S, Tag); 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, void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD,
SourceLocation FinalLoc, SourceLocation FinalLoc,
SourceLocation LBraceLoc) { SourceLocation LBraceLoc) {
@ -7783,6 +7787,11 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD,
Consumer.HandleTagDeclDefinition(Tag); Consumer.HandleTagDeclDefinition(Tag);
} }
void Sema::ActOnObjCContainerFinishDefinition(Decl *IDecl) {
// Exit this scope of this interface definition.
PopDeclContext();
}
void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) { void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) {
AdjustDeclIfTemplate(TagD); AdjustDeclIfTemplate(TagD);
TagDecl *Tag = cast<TagDecl>(TagD); TagDecl *Tag = cast<TagDecl>(TagD);
@ -8327,7 +8336,6 @@ TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) {
/// in order to create an IvarDecl object for it. /// in order to create an IvarDecl object for it.
Decl *Sema::ActOnIvar(Scope *S, Decl *Sema::ActOnIvar(Scope *S,
SourceLocation DeclStart, SourceLocation DeclStart,
Decl *IntfDecl,
Declarator &D, ExprTy *BitfieldWidth, Declarator &D, ExprTy *BitfieldWidth,
tok::ObjCKeywordKind Visibility) { tok::ObjCKeywordKind Visibility) {
@ -8370,7 +8378,7 @@ Decl *Sema::ActOnIvar(Scope *S,
Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility) Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility)
: ObjCIvarDecl::None; : ObjCIvarDecl::None;
// Must set ivar's DeclContext to its enclosing interface. // Must set ivar's DeclContext to its enclosing interface.
ObjCContainerDecl *EnclosingDecl = cast<ObjCContainerDecl>(IntfDecl); ObjCContainerDecl *EnclosingDecl = cast<ObjCContainerDecl>(CurContext);
ObjCContainerDecl *EnclosingContext; ObjCContainerDecl *EnclosingContext;
if (ObjCImplementationDecl *IMPDecl = if (ObjCImplementationDecl *IMPDecl =
dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) { dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
@ -8432,7 +8440,7 @@ Decl *Sema::ActOnIvar(Scope *S,
/// class and class extensions. For every class @interface and class /// class and class extensions. For every class @interface and class
/// extension @interface, if the last ivar is a bitfield of any type, /// 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. /// then add an implicit `char :0` ivar to the end of that interface.
void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *EnclosingDecl, void Sema::ActOnLastBitfield(SourceLocation DeclLoc,
SmallVectorImpl<Decl *> &AllIvarDecls) { SmallVectorImpl<Decl *> &AllIvarDecls) {
if (!LangOpts.ObjCNonFragileABI2 || AllIvarDecls.empty()) if (!LangOpts.ObjCNonFragileABI2 || AllIvarDecls.empty())
return; return;
@ -8446,9 +8454,9 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *EnclosingDecl,
Ivar->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); Ivar->getBitWidth()->EvaluateAsInt(Context).getZExtValue();
if (BitFieldSize == 0) if (BitFieldSize == 0)
return; return;
ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(EnclosingDecl); ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CurContext);
if (!ID) { if (!ID) {
if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) { if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(CurContext)) {
if (!CD->IsClassExtension()) if (!CD->IsClassExtension())
return; return;
} }
@ -8460,7 +8468,7 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *EnclosingDecl,
llvm::APInt Zero(Context.getTypeSize(Context.IntTy), 0); llvm::APInt Zero(Context.getTypeSize(Context.IntTy), 0);
Expr * BW = IntegerLiteral::Create(Context, Zero, Context.IntTy, DeclLoc); Expr * BW = IntegerLiteral::Create(Context, Zero, Context.IntTy, DeclLoc);
Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(EnclosingDecl), Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(CurContext),
DeclLoc, DeclLoc, 0, DeclLoc, DeclLoc, 0,
Context.CharTy, Context.CharTy,
Context.getTrivialTypeSourceInfo(Context.CharTy, Context.getTrivialTypeSourceInfo(Context.CharTy,
@ -9332,3 +9340,7 @@ void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name,
std::pair<IdentifierInfo*,WeakInfo>(AliasName, W)); std::pair<IdentifierInfo*,WeakInfo>(AliasName, W));
} }
} }
Decl *Sema::getObjCDeclContext() const {
return (dyn_cast_or_null<ObjCContainerDecl>(CurContext));
}

View File

@ -2052,15 +2052,14 @@ void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID,
// 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, void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
Decl *ClassDecl,
Decl **allMethods, unsigned allNum, Decl **allMethods, unsigned allNum,
Decl **allProperties, unsigned pNum, Decl **allProperties, unsigned pNum,
DeclGroupPtrTy *allTUVars, unsigned tuvNum) { DeclGroupPtrTy *allTUVars, unsigned tuvNum) {
// 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() if (!CurContext->isObjCContainer())
// should be true.
if (!ClassDecl)
return; return;
ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
Decl *ClassDecl = cast<Decl>(OCD);
bool isInterfaceDeclKind = bool isInterfaceDeclKind =
isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCCategoryDecl>(ClassDecl) isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCCategoryDecl>(ClassDecl)
@ -2427,7 +2426,7 @@ private:
Decl *Sema::ActOnMethodDeclaration( Decl *Sema::ActOnMethodDeclaration(
Scope *S, Scope *S,
SourceLocation MethodLoc, SourceLocation EndLoc, SourceLocation MethodLoc, SourceLocation EndLoc,
tok::TokenKind MethodType, Decl *ClassDecl, tok::TokenKind MethodType,
ObjCDeclSpec &ReturnQT, ParsedType ReturnType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
SourceLocation SelectorStartLoc, SourceLocation SelectorStartLoc,
Selector Sel, Selector Sel,
@ -2438,10 +2437,12 @@ Decl *Sema::ActOnMethodDeclaration(
AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind, AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind,
bool isVariadic, bool MethodDefinition) { bool isVariadic, bool MethodDefinition) {
// Make sure we can establish a context for the method. // Make sure we can establish a context for the method.
if (!ClassDecl) { if (!CurContext->isObjCContainer()) {
Diag(MethodLoc, diag::error_missing_method_context); Diag(MethodLoc, diag::error_missing_method_context);
return 0; return 0;
} }
ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
Decl *ClassDecl = cast<Decl>(OCD);
QualType resultDeclType; QualType resultDeclType;
TypeSourceInfo *ResultTInfo = 0; TypeSourceInfo *ResultTInfo = 0;
@ -2464,7 +2465,7 @@ Decl *Sema::ActOnMethodDeclaration(
ObjCMethodDecl* ObjCMethod = ObjCMethodDecl* ObjCMethod =
ObjCMethodDecl::Create(Context, MethodLoc, EndLoc, Sel, resultDeclType, ObjCMethodDecl::Create(Context, MethodLoc, EndLoc, Sel, resultDeclType,
ResultTInfo, ResultTInfo,
cast<DeclContext>(ClassDecl), CurContext,
MethodType == tok::minus, isVariadic, MethodType == tok::minus, isVariadic,
/*isSynthesized=*/false, /*isSynthesized=*/false,
/*isImplicitlyDeclared=*/false, /*isDefined=*/false, /*isImplicitlyDeclared=*/false, /*isDefined=*/false,
@ -2656,7 +2657,12 @@ Decl *Sema::ActOnMethodDeclaration(
bool Sema::CheckObjCDeclScope(Decl *D) { bool Sema::CheckObjCDeclScope(Decl *D) {
if (isa<TranslationUnitDecl>(CurContext->getRedeclContext())) if (isa<TranslationUnitDecl>(CurContext->getRedeclContext()))
return false; 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); Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope);
D->setInvalidDecl(); D->setInvalidDecl();

View File

@ -74,7 +74,6 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
ObjCDeclSpec &ODS, ObjCDeclSpec &ODS,
Selector GetterSel, Selector GetterSel,
Selector SetterSel, Selector SetterSel,
Decl *ClassCategory,
bool *isOverridingProperty, bool *isOverridingProperty,
tok::ObjCKeywordKind MethodImplKind, tok::ObjCKeywordKind MethodImplKind,
DeclContext *lexicalDC) { DeclContext *lexicalDC) {
@ -101,12 +100,11 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
!(Attributes & ObjCDeclSpec::DQ_PR_weak))); !(Attributes & ObjCDeclSpec::DQ_PR_weak)));
// Proceed with constructing the ObjCPropertDecls. // Proceed with constructing the ObjCPropertDecls.
ObjCContainerDecl *ClassDecl = ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(CurContext);
cast<ObjCContainerDecl>(ClassCategory);
if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl))
if (CDecl->IsClassExtension()) { if (CDecl->IsClassExtension()) {
Decl *Res = HandlePropertyInClassExtension(S, CDecl, AtLoc, Decl *Res = HandlePropertyInClassExtension(S, AtLoc,
FD, GetterSel, SetterSel, FD, GetterSel, SetterSel,
isAssign, isReadWrite, isAssign, isReadWrite,
Attributes, Attributes,
@ -137,7 +135,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
} }
Decl * Decl *
Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl, Sema::HandlePropertyInClassExtension(Scope *S,
SourceLocation AtLoc, FieldDeclarator &FD, SourceLocation AtLoc, FieldDeclarator &FD,
Selector GetterSel, Selector SetterSel, Selector GetterSel, Selector SetterSel,
const bool isAssign, const bool isAssign,
@ -146,9 +144,9 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl,
bool *isOverridingProperty, bool *isOverridingProperty,
TypeSourceInfo *T, TypeSourceInfo *T,
tok::ObjCKeywordKind MethodImplKind) { tok::ObjCKeywordKind MethodImplKind) {
ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(CurContext);
// Diagnose if this property is already in continuation class. // Diagnose if this property is already in continuation class.
DeclContext *DC = cast<DeclContext>(CDecl); DeclContext *DC = CurContext;
IdentifierInfo *PropertyId = FD.D.getIdentifier(); IdentifierInfo *PropertyId = FD.D.getIdentifier();
ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface(); ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface();
@ -235,14 +233,20 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl,
ProtocolPropertyODS. ProtocolPropertyODS.
setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind) setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind)
PIkind); PIkind);
// Must re-establish the context from class extension to primary
// class context.
ActOnObjCContainerFinishDefinition(CDecl);
ActOnObjCContainerStartDefinition(CCPrimary);
Decl *ProtocolPtrTy = Decl *ProtocolPtrTy =
ActOnProperty(S, AtLoc, FD, ProtocolPropertyODS, ActOnProperty(S, AtLoc, FD, ProtocolPropertyODS,
PIDecl->getGetterName(), PIDecl->getGetterName(),
PIDecl->getSetterName(), PIDecl->getSetterName(),
CCPrimary, isOverridingProperty, isOverridingProperty,
MethodImplKind, MethodImplKind,
/* lexicalDC = */ CDecl); /* lexicalDC = */ CDecl);
// restore class extension context.
ActOnObjCContainerFinishDefinition(CCPrimary);
ActOnObjCContainerStartDefinition(CDecl);
PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy); PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy);
} }
PIDecl->makeitReadWriteAttribute(); PIDecl->makeitReadWriteAttribute();
@ -507,12 +511,11 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
SourceLocation AtLoc, SourceLocation AtLoc,
SourceLocation PropertyLoc, SourceLocation PropertyLoc,
bool Synthesize, bool Synthesize,
Decl *ClassCatImpDecl,
IdentifierInfo *PropertyId, IdentifierInfo *PropertyId,
IdentifierInfo *PropertyIvar, IdentifierInfo *PropertyIvar,
SourceLocation PropertyIvarLoc) { SourceLocation PropertyIvarLoc) {
ObjCContainerDecl *ClassImpDecl = ObjCContainerDecl *ClassImpDecl =
cast_or_null<ObjCContainerDecl>(ClassCatImpDecl); cast_or_null<ObjCContainerDecl>(CurContext);
// Make sure we have a context for the property implementation declaration. // Make sure we have a context for the property implementation declaration.
if (!ClassImpDecl) { if (!ClassImpDecl) {
Diag(AtLoc, diag::error_missing_property_context); Diag(AtLoc, diag::error_missing_property_context);
@ -1281,7 +1284,7 @@ void Sema::DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl,
// Saying that they are located at the @implementation isn't really going // Saying that they are located at the @implementation isn't really going
// to help users. // to help users.
ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(), ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(),
true,IMPDecl, true,
Prop->getIdentifier(), Prop->getIdentifier(), Prop->getIdentifier(), Prop->getIdentifier(),
SourceLocation()); SourceLocation());
} }

View File

@ -5,4 +5,3 @@
extern "C" { @implementation Foo - (id)initWithBar:(Baz<WozBar>)pepper { extern "C" { @implementation Foo - (id)initWithBar:(Baz<WozBar>)pepper {
// CHECK: warning: cannot find interface declaration for 'Foo' // CHECK: warning: cannot find interface declaration for 'Foo'
// CHECK: error: '@end' is missing in implementation context

View File

@ -32,3 +32,21 @@ void test(id <NSCopying, NSPROTO, NSPROTO2> bar)
{ {
NSObject <NSCopying> *Init = bar; // expected-warning {{initializing 'NSObject<NSCopying> *' with an expression of incompatible type 'id<NSCopying,NSPROTO,NSPROTO2>'}} NSObject <NSCopying> *Init = bar; // expected-warning {{initializing 'NSObject<NSCopying> *' with an expression of incompatible type 'id<NSCopying,NSPROTO,NSPROTO2>'}}
} }
// rdar://8843851
@interface NSObject (CAT)
+ (struct S*)Meth : (struct S*)arg;
@end
struct S {
char *types;
};
@interface I
@end
@implementation I
- (struct S *)Meth : (struct S*)a {
return [NSObject Meth : a];
}
@end