On Fri, Jun 19, 2015 at 4:18 PM, Douglas Gregor <dgre...@apple.com> wrote:
> Author: dgregor > Date: Fri Jun 19 18:18:00 2015 > New Revision: 240188 > > URL: http://llvm.org/viewvc/llvm-project?rev=240188&view=rev > Log: > Handle 'instancetype' in ParseDeclarationSpecifiers. > > ...instead of as a special case in ParseObjCTypeName with lots of > duplicated logic. Besides being a nice refactoring, this also allows > "- (instancetype __nonnull)self" in addition to "- (nonnull > instancetype)self". > > rdar://problem/19924646 > > Modified: > cfe/trunk/include/clang/Parse/Parser.h > cfe/trunk/lib/Parse/ParseDecl.cpp > cfe/trunk/lib/Parse/ParseObjc.cpp > cfe/trunk/test/SemaObjC/nullability.m > > Modified: cfe/trunk/include/clang/Parse/Parser.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=240188&r1=240187&r2=240188&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Parse/Parser.h (original) > +++ cfe/trunk/include/clang/Parse/Parser.h Fri Jun 19 18:18:00 2015 > @@ -626,6 +626,16 @@ private: > const char *&PrevSpec, unsigned &DiagID, > bool &isInvalid); > > + /// Returns true if the current token is the identifier 'instancetype'. > + /// > + /// Should only be used in Objective-C language modes. > + bool isObjCInstancetype() { > + assert(getLangOpts().ObjC1); > + if (!Ident_instancetype) > + Ident_instancetype = PP.getIdentifierInfo("instancetype"); > + return Tok.getIdentifierInfo() == Ident_instancetype; > This will assert if Tok ends up being an annotation token (see e.g. PR24515). (resending to the new list) > + } > + > /// TryKeywordIdentFallback - For compatibility with system headers > using > /// keywords as identifiers, attempt to convert the current token to an > /// identifier and optionally disable the keyword for the remainder of > the > @@ -1692,7 +1702,8 @@ private: > DSC_trailing, // C++11 trailing-type-specifier in a trailing return > type > DSC_alias_declaration, // C++11 type-specifier-seq in an > alias-declaration > DSC_top_level, // top-level/namespace declaration context > - DSC_template_type_arg // template type argument context > + DSC_template_type_arg, // template type argument context > + DSC_objc_method_result, // ObjC method result context, enables > 'instancetype' > }; > > /// Is this a context in which we are parsing just a type-specifier (or > @@ -1702,6 +1713,7 @@ private: > case DSC_normal: > case DSC_class: > case DSC_top_level: > + case DSC_objc_method_result: > return false; > > case DSC_template_type_arg: > > Modified: cfe/trunk/lib/Parse/ParseDecl.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=240188&r1=240187&r2=240188&view=diff > > ============================================================================== > --- cfe/trunk/lib/Parse/ParseDecl.cpp (original) > +++ cfe/trunk/lib/Parse/ParseDecl.cpp Fri Jun 19 18:18:00 2015 > @@ -2941,6 +2941,19 @@ void Parser::ParseDeclarationSpecifiers( > if (DS.isTypeAltiVecVector()) > goto DoneWithDeclSpec; > > + if (DSContext == DSC_objc_method_result && isObjCInstancetype()) { > + ParsedType TypeRep = Actions.ActOnObjCInstanceType(Loc); > + assert(TypeRep); > + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, > PrevSpec, > + DiagID, TypeRep, Policy); > + if (isInvalid) > + break; > + > + DS.SetRangeEnd(Loc); > + ConsumeToken(); > + continue; > + } > + > ParsedType TypeRep = > Actions.getTypeName(*Tok.getIdentifierInfo(), > Tok.getLocation(), getCurScope()); > > Modified: cfe/trunk/lib/Parse/ParseObjc.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=240188&r1=240187&r2=240188&view=diff > > ============================================================================== > --- cfe/trunk/lib/Parse/ParseObjc.cpp (original) > +++ cfe/trunk/lib/Parse/ParseObjc.cpp Fri Jun 19 18:18:00 2015 > @@ -1005,11 +1005,14 @@ ParsedType Parser::ParseObjCTypeName(Obj > ParseObjCTypeQualifierList(DS, context); > > ParsedType Ty; > - if (isTypeSpecifierQualifier()) { > + if (isTypeSpecifierQualifier() || isObjCInstancetype()) { > // Parse an abstract declarator. > DeclSpec declSpec(AttrFactory); > declSpec.setObjCQualifiers(&DS); > - ParseSpecifierQualifierList(declSpec); > + DeclSpecContext dsContext = DSC_normal; > + if (context == Declarator::ObjCResultContext) > + dsContext = DSC_objc_method_result; > + ParseSpecifierQualifierList(declSpec, AS_none, dsContext); > declSpec.SetRangeEnd(Tok.getLocation()); > Declarator declarator(declSpec, context); > ParseDeclarator(declarator); > @@ -1033,38 +1036,6 @@ ParsedType Parser::ParseObjCTypeName(Obj > if (context == Declarator::ObjCParameterContext) > takeDeclAttributes(*paramAttrs, declarator); > } > - } else if (context == Declarator::ObjCResultContext && > - Tok.is(tok::identifier)) { > - if (!Ident_instancetype) > - Ident_instancetype = PP.getIdentifierInfo("instancetype"); > - > - if (Tok.getIdentifierInfo() == Ident_instancetype) { > - SourceLocation loc = ConsumeToken(); > - Ty = Actions.ActOnObjCInstanceType(loc); > - > - // Synthesize an abstract declarator so we can use > Sema::ActOnTypeName. > - bool addedToDeclSpec = false; > - const char *prevSpec; > - unsigned diagID; > - DeclSpec declSpec(AttrFactory); > - declSpec.setObjCQualifiers(&DS); > - declSpec.SetTypeSpecType(DeclSpec::TST_typename, loc, prevSpec, > diagID, > - Ty, > - > Actions.getASTContext().getPrintingPolicy()); > - declSpec.SetRangeEnd(loc); > - Declarator declarator(declSpec, context); > - > - // Map a nullability specifier to a context-sensitive keyword > attribute. > - if (DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) > - addContextSensitiveTypeNullability(*this, declarator, > - DS.getNullability(), > - DS.getNullabilityLoc(), > - addedToDeclSpec); > - > - TypeResult type = Actions.ActOnTypeName(getCurScope(), declarator); > - if (!type.isInvalid()) > - Ty = type.get(); > - } > } > > if (Tok.is(tok::r_paren)) > > Modified: cfe/trunk/test/SemaObjC/nullability.m > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/nullability.m?rev=240188&r1=240187&r2=240188&view=diff > > ============================================================================== > --- cfe/trunk/test/SemaObjC/nullability.m (original) > +++ cfe/trunk/test/SemaObjC/nullability.m Fri Jun 19 18:18:00 2015 > @@ -156,6 +156,10 @@ __attribute__((objc_root_class)) > - (nonnull instancetype)initWithBlah:(nonnull id)blah; > - (nullable instancetype)returnMe; > + (nullable instancetype)returnInstanceOfMe; > + > +- (nonnull instancetype __nullable)initWithBlah2:(nonnull id)blah; // > expected-error {{nullability specifier '__nullable' conflicts with existing > specifier '__nonnull'}} > +- (instancetype __nullable)returnMe2; > ++ (__nonnull instancetype)returnInstanceOfMe2; > @end > > void test_instancetype(InitializableClass * __nonnull ic, id __nonnull > object) { > @@ -163,6 +167,9 @@ void test_instancetype(InitializableClas > ip = [InitializableClass returnMe]; // expected-warning{{incompatible > pointer types assigning to 'int *' from 'id __nullable'}} > ip = [InitializableClass returnInstanceOfMe]; // > expected-warning{{incompatible pointer types assigning to 'int *' from > 'InitializableClass * __nullable'}} > ip = [object returnMe]; // expected-warning{{incompatible pointer types > assigning to 'int *' from 'id __nullable'}} > + > + ip = [ic returnMe2]; // expected-warning{{incompatible pointer types > assigning to 'int *' from 'InitializableClass * __nullable'}} > + ip = [InitializableClass returnInstanceOfMe2]; // > expected-warning{{incompatible pointer types assigning to 'int *' from > 'InitializableClass * __nonnull'}} > } > > // Check null_resettable getters/setters. > > > _______________________________________________ > cfe-commits mailing list > cfe-comm...@cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits