r240188 - Handle 'instancetype' in ParseDeclarationSpecifiers.
Douglas Gregor
dgregor at apple.com
Fri Jun 19 16:18:00 PDT 2015
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;
+ }
+
/// 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.
More information about the cfe-commits
mailing list