Improve LLDB's implicit cast-to-id to work with C++11 auto and any Objective-C object...
authorDouglas Gregor <dgregor@apple.com>
Thu, 7 Mar 2013 22:57:58 +0000 (22:57 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 7 Mar 2013 22:57:58 +0000 (22:57 +0000)
llvm-svn: 176665

clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/test/SemaObjC/debugger-cast-result-to-id.m
clang/test/SemaObjCXX/debugger-cast-result-to-id.mm

index 4fa7905..00d1cf1 100644 (file)
@@ -7125,6 +7125,20 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
         DeduceInit = CXXDirectInit->getExpr(0);
       }
     }
+
+    // Expressions default to 'id' when we're in a debugger.
+    bool DefaultedToAuto = false;
+    if (getLangOpts().DebuggerCastResultToId &&
+        Init->getType() == Context.UnknownAnyTy) {
+      ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType());
+      if (Result.isInvalid()) {
+        VDecl->setInvalidDecl();
+        return;
+      }
+      Init = Result.take();
+      DefaultedToAuto = true;
+    }
+    
     TypeSourceInfo *DeducedType = 0;
     if (DeduceAutoType(VDecl->getTypeSourceInfo(), DeduceInit, DeducedType) ==
             DAR_Failed)
@@ -7145,7 +7159,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
     // 'id' instead of a specific object type prevents most of our usual checks.
     // We only want to warn outside of template instantiations, though:
     // inside a template, the 'id' could have come from a parameter.
-    if (ActiveTemplateInstantiations.empty() &&
+    if (ActiveTemplateInstantiations.empty() && !DefaultedToAuto &&
         DeducedType->getType()->isObjCIdType()) {
       SourceLocation Loc = DeducedType->getTypeLoc().getBeginLoc();
       Diag(Loc, diag::warn_auto_var_is_id)
@@ -7236,17 +7250,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
   // CheckInitializerTypes may change it.
   QualType DclT = VDecl->getType(), SavT = DclT;
   
-  // Top-level message sends default to 'id' when we're in a debugger
-  // and we are assigning it to a variable of 'id' type.
-  if (getLangOpts().DebuggerCastResultToId && DclT->isObjCIdType())
-    if (Init->getType() == Context.UnknownAnyTy && isa<ObjCMessageExpr>(Init)) {
-      ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType());
-      if (Result.isInvalid()) {
-        VDecl->setInvalidDecl();
-        return;
-      }
-      Init = Result.take();
+  // Expressions default to 'id' when we're in a debugger
+  // and we are assigning it to a variable of Objective-C pointer type.
+  if (getLangOpts().DebuggerCastResultToId && DclT->isObjCObjectPointerType() &&
+      Init->getType() == Context.UnknownAnyTy) {
+    ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType());
+    if (Result.isInvalid()) {
+      VDecl->setInvalidDecl();
+      return;
     }
+    Init = Result.take();
+  }
 
   // Perform the initialization.
   if (!VDecl->isInvalidDecl()) {
index 49d6611..f63ed09 100644 (file)
@@ -5489,10 +5489,9 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
   if (DiagnoseUnexpandedParameterPack(FullExpr.get()))
     return ExprError();
 
-  // Top-level message sends default to 'id' when we're in a debugger.
+  // Top-level expressions default to 'id' when we're in a debugger.
   if (DiscardedValue && getLangOpts().DebuggerCastResultToId &&
-      FullExpr.get()->getType() == Context.UnknownAnyTy &&
-      isa<ObjCMessageExpr>(FullExpr.get())) {
+      FullExpr.get()->getType() == Context.UnknownAnyTy) {
     FullExpr = forceUnknownAnyToType(FullExpr.take(), Context.getObjCIdType());
     if (FullExpr.isInvalid())
       return ExprError();
index 00a02be..ecf3e74 100644 (file)
@@ -6,6 +6,8 @@ extern __unknown_anytype test1();
 void test_unknown_anytype_receiver() {
   (void)(int)[[test0 unknownMethod] otherUnknownMethod];;
   (void)(id)[[test1() unknownMethod] otherUnknownMethod];
+  id x = test0;
+  id y = test1();
 }
 
 // rdar://10988847
index cd7aa7b..815ae38 100644 (file)
@@ -1,7 +1,21 @@
-// RUN: %clang_cc1 -fdebugger-support -fdebugger-cast-result-to-id -funknown-anytype -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fdebugger-support -fdebugger-cast-result-to-id -funknown-anytype -fsyntax-only -verify %s
+
+extern __unknown_anytype test0a;
+extern __unknown_anytype test1a();
+extern __unknown_anytype test0b;
+extern __unknown_anytype test1b();
+extern __unknown_anytype test0c;
+extern __unknown_anytype test1c();
+extern __unknown_anytype test0d;
+extern __unknown_anytype test1d();
+extern __unknown_anytype test0d;
+extern __unknown_anytype test1d();
+
+@interface A
+@end
 
 // rdar://problem/9416370
-namespace test0 {
+namespace rdar9416370 {
   void test(id x) {
     if ([x foo]) {} // expected-error {{no known method '-foo'; cast the message send to the method's return type}}
     [x foo];
@@ -10,8 +24,20 @@ namespace test0 {
 
 // rdar://10988847
 @class NSString; // expected-note {{forward declaration of class here}}
-namespace test1 {
-  void rdar10988847() {
+namespace rdar10988847 {
+  void test() {
     id s = [NSString stringWithUTF8String:"foo"]; // expected-warning {{receiver 'NSString' is a forward class and corresponding @interface may not exist}}
   }
 }
+
+// rdar://13338107
+namespace rdar13338107 {
+  void test() {
+    id x1 = test0a;
+    id x2 = test1a();
+    A *x3 = test0b;
+    A *x4 = test1b();
+    auto x5 = test0c;
+    auto x6 = test1c();
+  }
+}