From e83b95641f911e44c8c092bc0eef7743df0cd73d Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 7 Jul 2015 03:57:53 +0000 Subject: Substitute type arguments into uses of Objective-C interface members. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When messaging a method that was defined in an Objective-C class (or category or extension thereof) that has type parameters, substitute the type arguments for those type parameters. Similarly, substitute into property accesses, instance variables, and other references. This includes general infrastructure for substituting the type arguments associated with an ObjCObject(Pointer)Type into a type referenced within a particular context, handling all of the substitutions required to deal with (e.g.) inheritance involving parameterized classes. In cases where no type arguments are available (e.g., because we're messaging via some unspecialized type, id, etc.), we substitute in the type bounds for the type parameters instead. Example: @interface NSSet> : NSObject - (T)firstObject; @end void f(NSSet *stringSet, NSSet *anySet) { [stringSet firstObject]; // produces NSString* [anySet firstObject]; // produces id (the bound) } When substituting for the type parameters given an unspecialized context (i.e., no specific type arguments were given), substituting the type bounds unconditionally produces type signatures that are too strong compared to the pre-generics signatures. Instead, use the following rule: - In covariant positions, such as method return types, replace type parameters with “id” or “Class” (the latter only when the type parameter bound is “Class” or qualified class, e.g, “Class”) - In other positions (e.g., parameter types), replace type parameters with their type bounds. - When a specialized Objective-C object or object pointer type contains a type parameter in its type arguments (e.g., NSArray*, but not NSArray *), replace the entire object/object pointer type with its unspecialized version (e.g., NSArray *). llvm-svn: 241543 --- clang/lib/Sema/SemaDeclObjC.cpp | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'clang/lib/Sema/SemaDeclObjC.cpp') diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index ac1e3923afa..f28abf4c070 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -600,7 +600,8 @@ ActOnSuperClassOfClassInterface(Scope *S, } } -DeclResult Sema::actOnObjCTypeParam(Scope *S, IdentifierInfo *paramName, +DeclResult Sema::actOnObjCTypeParam(Scope *S, unsigned index, + IdentifierInfo *paramName, SourceLocation paramLoc, SourceLocation colonLoc, ParsedType parsedTypeBound) { @@ -643,6 +644,23 @@ DeclResult Sema::actOnObjCTypeParam(Scope *S, IdentifierInfo *paramName, // Forget the bound; we'll default to id later. typeBoundInfo = nullptr; } + + // Type bounds cannot have explicit nullability. + if (typeBoundInfo) { + // Type arguments cannot explicitly specify nullability. + if (auto nullability = AttributedType::stripOuterNullability(typeBound)) { + // Look at the type location information to find the nullability + // specifier so we can zap it. + SourceLocation nullabilityLoc + = typeBoundInfo->getTypeLoc().findNullabilityLoc(); + SourceLocation diagLoc + = nullabilityLoc.isValid()? nullabilityLoc + : typeBoundInfo->getTypeLoc().getLocStart(); + Diag(diagLoc, diag::err_type_param_bound_explicit_nullability) + << paramName << typeBoundInfo->getType() + << FixItHint::CreateRemoval(nullabilityLoc); + } + } } // If there was no explicit type bound (or we removed it due to an error), @@ -653,8 +671,8 @@ DeclResult Sema::actOnObjCTypeParam(Scope *S, IdentifierInfo *paramName, } // Create the type parameter. - return ObjCTypeParamDecl::Create(Context, CurContext, paramLoc, paramName, - colonLoc, typeBoundInfo); + return ObjCTypeParamDecl::Create(Context, CurContext, index, paramLoc, + paramName, colonLoc, typeBoundInfo); } ObjCTypeParamList *Sema::actOnObjCTypeParamList(Scope *S, @@ -868,6 +886,7 @@ ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc, ObjCTypeParamDecl::Create( Context, CurContext, + typeParam->getIndex(), SourceLocation(), typeParam->getIdentifier(), SourceLocation(), -- cgit v1.2.3