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