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/DiagnosticFrontend.h"
16#include "clang/Basic/DiagnosticIDs.h"
17#include "clang/Basic/IdentifierTable.h"
18#include "clang/Basic/SourceLocation.h"
19#include "clang/Basic/TargetInfo.h"
20#include "clang/Basic/Version.h"
21#include "clang/CodeGen/CodeGenAction.h"
22#include "clang/CodeGen/ModuleBuilder.h"
23#include "clang/Edit/Commit.h"
24#include "clang/Edit/EditedSource.h"
25#include "clang/Edit/EditsReceiver.h"
26#include "clang/Frontend/CompilerInstance.h"
27#include "clang/Frontend/CompilerInvocation.h"
28#include "clang/Frontend/FrontendActions.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())) {
618 if (lang_opts.ObjC) {
620 language_fallback_reason =
"Possibly stopped inside system library, so "
621 "speculatively enabled Objective-C. ";
628 lang_opts.ObjC =
true;
629 lang_opts.CPlusPlus =
true;
630 lang_opts.CPlusPlus11 =
true;
631 compiler.getHeaderSearchOpts().UseLibcxx =
true;
634 if (language != language_for_note) {
636 language_fallback_reason = llvm::formatv(
637 "Expression evaluation in {0} not supported. ",
640 language_fallback_reason +=
641 llvm::formatv(
"Falling back to default language. ");
647 llvm::formatv(
"{0}Ran expression as '{1}'.", language_fallback_reason,
653 lang_opts.Bool =
true;
654 lang_opts.WChar =
true;
655 lang_opts.Blocks =
true;
656 lang_opts.DebuggerSupport =
659 lang_opts.DebuggerCastResultToId =
true;
661 lang_opts.CharIsSigned =
667 lang_opts.SpellChecking =
false;
669 if (process_sp && lang_opts.ObjC) {
671 switch (runtime->GetRuntimeVersion()) {
673 lang_opts.ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7));
677 lang_opts.ObjCRuntime.set(ObjCRuntime::FragileMacOSX,
678 VersionTuple(10, 7));
681 lang_opts.ObjCRuntime.set(ObjCRuntime::GNUstep, VersionTuple(2, 0));
685 if (runtime->HasNewLiteralsAndIndexing())
686 lang_opts.DebuggerObjCLiteral =
true;
690 lang_opts.ThreadsafeStatics =
false;
691 lang_opts.AccessControl =
false;
692 lang_opts.DollarIdents =
true;
696 lang_opts.NoBuiltin =
true;
701 LangOptions &lang_opts = compiler.getLangOpts();
702 lang_opts.Modules =
true;
704 lang_opts.ImplicitModules =
true;
706 lang_opts.ModulesLocalVisibility =
false;
710 lang_opts.ObjC =
true;
714 lang_opts.GNUMode =
true;
715 lang_opts.GNUKeywords =
true;
716 lang_opts.CPlusPlus11 =
true;
718 lang_opts.BuiltinHeadersInSystemModules =
false;
721 lang_opts.GNUCVersion = 40201;
731 std::vector<std::string> include_directories, std::string filename)
747 "Can't make an expression parser with a null scope.");
755 "Can't make an expression parser with a null target.");
760 m_compiler = std::make_unique<CompilerInstance>();
774 m_compiler->getDiagnostics().setErrorLimit(target_sp->GetExprErrorLimit());
776 if (
auto *target_info = TargetInfo::CreateTargetInfo(
778 m_compiler->getInvocation().getTargetOpts())) {
780 LLDB_LOGF(log,
"Target datalayout string: '%s'",
781 target_info->getDataLayoutString());
782 LLDB_LOGF(log,
"Target ABI: '%s'", target_info->getABI().str().c_str());
783 LLDB_LOGF(log,
"Target vector alignment: %d",
784 target_info->getMaxVectorAlign());
789 LLDB_LOGF(log,
"Failed to create TargetInfo for '%s'",
792 lldbassert(
false &&
"Failed to create TargetInfo.");
797 auto *clang_expr = dyn_cast<ClangUserExpression>(&
m_expr);
798 if (clang_expr && clang_expr->DidImportCxxModules()) {
799 LLDB_LOG(log,
"Adding lang options for importing C++ modules");
805 m_compiler->getCodeGenOpts().EmitDeclMetadata =
true;
806 m_compiler->getCodeGenOpts().InstrumentFunctions =
false;
808 CodeGenOptions::FramePointerKind::All);
809 if (generate_debug_info)
810 m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
812 m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::NoDebugInfo);
827 m_compiler->getDiagnostics().getDiagnosticOptions(),
828 clang_expr ? clang_expr->GetFilename() : StringRef());
829 m_compiler->getDiagnostics().setClient(diag_mgr);
852 if (
auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(
853 target_sp->GetPersistentExpressionStateForLanguage(
855 if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
856 clang_persistent_vars->GetClangModulesDeclVendor()) {
857 std::unique_ptr<PPCallbacks> pp_callbacks(
862 m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
870 auto &builtin_context = PP.getBuiltinInfo();
871 builtin_context.initializeBuiltins(PP.getIdentifierTable(),
875 clang::ASTContext &ast_context =
m_compiler->getASTContext();
878 "Expression ASTContext for '" +
m_filename +
"'", ast_context);
880 std::string module_name(
"$__lldb_module");
899class CodeComplete :
public CodeCompleteConsumer {
900 CodeCompletionTUInfo m_info;
903 unsigned m_position = 0;
906 clang::PrintingPolicy m_desc_policy;
908 struct CompletionWithPriority {
916 bool operator<(
const CompletionWithPriority &o)
const {
918 if (Priority != o.Priority)
919 return Priority > o.Priority;
922 return completion.
GetUniqueKey() < o.completion.GetUniqueKey();
929 std::vector<CompletionWithPriority> m_completions;
936 static bool IsIdChar(
char c) {
937 return c ==
'_' || std::isalnum(c) || c ==
'$';
942 static bool IsTokenSeparator(
char c) {
return c ==
' ' || c ==
'\t'; }
947 StringRef dropUnrelatedFrontTokens(StringRef cmd)
const {
953 if (IsTokenSeparator(cmd.back()))
958 StringRef to_remove = cmd;
959 while (!to_remove.empty() && !IsTokenSeparator(to_remove.back())) {
960 to_remove = to_remove.drop_back();
962 cmd = cmd.drop_front(to_remove.size());
968 StringRef removeLastToken(StringRef cmd)
const {
969 while (!cmd.empty() && IsIdChar(cmd.back())) {
970 cmd = cmd.drop_back();
978 std::string mergeCompletion(StringRef existing,
unsigned pos,
979 StringRef completion)
const {
980 StringRef existing_command = existing.substr(0, pos);
983 existing_command = removeLastToken(existing_command);
987 existing_command = dropUnrelatedFrontTokens(existing_command);
988 return existing_command.str() + completion.str();
1001 CodeComplete(clang::LangOptions ops, std::string expr,
unsigned position)
1002 : CodeCompleteConsumer(CodeCompleteOptions()),
1003 m_info(std::make_shared<GlobalCodeCompletionAllocator>()), m_expr(expr),
1004 m_position(position), m_desc_policy(ops) {
1008 m_desc_policy.SuppressScope =
true;
1009 m_desc_policy.SuppressTagKeyword =
true;
1010 m_desc_policy.FullyQualifiedName =
false;
1011 m_desc_policy.TerseOutput =
true;
1012 m_desc_policy.IncludeNewlines =
false;
1013 m_desc_policy.UseVoidForZeroParams =
false;
1014 m_desc_policy.Bool =
true;
1019 bool isResultFilteredOut(StringRef Filter,
1020 CodeCompletionResult Result)
override {
1022 switch (Result.Kind) {
1023 case CodeCompletionResult::RK_Declaration:
1025 Result.Declaration->getIdentifier() &&
1026 Result.Declaration->getIdentifier()->getName().starts_with(Filter));
1027 case CodeCompletionResult::RK_Keyword:
1028 return !StringRef(Result.Keyword).starts_with(Filter);
1029 case CodeCompletionResult::RK_Macro:
1030 return !Result.Macro->getName().starts_with(Filter);
1031 case CodeCompletionResult::RK_Pattern:
1032 return !StringRef(Result.Pattern->getAsString()).starts_with(Filter);
1037 assert(
false &&
"Unknown completion result type?");
1052 std::optional<CompletionWithPriority>
1053 getCompletionForResult(
const CodeCompletionResult &R)
const {
1054 std::string ToInsert;
1055 std::string Description;
1058 case CodeCompletionResult::RK_Declaration: {
1059 const NamedDecl *D = R.Declaration;
1060 ToInsert = R.Declaration->getNameAsString();
1064 if (
const FunctionDecl *F = dyn_cast<FunctionDecl>(D)) {
1065 if (F->getNumParams() == 0)
1069 raw_string_ostream
OS(Description);
1070 F->print(
OS, m_desc_policy,
false);
1071 }
else if (
const VarDecl *V = dyn_cast<VarDecl>(D)) {
1072 Description = V->getType().getAsString(m_desc_policy);
1073 }
else if (
const FieldDecl *F = dyn_cast<FieldDecl>(D)) {
1074 Description = F->getType().getAsString(m_desc_policy);
1075 }
else if (
const NamespaceDecl *N = dyn_cast<NamespaceDecl>(D)) {
1078 if (!N->isAnonymousNamespace())
1083 case CodeCompletionResult::RK_Keyword:
1084 ToInsert = R.Keyword;
1086 case CodeCompletionResult::RK_Macro:
1087 ToInsert = R.Macro->getName().str();
1089 case CodeCompletionResult::RK_Pattern:
1090 ToInsert = R.Pattern->getTypedText();
1095 if (llvm::StringRef(ToInsert).starts_with(
"$__lldb_"))
1096 return std::nullopt;
1097 if (ToInsert.empty())
1098 return std::nullopt;
1101 std::string CompletionSuggestion =
1102 mergeCompletion(m_expr, m_position, ToInsert);
1104 CompletionResult::Completion completion(CompletionSuggestion, Description,
1105 CompletionMode::Normal);
1106 return {{completion, R.Priority}};
1111 void GetCompletions(CompletionRequest &request) {
1114 llvm::sort(m_completions);
1116 for (
const CompletionWithPriority &C : m_completions)
1118 C.completion.GetDescription(),
1119 C.completion.GetMode());
1124 void ProcessCodeCompleteResults(Sema &SemaRef, CodeCompletionContext Context,
1125 CodeCompletionResult *Results,
1126 unsigned NumResults)
override {
1130 StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();
1134 for (
unsigned I = 0; I != NumResults; ++I) {
1136 if (!Filter.empty() && isResultFilteredOut(Filter, Results[I]))
1139 CodeCompletionResult &R = Results[I];
1140 std::optional<CompletionWithPriority> CompletionAndPriority =
1141 getCompletionForResult(R);
1142 if (!CompletionAndPriority)
1144 m_completions.push_back(*CompletionAndPriority);
1156 void ProcessOverloadCandidates(Sema &S,
unsigned CurrentArg,
1157 OverloadCandidate *Candidates,
1158 unsigned NumCandidates,
1159 SourceLocation OpenParLoc,
1160 bool Braced)
override {
1164 CodeCompletionAllocator &getAllocator()
override {
1165 return m_info.getAllocator();
1168 CodeCompletionTUInfo &getCodeCompletionTUInfo()
override {
return m_info; }
1173 unsigned pos,
unsigned typed_pos) {
1188 CC.GetCompletions(request);
1198 CodeCompleteConsumer *completion_consumer,
1199 unsigned completion_line,
1200 unsigned completion_column) {
1207 const char *expr_text =
m_expr.Text();
1209 clang::SourceManager &source_mgr =
m_compiler->getSourceManager();
1210 bool created_main_file =
false;
1216 bool should_create_file = completion_consumer !=
nullptr;
1219 should_create_file |=
m_compiler->getCodeGenOpts().getDebugInfo() ==
1220 codegenoptions::FullDebugInfo;
1222 if (should_create_file) {
1224 llvm::SmallString<128> result_path;
1225 if (
FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
1226 tmpdir_file_spec.AppendPathComponent(
"lldb-%%%%%%.expr");
1227 std::string temp_source_path = tmpdir_file_spec.GetPath();
1228 llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path);
1230 llvm::sys::fs::createTemporaryFile(
"lldb",
"expr", temp_fd, result_path);
1233 if (temp_fd != -1) {
1235 const size_t expr_text_len = strlen(expr_text);
1236 size_t bytes_written = expr_text_len;
1238 if (bytes_written == expr_text_len) {
1240 if (
auto fileEntry =
m_compiler->getFileManager().getOptionalFileRef(
1242 source_mgr.setMainFileID(source_mgr.createFileID(
1243 *fileEntry, SourceLocation(), SrcMgr::C_User));
1244 created_main_file =
true;
1251 if (!created_main_file) {
1252 std::unique_ptr<MemoryBuffer> memory_buffer =
1253 MemoryBuffer::getMemBufferCopy(expr_text,
m_filename);
1254 source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer)));
1261 dyn_cast<ClangExpressionHelper>(
m_expr.GetTypeSystemHelper());
1267 if (completion_consumer) {
1269 source_mgr.getFileEntryRefForID(source_mgr.getMainFileID());
1274 ++completion_column;
1275 PP.SetCodeCompletionPoint(*main_file, completion_line, completion_column);
1278 ASTConsumer *ast_transformer =
1281 std::unique_ptr<clang::ASTConsumer> Consumer;
1282 if (ast_transformer) {
1283 Consumer = std::make_unique<ASTConsumerForwarder>(ast_transformer);
1287 Consumer = std::make_unique<ASTConsumer>();
1290 clang::ASTContext &ast_context =
m_compiler->getASTContext();
1293 *Consumer, TU_Complete, completion_consumer));
1294 m_compiler->setASTConsumer(std::move(Consumer));
1296 if (ast_context.getLangOpts().Modules) {
1306 llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source =
1309 auto ast_source_wrapper =
1310 llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(ast_source);
1312 if (ast_context.getExternalSource()) {
1313 auto module_wrapper = llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(
1314 ast_context.getExternalSourcePtr());
1316 auto multiplexer = llvm::makeIntrusiveRefCnt<SemaSourceWithPriorities>(
1317 module_wrapper, ast_source_wrapper);
1319 ast_context.setExternalSource(multiplexer);
1321 ast_context.setExternalSource(ast_source);
1323 m_compiler->getSema().addExternalSource(ast_source_wrapper);
1328 if (ast_context.getLangOpts().Modules) {
1329 assert(
m_compiler->getASTContext().getExternalSource() &&
1330 "ASTContext doesn't know about the ASTReader?");
1331 assert(
m_compiler->getSema().getExternalSource() &&
1332 "Sema doesn't know about the ASTReader?");
1336 llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(
1338 ParseAST(
m_compiler->getSema(),
false,
false);
1342 if (ast_context.getLangOpts().Modules)
1354 unsigned num_errors = adapter->getNumErrors();
1359 "while importing modules:");
1372static void ApplyFixIt(
const FixItHint &fixit, clang::edit::Commit &commit) {
1374 if (fixit.CodeToInsert.empty()) {
1375 if (fixit.InsertFromRange.isValid()) {
1376 commit.insertFromRange(fixit.RemoveRange.getBegin(),
1377 fixit.InsertFromRange,
false,
1378 fixit.BeforePreviousInsertions);
1381 commit.remove(fixit.RemoveRange);
1384 if (fixit.RemoveRange.isTokenRange() ||
1385 fixit.RemoveRange.getBegin() != fixit.RemoveRange.getEnd()) {
1386 commit.replace(fixit.RemoveRange, fixit.CodeToInsert);
1389 commit.insert(fixit.RemoveRange.getBegin(), fixit.CodeToInsert,
1390 false, fixit.BeforePreviousInsertions);
1395 clang::SourceManager &source_manager =
m_compiler->getSourceManager();
1396 clang::edit::EditedSource editor(source_manager,
m_compiler->getLangOpts(),
1398 clang::edit::Commit commit(editor);
1399 clang::Rewriter rewriter(source_manager,
m_compiler->getLangOpts());
1401 class RewritesReceiver :
public edit::EditsReceiver {
1405 RewritesReceiver(Rewriter &in_rewrite) : rewrite(in_rewrite) {}
1407 void insert(SourceLocation loc, StringRef text)
override {
1408 rewrite.InsertText(loc, text);
1410 void replace(CharSourceRange range, StringRef text)
override {
1411 rewrite.ReplaceText(range.getBegin(), rewrite.getRangeSize(range), text);
1415 RewritesReceiver rewrites_receiver(rewriter);
1418 size_t num_diags = diagnostics.size();
1422 for (
const auto &diag : diagnostic_manager.
Diagnostics()) {
1423 const auto *diagnostic = llvm::dyn_cast<ClangDiagnostic>(diag.get());
1426 if (!diagnostic->HasFixIts())
1428 for (
const FixItHint &fixit : diagnostic->FixIts())
1433 if (!commit.isCommitable())
1435 else if (!editor.commit(commit))
1439 editor.applyRewrites(rewrites_receiver);
1440 RewriteBuffer &main_file_buffer =
1441 rewriter.getEditBuffer(source_manager.getMainFileID());
1443 std::string fixed_expression;
1444 llvm::raw_string_ostream out_stream(fixed_expression);
1446 main_file_buffer.write(out_stream);
1453 llvm::Module *module,
const char *orig_name) {
1454 for (
const auto &func : module->getFunctionList()) {
1455 const StringRef &name = func.getName();
1456 if (name.contains(orig_name)) {
1475 std::unique_ptr<llvm::Module> llvm_module_up(
1478 if (!llvm_module_up) {
1489 m_expr.FunctionName())) {
1491 "Couldn't find %s() in the module",
m_expr.FunctionName());
1502 sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything);
1509 auto lang =
m_expr.Language();
1510 LLDB_LOGF(log,
"%s - Current expression language is %s\n", __FUNCTION__,
1511 lang.GetDescription().data());
1513 if (process_sp && lang) {
1514 auto runtime = process_sp->GetLanguageRuntime(lang.AsLanguageType());
1516 runtime->GetIRPasses(custom_passes);
1522 "%s - Running Early IR Passes from LanguageRuntime on "
1523 "expression module '%s'",
1524 __FUNCTION__,
m_expr.FunctionName());
1529 execution_unit_sp = std::make_shared<IRExecutionUnit>(
1535 if (
auto *options =
m_expr.GetOptions())
1536 execution_unit_sp->AppendPreferredSymbolContexts(
1537 options->GetPreferredSymbolContexts());
1540 dyn_cast<ClangExpressionHelper>(
m_expr.GetTypeSystemHelper());
1542 type_system_helper->
DeclMap();
1547 *execution_unit_sp, error_stream,
1550 if (!ir_for_target.
runOnModule(*execution_unit_sp->GetModule())) {
1561 bool interpret_function_calls =
1564 *execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(),
1565 interpret_error, interpret_function_calls);
1569 "Can't evaluate the expression without a running target due to: %s",
1577 "Expression needed to run in the target, but the "
1578 "target can't be run");
1584 "Top-level code needs to be inserted into a runnable "
1585 "target, but the target can't be run");
1591 if (
m_expr.NeedsValidation() && process) {
1597 if (Error Err = dynamic_checkers->
Install(install_diags, exe_ctx))
1603 LLDB_LOGF(log,
"== [ClangExpressionParser::PrepareForExecution] "
1604 "Finished installing dynamic checkers ==");
1607 if (
auto *checker_funcs = llvm::dyn_cast<ClangDynamicCheckerFunctions>(
1612 llvm::Module *module = execution_unit_sp->GetModule();
1613 if (!module || !ir_dynamic_checks.
runOnModule(*module)) {
1615 "Couldn't add dynamic checks to the expression");
1621 "%s - Running Late IR Passes from LanguageRuntime on "
1622 "expression module '%s'",
1623 __FUNCTION__,
m_expr.FunctionName());
1633 execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
1636 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.