<div dir="ltr">The test here flakily fails, maybe 1 in 10 times: <a href="http://45.33.8.238/mac/11180/step_7.txt">http://45.33.8.238/mac/11180/step_7.txt</a><div><br></div><div>error: 'error' diagnostics seen but not expected: <br>  File /Users/thakis/src/llvm-project/clang/test/SemaObjC/parameterized_classes_subst.m Line 479: type argument 'T' (aka 'id') does not satisfy the bound ('id<NSCopying>') of type parameter 'T'<br>error: 'note' diagnostics seen but not expected: <br>  File /Users/thakis/src/llvm-project/clang/test/SemaObjC/parameterized_classes_subst.m Line 475: type parameter 'T' declared here<br>2 errors generated.<br></div><div><br></div><div>Maybe if this is emitted depends on the order of something in a data structure that has no deterministic order, or similar?</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Apr 3, 2020 at 7:29 PM Volodymyr Sapsai via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Author: Volodymyr Sapsai<br>
Date: 2020-04-03T16:29:02-07:00<br>
New Revision: a8c8b627f23f204fb621bd2a8c495cfc8bc16ae7<br>
<br>
URL: <a href="https://github.com/llvm/llvm-project/commit/a8c8b627f23f204fb621bd2a8c495cfc8bc16ae7" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/a8c8b627f23f204fb621bd2a8c495cfc8bc16ae7</a><br>
DIFF: <a href="https://github.com/llvm/llvm-project/commit/a8c8b627f23f204fb621bd2a8c495cfc8bc16ae7.diff" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/a8c8b627f23f204fb621bd2a8c495cfc8bc16ae7.diff</a><br>
<br>
LOG: [ObjC generics] Fix not inheriting type bounds in categories/extensions.<br>
<br>
When a category/extension doesn't repeat a type bound, corresponding<br>
type parameter is substituted with `id` when used as a type argument. As<br>
a result, in the added test case it was causing errors like<br>
<br>
> type argument 'T' (aka 'id') does not satisfy the bound ('id<NSCopying>') of type parameter 'T'<br>
<br>
We are already checking that type parameters should be consistent<br>
everywhere (see `checkTypeParamListConsistency`) and update<br>
`ObjCTypeParamDecl` to have correct underlying type. And when we use the<br>
type parameter as a method return type or a method parameter type, it is<br>
substituted to the bounded type. But when we use the type parameter as a<br>
type argument, we check `ObjCTypeParamType` that wasn't updated and<br>
remains `id`.<br>
<br>
Fix by updating not only `ObjCTypeParamDecl` UnderlyingType but also<br>
TypeForDecl as we use the underlying type to create a canonical type for<br>
`ObjCTypeParamType` (see `ASTContext::getObjCTypeParamType`).<br>
<br>
This is a different approach to fixing the issue. The previous one was<br>
02c2ab3d8872416589bd1a6ca3dfb96ba373a3b9 which was reverted in<br>
4c539e8da1b3de38a53ef3f7497f5c45a3243b61. The problem with the previous<br>
approach was that `ObjCTypeParamType::desugar` was returning underlying<br>
type for `ObjCTypeParamDecl` without applying any protocols stored in<br>
`ObjCTypeParamType`. It caused inconsistencies in comparing types before<br>
and after desugaring.<br>
<br>
rdar://problem/54329242<br>
<br>
Reviewed By: erik.pilkington<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D72872" rel="noreferrer" target="_blank">https://reviews.llvm.org/D72872</a><br>
<br>
Added: <br>
<br>
<br>
Modified: <br>
    clang/include/clang/AST/ASTContext.h<br>
    clang/lib/AST/ASTContext.cpp<br>
    clang/lib/AST/Type.cpp<br>
    clang/lib/Sema/SemaDeclObjC.cpp<br>
    clang/test/SemaObjC/parameterized_classes_collection_literal.m<br>
    clang/test/SemaObjC/parameterized_classes_subst.m<br>
<br>
Removed: <br>
<br>
<br>
<br>
################################################################################<br>
diff  --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h<br>
index 6813ab58874e..6360f18217c7 100644<br>
--- a/clang/include/clang/AST/ASTContext.h<br>
+++ b/clang/include/clang/AST/ASTContext.h<br>
@@ -1442,6 +1442,8 @@ class ASTContext : public RefCountedBase<ASTContext> {<br>
<br>
   QualType getObjCTypeParamType(const ObjCTypeParamDecl *Decl,<br>
                                 ArrayRef<ObjCProtocolDecl *> protocols) const;<br>
+  void adjustObjCTypeParamBoundType(const ObjCTypeParamDecl *Orig,<br>
+                                    ObjCTypeParamDecl *New) const;<br>
<br>
   bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl);<br>
<br>
<br>
diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp<br>
index 1e81e0a67b4d..06dcb6fa0580 100644<br>
--- a/clang/lib/AST/ASTContext.cpp<br>
+++ b/clang/lib/AST/ASTContext.cpp<br>
@@ -4874,6 +4874,17 @@ ASTContext::getObjCTypeParamType(const ObjCTypeParamDecl *Decl,<br>
   return QualType(newType, 0);<br>
 }<br>
<br>
+void ASTContext::adjustObjCTypeParamBoundType(const ObjCTypeParamDecl *Orig,<br>
+                                              ObjCTypeParamDecl *New) const {<br>
+  New->setTypeSourceInfo(getTrivialTypeSourceInfo(Orig->getUnderlyingType()));<br>
+  // Update TypeForDecl after updating TypeSourceInfo.<br>
+  auto NewTypeParamTy = cast<ObjCTypeParamType>(New->getTypeForDecl());<br>
+  SmallVector<ObjCProtocolDecl *, 8> protocols;<br>
+  protocols.append(NewTypeParamTy->qual_begin(), NewTypeParamTy->qual_end());<br>
+  QualType UpdatedTy = getObjCTypeParamType(New, protocols);<br>
+  New->setTypeForDecl(UpdatedTy.getTypePtr());<br>
+}<br>
+<br>
 /// ObjCObjectAdoptsQTypeProtocols - Checks that protocols in IC's<br>
 /// protocol list adopt all protocols in QT's qualified-id protocol<br>
 /// list.<br>
<br>
diff  --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp<br>
index 3428437c3146..7c65378261ad 100644<br>
--- a/clang/lib/AST/Type.cpp<br>
+++ b/clang/lib/AST/Type.cpp<br>
@@ -3534,6 +3534,7 @@ void ObjCTypeParamType::Profile(llvm::FoldingSetNodeID &ID,<br>
                                 const ObjCTypeParamDecl *OTPDecl,<br>
                                 ArrayRef<ObjCProtocolDecl *> protocols) {<br>
   ID.AddPointer(OTPDecl);<br>
+  ID.AddPointer(OTPDecl->getUnderlyingType().getAsOpaquePtr());<br>
   ID.AddInteger(protocols.size());<br>
   for (auto proto : protocols)<br>
     ID.AddPointer(proto);<br>
<br>
diff  --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp<br>
index 934e1a23141c..6db57898e378 100644<br>
--- a/clang/lib/Sema/SemaDeclObjC.cpp<br>
+++ b/clang/lib/Sema/SemaDeclObjC.cpp<br>
@@ -938,8 +938,7 @@ static bool checkTypeParamListConsistency(Sema &S,<br>
<br>
       // Override the new type parameter's bound type with the previous type,<br>
       // so that it's consistent.<br>
-      newTypeParam->setTypeSourceInfo(<br>
-        S.Context.getTrivialTypeSourceInfo(prevTypeParam->getUnderlyingType()));<br>
+      S.Context.adjustObjCTypeParamBoundType(prevTypeParam, newTypeParam);<br>
       continue;<br>
     }<br>
<br>
@@ -966,8 +965,7 @@ static bool checkTypeParamListConsistency(Sema &S,<br>
     }<br>
<br>
     // Update the new type parameter's bound to match the previous one.<br>
-    newTypeParam->setTypeSourceInfo(<br>
-      S.Context.getTrivialTypeSourceInfo(prevTypeParam->getUnderlyingType()));<br>
+    S.Context.adjustObjCTypeParamBoundType(prevTypeParam, newTypeParam);<br>
   }<br>
<br>
   return false;<br>
<br>
diff  --git a/clang/test/SemaObjC/parameterized_classes_collection_literal.m b/clang/test/SemaObjC/parameterized_classes_collection_literal.m<br>
index 472746e09db9..034d2e8da217 100644<br>
--- a/clang/test/SemaObjC/parameterized_classes_collection_literal.m<br>
+++ b/clang/test/SemaObjC/parameterized_classes_collection_literal.m<br>
@@ -29,7 +29,9 @@ + (instancetype)arrayWithObjects:(const T [])objects count:(NSUInteger)cnt;<br>
 @end<br>
<br>
 @interface NSDictionary<K, V> : NSObject <NSCopying><br>
-+ (instancetype)dictionaryWithObjects:(const V [])objects forKeys:(const K [])keys count:(NSUInteger)cnt;<br>
++ (instancetype)dictionaryWithObjects:(const V [])objects<br>
+                              forKeys:(const K <NSCopying> [])keys<br>
+                                count:(NSUInteger)cnt;<br>
 @end<br>
<br>
 void testArrayLiteral(void) {<br>
@@ -50,3 +52,9 @@ void testDictionaryLiteral(void) {<br>
     @"world" : @"blah" // expected-warning{{object of type 'NSString *' is not compatible with dictionary value type 'NSNumber *'}}<br>
   };<br>
 }<br>
+<br>
+void testCastingInDictionaryLiteral(NSString *arg) {<br>
+  NSDictionary *dict = @{<br>
+    (id)arg : @"foo",<br>
+  };<br>
+}<br>
<br>
diff  --git a/clang/test/SemaObjC/parameterized_classes_subst.m b/clang/test/SemaObjC/parameterized_classes_subst.m<br>
index d14a6e9deb40..b6d884760d29 100644<br>
--- a/clang/test/SemaObjC/parameterized_classes_subst.m<br>
+++ b/clang/test/SemaObjC/parameterized_classes_subst.m<br>
@@ -467,3 +467,17 @@ - (void)mapUsingBlock:(id (^)(id))block {<br>
 - (void)mapUsingBlock2:(id)block { // expected-warning{{conflicting parameter types in implementation}}<br>
 }<br>
 @end<br>
+<br>
+// --------------------------------------------------------------------------<br>
+// Use a type parameter as a type argument.<br>
+// --------------------------------------------------------------------------<br>
+// Type bounds in a category/extension are omitted. rdar://problem/54329242<br>
+@interface ParameterizedContainer<T : id<NSCopying>><br>
+- (ParameterizedContainer<T> *)inInterface;<br>
+@end<br>
+@interface ParameterizedContainer<T> (Cat)<br>
+- (ParameterizedContainer<T> *)inCategory;<br>
+@end<br>
+@interface ParameterizedContainer<U> ()<br>
+- (ParameterizedContainer<U> *)inExtension;<br>
+@end<br>
<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div>