// (lldb::opaque_compiler_type_t type, "-[NString
// stringWithCString:]")
const CompilerType &method_compiler_type, lldb::AccessType access,
- bool is_artificial, bool is_variadic);
+ bool is_artificial, bool is_variadic, bool is_objc_direct_call);
static bool SetHasExternalStorage(lldb::opaque_compiler_type_t type,
bool has_extern);
--- /dev/null
+OBJC_SOURCES := main.m
+LD_EXTRAS := -lobjc -framework Foundation
+
+include Makefile.rules
--- /dev/null
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(
+ __file__, globals(), [decorators.skipUnlessDarwin])
--- /dev/null
+#import <Foundation/Foundation.h>
+
+int side_effect = 0;
+
+NSString *str = @"some string";
+
+const char *directCallConflictingName() {
+ return "wrong function";
+}
+
+@interface Foo : NSObject {
+ int instance_var;
+}
+-(int) entryPoint;
+@end
+
+@implementation Foo
+-(int) entryPoint
+{
+ // Try calling directly with self. Same as in the main method otherwise.
+ return 0; //%self.expect("expr [self directCallNoArgs]", substrs=["called directCallNoArgs"])
+ //%self.expect("expr [self directCallArgs: 1111]", substrs=["= 2345"])
+ //%self.expect("expr side_effect = 0; [self directCallVoidReturn]; side_effect", substrs=["= 4321"])
+ //%self.expect("expr [self directCallNSStringArg: str]", substrs=['@"some string"'])
+ //%self.expect("expr [self directCallIdArg: (id)str]", substrs=['@"some string appendix"'])
+ //%self.expect("expr [self directCallConflictingName]", substrs=["correct function"])
+}
+
+// Declare several objc_direct functions we can test.
+-(const char *) directCallNoArgs __attribute__((objc_direct))
+{
+ return "called directCallNoArgs";
+}
+
+-(void) directCallVoidReturn __attribute__((objc_direct))
+{
+ side_effect = 4321;
+}
+
+-(int) directCallArgs:(int)i __attribute__((objc_direct))
+{
+ // Use the arg in some way to make sure that gets passed correctly.
+ return i + 1234;
+}
+
+-(NSString *) directCallNSStringArg:(NSString *)str __attribute__((objc_direct))
+{
+ return str;
+}
+
+-(NSString *) directCallIdArg:(id)param __attribute__((objc_direct))
+{
+ return [param stringByAppendingString:@" appendix"];
+}
+
+// We have another function with the same name above. Make sure this doesn't influence
+// what we call.
+-(const char *) directCallConflictingName __attribute__((objc_direct))
+{
+ return "correct function";
+}
+@end
+
+int main()
+{
+ Foo *foo = [[Foo alloc] init];
+ [foo directCallNoArgs];
+ [foo directCallArgs: 1];
+ [foo directCallVoidReturn];
+ [foo directCallNSStringArg: str];
+ [foo directCallIdArg: (id)str];
+ [foo entryPoint]; //%self.expect("expr [foo directCallNoArgs]", substrs=["called directCallNoArgs"])
+ //%self.expect("expr [foo directCallArgs: 1111]", substrs=["= 2345"])
+ //%self.expect("expr side_effect = 0; [foo directCallVoidReturn]; side_effect", substrs=["= 4321"])
+ //%self.expect("expr [foo directCallNSStringArg: str]", substrs=['@"some string"'])
+ //%self.expect("expr [foo directCallIdArg: (id)str]", substrs=['@"some string appendix"'])
+ //%self.expect("expr [foo directCallConflictingName]", substrs=["correct function"])
+ return 0;
+}
is_complete_objc_class = form_value.Signed();
break;
+ case DW_AT_APPLE_objc_direct:
+ is_objc_direct_call = true;
+ break;
+
case DW_AT_APPLE_runtime_class:
class_language = (LanguageType)form_value.Signed();
break;
clang::ObjCMethodDecl *objc_method_decl =
m_ast.AddMethodToObjCObjectType(
class_opaque_type, attrs.name.GetCString(), clang_type,
- attrs.accessibility, attrs.is_artificial, is_variadic);
+ attrs.accessibility, attrs.is_artificial, is_variadic,
+ attrs.is_objc_direct_call);
type_handled = objc_method_decl != NULL;
if (type_handled) {
LinkDeclContextToDIE(objc_method_decl, die);
bool is_scoped_enum = false;
bool is_vector = false;
bool is_virtual = false;
+ bool is_objc_direct_call = false;
bool exports_symbols = false;
clang::StorageClass storage = clang::SC_None;
const char *mangled_name = nullptr;
// (lldb::opaque_compiler_type_t type, "-[NString
// stringWithCString:]")
const CompilerType &method_clang_type, lldb::AccessType access,
- bool is_artificial, bool is_variadic) {
+ bool is_artificial, bool is_variadic, bool is_objc_direct_call) {
if (!type || !method_clang_type.IsValid())
return nullptr;
llvm::ArrayRef<clang::SourceLocation>());
}
+ if (is_objc_direct_call) {
+ // Add a the objc_direct attribute to the declaration we generate that
+ // we generate a direct method call for this ObjCMethodDecl.
+ objc_method_decl->addAttr(
+ clang::ObjCDirectAttr::CreateImplicit(*ast, SourceLocation()));
+ // Usually Sema is creating implicit parameters (e.g., self) when it
+ // parses the method. We don't have a parsing Sema when we build our own
+ // AST here so we manually need to create these implicit parameters to
+ // make the direct call code generation happy.
+ objc_method_decl->createImplicitParams(*ast, class_interface_decl);
+ }
+
class_interface_decl->addDecl(objc_method_decl);
#ifdef LLDB_CONFIGURATION_DEBUG