]> granicus.if.org Git - clang/commitdiff
ObjCXX: fix a crash during typo correction.
authorManman Ren <manman.ren@gmail.com>
Tue, 2 Feb 2016 22:23:03 +0000 (22:23 +0000)
committerManman Ren <manman.ren@gmail.com>
Tue, 2 Feb 2016 22:23:03 +0000 (22:23 +0000)
For ObjCXX, we can create a CastExpr with Kind being CK_UserDefinedConversion
and SubExpr being BlockExpr. Specifically one can return BlockExpr from
BuildCXXMemberCallExpr and the result can be used to build a CastExpr.

Fix the assumption in CastExpr::getSubExprAsWritten that SubExpr can only
be CXXMemberCallExpr.

rdar://problem/24364077

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@259591 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/Expr.cpp
test/SemaObjCXX/block-for-lambda-conversion.mm [new file with mode: 0644]

index 1b62a7b579ee6e2e934e9040982104d87bcd03c2..5590527819e9b1db487744b357469e22f68b909e 100644 (file)
@@ -1744,8 +1744,13 @@ Expr *CastExpr::getSubExprAsWritten() {
     // subexpression describing the call; strip it off.
     if (E->getCastKind() == CK_ConstructorConversion)
       SubExpr = cast<CXXConstructExpr>(SubExpr)->getArg(0);
-    else if (E->getCastKind() == CK_UserDefinedConversion)
-      SubExpr = cast<CXXMemberCallExpr>(SubExpr)->getImplicitObjectArgument();
+    else if (E->getCastKind() == CK_UserDefinedConversion) {
+      assert((isa<CXXMemberCallExpr>(SubExpr) ||
+              isa<BlockExpr>(SubExpr)) &&
+             "Unexpected SubExpr for CK_UserDefinedConversion.");
+      if (isa<CXXMemberCallExpr>(SubExpr))
+        SubExpr = cast<CXXMemberCallExpr>(SubExpr)->getImplicitObjectArgument();
+    }
     
     // If the subexpression we're left with is an implicit cast, look
     // through that, too.
diff --git a/test/SemaObjCXX/block-for-lambda-conversion.mm b/test/SemaObjCXX/block-for-lambda-conversion.mm
new file mode 100644 (file)
index 0000000..671e83d
--- /dev/null
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -fsyntax-only -fblocks -verify -std=c++11 %s
+
+enum NSEventType {
+  NSEventTypeFlagsChanged = 12
+};
+
+enum NSEventMask {
+  NSEventMaskLeftMouseDown = 1
+};
+
+static const NSEventType NSFlagsChanged = NSEventTypeFlagsChanged;
+
+@interface NSObject
+@end
+@interface NSEvent : NSObject {
+}
++ (nullable id)
+addMonitor:(NSEventMask)mask handler:(NSEvent *_Nullable (^)(NSEvent *))block;
+@end
+
+void test(id weakThis) {
+  id m_flagsChangedEventMonitor = [NSEvent
+      addMonitor:NSFlagsChangedMask //expected-error {{use of undeclared identifier 'NSFlagsChangedMask'}}
+         handler:[weakThis](NSEvent *flagsChangedEvent) {
+             return flagsChangedEvent;
+         }];
+}