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 | a55902bf98a4a0b5929ddd80c4ed8fffb2eb2af3 (patch) | |
| tree | f9c3d5556ff3180eb4d5b4c24130886c14203e06 /clang/lib/Parse | |
| parent | 4a4772fae267b4d0c7273bf6f30605f4ece645c8 (diff) | |
| download | bcm5719-llvm-a55902bf98a4a0b5929ddd80c4ed8fffb2eb2af3.tar.gz bcm5719-llvm-a55902bf98a4a0b5929ddd80c4ed8fffb2eb2af3.zip | |
Parse attributes written in an ObjC method parameter type as
attributes on the parameter declaration.
llvm-svn: 140944
Diffstat (limited to 'clang/lib/Parse')
| -rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseObjc.cpp | 82 |
3 files changed, 72 insertions, 14 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index e9d3185b9a8..0e4fee3086d 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -33,12 +33,10 @@ using namespace clang; /// Called type-id in C++. TypeResult Parser::ParseTypeName(SourceRange *Range, Declarator::TheContext Context, - ObjCDeclSpec *objcQuals, AccessSpecifier AS, Decl **OwnedType) { // Parse the common declaration-specifiers piece. DeclSpec DS(AttrFactory); - DS.setObjCQualifiers(objcQuals); ParseSpecifierQualifierList(DS, AS); if (OwnedType) *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : 0; diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 2fd5c0059dc..5d7a7729f18 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -519,7 +519,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, TypeAlias = ParseTypeName(0, TemplateInfo.Kind ? Declarator::AliasTemplateContext : - Declarator::AliasDeclContext, 0, AS, OwnedType); + Declarator::AliasDeclContext, AS, OwnedType); } else // Parse (optional) attributes (most likely GNU strong-using extension). MaybeParseGNUAttributes(attrs); diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 1d600626026..6ebe3b2df1e 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/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); |

