diff options
| author | John McCall <rjmccall@apple.com> | 2011-07-13 17:56:40 +0000 |
|---|---|---|
| committer | John McCall <rjmccall@apple.com> | 2011-07-13 17:56:40 +0000 |
| commit | 3f4138c5d0429c7554ef1c3f705ac6cd6414cf1f (patch) | |
| tree | ff7201e7b24ddd64e83aade01d3c936e4a7349ce /clang | |
| parent | 17585e7940e35628a349ae70a45f3b0061be44d6 (diff) | |
| download | bcm5719-llvm-3f4138c5d0429c7554ef1c3f705ac6cd6414cf1f.tar.gz bcm5719-llvm-3f4138c5d0429c7554ef1c3f705ac6cd6414cf1f.zip | |
In debugger mode, make ObjC message sends to unknown selectors return
__unknown_anytype, and rewrite such message sends correctly.
I had to bite the bullet and actually add a debugger support mode for this
one, which is a bit unfortunate, but there really isn't anything else
I could imagine doing; this is clearly just debugger-specific behavior.
llvm-svn: 135051
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/Basic/LangOptions.h | 4 | ||||
| -rw-r--r-- | clang/include/clang/Driver/CC1Options.td | 2 | ||||
| -rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 10 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 9 | ||||
| -rw-r--r-- | clang/test/SemaObjC/debugger-support.m | 14 |
6 files changed, 35 insertions, 7 deletions
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 6d4dc5b8dcb..dc77d4c1496 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -119,6 +119,8 @@ public: unsigned InlineVisibilityHidden : 1; // Whether inline C++ methods have // hidden visibility by default. unsigned ParseUnknownAnytype: 1; /// Let the user write __unknown_anytype. + unsigned DebuggerSupport : 1; /// Do things that only make sense when + /// supporting a debugger unsigned SpellChecking : 1; // Whether to perform spell-checking for error // recovery. @@ -241,7 +243,7 @@ public: FakeAddressSpaceMap = 0; MRTD = 0; DelayedTemplateParsing = 0; - ParseUnknownAnytype = 0; + ParseUnknownAnytype = DebuggerSupport = 0; } GCMode getGCMode() const { return (GCMode) GC; } diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 8cadbe92da7..d8404365a16 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -582,6 +582,8 @@ def fdelayed_template_parsing : Flag<"-fdelayed-template-parsing">, "translation unit ">; def funknown_anytype : Flag<"-funknown-anytype">, HelpText<"Enable parser support for the __unknown_anytype type; for testing purposes only">; +def fdebugger_support : Flag<"-fdebugger-support">, + HelpText<"Enable special debugger support behavior">; def fdeprecated_macro : Flag<"-fdeprecated-macro">, HelpText<"Defines the __DEPRECATED macro">; def fno_deprecated_macro : Flag<"-fno-deprecated-macro">, diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 05b3377b3ef..06b72602fd1 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -737,6 +737,8 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-ffake-address-space-map"); if (Opts.ParseUnknownAnytype) Res.push_back("-funknown-anytype"); + if (Opts.DebuggerSupport) + Res.push_back("-fdebugger-support"); if (Opts.DelayedTemplateParsing) Res.push_back("-fdelayed-template-parsing"); if (Opts.Deprecated) @@ -1667,6 +1669,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.MRTD = Args.hasArg(OPT_mrtd); Opts.FakeAddressSpaceMap = Args.hasArg(OPT_ffake_address_space_map); Opts.ParseUnknownAnytype = Args.hasArg(OPT_funknown_anytype); + Opts.DebuggerSupport = Args.hasArg(OPT_fdebugger_support); // Record whether the __DEPRECATED define was requested. Opts.Deprecated = Args.hasFlag(OPT_fdeprecated_macro, diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index fa8721ce345..22185ed69ec 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -9552,9 +9552,6 @@ ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *call) { } ExprResult RebuildUnknownAnyExpr::VisitObjCMessageExpr(ObjCMessageExpr *msg) { - ObjCMethodDecl *method = msg->getMethodDecl(); - assert(method && "__unknown_anytype message without result type?"); - // Verify that this is a legal result type of a call. if (DestType->isArrayType() || DestType->isFunctionType()) { S.Diag(msg->getExprLoc(), diag::err_func_returning_array_function) @@ -9562,8 +9559,11 @@ ExprResult RebuildUnknownAnyExpr::VisitObjCMessageExpr(ObjCMessageExpr *msg) { return ExprError(); } - assert(method->getResultType() == S.Context.UnknownAnyTy); - method->setResultType(DestType); + // Rewrite the method result type if available. + if (ObjCMethodDecl *method = msg->getMethodDecl()) { + assert(method->getResultType() == S.Context.UnknownAnyTy); + method->setResultType(DestType); + } // Change the type of the message. msg->setType(DestType.getNonReferenceType()); diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 22953da97bc..3df6d3f96e4 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -355,7 +355,14 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, : diag::warn_inst_method_not_found; Diag(lbrac, DiagID) << Sel << isClassMessage << SourceRange(lbrac, rbrac); - ReturnType = Context.getObjCIdType(); + + // In debuggers, we want to use __unknown_anytype for these + // results so that clients can cast them. + if (getLangOptions().DebuggerSupport) { + ReturnType = Context.UnknownAnyTy; + } else { + ReturnType = Context.getObjCIdType(); + } VK = VK_RValue; return false; } diff --git a/clang/test/SemaObjC/debugger-support.m b/clang/test/SemaObjC/debugger-support.m new file mode 100644 index 00000000000..21c096edad4 --- /dev/null +++ b/clang/test/SemaObjC/debugger-support.m @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fdebugger-support %s -emit-llvm -o - | FileCheck %s + +// rdar://problem/9416370 +void test0(id x) { + struct A { int w, x, y, z; }; + struct A result = (struct A) [x makeStruct]; + // CHECK: define void @test0( + // CHECK: [[X:%.*]] = alloca i8*, align 8 + // CHECK-NEXT: [[RESULT:%.*]] = alloca [[A:%.*]], align 4 + // CHECK-NEXT: store i8* {{%.*}}, i8** [[X]], + // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]], + // CHECK-NEXT: [[T1:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_" + // CHECK-NEXT: [[T2:%.*]] = call { i64, i64 } bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to { i64, i64 } (i8*, i8*)*)(i8* [[T0]], i8* [[T1]]) +} |

