r281358 - ObjectiveC Generics: Start using ObjCTypeParamType.
Manman Ren via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 13 10:41:05 PDT 2016
Author: mren
Date: Tue Sep 13 12:41:05 2016
New Revision: 281358
URL: http://llvm.org/viewvc/llvm-project?rev=281358&view=rev
Log:
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
Modified:
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/DeclObjC.cpp
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/Sema/SemaDeclObjC.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
cfe/trunk/test/SemaObjC/kindof.m
cfe/trunk/test/SemaObjC/parameterized_classes_subst.m
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=281358&r1=281357&r2=281358&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Sep 13 12:41:05 2016
@@ -3883,6 +3883,11 @@ ASTContext::applyObjCProtocolQualifiers(
bool allowOnPointerType) const {
hasError = false;
+ if (const ObjCTypeParamType *objT =
+ dyn_cast<ObjCTypeParamType>(type.getTypePtr())) {
+ return getObjCTypeParamType(objT->getDecl(), protocols);
+ }
+
// Apply protocol qualifiers to ObjCObjectPointerType.
if (allowOnPointerType) {
if (const ObjCObjectPointerType *objPtr =
Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=281358&r1=281357&r2=281358&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Tue Sep 13 12:41:05 2016
@@ -1320,8 +1320,12 @@ ObjCTypeParamDecl *ObjCTypeParamDecl::Cr
IdentifierInfo *name,
SourceLocation colonLoc,
TypeSourceInfo *boundInfo) {
- return new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index,
- nameLoc, name, colonLoc, boundInfo);
+ auto *TPDecl =
+ new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index,
+ nameLoc, name, colonLoc, boundInfo);
+ QualType TPType = ctx.getObjCTypeParamType(TPDecl, {});
+ TPDecl->setTypeForDecl(TPType.getTypePtr());
+ return TPDecl;
}
ObjCTypeParamDecl *ObjCTypeParamDecl::CreateDeserialized(ASTContext &ctx,
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=281358&r1=281357&r2=281358&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Tue Sep 13 12:41:05 2016
@@ -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) {
Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=281358&r1=281357&r2=281358&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Tue Sep 13 12:41:05 2016
@@ -2353,7 +2353,7 @@ static bool CheckMethodOverrideParam(Sem
}
if (S.Context.hasSameUnqualifiedType(ImplTy, IfaceTy))
return true;
-
+
if (!Warn)
return false;
unsigned DiagID =
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=281358&r1=281357&r2=281358&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Tue Sep 13 12:41:05 2016
@@ -1157,6 +1157,20 @@ TypeResult Sema::actOnObjCTypeArgsAndPro
ResultTL = ObjCObjectPointerTL.getPointeeLoc();
}
+ if (auto OTPTL = ResultTL.getAs<ObjCTypeParamTypeLoc>()) {
+ // Protocol qualifier information.
+ if (OTPTL.getNumProtocols() > 0) {
+ assert(OTPTL.getNumProtocols() == Protocols.size());
+ OTPTL.setProtocolLAngleLoc(ProtocolLAngleLoc);
+ OTPTL.setProtocolRAngleLoc(ProtocolRAngleLoc);
+ for (unsigned i = 0, n = Protocols.size(); i != n; ++i)
+ OTPTL.setProtocolLoc(i, ProtocolLocs[i]);
+ }
+
+ // We're done. Return the completed type to the parser.
+ return CreateParsedType(Result, ResultTInfo);
+ }
+
auto ObjCObjectTL = ResultTL.castAs<ObjCObjectTypeLoc>();
// Type argument information.
@@ -5875,7 +5889,6 @@ bool Sema::checkNullabilityTypeSpecifier
// For the context-sensitive keywords/Objective-C property
// attributes, require that the type be a single-level pointer.
if (isContextSensitive) {
- // Make sure that the pointee isn't itself a pointer type.
QualType pointeeType = desugared->getPointeeType();
if (pointeeType->isAnyPointerType() ||
pointeeType->isObjCObjectPointerType() ||
@@ -5899,6 +5912,13 @@ bool Sema::checkNullabilityTypeSpecifier
}
bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) {
+ if (isa<ObjCTypeParamType>(type)) {
+ // Build the attributed type to record where __kindof occurred.
+ type = Context.getAttributedType(AttributedType::attr_objc_kindof,
+ type, type);
+ return false;
+ }
+
// Find out if it's an Objective-C object or object pointer type;
const ObjCObjectPointerType *ptrType = type->getAs<ObjCObjectPointerType>();
const ObjCObjectType *objType = ptrType ? ptrType->getObjectType()
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp?rev=281358&r1=281357&r2=281358&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp Tue Sep 13 12:41:05 2016
@@ -626,7 +626,7 @@ static bool isObjCTypeParamDependent(Qua
: public RecursiveASTVisitor<IsObjCTypeParamDependentTypeVisitor> {
public:
IsObjCTypeParamDependentTypeVisitor() : Result(false) {}
- bool VisitTypedefType(const TypedefType *Type) {
+ bool VisitObjCTypeParamType(const ObjCTypeParamType *Type) {
if (isa<ObjCTypeParamDecl>(Type->getDecl())) {
Result = true;
return false;
Modified: cfe/trunk/test/SemaObjC/kindof.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/kindof.m?rev=281358&r1=281357&r2=281358&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/kindof.m (original)
+++ cfe/trunk/test/SemaObjC/kindof.m Tue Sep 13 12:41:05 2016
@@ -385,7 +385,7 @@ void testNullability() {
@end
@interface NSGeneric<ObjectType> : NSObject
-- (void)test:(__kindof ObjectType)T;
+- (void)test:(__kindof ObjectType)T; // expected-note{{passing argument to parameter 'T' here}}
- (void)mapUsingBlock:(id (^)(__kindof ObjectType))block;
@end
@implementation NSGeneric
@@ -395,6 +395,14 @@ void testNullability() {
}
@end
+void testGeneric(NSGeneric<NSString*> *generic) {
+ NSObject *NSObject_obj;
+ // Assign from NSObject_obj to __kindof NSString*.
+ [generic test:NSObject_obj]; // expected-warning{{incompatible pointer types sending 'NSObject *' to parameter of type '__kindof NSString *'}}
+ NSString *NSString_str;
+ [generic test:NSString_str];
+}
+
// Check that clang doesn't crash when a type parameter is illegal.
@interface Array1<T> : NSObject
@end
Modified: cfe/trunk/test/SemaObjC/parameterized_classes_subst.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/parameterized_classes_subst.m?rev=281358&r1=281357&r2=281358&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/parameterized_classes_subst.m (original)
+++ cfe/trunk/test/SemaObjC/parameterized_classes_subst.m Tue Sep 13 12:41:05 2016
@@ -426,3 +426,36 @@ void test_ternary_operator(NSArray<NSStr
// warning about likely protocol/class name typos.
// --------------------------------------------------------------------------
typedef NSArray<NSObject> ArrayOfNSObjectWarning; // expected-warning{{parameterized class 'NSArray' already conforms to the protocols listed; did you forget a '*'?}}
+
+// rdar://25060179
+ at interface MyMutableDictionary<KeyType, ObjectType> : NSObject
+- (void)setObject:(ObjectType)obj forKeyedSubscript:(KeyType <NSCopying>)key; // expected-note{{passing argument to parameter 'obj' here}} \
+ // expected-note{{passing argument to parameter 'key' here}}
+ at end
+
+void bar(MyMutableDictionary<NSString *, NSString *> *stringsByString,
+ NSNumber *n1, NSNumber *n2) {
+ // We warn here when the key types do not match.
+ stringsByString[n1] = n2; // expected-warning{{incompatible pointer types sending 'NSNumber *' to parameter of type 'NSString *'}} \
+ // expected-warning{{incompatible pointer types sending 'NSNumber *' to parameter of type 'NSString<NSCopying> *'}}
+}
+
+ at interface MyTest<K, V> : NSObject <NSCopying>
+- (V)test:(K)key;
+- (V)test2:(K)key; // expected-note{{previous definition is here}}
+- (void)mapUsingBlock:(id (^)(V))block;
+- (void)mapUsingBlock2:(id (^)(V))block; // expected-note{{previous definition is here}}
+ at end
+
+ at implementation MyTest
+- (id)test:(id)key {
+ return key;
+}
+- (int)test2:(id)key{ // expected-warning{{conflicting return type in implementation}}
+ return 0;
+}
+- (void)mapUsingBlock:(id (^)(id))block {
+}
+- (void)mapUsingBlock2:(id)block { // expected-warning{{conflicting parameter types in implementation}}
+}
+ at end
More information about the cfe-commits
mailing list