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 | 48218c60d6b53b7880917d1366ee716dec2145ca (patch) | |
tree | 47b3a24c4ac357c2a13cfb0fdf5e3f6449fc73ad | |
parent | 8beb6a2426b5a6b79ecf019316d9fbd30755e087 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@135051 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/LangOptions.h | 4 | ||||
-rw-r--r-- | include/clang/Driver/CC1Options.td | 2 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 9 | ||||
-rw-r--r-- | test/SemaObjC/debugger-support.m | 14 |
6 files changed, 35 insertions, 7 deletions
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 6d4dc5b8dc..dc77d4c149 100644 --- a/include/clang/Basic/LangOptions.h +++ b/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/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 8cadbe92da..d8404365a1 100644 --- a/include/clang/Driver/CC1Options.td +++ b/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/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 05b3377b3e..06b72602fd 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/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/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index fa8721ce34..22185ed69e 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/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/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 22953da97b..3df6d3f96e 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/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/test/SemaObjC/debugger-support.m b/test/SemaObjC/debugger-support.m new file mode 100644 index 0000000000..21c096edad --- /dev/null +++ b/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]]) +} |