diff options
author | John McCall <rjmccall@apple.com> | 2011-10-01 09:56:14 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-10-01 09:56:14 +0000 |
commit | cdda47faab5c2c61c239491a1a091e071ed3e38e (patch) | |
tree | 83d314cf2ed731d058e03437d8cd1896fa1c076c /lib/Parse/ParseObjc.cpp | |
parent | b459cf34c4df1a1317a9bda1e1e2cc32364e62cf (diff) |
Parse attributes written in an ObjC method parameter type as
attributes on the parameter declaration.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140944 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseObjc.cpp')
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 82 |
1 files changed, 71 insertions, 11 deletions
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 1d60062602..6ebe3b2df1 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -742,11 +742,14 @@ bool Parser::isTokIdentifier_in() const { /// objc-type-qualifiers objc-type-qualifier /// void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, - ObjCTypeNameContext Context) { + Declarator::TheContext Context) { + assert(Context == Declarator::ObjCParameterContext || + Context == Declarator::ObjCResultContext); + while (1) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCPassingType(getCurScope(), DS, - Context == OTN_ParameterType); + Context == Declarator::ObjCParameterContext); return cutOffParsing(); } @@ -779,12 +782,51 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, } } +/// Take all the decl attributes out of the given list and add +/// them to the given attribute set. +static void takeDeclAttributes(ParsedAttributes &attrs, + AttributeList *list) { + while (list) { + AttributeList *cur = list; + list = cur->getNext(); + + if (!cur->isUsedAsTypeAttr()) { + // Clear out the next pointer. We're really completely + // destroying the internal invariants of the declarator here, + // but it doesn't matter because we're done with it. + cur->setNext(0); + attrs.add(cur); + } + } +} + +/// takeDeclAttributes - Take all the decl attributes from the given +/// declarator and add them to the given list. +static void takeDeclAttributes(ParsedAttributes &attrs, + Declarator &D) { + // First, take ownership of all attributes. + attrs.getPool().takeAllFrom(D.getAttributePool()); + attrs.getPool().takeAllFrom(D.getDeclSpec().getAttributePool()); + + // Now actually move the attributes over. + takeDeclAttributes(attrs, D.getDeclSpec().getAttributes().getList()); + takeDeclAttributes(attrs, D.getAttributes()); + for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) + takeDeclAttributes(attrs, + const_cast<AttributeList*>(D.getTypeObject(i).getAttrs())); +} + /// objc-type-name: /// '(' objc-type-qualifiers[opt] type-name ')' /// '(' objc-type-qualifiers[opt] ')' /// ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, - ObjCTypeNameContext Context) { + Declarator::TheContext context, + ParsedAttributes *paramAttrs) { + assert(context == Declarator::ObjCParameterContext || + context == Declarator::ObjCResultContext); + assert((paramAttrs != 0) == (context == Declarator::ObjCParameterContext)); + assert(Tok.is(tok::l_paren) && "expected ("); SourceLocation LParenLoc = ConsumeParen(); @@ -792,15 +834,30 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, ObjCDeclContextSwitch ObjCDC(*this); // Parse type qualifiers, in, inout, etc. - ParseObjCTypeQualifierList(DS, Context); + ParseObjCTypeQualifierList(DS, context); ParsedType Ty; if (isTypeSpecifierQualifier()) { - TypeResult TypeSpec = - ParseTypeName(0, Declarator::ObjCPrototypeContext, &DS); - if (!TypeSpec.isInvalid()) - Ty = TypeSpec.get(); - } else if (Context == OTN_ResultType && Tok.is(tok::identifier)) { + // Parse an abstract declarator. + DeclSpec declSpec(AttrFactory); + declSpec.setObjCQualifiers(&DS); + ParseSpecifierQualifierList(declSpec); + Declarator declarator(declSpec, context); + ParseDeclarator(declarator); + + // If that's not invalid, extract a type. + if (!declarator.isInvalidType()) { + TypeResult type = Actions.ActOnTypeName(getCurScope(), declarator); + if (!type.isInvalid()) + Ty = type.get(); + + // If we're parsing a parameter, steal all the decl attributes + // and add them to the decl spec. + if (context == Declarator::ObjCParameterContext) + takeDeclAttributes(*paramAttrs, declarator); + } + } else if (context == Declarator::ObjCResultContext && + Tok.is(tok::identifier)) { if (!Ident_instancetype) Ident_instancetype = PP.getIdentifierInfo("instancetype"); @@ -869,7 +926,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ParsedType ReturnType; ObjCDeclSpec DSRet; if (Tok.is(tok::l_paren)) - ReturnType = ParseObjCTypeName(DSRet, OTN_ResultType); + ReturnType = ParseObjCTypeName(DSRet, Declarator::ObjCResultContext, 0); // If attributes exist before the method, parse them. ParsedAttributes methodAttrs(AttrFactory); @@ -934,9 +991,12 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ArgInfo.Type = ParsedType(); if (Tok.is(tok::l_paren)) // Parse the argument type if present. - ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec, OTN_ParameterType); + ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec, + Declarator::ObjCParameterContext, + ¶mAttrs); // If attributes exist before the argument name, parse them. + // Regardless, collect all the attributes we've parsed so far. ArgInfo.ArgAttrs = 0; if (getLang().ObjC2) { MaybeParseGNUAttributes(paramAttrs); |