9#include "clang/AST/ASTContext.h"
10#include "clang/AST/ASTDiagnostic.h"
11#include "clang/AST/ExternalASTSource.h"
12#include "clang/AST/PrettyPrinter.h"
13#include "clang/Basic/Builtins.h"
14#include "clang/Basic/DarwinSDKInfo.h"
15#include "clang/Basic/DiagnosticIDs.h"
16#include "clang/Basic/IdentifierTable.h"
17#include "clang/Basic/SourceLocation.h"
18#include "clang/Basic/TargetInfo.h"
19#include "clang/Basic/Version.h"
20#include "clang/CodeGen/CodeGenAction.h"
21#include "clang/CodeGen/ModuleBuilder.h"
22#include "clang/Edit/Commit.h"
23#include "clang/Edit/EditedSource.h"
24#include "clang/Edit/EditsReceiver.h"
25#include "clang/Frontend/CompilerInstance.h"
26#include "clang/Frontend/CompilerInvocation.h"
27#include "clang/Frontend/FrontendActions.h"
28#include "clang/Frontend/FrontendDiagnostic.h"
29#include "clang/Frontend/FrontendPluginRegistry.h"
30#include "clang/Frontend/TextDiagnostic.h"
31#include "clang/Frontend/TextDiagnosticBuffer.h"
32#include "clang/Frontend/TextDiagnosticPrinter.h"
33#include "clang/Lex/Preprocessor.h"
34#include "clang/Parse/ParseAST.h"
35#include "clang/Rewrite/Core/Rewriter.h"
36#include "clang/Rewrite/Frontend/FrontendActions.h"
37#include "clang/Sema/CodeCompleteConsumer.h"
38#include "clang/Sema/Sema.h"
39#include "clang/Sema/SemaConsumer.h"
41#include "llvm/ADT/StringRef.h"
42#include "llvm/ExecutionEngine/ExecutionEngine.h"
43#include "llvm/Support/CrashRecoveryContext.h"
44#include "llvm/Support/Debug.h"
45#include "llvm/Support/Error.h"
46#include "llvm/Support/FileSystem.h"
47#include "llvm/Support/TargetSelect.h"
48#include "llvm/TargetParser/Triple.h"
50#include "llvm/IR/LLVMContext.h"
51#include "llvm/IR/Module.h"
52#include "llvm/Support/DynamicLibrary.h"
53#include "llvm/Support/ErrorHandling.h"
54#include "llvm/Support/MemoryBuffer.h"
55#include "llvm/Support/Signals.h"
56#include "llvm/TargetParser/Host.h"
106using namespace clang;
125 clang::SourceManager &source_mgr)
129 void moduleImport(SourceLocation import_location, clang::ModuleIdPath path,
130 const clang::Module * )
override {
133 llvm::StringRef filename =
134 m_source_mgr.getPresumedLoc(import_location).getFilename();
140 for (
const IdentifierLoc &component : path)
141 module.path.push_back(
142 ConstString(component.getIdentifierInfo()->getName()));
145 if (
auto err =
m_decl_vendor.AddModule(module, &exported_modules)) {
161 for (
auto &fix_it : Info.getFixItHints()) {
174 m_os = std::make_unique<llvm::raw_string_ostream>(
m_output);
176 std::make_unique<clang::TextDiagnosticPrinter>(*
m_os,
m_options);
189 for (
auto it = diags.rbegin(); it != diags.rend(); it++) {
202 const clang::Diagnostic &Info)
override {
211 llvm::SmallVector<char, 32> diag_str;
212 Info.FormatDiagnostic(diag_str);
213 diag_str.push_back(
'\0');
214 const char *plain_diag = diag_str.data();
215 LLDB_LOG(log,
"Received diagnostic outside parsing: {0}", plain_diag);
221 DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
229 case DiagnosticsEngine::Level::Fatal:
230 case DiagnosticsEngine::Level::Error:
233 case DiagnosticsEngine::Level::Warning:
236 case DiagnosticsEngine::Level::Remark:
237 case DiagnosticsEngine::Level::Ignored:
240 case DiagnosticsEngine::Level::Note:
250 if (!clang_diag || clang_diag->HasFixIts())
260 std::string stripped_output =
261 std::string(llvm::StringRef(
m_output).trim());
264 if (Info.hasSourceManager()) {
266 clang::SourceManager &sm = Info.getSourceManager();
267 const clang::SourceLocation sloc = Info.getLocation();
268 if (sloc.isValid()) {
269 const clang::FullSourceLoc fsloc(sloc, sm);
270 clang::PresumedLoc PLoc = fsloc.getPresumedLoc(
true);
272 PLoc.isValid() ? PLoc.getFilename() : StringRef{};
274 loc.
line = fsloc.getSpellingLineNumber();
275 loc.
column = fsloc.getSpellingColumnNumber();
277 loc.
hidden = filename.starts_with(
"<lldb wrapper ");
280 for (
const auto &range : Info.getRanges()) {
281 if (range.getBegin() == sloc) {
283 unsigned end_col = sm.getSpellingColumnNumber(range.getEnd());
292 llvm::SmallString<0> msg;
293 Info.FormatDiagnostic(msg);
296 auto new_diagnostic =
297 std::make_unique<ClangDiagnostic>(detail, Info.getID());
306 m_manager->AddDiagnostic(std::move(new_diagnostic));
321 std::unique_ptr<llvm::raw_string_ostream>
m_os;
327 std::vector<std::string> include_directories,
331 HeaderSearchOptions &search_opts = compiler->getHeaderSearchOpts();
333 for (
const std::string &dir : include_directories) {
334 search_opts.AddPath(dir, frontend::System,
false,
true);
335 LLDB_LOG(log,
"Added user include dir: {0}", dir);
338 llvm::SmallString<128> module_cache;
340 props.GetClangModulesCachePath().GetPath(module_cache);
341 search_opts.ModuleCachePath = std::string(module_cache.str());
342 LLDB_LOG(log,
"Using module cache path: {0}", module_cache.c_str());
346 search_opts.ImplicitModuleMaps =
true;
354 if (token ==
"using")
357 if (token ==
"__null")
360 LangOptions cpp_lang_opts;
361 cpp_lang_opts.CPlusPlus =
true;
362 cpp_lang_opts.CPlusPlus11 =
true;
363 cpp_lang_opts.CPlusPlus20 =
true;
365 clang::IdentifierInfo &ii = idents.get(token);
368 if (!ii.isCPlusPlusKeyword(cpp_lang_opts))
371 if (ii.getTokenID() == clang::tok::identifier)
375 ii.revertTokenIDToIdentifier();
380#define KEYWORD(NAME, FLAGS) RemoveCppKeyword(idents, llvm::StringRef(#NAME));
381#include "clang/Basic/TokenKinds.def"
387 const std::vector<const char *> groupsToIgnore = {
390 "unused-getter-return-value",
392 for (
const char *group : groupsToIgnore) {
393 compiler.getDiagnostics().setSeverityForGroup(
394 clang::diag::Flavor::WarningOrError, group,
395 clang::diag::Severity::Ignored, SourceLocation());
407 if (target_arch.
IsMIPS()) {
420 if (target_arch.
GetTriple().isRISCV64()) {
435 if (target_arch.
GetTriple().isRISCV32()) {
450 if (target_arch.
GetTriple().isLoongArch64()) {
471 const auto target_machine = target_arch.
GetMachine();
473 std::string triple = target_arch.
GetTriple().str();
474 compiler.getTargetOpts().Triple = triple;
475 LLDB_LOGF(log,
"Using %s as the target triple",
476 compiler.getTargetOpts().Triple.c_str());
484 compiler.getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
485 LLDB_LOGF(log,
"Using default target triple of %s",
486 compiler.getTargetOpts().Triple.c_str());
490 if (compiler.getTargetOpts().Triple.find(
"arm64") == std::string::npos &&
491 compiler.getTargetOpts().Triple.find(
"arm") != std::string::npos &&
492 compiler.getTargetOpts().Triple.find(
"ios") != std::string::npos) {
493 compiler.getTargetOpts().ABI =
"apcs-gnu";
496 if (target_machine == llvm::Triple::x86 ||
497 target_machine == llvm::Triple::x86_64) {
498 compiler.getTargetOpts().FeaturesAsWritten.push_back(
"+sse");
499 compiler.getTargetOpts().FeaturesAsWritten.push_back(
"+sse2");
509 compiler.getTargetOpts().ABI = std::move(abi);
511 if ((target_machine == llvm::Triple::riscv64 &&
512 compiler.getTargetOpts().ABI ==
"lp64f") ||
513 (target_machine == llvm::Triple::riscv32 &&
514 compiler.getTargetOpts().ABI ==
"ilp32f"))
515 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+f");
517 if ((target_machine == llvm::Triple::riscv64 &&
518 compiler.getTargetOpts().ABI ==
"lp64d") ||
519 (target_machine == llvm::Triple::riscv32 &&
520 compiler.getTargetOpts().ABI ==
"ilp32d"))
521 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+d");
523 if ((target_machine == llvm::Triple::loongarch64 &&
524 compiler.getTargetOpts().ABI ==
"lp64f"))
525 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+f");
527 if ((target_machine == llvm::Triple::loongarch64 &&
528 compiler.getTargetOpts().ABI ==
"lp64d"))
529 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+d");
549 "Frame has language of type {0}\nPicked {1} for expression evaluation.",
551 frame_sp ? frame_sp->GetLanguage().AsLanguageType()
556 std::string language_fallback_reason;
558 LangOptions &lang_opts = compiler.getLangOpts();
570 lang_opts.CPlusPlus =
true;
573 language_fallback_reason =
574 "Expression evaluation in pure C not supported. ";
577 lang_opts.ObjC =
true;
580 lang_opts.CPlusPlus =
true;
583 language_fallback_reason =
584 "Expression evaluation in pure Objective-C not supported. ";
592 lang_opts.CPlusPlus11 =
true;
595 lang_opts.CPlusPlus20 =
true;
601 lang_opts.CPlusPlus14 =
true;
602 lang_opts.CPlusPlus17 =
true;
607 lang_opts.CPlusPlus11 =
true;
608 compiler.getHeaderSearchOpts().UseLibcxx =
true;
611 lang_opts.CPlusPlus =
true;
615 && !(frame_sp && frame_sp->HasDebugInformation()))
622 lang_opts.ObjC =
true;
623 lang_opts.CPlusPlus =
true;
624 lang_opts.CPlusPlus11 =
true;
625 compiler.getHeaderSearchOpts().UseLibcxx =
true;
628 if (language != language_for_note) {
630 language_fallback_reason = llvm::formatv(
631 "Expression evaluation in {0} not supported. ",
634 language_fallback_reason +=
635 llvm::formatv(
"Falling back to default language. ");
641 llvm::formatv(
"{0}Ran expression as '{1}'.", language_fallback_reason,
647 lang_opts.Bool =
true;
648 lang_opts.WChar =
true;
649 lang_opts.Blocks =
true;
650 lang_opts.DebuggerSupport =
653 lang_opts.DebuggerCastResultToId =
true;
655 lang_opts.CharIsSigned =
661 lang_opts.SpellChecking =
false;
663 if (process_sp && lang_opts.ObjC) {
665 switch (runtime->GetRuntimeVersion()) {
667 lang_opts.ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7));
671 lang_opts.ObjCRuntime.set(ObjCRuntime::FragileMacOSX,
672 VersionTuple(10, 7));
675 lang_opts.ObjCRuntime.set(ObjCRuntime::GNUstep, VersionTuple(2, 0));
679 if (runtime->HasNewLiteralsAndIndexing())
680 lang_opts.DebuggerObjCLiteral =
true;
684 lang_opts.ThreadsafeStatics =
false;
685 lang_opts.AccessControl =
false;
686 lang_opts.DollarIdents =
true;
690 lang_opts.NoBuiltin =
true;
695 LangOptions &lang_opts = compiler.getLangOpts();
696 lang_opts.Modules =
true;
698 lang_opts.ImplicitModules =
true;
700 lang_opts.ModulesLocalVisibility =
false;
704 lang_opts.ObjC =
true;
708 lang_opts.GNUMode =
true;
709 lang_opts.GNUKeywords =
true;
710 lang_opts.CPlusPlus11 =
true;
712 lang_opts.BuiltinHeadersInSystemModules =
false;
715 lang_opts.GNUCVersion = 40201;
725 std::vector<std::string> include_directories, std::string filename)
741 "Can't make an expression parser with a null scope.");
749 "Can't make an expression parser with a null target.");
754 m_compiler = std::make_unique<CompilerInstance>();
768 m_compiler->getDiagnostics().setErrorLimit(target_sp->GetExprErrorLimit());
770 if (
auto *target_info = TargetInfo::CreateTargetInfo(
772 m_compiler->getInvocation().getTargetOpts())) {
774 LLDB_LOGF(log,
"Target datalayout string: '%s'",
775 target_info->getDataLayoutString());
776 LLDB_LOGF(log,
"Target ABI: '%s'", target_info->getABI().str().c_str());
777 LLDB_LOGF(log,
"Target vector alignment: %d",
778 target_info->getMaxVectorAlign());
783 LLDB_LOGF(log,
"Failed to create TargetInfo for '%s'",
786 lldbassert(
false &&
"Failed to create TargetInfo.");
791 auto *clang_expr = dyn_cast<ClangUserExpression>(&
m_expr);
792 if (clang_expr && clang_expr->DidImportCxxModules()) {
793 LLDB_LOG(log,
"Adding lang options for importing C++ modules");
799 m_compiler->getCodeGenOpts().EmitDeclMetadata =
true;
800 m_compiler->getCodeGenOpts().InstrumentFunctions =
false;
802 CodeGenOptions::FramePointerKind::All);
803 if (generate_debug_info)
804 m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
806 m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::NoDebugInfo);
821 m_compiler->getDiagnostics().getDiagnosticOptions(),
822 clang_expr ? clang_expr->GetFilename() : StringRef());
823 m_compiler->getDiagnostics().setClient(diag_mgr);
846 if (
auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(
847 target_sp->GetPersistentExpressionStateForLanguage(
849 if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
850 clang_persistent_vars->GetClangModulesDeclVendor()) {
851 std::unique_ptr<PPCallbacks> pp_callbacks(
856 m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
864 auto &builtin_context = PP.getBuiltinInfo();
865 builtin_context.initializeBuiltins(PP.getIdentifierTable(),
869 clang::ASTContext &ast_context =
m_compiler->getASTContext();
872 "Expression ASTContext for '" +
m_filename +
"'", ast_context);
874 std::string module_name(
"$__lldb_module");
893class CodeComplete :
public CodeCompleteConsumer {
894 CodeCompletionTUInfo m_info;
897 unsigned m_position = 0;
900 clang::PrintingPolicy m_desc_policy;
902 struct CompletionWithPriority {
910 bool operator<(
const CompletionWithPriority &o)
const {
912 if (Priority != o.Priority)
913 return Priority > o.Priority;
916 return completion.
GetUniqueKey() < o.completion.GetUniqueKey();
923 std::vector<CompletionWithPriority> m_completions;
930 static bool IsIdChar(
char c) {
931 return c ==
'_' || std::isalnum(c) || c ==
'$';
936 static bool IsTokenSeparator(
char c) {
return c ==
' ' || c ==
'\t'; }
941 StringRef dropUnrelatedFrontTokens(StringRef cmd)
const {
947 if (IsTokenSeparator(cmd.back()))
952 StringRef to_remove = cmd;
953 while (!to_remove.empty() && !IsTokenSeparator(to_remove.back())) {
954 to_remove = to_remove.drop_back();
956 cmd = cmd.drop_front(to_remove.size());
962 StringRef removeLastToken(StringRef cmd)
const {
963 while (!cmd.empty() && IsIdChar(cmd.back())) {
964 cmd = cmd.drop_back();
972 std::string mergeCompletion(StringRef existing,
unsigned pos,
973 StringRef completion)
const {
974 StringRef existing_command = existing.substr(0, pos);
977 existing_command = removeLastToken(existing_command);
981 existing_command = dropUnrelatedFrontTokens(existing_command);
982 return existing_command.str() + completion.str();
995 CodeComplete(clang::LangOptions ops, std::string expr,
unsigned position)
996 : CodeCompleteConsumer(CodeCompleteOptions()),
997 m_info(std::make_shared<GlobalCodeCompletionAllocator>()), m_expr(expr),
998 m_position(position), m_desc_policy(ops) {
1002 m_desc_policy.SuppressScope =
true;
1003 m_desc_policy.SuppressTagKeyword =
true;
1004 m_desc_policy.FullyQualifiedName =
false;
1005 m_desc_policy.TerseOutput =
true;
1006 m_desc_policy.IncludeNewlines =
false;
1007 m_desc_policy.UseVoidForZeroParams =
false;
1008 m_desc_policy.Bool =
true;
1013 bool isResultFilteredOut(StringRef Filter,
1014 CodeCompletionResult Result)
override {
1016 switch (Result.Kind) {
1017 case CodeCompletionResult::RK_Declaration:
1019 Result.Declaration->getIdentifier() &&
1020 Result.Declaration->getIdentifier()->getName().starts_with(Filter));
1021 case CodeCompletionResult::RK_Keyword:
1022 return !StringRef(Result.Keyword).starts_with(Filter);
1023 case CodeCompletionResult::RK_Macro:
1024 return !Result.Macro->getName().starts_with(Filter);
1025 case CodeCompletionResult::RK_Pattern:
1026 return !StringRef(Result.Pattern->getAsString()).starts_with(Filter);
1031 assert(
false &&
"Unknown completion result type?");
1046 std::optional<CompletionWithPriority>
1047 getCompletionForResult(
const CodeCompletionResult &R)
const {
1048 std::string ToInsert;
1049 std::string Description;
1052 case CodeCompletionResult::RK_Declaration: {
1053 const NamedDecl *D = R.Declaration;
1054 ToInsert = R.Declaration->getNameAsString();
1058 if (
const FunctionDecl *F = dyn_cast<FunctionDecl>(D)) {
1059 if (F->getNumParams() == 0)
1063 raw_string_ostream
OS(Description);
1064 F->print(
OS, m_desc_policy,
false);
1065 }
else if (
const VarDecl *V = dyn_cast<VarDecl>(D)) {
1066 Description = V->getType().getAsString(m_desc_policy);
1067 }
else if (
const FieldDecl *F = dyn_cast<FieldDecl>(D)) {
1068 Description = F->getType().getAsString(m_desc_policy);
1069 }
else if (
const NamespaceDecl *N = dyn_cast<NamespaceDecl>(D)) {
1072 if (!N->isAnonymousNamespace())
1077 case CodeCompletionResult::RK_Keyword:
1078 ToInsert = R.Keyword;
1080 case CodeCompletionResult::RK_Macro:
1081 ToInsert = R.Macro->getName().str();
1083 case CodeCompletionResult::RK_Pattern:
1084 ToInsert = R.Pattern->getTypedText();
1089 if (llvm::StringRef(ToInsert).starts_with(
"$__lldb_"))
1090 return std::nullopt;
1091 if (ToInsert.empty())
1092 return std::nullopt;
1095 std::string CompletionSuggestion =
1096 mergeCompletion(m_expr, m_position, ToInsert);
1098 CompletionResult::Completion completion(CompletionSuggestion, Description,
1099 CompletionMode::Normal);
1100 return {{completion, R.Priority}};
1105 void GetCompletions(CompletionRequest &request) {
1108 llvm::sort(m_completions);
1110 for (
const CompletionWithPriority &C : m_completions)
1112 C.completion.GetDescription(),
1113 C.completion.GetMode());
1118 void ProcessCodeCompleteResults(Sema &SemaRef, CodeCompletionContext Context,
1119 CodeCompletionResult *Results,
1120 unsigned NumResults)
override {
1124 StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();
1128 for (
unsigned I = 0; I != NumResults; ++I) {
1130 if (!Filter.empty() && isResultFilteredOut(Filter, Results[I]))
1133 CodeCompletionResult &R = Results[I];
1134 std::optional<CompletionWithPriority> CompletionAndPriority =
1135 getCompletionForResult(R);
1136 if (!CompletionAndPriority)
1138 m_completions.push_back(*CompletionAndPriority);
1150 void ProcessOverloadCandidates(Sema &S,
unsigned CurrentArg,
1151 OverloadCandidate *Candidates,
1152 unsigned NumCandidates,
1153 SourceLocation OpenParLoc,
1154 bool Braced)
override {
1158 CodeCompletionAllocator &getAllocator()
override {
1159 return m_info.getAllocator();
1162 CodeCompletionTUInfo &getCodeCompletionTUInfo()
override {
return m_info; }
1167 unsigned pos,
unsigned typed_pos) {
1182 CC.GetCompletions(request);
1192 CodeCompleteConsumer *completion_consumer,
1193 unsigned completion_line,
1194 unsigned completion_column) {
1201 const char *expr_text =
m_expr.Text();
1203 clang::SourceManager &source_mgr =
m_compiler->getSourceManager();
1204 bool created_main_file =
false;
1210 bool should_create_file = completion_consumer !=
nullptr;
1213 should_create_file |=
m_compiler->getCodeGenOpts().getDebugInfo() ==
1214 codegenoptions::FullDebugInfo;
1216 if (should_create_file) {
1218 llvm::SmallString<128> result_path;
1219 if (
FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
1220 tmpdir_file_spec.AppendPathComponent(
"lldb-%%%%%%.expr");
1221 std::string temp_source_path = tmpdir_file_spec.GetPath();
1222 llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path);
1224 llvm::sys::fs::createTemporaryFile(
"lldb",
"expr", temp_fd, result_path);
1227 if (temp_fd != -1) {
1229 const size_t expr_text_len = strlen(expr_text);
1230 size_t bytes_written = expr_text_len;
1232 if (bytes_written == expr_text_len) {
1234 if (
auto fileEntry =
m_compiler->getFileManager().getOptionalFileRef(
1236 source_mgr.setMainFileID(source_mgr.createFileID(
1237 *fileEntry, SourceLocation(), SrcMgr::C_User));
1238 created_main_file =
true;
1245 if (!created_main_file) {
1246 std::unique_ptr<MemoryBuffer> memory_buffer =
1247 MemoryBuffer::getMemBufferCopy(expr_text,
m_filename);
1248 source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer)));
1255 dyn_cast<ClangExpressionHelper>(
m_expr.GetTypeSystemHelper());
1261 if (completion_consumer) {
1263 source_mgr.getFileEntryRefForID(source_mgr.getMainFileID());
1268 ++completion_column;
1269 PP.SetCodeCompletionPoint(*main_file, completion_line, completion_column);
1272 ASTConsumer *ast_transformer =
1275 std::unique_ptr<clang::ASTConsumer> Consumer;
1276 if (ast_transformer) {
1277 Consumer = std::make_unique<ASTConsumerForwarder>(ast_transformer);
1281 Consumer = std::make_unique<ASTConsumer>();
1284 clang::ASTContext &ast_context =
m_compiler->getASTContext();
1287 *Consumer, TU_Complete, completion_consumer));
1288 m_compiler->setASTConsumer(std::move(Consumer));
1290 if (ast_context.getLangOpts().Modules) {
1300 llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source =
1303 auto ast_source_wrapper =
1304 llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(ast_source);
1306 if (ast_context.getExternalSource()) {
1307 auto module_wrapper = llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(
1308 ast_context.getExternalSourcePtr());
1310 auto multiplexer = llvm::makeIntrusiveRefCnt<SemaSourceWithPriorities>(
1311 module_wrapper, ast_source_wrapper);
1313 ast_context.setExternalSource(multiplexer);
1315 ast_context.setExternalSource(ast_source);
1317 m_compiler->getSema().addExternalSource(ast_source_wrapper);
1322 if (ast_context.getLangOpts().Modules) {
1323 assert(
m_compiler->getASTContext().getExternalSource() &&
1324 "ASTContext doesn't know about the ASTReader?");
1325 assert(
m_compiler->getSema().getExternalSource() &&
1326 "Sema doesn't know about the ASTReader?");
1330 llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(
1332 ParseAST(
m_compiler->getSema(),
false,
false);
1336 if (ast_context.getLangOpts().Modules)
1348 unsigned num_errors = adapter->getNumErrors();
1353 "while importing modules:");
1366static void ApplyFixIt(
const FixItHint &fixit, clang::edit::Commit &commit) {
1368 if (fixit.CodeToInsert.empty()) {
1369 if (fixit.InsertFromRange.isValid()) {
1370 commit.insertFromRange(fixit.RemoveRange.getBegin(),
1371 fixit.InsertFromRange,
false,
1372 fixit.BeforePreviousInsertions);
1375 commit.remove(fixit.RemoveRange);
1378 if (fixit.RemoveRange.isTokenRange() ||
1379 fixit.RemoveRange.getBegin() != fixit.RemoveRange.getEnd()) {
1380 commit.replace(fixit.RemoveRange, fixit.CodeToInsert);
1383 commit.insert(fixit.RemoveRange.getBegin(), fixit.CodeToInsert,
1384 false, fixit.BeforePreviousInsertions);
1389 clang::SourceManager &source_manager =
m_compiler->getSourceManager();
1390 clang::edit::EditedSource editor(source_manager,
m_compiler->getLangOpts(),
1392 clang::edit::Commit commit(editor);
1393 clang::Rewriter rewriter(source_manager,
m_compiler->getLangOpts());
1395 class RewritesReceiver :
public edit::EditsReceiver {
1399 RewritesReceiver(Rewriter &in_rewrite) : rewrite(in_rewrite) {}
1401 void insert(SourceLocation loc, StringRef text)
override {
1402 rewrite.InsertText(loc, text);
1404 void replace(CharSourceRange range, StringRef text)
override {
1405 rewrite.ReplaceText(range.getBegin(), rewrite.getRangeSize(range), text);
1409 RewritesReceiver rewrites_receiver(rewriter);
1412 size_t num_diags = diagnostics.size();
1416 for (
const auto &diag : diagnostic_manager.
Diagnostics()) {
1417 const auto *diagnostic = llvm::dyn_cast<ClangDiagnostic>(diag.get());
1420 if (!diagnostic->HasFixIts())
1422 for (
const FixItHint &fixit : diagnostic->FixIts())
1427 if (!commit.isCommitable())
1429 else if (!editor.commit(commit))
1433 editor.applyRewrites(rewrites_receiver);
1434 RewriteBuffer &main_file_buffer =
1435 rewriter.getEditBuffer(source_manager.getMainFileID());
1437 std::string fixed_expression;
1438 llvm::raw_string_ostream out_stream(fixed_expression);
1440 main_file_buffer.write(out_stream);
1447 llvm::Module *module,
const char *orig_name) {
1448 for (
const auto &func : module->getFunctionList()) {
1449 const StringRef &name = func.getName();
1450 if (name.contains(orig_name)) {
1469 std::unique_ptr<llvm::Module> llvm_module_up(
1472 if (!llvm_module_up) {
1483 m_expr.FunctionName())) {
1485 "Couldn't find %s() in the module",
m_expr.FunctionName());
1496 sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything);
1503 auto lang =
m_expr.Language();
1504 LLDB_LOGF(log,
"%s - Current expression language is %s\n", __FUNCTION__,
1505 lang.GetDescription().data());
1507 if (process_sp && lang) {
1508 auto runtime = process_sp->GetLanguageRuntime(lang.AsLanguageType());
1510 runtime->GetIRPasses(custom_passes);
1516 "%s - Running Early IR Passes from LanguageRuntime on "
1517 "expression module '%s'",
1518 __FUNCTION__,
m_expr.FunctionName());
1523 execution_unit_sp = std::make_shared<IRExecutionUnit>(
1529 if (
auto *options =
m_expr.GetOptions())
1530 execution_unit_sp->AppendPreferredSymbolContexts(
1531 options->GetPreferredSymbolContexts());
1534 dyn_cast<ClangExpressionHelper>(
m_expr.GetTypeSystemHelper());
1536 type_system_helper->
DeclMap();
1541 *execution_unit_sp, error_stream,
1544 if (!ir_for_target.
runOnModule(*execution_unit_sp->GetModule())) {
1555 bool interpret_function_calls =
1558 *execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(),
1559 interpret_error, interpret_function_calls);
1563 "Can't evaluate the expression without a running target due to: %s",
1571 "Expression needed to run in the target, but the "
1572 "target can't be run");
1578 "Top-level code needs to be inserted into a runnable "
1579 "target, but the target can't be run");
1585 if (
m_expr.NeedsValidation() && process) {
1591 if (Error Err = dynamic_checkers->
Install(install_diags, exe_ctx))
1597 LLDB_LOGF(log,
"== [ClangExpressionParser::PrepareForExecution] "
1598 "Finished installing dynamic checkers ==");
1601 if (
auto *checker_funcs = llvm::dyn_cast<ClangDynamicCheckerFunctions>(
1606 llvm::Module *module = execution_unit_sp->GetModule();
1607 if (!module || !ir_dynamic_checks.
runOnModule(*module)) {
1609 "Couldn't add dynamic checks to the expression");
1615 "%s - Running Late IR Passes from LanguageRuntime on "
1616 "expression module '%s'",
1617 __FUNCTION__,
m_expr.FunctionName());
1627 execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
1630 execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
static void SetupModuleHeaderPaths(CompilerInstance *compiler, std::vector< std::string > include_directories, lldb::TargetSP target_sp)
static void RemoveAllCppKeywords(IdentifierTable &idents)
Remove all C++ keywords from the given identifier table.
static void SetupLangOpts(CompilerInstance &compiler, ExecutionContextScope &exe_scope, const Expression &expr, DiagnosticManager &diagnostic_manager)
static void ApplyFixIt(const FixItHint &fixit, clang::edit::Commit &commit)
Applies the given Fix-It hint to the given commit.
static void SetupImportStdModuleLangOpts(CompilerInstance &compiler, lldb_private::Target &target)
static void AddAllFixIts(ClangDiagnostic *diag, const clang::Diagnostic &Info)
static void SetupDefaultClangDiagnostics(CompilerInstance &compiler)
Configures Clang diagnostics for the expression parser.
static void SetupTargetOpts(CompilerInstance &compiler, lldb_private::Target const &target)
static void RemoveCppKeyword(IdentifierTable &idents, llvm::StringRef token)
Iff the given identifier is a C++ keyword, remove it from the identifier table (i....
static bool FindFunctionInModule(ConstString &mangled_name, llvm::Module *module, const char *orig_name)
static std::string GetClangTargetABI(const ArchSpec &target_arch)
Returns a string representing current ABI.
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
#define LLDB_LOGF(log,...)
void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override
std::unique_ptr< clang::TextDiagnosticPrinter > m_passthrough
DiagnosticOptions m_options
void EndSourceFile() override
std::string m_output
Output string filled by m_os.
ClangDiagnosticManagerAdapter(DiagnosticOptions &opts, StringRef filename)
void ResetManager(DiagnosticManager *manager=nullptr)
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) override
ClangDiagnostic * MaybeGetLastClangDiag() const
Returns the last error ClangDiagnostic message that the DiagnosticManager received or a nullptr.
std::unique_ptr< llvm::raw_string_ostream > m_os
Output stream of m_passthrough.
DiagnosticManager * m_manager
llvm::StringRef getErrorString()
ClangModulesDeclVendor & m_decl_vendor
void moduleImport(SourceLocation import_location, clang::ModuleIdPath path, const clang::Module *) override
clang::SourceManager & m_source_mgr
ClangPersistentVariables & m_persistent_vars
LLDBPreprocessorCallbacks(ClangModulesDeclVendor &decl_vendor, ClangPersistentVariables &persistent_vars, clang::SourceManager &source_mgr)
StreamString m_error_stream
Accumulates error messages across all moduleImport calls.
Transforms the IR for a function to run in the target.
bool runOnModule(llvm::Module &llvm_module)
Run this IR transformer on a single module.
static bool CanInterpret(llvm::Module &module, llvm::Function &function, lldb_private::Status &error, const bool support_function_calls)
An architecture specification class.
bool IsValid() const
Tests if this ArchSpec is valid.
llvm::Triple & GetTriple()
Architecture triple accessor.
@ eLoongArch_abi_single_float
soft float
@ eLoongArch_abi_soft_float
@ eLoongArch_abi_mask
double precision floating point, +d
@ eLoongArch_abi_double_float
single precision floating point, +f
bool IsMIPS() const
if MIPS architecture return true.
bool CharIsSignedByDefault() const
Returns true if 'char' is a signed type by default in the architecture false otherwise.
uint32_t GetFlags() const
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
@ eRISCV_float_abi_double
single precision floating point, +f
@ eRISCV_float_abi_soft
RVC, +c.
@ eRISCV_float_abi_quad
double precision floating point, +d
@ eRISCV_float_abi_mask
quad precision floating point, +q
@ eRISCV_float_abi_single
soft float
std::string GetClangTargetCPU() const
Returns a string representing current architecture as a target CPU for tools like compiler,...
llvm::IntrusiveRefCntPtr< clang::ExternalASTSource > CreateProxy()
void InstallASTContext(TypeSystemClang &ast_context)
void AddFixitHint(const clang::FixItHint &fixit)
llvm::Error Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) override
Install the utility functions into a process.
"lldb/Expression/ClangExpressionDeclMap.h" Manages named entities that are defined in LLDB's debug in...
void InstallDiagnosticManager(DiagnosticManager &diag_manager)
void InstallCodeGenerator(clang::ASTConsumer *code_gen)
virtual void CommitPersistentDecls()
virtual clang::ASTConsumer * ASTTransformer(clang::ASTConsumer *passthrough)=0
Return the object that the parser should allow to access ASTs.
virtual ClangExpressionDeclMap * DeclMap()=0
Return the object that the parser should use when resolving external values.
std::string m_filename
File name used for the user expression.
bool RewriteExpression(DiagnosticManager &diagnostic_manager) override
Try to use the FixIts in the diagnostic_manager to rewrite the expression.
unsigned ParseInternal(DiagnosticManager &diagnostic_manager, clang::CodeCompleteConsumer *completion=nullptr, unsigned completion_line=0, unsigned completion_column=0)
Parses the expression.
ClangExpressionParser(ExecutionContextScope *exe_scope, Expression &expr, bool generate_debug_info, DiagnosticManager &diagnostic_manager, std::vector< std::string > include_directories={}, std::string filename="<clang expression>")
Constructor.
std::unique_ptr< clang::CompilerInstance > m_compiler
The Clang compiler used to parse expressions into IR.
Status DoPrepareForExecution(lldb::addr_t &func_addr, lldb::addr_t &func_end, lldb::IRExecutionUnitSP &execution_unit_sp, ExecutionContext &exe_ctx, bool &can_interpret, lldb_private::ExecutionPolicy execution_policy) override
Ready an already-parsed expression for execution, possibly evaluating it statically.
unsigned Parse(DiagnosticManager &diagnostic_manager)
Parse a single expression and convert it to IR using Clang.
bool Complete(CompletionRequest &request, unsigned line, unsigned pos, unsigned typed_pos) override
Attempts to find possible command line completions for the given expression.
~ClangExpressionParser() override
Destructor.
std::unique_ptr< llvm::LLVMContext > m_llvm_context
The LLVM context to generate IR into.
std::unique_ptr< clang::CodeGenerator > m_code_generator
The Clang object that generates IR.
LLDBPreprocessorCallbacks * m_pp_callbacks
Called when the preprocessor encounters module imports.
std::vector< std::string > m_include_directories
std::shared_ptr< TypeSystemClang > m_ast_context
static const llvm::StringRef g_prefix_file_name
The file name we use for the wrapper code that we inject before the user expression.
std::vector< ModuleID > ModuleVector
"lldb/Expression/ClangPersistentVariables.h" Manages persistent values that need to be preserved betw...
"lldb/Expression/ClangUserExpression.h" Encapsulates a single expression for use with Clang
"lldb/Utility/ArgCompletionRequest.h"
void AddCompletion(llvm::StringRef completion, llvm::StringRef description="", CompletionMode mode=CompletionMode::Normal)
Adds a possible completion string.
A single completion and all associated data.
std::string GetUniqueKey() const
Generates a string that uniquely identifies this completion result.
A uniqued constant string class.
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
void SetString(llvm::StringRef s)
size_t void PutString(lldb::Severity severity, llvm::StringRef str)
const DiagnosticList & Diagnostics() const
llvm::Error GetAsError(lldb::ExpressionResults result, llvm::Twine message={}) const
Returns an ExpressionError with arg as error code.
void SetFixedExpression(std::string fixed_expression)
void AppendMessageToDiagnostic(llvm::StringRef str)
void AddDiagnostic(llvm::StringRef message, lldb::Severity severity, DiagnosticOrigin origin, uint32_t compiler_id=LLDB_INVALID_COMPILER_ID)
"lldb/Target/ExecutionContextScope.h" Inherit from this if your object can reconstruct its execution ...
virtual lldb::StackFrameSP CalculateStackFrame()=0
virtual lldb::ProcessSP CalculateProcess()=0
virtual lldb::TargetSP CalculateTarget()=0
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
const lldb::TargetSP & GetTargetSP() const
Get accessor to get the target shared pointer.
const lldb::ProcessSP & GetProcessSP() const
Get accessor to get the process shared pointer.
const lldb::StackFrameSP & GetFrameSP() const
Get accessor to get the frame shared pointer.
Process * GetProcessPtr() const
Returns a pointer to the process object.
ExpressionParser(ExecutionContextScope *exe_scope, Expression &expr, bool generate_debug_info)
Constructor.
Expression & m_expr
The expression to be parsed.
Encapsulates a single expression for use in lldb.
virtual SourceLanguage Language() const
Return the language that should be used when parsing.
virtual ResultType DesiredResultType() const
Return the desired result type of the function, or eResultTypeAny if indifferent.
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
static FileSystem & Instance()
"lldb/Expression/IRDynamicChecks.h" Adds dynamic checks to a user-entered expression to reduce its li...
bool runOnModule(llvm::Module &M) override
Run this IR transformer on a single module.
static const char * GetNameForLanguageType(lldb::LanguageType language)
Returns the internal LLDB name for the specified language.
static llvm::StringRef GetDisplayNameForLanguageType(lldb::LanguageType language)
Returns a user-friendly name for the specified language.
static ModuleListProperties & GetGlobalModuleListProperties()
Status Close() override
Flush any buffers and release any resources owned by the file.
Status Write(const void *buf, size_t &num_bytes) override
Write bytes from buf to a file at the current file position.
static ObjCLanguageRuntime * Get(Process &process)
A plug-in interface definition class for debugging a process.
void SetDynamicCheckers(DynamicCheckerFunctions *dynamic_checkers)
DynamicCheckerFunctions * GetDynamicCheckers()
bool CanInterpretFunctionCalls()
Determines whether executing function calls using the interpreter is possible for this process.
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
static Status FromErrorString(const char *str)
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
bool Success() const
Test for success condition.
llvm::StringRef GetString() const
Defines a symbol context baton that can be handed other debug core functions.
lldb::TargetSP target_sp
The Target for a given query.
const ArchSpec & GetArchitecture() const
const char * GetUserText()
Return the string that the user typed.
#define LLDB_INVALID_ADDRESS
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
FileSpec GetClangResourceDir()
ExecutionPolicy
Expression execution policies.
@ eExecutionPolicyTopLevel
std::vector< std::unique_ptr< Diagnostic > > DiagnosticList
bool operator<(const Address &lhs, const Address &rhs)
std::shared_ptr< lldb_private::IRExecutionUnit > IRExecutionUnitSP
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
LanguageType
Programming language type.
@ eLanguageTypeC_plus_plus_20
ISO C++:2020.
@ eLanguageTypeC_plus_plus_14
ISO C++:2014.
@ eLanguageTypeC11
ISO C:2011.
@ eLanguageTypeC99
ISO C:1999.
@ eLanguageTypeC_plus_plus_03
ISO C++:2003.
@ eLanguageTypeUnknown
Unknown or invalid language value.
@ eLanguageTypeC_plus_plus_17
ISO C++:2017.
@ eLanguageTypeObjC_plus_plus
Objective-C++.
@ eLanguageTypeC_plus_plus_11
ISO C++:2011.
@ eLanguageTypeC89
ISO C:1989.
@ eLanguageTypeC
Non-standardized C, such as K&R.
@ eLanguageTypeObjC
Objective-C.
@ eLanguageTypeC_plus_plus
ISO C++:1998.
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::Target > TargetSP
A source location consisting of a file name and position.
unsigned line
1 in the example above.
bool in_user_input
Whether this source location refers to something the user typed as part of the command,...
FileSpec file
"<user expression 0>" in the example above.
uint16_t length
3 in the example above.
uint16_t column
5 in the example above.
bool hidden
Whether this source location should be surfaced to the user.
A compiler-independent representation of an lldb_private::Diagnostic.
std::optional< SourceLocation > source_location
Contains this diagnostic's source location, if applicable.
lldb::Severity severity
Contains eSeverityError in the example above.
std::string rendered
Contains the fully rendered error message, without "error: ", but including the source context.
std::string message
Contains "use of undeclared identifier 'foo'" in the example above.
std::shared_ptr< llvm::legacy::PassManager > EarlyPasses
std::shared_ptr< llvm::legacy::PassManager > LatePasses
lldb::LanguageType AsLanguageType() const
Information needed to import a source-language module.