forked from OSchip/llvm-project
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
This commit is contained in:
parent
17585e7940
commit
3f4138c5d0
|
@ -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; }
|
||||
|
|
|
@ -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">,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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]])
|
||||
}
|
Loading…
Reference in New Issue