diff options
author | Manman Ren <manman.ren@gmail.com> | 2016-09-13 17:41:05 +0000 |
---|---|---|
committer | Manman Ren <manman.ren@gmail.com> | 2016-09-13 17:41:05 +0000 |
commit | 1286300e382671aaf0680870ca41c06cc1ea53a4 (patch) | |
tree | 794d00f3c31208857a245b1955c5d970b31777a7 /lib/AST/Type.cpp | |
parent | 3c62e64cb2fb5295fabfde89e73e2b689d899732 (diff) |
ObjectiveC Generics: Start using ObjCTypeParamType.
For ObjC type parameter, we used to have TypedefType that is canonicalized to
id or the bound type. We can't represent "T <protocol>" and thus will lose
the type information in the following example:
@interface MyMutableDictionary<KeyType, ObjectType> : NSObject
- (void)setObject:(ObjectType)obj forKeyedSubscript:(KeyType <NSCopying>)key;
@end
MyMutableDictionary<NSString *, NSString *> *stringsByString;
NSNumber *n1, *n2;
stringsByString[n1] = n2;
--> no warning on type mismatch of the key.
To fix the problem, we introduce a new type ObjCTypeParamType that supports
a list of protocol qualifiers.
We create ObjCTypeParamType for ObjCTypeParamDecl when we create
ObjCTypeParamDecl. We also substitute ObjCTypeParamType instead of TypedefType
on an ObjCTypeParamDecl.
rdar://24619481
rdar://25060179
Differential Revision: http://reviews.llvm.org/D23080
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@281358 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/Type.cpp')
-rw-r--r-- | lib/AST/Type.cpp | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 556d225612..4aa07568dc 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1081,13 +1081,24 @@ QualType QualType::substObjCTypeArgs( // Replace an Objective-C type parameter reference with the corresponding // type argument. - if (const auto *typedefTy = dyn_cast<TypedefType>(splitType.Ty)) { - if (auto *typeParam = dyn_cast<ObjCTypeParamDecl>(typedefTy->getDecl())) { + if (const auto *OTPTy = dyn_cast<ObjCTypeParamType>(splitType.Ty)) { + if (auto *typeParam = dyn_cast<ObjCTypeParamDecl>(OTPTy->getDecl())) { // If we have type arguments, use them. if (!typeArgs.empty()) { - // FIXME: Introduce SubstObjCTypeParamType ? QualType argType = typeArgs[typeParam->getIndex()]; - return ctx.getQualifiedType(argType, splitType.Quals); + if (OTPTy->qual_empty()) + return ctx.getQualifiedType(argType, splitType.Quals); + + // Apply protocol lists if exists. + bool hasError; + SmallVector<ObjCProtocolDecl*, 8> protocolsVec; + protocolsVec.append(OTPTy->qual_begin(), + OTPTy->qual_end()); + ArrayRef<ObjCProtocolDecl *> protocolsToApply = protocolsVec; + QualType resultTy = ctx.applyObjCProtocolQualifiers(argType, + protocolsToApply, hasError, true/*allowOnPointerType*/); + + return ctx.getQualifiedType(resultTy, splitType.Quals); } switch (context) { |