# LLDB modules
import use_lldb_suite
+import lldbtest
import lldb
from . import configuration
compilerRtPath = os.path.join(os.path.dirname(__file__), "..", "..", "..", "..", "llvm","projects","compiler-rt")
return "compiler-rt not found" if not os.path.exists(compilerRtPath) else None
return skipTestIfFn(is_compiler_rt_missing)(func)
+
+def skipUnlessClangModules():
+ """Decorate the item to skip test unless Clang -gmodules flag is supported."""
+ def is_compiler_clang_with_gmodules(self):
+ builder = lldbtest.builder_module()
+ compiler_path = builder.getCompiler()
+ compiler = os.path.basename(compiler_path)
+ if compiler != "clang":
+ return "Test requires clang as compiler"
+ clang_help = os.popen("%s --help" % (compiler_path)).read()
+ match = re.match(".* -gmodules ", clang_help, re.DOTALL)
+ return "Clang version doesn't support -gmodules flag" if not match else None
+ return skipTestIfFn(is_compiler_clang_with_gmodules)
--- /dev/null
+LEVEL = ../../../make
+
+PCH_CXX_SOURCE = pch.h
+CXX_SOURCES = main.cpp
+CFLAGS_EXTRAS += $(MODULE_DEBUG_INFO_FLAGS)
+
+include $(LEVEL)/Makefile.rules
--- /dev/null
+import lldb, os
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestWithGmodulesDebugInfo(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @expectedFailureAll(bugnumber="llvm.org/pr27412")
+ @skipUnlessClangModules()
+ def test_specialized_typedef_from_pch(self):
+ clang_help = os.popen("clang --help").read()
+ match = re.match(".* -gmodules ", clang_help, re.DOTALL)
+ if not match:
+ self.skipTest("Clang version doesn't support -gmodules flag")
+ return
+
+ self.build()
+ cwd = os.getcwd()
+
+ src_file = os.path.join(cwd, "main.cpp")
+ src_file_spec = lldb.SBFileSpec(src_file)
+ self.assertTrue(src_file_spec.IsValid(), "breakpoint file")
+
+ # Get the path of the executable
+ exe_path = os.path.join(cwd, 'a.out')
+
+ # Load the executable
+ target = self.dbg.CreateTarget(exe_path)
+ self.assertTrue(target.IsValid(), VALID_TARGET)
+
+ # Break on interesting line
+ breakpoint = target.BreakpointCreateBySourceRegex("break here", src_file_spec)
+ self.assertTrue(breakpoint.IsValid() and breakpoint.GetNumLocations() >= 1, VALID_BREAKPOINT)
+
+ # Launch the process
+ process = target.LaunchSimple(None, None, self.get_process_working_directory())
+ self.assertTrue(process.IsValid(), PROCESS_IS_VALID)
+
+ # Get the thread of the process
+ self.assertTrue(process.GetState() == lldb.eStateStopped)
+ thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
+ self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition")
+
+ # Get frame for current thread
+ frame = thread.frames[0]
+
+ testValue = frame.EvaluateExpression("test")
+ self.assertTrue(testValue.GetError().Success(), "Test expression value invalid: %s" % (testValue.GetError().GetCString()))
+ self.assertTrue(testValue.GetTypeName() == "IntContainer", "Test expression type incorrect")
+
+ memberValue = testValue.GetChildMemberWithName("storage")
+ self.assertTrue(memberValue.GetError().Success(), "Member value missing or invalid: %s" % (testValue.GetError().GetCString()))
+ self.assertTrue(memberValue.GetTypeName() == "int", "Member type incorrect")
+ self.assertEqual(42, memberValue.GetValueAsSigned(), "Member value incorrect")
--- /dev/null
+int main(int argc, const char * argv[])
+{
+ IntContainer test(42);
+ return 0; // break here
+}
--- /dev/null
+template<typename T>
+class GenericContainer {
+ private:
+ T storage;
+
+ public:
+ GenericContainer(T value) {
+ storage = value;
+ };
+};
+
+typedef GenericContainer<int> IntContainer;
LIMIT_DEBUG_INFO_FLAGS =
NO_LIMIT_DEBUG_INFO_FLAGS =
+MODULE_DEBUG_INFO_FLAGS =
ifneq (,$(findstring clang,$(CC)))
LIMIT_DEBUG_INFO_FLAGS += -flimit-debug-info
NO_LIMIT_DEBUG_INFO_FLAGS += -fno-limit-debug-info
+ MODULE_DEBUG_INFO_FLAGS += -gmodules
endif
DEBUG_INFO_FLAG ?= -g
endif
#----------------------------------------------------------------------
+# Check if we have a precompiled header
+#----------------------------------------------------------------------
+ifneq "$(strip $(PCH_CXX_SOURCE))" ""
+ PCH_OUTPUT = $(PCH_CXX_SOURCE:.h=.h.pch)
+ PCHFLAGS = -include $(PCH_CXX_SOURCE)
+endif
+
+#----------------------------------------------------------------------
# Check if we have any C source files
#----------------------------------------------------------------------
ifneq "$(strip $(C_SOURCES))" ""
endif
#----------------------------------------------------------------------
+# Make the precompiled header and compile C++ sources against it
+#----------------------------------------------------------------------
+
+#ifneq "$(PCH_OUTPUT)" ""
+$(PCH_OUTPUT) : $(PCH_CXX_SOURCE)
+ $(CXX) $(CXXFLAGS) -x c++-header -o $(PCH_OUTPUT) $(PCH_CXX_SOURCE)
+%.o : %.cpp $(PCH_OUTPUT)
+ $(CXX) $(PCHFLAGS) $(CXXFLAGS) $(CFLAGS) -c -o $@ $<
+#endif
+
+#----------------------------------------------------------------------
# Automatic variables based on items already entered. Below we create
# an object's lists from the list of sources by replacing all entries
# that end with .c with .o, and we also create a list of prerequisite
$(RM) -r $(DYLIB_FILENAME).dSYM
$(RM) $(DYLIB_OBJECTS) $(DYLIB_PREREQS) $(DYLIB_PREREQS:.d=.d.tmp) $(DYLIB_DWOS) $(DYLIB_FILENAME) $(DYLIB_FILENAME).debug
endif
+ifneq "$(PCH_OUTPUT)" ""
+ $(RM) $(PCH_OUTPUT)
+endif
ifneq "$(DSYM)" ""
$(RM) -r "$(DSYM)"
endif