Index: cfe/trunk/include/clang/Basic/DiagnosticOptions.def =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticOptions.def +++ cfe/trunk/include/clang/Basic/DiagnosticOptions.def @@ -49,6 +49,7 @@ DIAGOPT(PedanticErrors, 1, 0) /// -pedantic-errors DIAGOPT(ShowColumn, 1, 1) /// Show column number on diagnostics. DIAGOPT(ShowLocation, 1, 1) /// Show source location information. +DIAGOPT(ShowLevel, 1, 1) /// Show diagnostic level. DIAGOPT(AbsolutePath, 1, 0) /// Use absolute paths. DIAGOPT(ShowCarets, 1, 1) /// Show carets in diagnostics. DIAGOPT(ShowFixits, 1, 1) /// Show fixit information. Index: cfe/trunk/lib/Frontend/TextDiagnostic.cpp =================================================================== --- cfe/trunk/lib/Frontend/TextDiagnostic.cpp +++ cfe/trunk/lib/Frontend/TextDiagnostic.cpp @@ -683,8 +683,9 @@ if (DiagOpts->ShowColors) OS.resetColor(); - printDiagnosticLevel(OS, Level, DiagOpts->ShowColors, - DiagOpts->CLFallbackMode); + if (DiagOpts->ShowLevel) + printDiagnosticLevel(OS, Level, DiagOpts->ShowColors, + DiagOpts->CLFallbackMode); printDiagnosticMessage(OS, /*IsSupplemental*/ Level == DiagnosticsEngine::Note, Message, OS.tell() - StartOfLocationInfo, Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/diagnostics/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/diagnostics/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/diagnostics/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/diagnostics/TestExprDiagnostics.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/diagnostics/TestExprDiagnostics.py +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/diagnostics/TestExprDiagnostics.py @@ -0,0 +1,113 @@ +""" +Test the diagnostics emitted by our embeded Clang instance that parses expressions. +""" + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +from lldbsuite.test.decorators import * + +class ExprDiagnosticsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + self.main_source = "main.cpp" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + + def test_source_and_caret_printing(self): + """Test that the source and caret positions LLDB prints are correct""" + self.build() + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + '// Break here', self.main_source_spec) + frame = thread.GetFrameAtIndex(0) + + # Test that source/caret are at the right position. + value = frame.EvaluateExpression("unknown_identifier") + self.assertFalse(value.GetError().Success()) + # We should get a nice diagnostic with a caret pointing at the start of + # the identifier. + self.assertIn("\nunknown_identifier\n^\n", value.GetError().GetCString()) + self.assertIn(":1:1", value.GetError().GetCString()) + + # Same as above but with the identifier in the middle. + value = frame.EvaluateExpression("1 + unknown_identifier ") + self.assertFalse(value.GetError().Success()) + self.assertIn("\n1 + unknown_identifier", value.GetError().GetCString()) + self.assertIn("\n ^\n", value.GetError().GetCString()) + + # Multiline expressions. + value = frame.EvaluateExpression("int a = 0;\nfoobar +=1;\na") + self.assertFalse(value.GetError().Success()) + # We should still get the right line information and caret position. + self.assertIn("\nfoobar +=1;\n^\n", value.GetError().GetCString()) + # It's the second line of the user expression. + self.assertIn(":2:1", value.GetError().GetCString()) + + # Top-level expressions. + top_level_opts = lldb.SBExpressionOptions(); + top_level_opts.SetTopLevel(True) + + value = frame.EvaluateExpression("void foo(unknown_type x) {}", top_level_opts) + self.assertFalse(value.GetError().Success()) + self.assertIn("\nvoid foo(unknown_type x) {}\n ^\n", value.GetError().GetCString()) + # Top-level expressions might use a different wrapper code, but the file name should still + # be the same. + self.assertIn(":1:10", value.GetError().GetCString()) + + # Multiline top-level expressions. + value = frame.EvaluateExpression("void x() {}\nvoid foo(unknown_type x) {}", top_level_opts) + self.assertFalse(value.GetError().Success()) + self.assertIn("\nvoid foo(unknown_type x) {}\n ^\n", value.GetError().GetCString()) + self.assertIn(":2:10", value.GetError().GetCString()) + + # Test that we render Clang's 'notes' correctly. + value = frame.EvaluateExpression("struct SFoo{}; struct SFoo { int x; };", top_level_opts) + self.assertFalse(value.GetError().Success()) + self.assertIn(":1:8: previous definition is here\nstruct SFoo{}; struct SFoo { int x; };\n ^\n", value.GetError().GetCString()) + + # Declarations from the debug information currently have no debug information. It's not clear what + # we should do in this case, but we should at least not print anything that's wrong. + # In the future our declarations should have valid source locations. + value = frame.EvaluateExpression("struct FooBar { double x };", top_level_opts) + self.assertFalse(value.GetError().Success()) + self.assertEqual("error: :1:8: redefinition of 'FooBar'\nstruct FooBar { double x };\n ^\n", value.GetError().GetCString()) + + value = frame.EvaluateExpression("foo(1, 2)") + self.assertFalse(value.GetError().Success()) + self.assertEqual("error: :1:1: no matching function for call to 'foo'\nfoo(1, 2)\n^~~\nnote: candidate function not viable: requires single argument 'x', but 2 arguments were provided\n\n", value.GetError().GetCString()) + + # Redefine something that we defined in a user-expression. We should use the previous expression file name + # for the original decl. + value = frame.EvaluateExpression("struct Redef { double x; };", top_level_opts) + value = frame.EvaluateExpression("struct Redef { float y; };", top_level_opts) + self.assertFalse(value.GetError().Success()) + self.assertIn("error: :1:8: redefinition of 'Redef'\nstruct Redef { float y; };\n ^\n:1:8: previous definition is here\nstruct Redef { double x; };\n ^", value.GetError().GetCString()) + + @skipUnlessDarwin + def test_source_locations_from_objc_modules(self): + self.build() + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + '// Break here', self.main_source_spec) + frame = thread.GetFrameAtIndex(0) + + # Import foundation so that the Obj-C module is loaded (which contains source locations + # that can be used by LLDB). + self.runCmd("expr @import Foundation") + value = frame.EvaluateExpression("NSLog(1);") + self.assertFalse(value.GetError().Success()) + print(value.GetError().GetCString()) + # LLDB should print the source line that defines NSLog. To not rely on any + # header paths/line numbers or the actual formatting of the Foundation headers, only look + # for a few tokens in the output. + # File path should come from Foundation framework. + self.assertIn("/Foundation.framework/", value.GetError().GetCString()) + # The NSLog definition source line should be printed. Return value and + # the first argument are probably stable enough that this test can check for them. + self.assertIn("void NSLog(NSString *format", value.GetError().GetCString()) + Index: lldb/trunk/packages/Python/lldbsuite/test/commands/expression/diagnostics/main.cpp =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/commands/expression/diagnostics/main.cpp +++ lldb/trunk/packages/Python/lldbsuite/test/commands/expression/diagnostics/main.cpp @@ -0,0 +1,11 @@ +void foo(int x) {} + +struct FooBar { + int i; +}; + +int main() { + FooBar f; + foo(1); + return 0; // Break here +} Index: lldb/trunk/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods.py +++ lldb/trunk/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods.py @@ -191,7 +191,7 @@ "expression self->non_existent_member", COMMAND_FAILED_AS_EXPECTED, error=True, - startstr="error: 'MyString' does not have a member named 'non_existent_member'") + substrs=["error:", "'MyString' does not have a member named 'non_existent_member'"]) # Use expression parser. self.runCmd("expression self->str") Index: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h =================================================================== --- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h +++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h @@ -29,7 +29,7 @@ return diag->getKind() == eDiagnosticOriginClang; } - ClangDiagnostic(const char *message, DiagnosticSeverity severity, + ClangDiagnostic(llvm::StringRef message, DiagnosticSeverity severity, uint32_t compiler_id) : Diagnostic(message, severity, eDiagnosticOriginClang, compiler_id) {} Index: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h =================================================================== --- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h +++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h @@ -53,9 +53,14 @@ /// @param[in] include_directories /// List of include directories that should be used when parsing the /// expression. + /// + /// @param[in] filename + /// Name of the source file that should be used when rendering + /// diagnostics (i.e. errors, warnings or notes from Clang). ClangExpressionParser(ExecutionContextScope *exe_scope, Expression &expr, bool generate_debug_info, - std::vector include_directories = {}); + std::vector include_directories = {}, + std::string filename = ""); /// Destructor ~ClangExpressionParser() override; @@ -178,6 +183,8 @@ std::unique_ptr m_ast_context; std::vector m_include_directories; + /// File name used for the user expression. + std::string m_filename; }; } Index: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp =================================================================== --- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -137,12 +137,14 @@ class ClangDiagnosticManagerAdapter : public clang::DiagnosticConsumer { public: - ClangDiagnosticManagerAdapter() - : m_passthrough(new clang::TextDiagnosticBuffer) {} - - ClangDiagnosticManagerAdapter( - const std::shared_ptr &passthrough) - : m_passthrough(passthrough) {} + ClangDiagnosticManagerAdapter(DiagnosticOptions &opts) { + DiagnosticOptions *m_options = new DiagnosticOptions(opts); + m_options->ShowPresumedLoc = true; + m_options->ShowLevel = false; + m_os.reset(new llvm::raw_string_ostream(m_output)); + m_passthrough.reset( + new clang::TextDiagnosticPrinter(*m_os, m_options, false)); + } void ResetManager(DiagnosticManager *manager = nullptr) { m_manager = manager; @@ -150,12 +152,12 @@ void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) override { - if (m_manager) { - llvm::SmallVector diag_str; - Info.FormatDiagnostic(diag_str); - diag_str.push_back('\0'); - const char *data = diag_str.data(); + // Render diagnostic message to m_output. + m_output.clear(); + m_passthrough->HandleDiagnostic(DiagLevel, Info); + m_os->flush(); + if (m_manager) { lldb_private::DiagnosticSeverity severity; bool make_new_diagnostic = true; @@ -172,12 +174,16 @@ severity = eDiagnosticSeverityRemark; break; case DiagnosticsEngine::Level::Note: - m_manager->AppendMessageToDiagnostic(data); + m_manager->AppendMessageToDiagnostic(m_output); make_new_diagnostic = false; } if (make_new_diagnostic) { + // ClangDiagnostic messages are expected to have no whitespace/newlines + // around them. + std::string stripped_output = llvm::StringRef(m_output).trim(); + ClangDiagnostic *new_diagnostic = - new ClangDiagnostic(data, severity, Info.getID()); + new ClangDiagnostic(stripped_output, severity, Info.getID()); m_manager->AddDiagnostic(new_diagnostic); // Don't store away warning fixits, since the compiler doesn't have @@ -194,23 +200,17 @@ } } } - - m_passthrough->HandleDiagnostic(DiagLevel, Info); - } - - void FlushDiagnostics(DiagnosticsEngine &Diags) { - m_passthrough->FlushDiagnostics(Diags); - } - - DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const { - return new ClangDiagnosticManagerAdapter(m_passthrough); } - clang::TextDiagnosticBuffer *GetPassthrough() { return m_passthrough.get(); } + clang::TextDiagnosticPrinter *GetPassthrough() { return m_passthrough.get(); } private: DiagnosticManager *m_manager = nullptr; - std::shared_ptr m_passthrough; + std::shared_ptr m_passthrough; + /// Output stream of m_passthrough. + std::shared_ptr m_os; + /// Output string filled by m_os. + std::string m_output; }; static void SetupModuleHeaderPaths(CompilerInstance *compiler, @@ -258,12 +258,11 @@ // Implementation of ClangExpressionParser //===----------------------------------------------------------------------===// -ClangExpressionParser::ClangExpressionParser( - ExecutionContextScope *exe_scope, Expression &expr, - bool generate_debug_info, std::vector include_directories) +ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, Expression &expr, + bool generate_debug_info, std::vector include_directories, std::string filename) : ExpressionParser(exe_scope, expr, generate_debug_info), m_compiler(), m_pp_callbacks(nullptr), - m_include_directories(std::move(include_directories)) { + m_include_directories(std::move(include_directories)), m_filename(std::move(filename)) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // We can't compile expressions without a target. So if the exe_scope is @@ -557,7 +556,9 @@ // 6. Set up the diagnostic buffer for reporting errors - m_compiler->getDiagnostics().setClient(new ClangDiagnosticManagerAdapter); + auto diag_mgr = new ClangDiagnosticManagerAdapter( + m_compiler->getDiagnostics().getDiagnosticOptions()); + m_compiler->getDiagnostics().setClient(diag_mgr); // 7. Set up the source management objects inside the compiler m_compiler->createFileManager(); @@ -869,8 +870,7 @@ ClangDiagnosticManagerAdapter *adapter = static_cast( m_compiler->getDiagnostics().getClient()); - clang::TextDiagnosticBuffer *diag_buf = adapter->GetPassthrough(); - diag_buf->FlushDiagnostics(m_compiler->getDiagnostics()); + auto diag_buf = adapter->GetPassthrough(); adapter->ResetManager(&diagnostic_manager); @@ -921,7 +921,7 @@ if (!created_main_file) { std::unique_ptr memory_buffer = - MemoryBuffer::getMemBufferCopy(expr_text, ""); + MemoryBuffer::getMemBufferCopy(expr_text, m_filename); source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer))); } Index: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h =================================================================== --- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h +++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h @@ -25,9 +25,11 @@ public: static const char *g_expression_prefix; - static ClangExpressionSourceCode *CreateWrapped(llvm::StringRef prefix, + static ClangExpressionSourceCode *CreateWrapped(llvm::StringRef filename, + llvm::StringRef prefix, llvm::StringRef body) { - return new ClangExpressionSourceCode("$__lldb_expr", prefix, body, Wrap); + return new ClangExpressionSourceCode(filename, "$__lldb_expr", prefix, body, + Wrap); } /// Generates the source code that will evaluate the expression. @@ -54,14 +56,20 @@ // Given a string returned by GetText, find the beginning and end of the body // passed to CreateWrapped. Return true if the bounds could be found. This // will also work on text with FixItHints applied. - static bool GetOriginalBodyBounds(std::string transformed_text, - lldb::LanguageType wrapping_language, - size_t &start_loc, size_t &end_loc); + bool GetOriginalBodyBounds(std::string transformed_text, + lldb::LanguageType wrapping_language, + size_t &start_loc, size_t &end_loc); protected: - ClangExpressionSourceCode(llvm::StringRef name, llvm::StringRef prefix, - llvm::StringRef body, Wrapping wrap) - : ExpressionSourceCode(name, prefix, body, wrap) {} + ClangExpressionSourceCode(llvm::StringRef filename, llvm::StringRef name, + llvm::StringRef prefix, llvm::StringRef body, + Wrapping wrap); + +private: + /// String marking the start of the user expression. + std::string m_start_marker; + /// String marking the end of the user expression. + std::string m_end_marker; }; } // namespace lldb_private Index: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp =================================================================== --- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp +++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp @@ -29,7 +29,9 @@ using namespace lldb_private; -const char *ClangExpressionSourceCode::g_expression_prefix = R"( +const char *ClangExpressionSourceCode::g_expression_prefix = + R"( +#line 1 "" #ifndef offsetof #define offsetof(t, d) __builtin_offsetof(t, d) #endif @@ -67,9 +69,6 @@ } )"; -static const char *c_start_marker = " /*LLDB_BODY_START*/\n "; -static const char *c_end_marker = ";\n /*LLDB_BODY_END*/\n"; - namespace { class AddMacroState { @@ -169,6 +168,17 @@ } } +lldb_private::ClangExpressionSourceCode::ClangExpressionSourceCode( + llvm::StringRef filename, llvm::StringRef name, llvm::StringRef prefix, + llvm::StringRef body, Wrapping wrap) + : ExpressionSourceCode(name, prefix, body, wrap) { + // Use #line markers to pretend that we have a single-line source file + // containing only the user expression. This will hide our wrapper code + // from the user when we render diagnostics with Clang. + m_start_marker = "#line 1 \"" + filename.str() + "\"\n"; + m_end_marker = "\n;\n#line 1 \"\"\n"; +} + namespace { /// Allows checking if a token is contained in a given expression. class TokenVerifier { @@ -401,9 +411,9 @@ case lldb::eLanguageTypeC: case lldb::eLanguageTypeC_plus_plus: case lldb::eLanguageTypeObjC: - tagged_body.append(c_start_marker); + tagged_body.append(m_start_marker); tagged_body.append(m_body); - tagged_body.append(c_end_marker); + tagged_body.append(m_end_marker); break; } switch (wrapping_language) { @@ -477,24 +487,19 @@ bool ClangExpressionSourceCode::GetOriginalBodyBounds( std::string transformed_text, lldb::LanguageType wrapping_language, size_t &start_loc, size_t &end_loc) { - const char *start_marker; - const char *end_marker; - switch (wrapping_language) { default: return false; case lldb::eLanguageTypeC: case lldb::eLanguageTypeC_plus_plus: case lldb::eLanguageTypeObjC: - start_marker = c_start_marker; - end_marker = c_end_marker; break; } - start_loc = transformed_text.find(start_marker); + start_loc = transformed_text.find(m_start_marker); if (start_loc == std::string::npos) return false; - start_loc += strlen(start_marker); - end_loc = transformed_text.find(end_marker); + start_loc += m_start_marker.size(); + end_loc = transformed_text.find(m_end_marker); return end_loc != std::string::npos; } Index: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h =================================================================== --- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h +++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h @@ -50,6 +50,15 @@ return "$"; } + /// Returns the next file name that should be used for user expressions. + std::string GetNextExprFileName() { + std::string name; + name.append(""); + return name; + } + llvm::Optional GetCompilerTypeFromPersistentDecl(ConstString type_name) override; @@ -66,6 +75,8 @@ } private: + /// The counter used by GetNextExprFileName. + uint32_t m_next_user_file_id = 0; // The counter used by GetNextPersistentVariableName uint32_t m_next_persistent_variable_id = 0; Index: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h =================================================================== --- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -15,6 +15,7 @@ #include "ASTStructExtractor.h" #include "ClangExpressionDeclMap.h" #include "ClangExpressionHelper.h" +#include "ClangExpressionSourceCode.h" #include "ClangExpressionVariable.h" #include "IRForTarget.h" @@ -216,6 +217,10 @@ /// were not able to calculate this position. llvm::Optional m_user_expression_start_pos; ResultDelegate m_result_delegate; + ClangPersistentVariables *m_clang_state; + std::unique_ptr m_source_code; + /// File name used for the expression. + std::string m_filename; /// The object (if any) in which context the expression is evaluated. /// See the comment to `UserExpression::Evaluate` for details. Index: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp =================================================================== --- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -23,7 +23,6 @@ #include "ClangDiagnostic.h" #include "ClangExpressionDeclMap.h" #include "ClangExpressionParser.h" -#include "ClangExpressionSourceCode.h" #include "ClangModulesDeclVendor.h" #include "ClangPersistentVariables.h" @@ -328,6 +327,7 @@ if (PersistentExpressionState *persistent_state = target->GetPersistentExpressionStateForLanguage( lldb::eLanguageTypeC)) { + m_clang_state = llvm::cast(persistent_state); m_result_delegate.RegisterPersistentState(persistent_state); } else { diagnostic_manager.PutString( @@ -392,18 +392,18 @@ DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, std::vector modules_to_import, bool for_completion) { + m_filename = m_clang_state->GetNextExprFileName(); std::string prefix = m_expr_prefix; if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) { m_transformed_text = m_expr_text; } else { - std::unique_ptr source_code( - ClangExpressionSourceCode::CreateWrapped(prefix.c_str(), - m_expr_text.c_str())); - - if (!source_code->GetText(m_transformed_text, m_expr_lang, - m_in_static_method, exe_ctx, !m_ctx_obj, - for_completion, modules_to_import)) { + m_source_code.reset(ClangExpressionSourceCode::CreateWrapped( + m_filename, prefix.c_str(), m_expr_text.c_str())); + + if (!m_source_code->GetText(m_transformed_text, m_expr_lang, + m_in_static_method, exe_ctx, !m_ctx_obj, + for_completion, modules_to_import)) { diagnostic_manager.PutString(eDiagnosticSeverityError, "couldn't construct expression body"); return; @@ -413,7 +413,7 @@ // transformed code. We need this later for the code completion. std::size_t original_start; std::size_t original_end; - bool found_bounds = source_code->GetOriginalBodyBounds( + bool found_bounds = m_source_code->GetOriginalBodyBounds( m_transformed_text, m_expr_lang, original_start, original_end); if (found_bounds) m_user_expression_start_pos = original_start; @@ -568,7 +568,7 @@ // parser_sp will never be empty. ClangExpressionParser parser(exe_scope, *this, generate_debug_info, - m_include_directories); + m_include_directories, m_filename); unsigned num_errors = parser.Parse(diagnostic_manager); @@ -581,8 +581,8 @@ size_t fixed_end; const std::string &fixed_expression = diagnostic_manager.GetFixedExpression(); - if (ClangExpressionSourceCode::GetOriginalBodyBounds( - fixed_expression, m_expr_lang, fixed_start, fixed_end)) + if (m_source_code->GetOriginalBodyBounds(fixed_expression, m_expr_lang, + fixed_start, fixed_end)) m_fixed_text = fixed_expression.substr(fixed_start, fixed_end - fixed_start); }