Hi John,

This test case:

id test_dict()
{
        return @{
                @"a": [](){},
                @"b": [](){}
        };
}

Crashes in IRGen because ExprWithCleanups for the dummy BlockDecl we use to facilitate lambda to block conversion
is at the wrong place.
This happens because a lambda _expression_ is considered a full _expression_ so it calls MaybeCreateExprWithCleanups
(see Sema::BuildBlockForLambdaConversion).
which ends up adding the clean up code for the BlockDecl of the first lambda to the _expression_ for the 2nd lambda!

Ideally, MaybeCreateExprWithCleanups should be called when the entire dictionary literal is seen. But in this case,
this does not happen. Attached patch fixes this by making sure that after ‘every’ parse of the ‘value’ _expression_
MaybeCreateExprWithCleanups is called. This, in effect, assumes that the ‘value’ literal is a full _expression_.
I don’t know the ramification of this change in the common case as couple of non-lambda literal tests broke.
(it now generates the none-exc version of call instead of exc versions in couple of places).

Please review. Let me know if you need additional info.

- Thanks, Fariborz

Index: lib/Sema/SemaExprObjC.cpp
===================================================================
--- lib/Sema/SemaExprObjC.cpp   (revision 217780)
+++ lib/Sema/SemaExprObjC.cpp   (working copy)
@@ -768,6 +768,10 @@
     if (Converted.isInvalid())
       return ExprError();
     
+    // Array literal index may have expressions which require
+    // cleanup.
+    Converted = MaybeCreateExprWithCleanups(Converted.get());
+    
     ElementsBuffer[I] = Converted.get();
   }
     
@@ -951,6 +955,9 @@
       = CheckObjCCollectionLiteralElement(*this, Elements[I].Value, ValueT);
     if (Value.isInvalid())
       return ExprError();
+    // Dictionary literal value may have expressions which require
+    // cleanup.
+    Value = MaybeCreateExprWithCleanups(Value.get());
     
     Elements[I].Key = Key.get();
     Elements[I].Value = Value.get();
Index: test/CodeGenObjCXX/lambda-in-objc-literals.mm
===================================================================
--- test/CodeGenObjCXX/lambda-in-objc-literals.mm       (revision 0)
+++ test/CodeGenObjCXX/lambda-in-objc-literals.mm       (working copy)
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s 
-fexceptions -std=c++11 -fblocks
+// rdar://16879958
+
+@protocol NSCopying @end
+typedef unsigned long NSUInteger;
+typedef long NSInteger;
+
+@interface NSDictionary
++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id <NSCopying> 
[])keys count:(NSUInteger)cnt;
+- (void)setObject:(id)object forKeyedSubscript:(id)key;
+- (id)objectForKeyedSubscript:(id)key;
++ (id) alloc;
+- (id)initWithObjects:(const id [])objects forKeys:(const id [])keys 
count:(unsigned long)cnt;
+@end
+
+@interface NSString<NSCopying>
+@end
+
+
+@class NSFastEnumerationState;
+
+@protocol NSFastEnumeration
+
+- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state 
objects:(id [])buffer count:(NSUInteger)len;
+
+@end
+
+@interface NSNumber
++ (NSNumber *)numberWithInt:(int)value;
+@end
+
+@interface NSArray <NSFastEnumeration>
++ (id) alloc;
++ (id)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;
+@end
+
+id test_dict()
+{
+        return @{
+                @"a": [](){},
+                @"b": [](){},
+                @"c": [](){}
+        };
+}
+
+id test_arr()
+{
+        return @[
+                [](){},
+                [](){}
+        ];
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to