diff options
author | Douglas Gregor <dgregor@apple.com> | 2015-07-07 03:58:54 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2015-07-07 03:58:54 +0000 |
commit | 1ac1b63c9ca898e66aae9775cca6045082907b9a (patch) | |
tree | b9196b185b0185c84e60f99881aaffd69f4da93d /clang/lib/Parse/ParseObjc.cpp | |
parent | ab209d83be5dadff4f17364a71f323b89e3c63f8 (diff) | |
download | bcm5719-llvm-1ac1b63c9ca898e66aae9775cca6045082907b9a.tar.gz bcm5719-llvm-1ac1b63c9ca898e66aae9775cca6045082907b9a.zip |
Implement variance for Objective-C type parameters.
Introduce co- and contra-variance for Objective-C type parameters,
which allows us to express that (for example) an NSArray is covariant
in its type parameter. This means that NSArray<NSMutableString *> * is
a subtype of NSArray<NSString *> *, which is expected of the immutable
Foundation collections.
Type parameters can be annotated with __covariant or __contravariant
to make them co- or contra-variant, respectively. This feature can be
detected by __has_feature(objc_generics_variance). Implements
rdar://problem/20217490.
llvm-svn: 241549
Diffstat (limited to 'clang/lib/Parse/ParseObjc.cpp')
-rw-r--r-- | clang/lib/Parse/ParseObjc.cpp | 42 |
1 files changed, 35 insertions, 7 deletions
diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 0f90b684685..4f16d47dfa7 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -416,11 +416,15 @@ static void addContextSensitiveTypeNullability(Parser &P, /// '<' objc-type-parameter (',' objc-type-parameter)* '>' /// /// objc-type-parameter: -/// identifier objc-type-parameter-bound[opt] +/// objc-type-parameter-variance? identifier objc-type-parameter-bound[opt] /// /// objc-type-parameter-bound: /// ':' type-name /// +/// objc-type-parameter-variance: +/// '__covariant' +/// '__contravariant' +/// /// \param lAngleLoc The location of the starting '<'. /// /// \param protocolIdents Will capture the list of identifiers, if the @@ -444,12 +448,15 @@ ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs( auto makeProtocolIdentsIntoTypeParameters = [&]() { unsigned index = 0; for (const auto &pair : protocolIdents) { - DeclResult typeParam = Actions.actOnObjCTypeParam(getCurScope(), - index++, - pair.first, - pair.second, - SourceLocation(), - ParsedType()); + DeclResult typeParam = Actions.actOnObjCTypeParam( + getCurScope(), + ObjCTypeParamVariance::Invariant, + SourceLocation(), + index++, + pair.first, + pair.second, + SourceLocation(), + ParsedType()); if (typeParam.isUsable()) typeParams.push_back(typeParam.get()); } @@ -460,7 +467,26 @@ ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs( bool invalid = false; lAngleLoc = ConsumeToken(); + do { + // Parse the variance, if any. + SourceLocation varianceLoc; + ObjCTypeParamVariance variance = ObjCTypeParamVariance::Invariant; + if (Tok.is(tok::kw___covariant) || Tok.is(tok::kw___contravariant)) { + variance = Tok.is(tok::kw___covariant) + ? ObjCTypeParamVariance::Covariant + : ObjCTypeParamVariance::Contravariant; + varianceLoc = ConsumeToken(); + + // Once we've seen a variance specific , we know this is not a + // list of protocol references. + if (mayBeProtocolList) { + // Up until now, we have been queuing up parameters because they + // might be protocol references. Turn them into parameters now. + makeProtocolIdentsIntoTypeParameters(); + } + } + // Parse the identifier. if (!Tok.is(tok::identifier)) { // Code completion. @@ -508,6 +534,8 @@ ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs( // Create the type parameter. DeclResult typeParam = Actions.actOnObjCTypeParam(getCurScope(), + variance, + varianceLoc, typeParams.size(), paramName, paramLoc, |