summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Expression/ClangExpressionDeclMap.h21
-rw-r--r--lldb/source/Expression/ClangExpressionDeclMap.cpp64
-rw-r--r--lldb/source/Expression/ClangExpressionParser.cpp3
-rw-r--r--lldb/test/lang/objc/modules-inline-functions/Makefile9
-rw-r--r--lldb/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py80
-rw-r--r--lldb/test/lang/objc/modules-inline-functions/main.m9
-rw-r--r--lldb/test/lang/objc/modules-inline-functions/module.map4
-rw-r--r--lldb/test/lang/objc/modules-inline-functions/myModule.c7
-rw-r--r--lldb/test/lang/objc/modules-inline-functions/myModule.h7
9 files changed, 193 insertions, 11 deletions
diff --git a/lldb/include/lldb/Expression/ClangExpressionDeclMap.h b/lldb/include/lldb/Expression/ClangExpressionDeclMap.h
index 8a4aa82b872..f24500ab523 100644
--- a/lldb/include/lldb/Expression/ClangExpressionDeclMap.h
+++ b/lldb/include/lldb/Expression/ClangExpressionDeclMap.h
@@ -100,6 +100,9 @@ public:
WillParse (ExecutionContext &exe_ctx,
Materializer *materializer);
+ void
+ InstallCodeGenerator (clang::ASTConsumer *code_gen);
+
//------------------------------------------------------------------
/// [Used by ClangExpressionParser] For each variable that had an unknown
/// type at the beginning of parsing, determine its final type now.
@@ -396,11 +399,6 @@ private:
{
public:
ParserVars(ClangExpressionDeclMap &decl_map) :
- m_exe_ctx(),
- m_sym_ctx(),
- m_persistent_vars(NULL),
- m_enable_lookups(false),
- m_materializer(NULL),
m_decl_map(decl_map)
{
}
@@ -415,12 +413,13 @@ private:
return NULL;
}
- ExecutionContext m_exe_ctx; ///< The execution context to use when parsing.
- SymbolContext m_sym_ctx; ///< The symbol context to use in finding variables and types.
- ClangPersistentVariables *m_persistent_vars; ///< The persistent variables for the process.
- bool m_enable_lookups; ///< Set to true during parsing if we have found the first "$__lldb" name.
- TargetInfo m_target_info; ///< Basic information about the target.
- Materializer *m_materializer; ///< If non-NULL, the materializer to use when reporting used variables.
+ ExecutionContext m_exe_ctx; ///< The execution context to use when parsing.
+ SymbolContext m_sym_ctx; ///< The symbol context to use in finding variables and types.
+ ClangPersistentVariables *m_persistent_vars = nullptr; ///< The persistent variables for the process.
+ bool m_enable_lookups = false; ///< Set to true during parsing if we have found the first "$__lldb" name.
+ TargetInfo m_target_info; ///< Basic information about the target.
+ Materializer *m_materializer = nullptr; ///< If non-NULL, the materializer to use when reporting used variables.
+ clang::ASTConsumer *m_code_gen = nullptr; ///< If non-NULL, a code generator that receives new top-level functions.
private:
ClangExpressionDeclMap &m_decl_map;
DISALLOW_COPY_AND_ASSIGN (ParserVars);
diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp
index 1a694f76d73..1f377305df0 100644
--- a/lldb/source/Expression/ClangExpressionDeclMap.cpp
+++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/Expression/ClangExpressionDeclMap.h"
+#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Decl.h"
@@ -111,6 +112,13 @@ ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx,
}
void
+ClangExpressionDeclMap::InstallCodeGenerator (clang::ASTConsumer *code_gen)
+{
+ assert(m_parser_vars);
+ m_parser_vars->m_code_gen = code_gen;
+}
+
+void
ClangExpressionDeclMap::DidParse()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -1487,6 +1495,62 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
}
}
}
+
+ if (!context.m_found.function_with_type_info)
+ {
+ // Try the modules next.
+
+ do
+ {
+ if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor())
+ {
+ bool append = false;
+ uint32_t max_matches = 1;
+ std::vector <clang::NamedDecl *> decls;
+
+ if (!modules_decl_vendor->FindDecls(name,
+ append,
+ max_matches,
+ decls))
+ break;
+
+ clang::NamedDecl *const decl_from_modules = decls[0];
+
+ if (llvm::isa<clang::FunctionDecl>(decl_from_modules))
+ {
+ if (log)
+ {
+ log->Printf(" CAS::FEVD[%u] Matching function found for \"%s\" in the modules",
+ current_id,
+ name.GetCString());
+ }
+
+ clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules);
+ clang::FunctionDecl *copied_function_decl = copied_decl ? dyn_cast<clang::FunctionDecl>(copied_decl) : nullptr;
+
+ if (!copied_function_decl)
+ {
+ if (log)
+ log->Printf(" CAS::FEVD[%u] - Couldn't export a function declaration from the modules",
+ current_id);
+
+ break;
+ }
+
+ if (copied_function_decl->getBody() && m_parser_vars->m_code_gen)
+ {
+ DeclGroupRef decl_group_ref(copied_function_decl);
+ m_parser_vars->m_code_gen->HandleTopLevelDecl(decl_group_ref);
+ }
+
+ context.AddNamedDecl(copied_function_decl);
+
+ context.m_found.function_with_type_info = true;
+ context.m_found.function = true;
+ }
+ }
+ } while (0);
+ }
if (target && !context.m_found.variable && !namespace_decl)
{
diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp
index 57e620bf2d9..9cc7b0fa684 100644
--- a/lldb/source/Expression/ClangExpressionParser.cpp
+++ b/lldb/source/Expression/ClangExpressionParser.cpp
@@ -409,6 +409,9 @@ ClangExpressionParser::Parse (Stream &stream)
ASTConsumer *ast_transformer = m_expr.ASTTransformer(m_code_generator.get());
+ if (ClangExpressionDeclMap *decl_map = m_expr.DeclMap())
+ decl_map->InstallCodeGenerator(m_code_generator.get());
+
if (ast_transformer)
ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext());
else
diff --git a/lldb/test/lang/objc/modules-inline-functions/Makefile b/lldb/test/lang/objc/modules-inline-functions/Makefile
new file mode 100644
index 00000000000..6ad9e0010bb
--- /dev/null
+++ b/lldb/test/lang/objc/modules-inline-functions/Makefile
@@ -0,0 +1,9 @@
+LEVEL = ../../../make
+
+C_SOURCES := myModule.c
+
+OBJC_SOURCES := main.m
+
+include $(LEVEL)/Makefile.rules
+
+CFLAGS += -fmodules -I$(PWD)
diff --git a/lldb/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py b/lldb/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py
new file mode 100644
index 00000000000..a9c7ce65067
--- /dev/null
+++ b/lldb/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py
@@ -0,0 +1,80 @@
+"""Test that inline functions from modules are imported correctly"""
+
+import os, time
+import unittest2
+import lldb
+import platform
+import lldbutil
+
+from distutils.version import StrictVersion
+
+from lldbtest import *
+
+class ModulesInlineFunctionsTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipUnlessDarwin
+ @dsym_test
+ def test_expr_with_dsym(self):
+ self.buildDsym()
+ self.expr()
+
+ @dwarf_test
+ @skipIfFreeBSD
+ @skipIfLinux
+ def test_expr_with_dwarf(self):
+ self.buildDwarf()
+ self.expr()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ # Find the line number to break inside main().
+ self.line = line_number('main.m', '// Set breakpoint here.')
+
+ def applies(self):
+ if platform.system() != "Darwin":
+ return False
+ if StrictVersion('12.0.0') > platform.release():
+ return False
+
+ return True
+
+ def common_setup(self):
+ exe = os.path.join(os.getcwd(), "a.out")
+ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+ # Break inside the foo function which takes a bar_ptr argument.
+ lldbutil.run_break_set_by_file_and_line (self, "main.m", self.line, num_expected_locations=1, loc_exact=True)
+
+ self.runCmd("run", RUN_SUCCEEDED)
+
+ # The stop reason of the thread should be breakpoint.
+ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+ substrs = ['stopped',
+ 'stop reason = breakpoint'])
+
+ # The breakpoint should have a hit count of 1.
+ self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
+ substrs = [' resolved, hit count = 1'])
+
+ def expr(self):
+ if not self.applies():
+ return
+
+ self.common_setup()
+
+ self.runCmd("settings set target.clang-module-search-paths \"" + os.getcwd() + "\"")
+
+ self.expect("expr @import myModule; 3", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = ["int", "3"])
+
+ self.expect("expr isInline(2)", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = ["4"])
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
diff --git a/lldb/test/lang/objc/modules-inline-functions/main.m b/lldb/test/lang/objc/modules-inline-functions/main.m
new file mode 100644
index 00000000000..13a5bf316ee
--- /dev/null
+++ b/lldb/test/lang/objc/modules-inline-functions/main.m
@@ -0,0 +1,9 @@
+@import Darwin;
+@import myModule;
+
+int main()
+{
+ int a = isInline(2);
+ int b = notInline();
+ printf("%d %d\n", a, b); // Set breakpoint here.
+}
diff --git a/lldb/test/lang/objc/modules-inline-functions/module.map b/lldb/test/lang/objc/modules-inline-functions/module.map
new file mode 100644
index 00000000000..2ef8064d15b
--- /dev/null
+++ b/lldb/test/lang/objc/modules-inline-functions/module.map
@@ -0,0 +1,4 @@
+module myModule {
+ header "myModule.h"
+ export *
+}
diff --git a/lldb/test/lang/objc/modules-inline-functions/myModule.c b/lldb/test/lang/objc/modules-inline-functions/myModule.c
new file mode 100644
index 00000000000..ad3c85d155e
--- /dev/null
+++ b/lldb/test/lang/objc/modules-inline-functions/myModule.c
@@ -0,0 +1,7 @@
+#include "myModule.h"
+
+int notInline()
+{
+ return 3;
+}
+
diff --git a/lldb/test/lang/objc/modules-inline-functions/myModule.h b/lldb/test/lang/objc/modules-inline-functions/myModule.h
new file mode 100644
index 00000000000..d50d0101f64
--- /dev/null
+++ b/lldb/test/lang/objc/modules-inline-functions/myModule.h
@@ -0,0 +1,7 @@
+int notInline();
+
+static __inline__ __attribute__ ((always_inline)) int isInline(int a)
+{
+ int b = a + a;
+ return b;
+}
OpenPOWER on IntegriCloud