From 1344e94cdf51cabb09d7b598323e54bbf333fcd5 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 7 Mar 2013 22:57:58 +0000 Subject: [PATCH] Improve LLDB's implicit cast-to-id to work with C++11 auto and any Objective-C object type . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176665 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 36 +++++++++++++------ lib/Sema/SemaExprCXX.cpp | 5 ++- test/SemaObjC/debugger-cast-result-to-id.m | 2 ++ test/SemaObjCXX/debugger-cast-result-to-id.mm | 34 +++++++++++++++--- 4 files changed, 59 insertions(+), 18 deletions(-) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 4fa790515d..00d1cf157b 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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(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()) { diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 49d66113dc..f63ed093a6 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -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(FullExpr.get())) { + FullExpr.get()->getType() == Context.UnknownAnyTy) { FullExpr = forceUnknownAnyToType(FullExpr.take(), Context.getObjCIdType()); if (FullExpr.isInvalid()) return ExprError(); diff --git a/test/SemaObjC/debugger-cast-result-to-id.m b/test/SemaObjC/debugger-cast-result-to-id.m index 00a02be2c3..ecf3e74ba7 100644 --- a/test/SemaObjC/debugger-cast-result-to-id.m +++ b/test/SemaObjC/debugger-cast-result-to-id.m @@ -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 diff --git a/test/SemaObjCXX/debugger-cast-result-to-id.mm b/test/SemaObjCXX/debugger-cast-result-to-id.mm index cd7aa7b6ac..815ae3833d 100644 --- a/test/SemaObjCXX/debugger-cast-result-to-id.mm +++ b/test/SemaObjCXX/debugger-cast-result-to-id.mm @@ -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(); + } +} -- 2.40.0