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/SourceLocation.h"
17#include "clang/Basic/TargetInfo.h"
18#include "clang/Basic/Version.h"
19#include "clang/CodeGen/CodeGenAction.h"
20#include "clang/CodeGen/ModuleBuilder.h"
21#include "clang/Edit/Commit.h"
22#include "clang/Edit/EditedSource.h"
23#include "clang/Edit/EditsReceiver.h"
24#include "clang/Frontend/CompilerInstance.h"
25#include "clang/Frontend/CompilerInvocation.h"
26#include "clang/Frontend/FrontendActions.h"
27#include "clang/Frontend/FrontendDiagnostic.h"
28#include "clang/Frontend/FrontendPluginRegistry.h"
29#include "clang/Frontend/TextDiagnostic.h"
30#include "clang/Frontend/TextDiagnosticBuffer.h"
31#include "clang/Frontend/TextDiagnosticPrinter.h"
32#include "clang/Lex/Preprocessor.h"
33#include "clang/Parse/ParseAST.h"
34#include "clang/Rewrite/Core/Rewriter.h"
35#include "clang/Rewrite/Frontend/FrontendActions.h"
36#include "clang/Sema/CodeCompleteConsumer.h"
37#include "clang/Sema/Sema.h"
38#include "clang/Sema/SemaConsumer.h"
40#include "llvm/ADT/StringRef.h"
41#include "llvm/ExecutionEngine/ExecutionEngine.h"
42#include "llvm/Support/CrashRecoveryContext.h"
43#include "llvm/Support/Debug.h"
44#include "llvm/Support/Error.h"
45#include "llvm/Support/FileSystem.h"
46#include "llvm/Support/TargetSelect.h"
47#include "llvm/TargetParser/Triple.h"
49#include "llvm/IR/LLVMContext.h"
50#include "llvm/IR/Module.h"
51#include "llvm/Support/DynamicLibrary.h"
52#include "llvm/Support/ErrorHandling.h"
53#include "llvm/Support/MemoryBuffer.h"
54#include "llvm/Support/Signals.h"
55#include "llvm/TargetParser/Host.h"
105using namespace clang;
123 clang::SourceManager &source_mgr)
127 void moduleImport(SourceLocation import_location, clang::ModuleIdPath path,
128 const clang::Module * )
override {
131 llvm::StringRef filename =
132 m_source_mgr.getPresumedLoc(import_location).getFilename();
138 for (
const std::pair<IdentifierInfo *, SourceLocation> &component : path)
157 for (
auto &fix_it : Info.getFixItHints()) {
168 DiagnosticOptions *options =
new DiagnosticOptions(opts);
169 options->ShowPresumedLoc =
true;
170 options->ShowLevel =
false;
171 m_os = std::make_shared<llvm::raw_string_ostream>(
m_output);
173 std::make_shared<clang::TextDiagnosticPrinter>(*
m_os, options);
186 for (
auto it = diags.rbegin(); it != diags.rend(); it++) {
199 const clang::Diagnostic &Info)
override {
208 llvm::SmallVector<char, 32> diag_str;
209 Info.FormatDiagnostic(diag_str);
210 diag_str.push_back(
'\0');
211 const char *plain_diag = diag_str.data();
212 LLDB_LOG(log,
"Received diagnostic outside parsing: {0}", plain_diag);
218 DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
226 case DiagnosticsEngine::Level::Fatal:
227 case DiagnosticsEngine::Level::Error:
230 case DiagnosticsEngine::Level::Warning:
233 case DiagnosticsEngine::Level::Remark:
234 case DiagnosticsEngine::Level::Ignored:
237 case DiagnosticsEngine::Level::Note:
247 if (!clang_diag || clang_diag->HasFixIts())
257 std::string stripped_output =
258 std::string(llvm::StringRef(
m_output).trim());
261 if (Info.hasSourceManager()) {
263 clang::SourceManager &sm = Info.getSourceManager();
264 const clang::SourceLocation sloc = Info.getLocation();
265 if (sloc.isValid()) {
266 const clang::FullSourceLoc fsloc(sloc, sm);
267 clang::PresumedLoc PLoc = fsloc.getPresumedLoc(
true);
269 PLoc.isValid() ? PLoc.getFilename() : StringRef{};
271 loc.
line = fsloc.getSpellingLineNumber();
272 loc.
column = fsloc.getSpellingColumnNumber();
274 loc.
hidden = filename.starts_with(
"<lldb wrapper ");
277 for (
const auto &range : Info.getRanges()) {
278 if (range.getBegin() == sloc) {
280 unsigned end_col = sm.getSpellingColumnNumber(range.getEnd());
289 llvm::SmallString<0> msg;
290 Info.FormatDiagnostic(msg);
293 auto new_diagnostic =
294 std::make_unique<ClangDiagnostic>(detail, Info.getID());
316 std::shared_ptr<llvm::raw_string_ostream>
m_os;
326static llvm::Expected<bool>
329 auto const &triple = arch_spec.
GetTriple();
332 return llvm::createStringError(
"Executable module not found.");
337 return llvm::createStringError(
"No Platform plugin found on target.");
339 auto sdk_or_err = platform_sp->GetSDKPathFromDebugInfo(*module_sp);
341 return sdk_or_err.takeError();
344 auto sdk_path_or_err =
345 HostInfo::GetSDKRoot(HostInfo::SDKOptions{std::move(sdk_or_err->first)});
346 if (!sdk_path_or_err)
347 return sdk_path_or_err.takeError();
351 return llvm::createStringError(
"No virtual filesystem available.");
354 auto parsed_or_err = clang::parseDarwinSDKInfo(*VFS, *sdk_path_or_err);
356 return parsed_or_err.takeError();
358 auto maybe_sdk = *parsed_or_err;
360 return llvm::createStringError(
"Couldn't find Darwin SDK info.");
366 std::vector<std::string> include_directories,
370 HeaderSearchOptions &search_opts = compiler->getHeaderSearchOpts();
372 for (
const std::string &dir : include_directories) {
373 search_opts.AddPath(dir, frontend::System,
false,
true);
374 LLDB_LOG(log,
"Added user include dir: {0}", dir);
377 llvm::SmallString<128> module_cache;
379 props.GetClangModulesCachePath().GetPath(module_cache);
380 search_opts.ModuleCachePath = std::string(module_cache.str());
381 LLDB_LOG(log,
"Using module cache path: {0}", module_cache.c_str());
385 search_opts.ImplicitModuleMaps =
true;
393 if (token ==
"using")
396 if (token ==
"__null")
399 LangOptions cpp_lang_opts;
400 cpp_lang_opts.CPlusPlus =
true;
401 cpp_lang_opts.CPlusPlus11 =
true;
402 cpp_lang_opts.CPlusPlus20 =
true;
404 clang::IdentifierInfo &ii = idents.get(token);
407 if (!ii.isCPlusPlusKeyword(cpp_lang_opts))
410 if (ii.getTokenID() == clang::tok::identifier)
414 ii.revertTokenIDToIdentifier();
419#define KEYWORD(NAME, FLAGS) RemoveCppKeyword(idents, llvm::StringRef(#NAME));
420#include "clang/Basic/TokenKinds.def"
426 const std::vector<const char *> groupsToIgnore = {
429 "unused-getter-return-value",
431 for (
const char *group : groupsToIgnore) {
432 compiler.getDiagnostics().setSeverityForGroup(
433 clang::diag::Flavor::WarningOrError, group,
434 clang::diag::Severity::Ignored, SourceLocation());
446 if (target_arch.
IsMIPS()) {
459 if (target_arch.
GetTriple().isRISCV64()) {
474 if (target_arch.
GetTriple().isRISCV32()) {
489 if (target_arch.
GetTriple().isLoongArch64()) {
510 const auto target_machine = target_arch.
GetMachine();
512 std::string triple = target_arch.
GetTriple().str();
513 compiler.getTargetOpts().Triple = triple;
514 LLDB_LOGF(log,
"Using %s as the target triple",
515 compiler.getTargetOpts().Triple.c_str());
523 compiler.getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
524 LLDB_LOGF(log,
"Using default target triple of %s",
525 compiler.getTargetOpts().Triple.c_str());
529 if (compiler.getTargetOpts().Triple.find(
"arm64") == std::string::npos &&
530 compiler.getTargetOpts().Triple.find(
"arm") != std::string::npos &&
531 compiler.getTargetOpts().Triple.find(
"ios") != std::string::npos) {
532 compiler.getTargetOpts().ABI =
"apcs-gnu";
535 if (target_machine == llvm::Triple::x86 ||
536 target_machine == llvm::Triple::x86_64) {
537 compiler.getTargetOpts().FeaturesAsWritten.push_back(
"+sse");
538 compiler.getTargetOpts().FeaturesAsWritten.push_back(
"+sse2");
548 compiler.getTargetOpts().ABI = std::move(abi);
550 if ((target_machine == llvm::Triple::riscv64 &&
551 compiler.getTargetOpts().ABI ==
"lp64f") ||
552 (target_machine == llvm::Triple::riscv32 &&
553 compiler.getTargetOpts().ABI ==
"ilp32f"))
554 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+f");
556 if ((target_machine == llvm::Triple::riscv64 &&
557 compiler.getTargetOpts().ABI ==
"lp64d") ||
558 (target_machine == llvm::Triple::riscv32 &&
559 compiler.getTargetOpts().ABI ==
"ilp32d"))
560 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+d");
562 if ((target_machine == llvm::Triple::loongarch64 &&
563 compiler.getTargetOpts().ABI ==
"lp64f"))
564 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+f");
566 if ((target_machine == llvm::Triple::loongarch64 &&
567 compiler.getTargetOpts().ABI ==
"lp64d"))
568 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+d");
588 frame_lang = frame_sp->GetLanguage().AsLanguageType();
591 LLDB_LOGF(log,
"Frame has language of type %s",
596 LangOptions &lang_opts = compiler.getLangOpts();
609 lang_opts.CPlusPlus =
true;
612 lang_opts.ObjC =
true;
615 lang_opts.CPlusPlus =
true;
623 lang_opts.CPlusPlus11 =
true;
626 lang_opts.CPlusPlus20 =
true;
632 lang_opts.CPlusPlus14 =
true;
633 lang_opts.CPlusPlus17 =
true;
638 lang_opts.CPlusPlus11 =
true;
639 compiler.getHeaderSearchOpts().UseLibcxx =
true;
642 lang_opts.CPlusPlus =
true;
646 && !(frame_sp && frame_sp->HasDebugInformation()))
653 lang_opts.ObjC =
true;
654 lang_opts.CPlusPlus =
true;
655 lang_opts.CPlusPlus11 =
true;
656 compiler.getHeaderSearchOpts().UseLibcxx =
true;
660 lang_opts.Bool =
true;
661 lang_opts.WChar =
true;
662 lang_opts.Blocks =
true;
663 lang_opts.DebuggerSupport =
666 lang_opts.DebuggerCastResultToId =
true;
668 lang_opts.CharIsSigned =
674 lang_opts.SpellChecking =
false;
676 if (process_sp && lang_opts.ObjC) {
678 switch (runtime->GetRuntimeVersion()) {
679 case ObjCLanguageRuntime::ObjCRuntimeVersions::eAppleObjC_V2:
680 lang_opts.ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7));
682 case ObjCLanguageRuntime::ObjCRuntimeVersions::eObjC_VersionUnknown:
683 case ObjCLanguageRuntime::ObjCRuntimeVersions::eAppleObjC_V1:
684 lang_opts.ObjCRuntime.set(ObjCRuntime::FragileMacOSX,
685 VersionTuple(10, 7));
687 case ObjCLanguageRuntime::ObjCRuntimeVersions::eGNUstep_libobjc2:
688 lang_opts.ObjCRuntime.set(ObjCRuntime::GNUstep, VersionTuple(2, 0));
692 if (runtime->HasNewLiteralsAndIndexing())
693 lang_opts.DebuggerObjCLiteral =
true;
697 lang_opts.ThreadsafeStatics =
false;
698 lang_opts.AccessControl =
false;
699 lang_opts.DollarIdents =
true;
703 lang_opts.NoBuiltin =
true;
709 LangOptions &lang_opts = compiler.getLangOpts();
710 lang_opts.Modules =
true;
712 lang_opts.ImplicitModules =
true;
714 lang_opts.ModulesLocalVisibility =
false;
718 lang_opts.ObjC =
true;
722 lang_opts.GNUMode =
true;
723 lang_opts.GNUKeywords =
true;
724 lang_opts.CPlusPlus11 =
true;
727 lang_opts.BuiltinHeadersInSystemModules = !*supported_or_err;
730 "Failed to determine BuiltinHeadersInSystemModules when "
731 "setting up import-std-module: {0}");
734 lang_opts.GNUCVersion = 40201;
743 bool generate_debug_info, std::vector<std::string> include_directories,
744 std::string filename)
746 m_pp_callbacks(nullptr),
747 m_include_directories(std::move(include_directories)),
748 m_filename(std::move(filename)) {
760 "Can't make an expression parser with a null scope.");
768 "Can't make an expression parser with a null target.");
773 m_compiler = std::make_unique<CompilerInstance>();
786 m_compiler->getDiagnostics().setErrorLimit(target_sp->GetExprErrorLimit());
788 if (
auto *target_info = TargetInfo::CreateTargetInfo(
792 LLDB_LOGF(log,
"Target datalayout string: '%s'",
793 target_info->getDataLayoutString());
794 LLDB_LOGF(log,
"Target ABI: '%s'", target_info->getABI().str().c_str());
795 LLDB_LOGF(log,
"Target vector alignment: %d",
796 target_info->getMaxVectorAlign());
801 LLDB_LOGF(log,
"Failed to create TargetInfo for '%s'",
804 lldbassert(
false &&
"Failed to create TargetInfo.");
809 auto *clang_expr = dyn_cast<ClangUserExpression>(&
m_expr);
810 if (clang_expr && clang_expr->DidImportCxxModules()) {
811 LLDB_LOG(log,
"Adding lang options for importing C++ modules");
817 m_compiler->getCodeGenOpts().EmitDeclMetadata =
true;
818 m_compiler->getCodeGenOpts().InstrumentFunctions =
false;
820 CodeGenOptions::FramePointerKind::All);
821 if (generate_debug_info)
822 m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
824 m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::NoDebugInfo);
838 m_compiler->getDiagnostics().getDiagnosticOptions(),
839 clang_expr ? clang_expr->GetFilename() : StringRef());
840 m_compiler->getDiagnostics().setClient(diag_mgr);
863 if (
auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(
864 target_sp->GetPersistentExpressionStateForLanguage(
866 if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
867 clang_persistent_vars->GetClangModulesDeclVendor()) {
868 std::unique_ptr<PPCallbacks> pp_callbacks(
873 m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
881 auto &builtin_context = PP.getBuiltinInfo();
882 builtin_context.initializeBuiltins(PP.getIdentifierTable(),
886 clang::ASTContext &ast_context =
m_compiler->getASTContext();
889 "Expression ASTContext for '" +
m_filename +
"'", ast_context);
891 std::string module_name(
"$__lldb_module");
910class CodeComplete :
public CodeCompleteConsumer {
911 CodeCompletionTUInfo m_info;
914 unsigned m_position = 0;
917 clang::PrintingPolicy m_desc_policy;
919 struct CompletionWithPriority {
927 bool operator<(
const CompletionWithPriority &o)
const {
929 if (Priority != o.Priority)
930 return Priority > o.Priority;
933 return completion.
GetUniqueKey() < o.completion.GetUniqueKey();
940 std::vector<CompletionWithPriority> m_completions;
947 static bool IsIdChar(
char c) {
948 return c ==
'_' || std::isalnum(c) || c ==
'$';
953 static bool IsTokenSeparator(
char c) {
return c ==
' ' || c ==
'\t'; }
958 StringRef dropUnrelatedFrontTokens(StringRef cmd)
const {
964 if (IsTokenSeparator(cmd.back()))
969 StringRef to_remove = cmd;
970 while (!to_remove.empty() && !IsTokenSeparator(to_remove.back())) {
971 to_remove = to_remove.drop_back();
973 cmd = cmd.drop_front(to_remove.size());
979 StringRef removeLastToken(StringRef cmd)
const {
980 while (!cmd.empty() && IsIdChar(cmd.back())) {
981 cmd = cmd.drop_back();
989 std::string mergeCompletion(StringRef existing,
unsigned pos,
990 StringRef completion)
const {
991 StringRef existing_command = existing.substr(0, pos);
994 existing_command = removeLastToken(existing_command);
998 existing_command = dropUnrelatedFrontTokens(existing_command);
999 return existing_command.str() + completion.str();
1012 CodeComplete(clang::LangOptions ops, std::string expr,
unsigned position)
1013 : CodeCompleteConsumer(CodeCompleteOptions()),
1014 m_info(std::make_shared<GlobalCodeCompletionAllocator>()), m_expr(expr),
1015 m_position(position), m_desc_policy(ops) {
1019 m_desc_policy.SuppressScope =
true;
1020 m_desc_policy.SuppressTagKeyword =
true;
1021 m_desc_policy.FullyQualifiedName =
false;
1022 m_desc_policy.TerseOutput =
true;
1023 m_desc_policy.IncludeNewlines =
false;
1024 m_desc_policy.UseVoidForZeroParams =
false;
1025 m_desc_policy.Bool =
true;
1030 bool isResultFilteredOut(StringRef Filter,
1031 CodeCompletionResult Result)
override {
1033 switch (Result.Kind) {
1034 case CodeCompletionResult::RK_Declaration:
1036 Result.Declaration->getIdentifier() &&
1037 Result.Declaration->getIdentifier()->getName().starts_with(Filter));
1038 case CodeCompletionResult::RK_Keyword:
1039 return !StringRef(Result.Keyword).starts_with(Filter);
1040 case CodeCompletionResult::RK_Macro:
1041 return !Result.Macro->getName().starts_with(Filter);
1042 case CodeCompletionResult::RK_Pattern:
1043 return !StringRef(Result.Pattern->getAsString()).starts_with(Filter);
1048 assert(
false &&
"Unknown completion result type?");
1063 std::optional<CompletionWithPriority>
1064 getCompletionForResult(
const CodeCompletionResult &R)
const {
1065 std::string ToInsert;
1066 std::string Description;
1069 case CodeCompletionResult::RK_Declaration: {
1070 const NamedDecl *D = R.Declaration;
1071 ToInsert = R.Declaration->getNameAsString();
1075 if (
const FunctionDecl *F = dyn_cast<FunctionDecl>(D)) {
1076 if (F->getNumParams() == 0)
1080 raw_string_ostream
OS(Description);
1081 F->print(
OS, m_desc_policy,
false);
1082 }
else if (
const VarDecl *V = dyn_cast<VarDecl>(D)) {
1083 Description = V->getType().getAsString(m_desc_policy);
1084 }
else if (
const FieldDecl *F = dyn_cast<FieldDecl>(D)) {
1085 Description = F->getType().getAsString(m_desc_policy);
1086 }
else if (
const NamespaceDecl *N = dyn_cast<NamespaceDecl>(D)) {
1089 if (!N->isAnonymousNamespace())
1094 case CodeCompletionResult::RK_Keyword:
1095 ToInsert = R.Keyword;
1097 case CodeCompletionResult::RK_Macro:
1098 ToInsert = R.Macro->getName().str();
1100 case CodeCompletionResult::RK_Pattern:
1101 ToInsert = R.Pattern->getTypedText();
1106 if (llvm::StringRef(ToInsert).starts_with(
"$__lldb_"))
1107 return std::nullopt;
1108 if (ToInsert.empty())
1109 return std::nullopt;
1112 std::string CompletionSuggestion =
1113 mergeCompletion(m_expr, m_position, ToInsert);
1116 CompletionMode::Normal);
1117 return {{completion, R.Priority}};
1125 llvm::sort(m_completions);
1127 for (
const CompletionWithPriority &C : m_completions)
1129 C.completion.GetDescription(),
1130 C.completion.GetMode());
1135 void ProcessCodeCompleteResults(Sema &SemaRef, CodeCompletionContext Context,
1136 CodeCompletionResult *Results,
1137 unsigned NumResults)
override {
1141 StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();
1145 for (
unsigned I = 0; I != NumResults; ++I) {
1147 if (!Filter.empty() && isResultFilteredOut(Filter, Results[I]))
1150 CodeCompletionResult &R = Results[I];
1151 std::optional<CompletionWithPriority> CompletionAndPriority =
1152 getCompletionForResult(R);
1153 if (!CompletionAndPriority)
1155 m_completions.push_back(*CompletionAndPriority);
1167 void ProcessOverloadCandidates(Sema &S,
unsigned CurrentArg,
1168 OverloadCandidate *Candidates,
1169 unsigned NumCandidates,
1170 SourceLocation OpenParLoc,
1171 bool Braced)
override {
1175 CodeCompletionAllocator &getAllocator()
override {
1176 return m_info.getAllocator();
1179 CodeCompletionTUInfo &getCodeCompletionTUInfo()
override {
return m_info; }
1184 unsigned pos,
unsigned typed_pos) {
1199 CC.GetCompletions(request);
1209 CodeCompleteConsumer *completion_consumer,
1210 unsigned completion_line,
1211 unsigned completion_column) {
1220 clang::SourceManager &source_mgr =
m_compiler->getSourceManager();
1221 bool created_main_file =
false;
1227 bool should_create_file = completion_consumer !=
nullptr;
1230 should_create_file |=
m_compiler->getCodeGenOpts().getDebugInfo() ==
1231 codegenoptions::FullDebugInfo;
1233 if (should_create_file) {
1235 llvm::SmallString<128> result_path;
1236 if (
FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
1237 tmpdir_file_spec.AppendPathComponent(
"lldb-%%%%%%.expr");
1238 std::string temp_source_path = tmpdir_file_spec.GetPath();
1239 llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path);
1241 llvm::sys::fs::createTemporaryFile(
"lldb",
"expr", temp_fd, result_path);
1244 if (temp_fd != -1) {
1246 const size_t expr_text_len = strlen(expr_text);
1247 size_t bytes_written = expr_text_len;
1249 if (bytes_written == expr_text_len) {
1251 if (
auto fileEntry =
m_compiler->getFileManager().getOptionalFileRef(
1253 source_mgr.setMainFileID(source_mgr.createFileID(
1254 *fileEntry, SourceLocation(), SrcMgr::C_User));
1255 created_main_file =
true;
1262 if (!created_main_file) {
1263 std::unique_ptr<MemoryBuffer> memory_buffer =
1264 MemoryBuffer::getMemBufferCopy(expr_text,
m_filename);
1265 source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer)));
1278 if (completion_consumer) {
1280 source_mgr.getFileEntryRefForID(source_mgr.getMainFileID());
1285 ++completion_column;
1286 PP.SetCodeCompletionPoint(*main_file, completion_line, completion_column);
1289 ASTConsumer *ast_transformer =
1292 std::unique_ptr<clang::ASTConsumer> Consumer;
1293 if (ast_transformer) {
1294 Consumer = std::make_unique<ASTConsumerForwarder>(ast_transformer);
1298 Consumer = std::make_unique<ASTConsumer>();
1301 clang::ASTContext &ast_context =
m_compiler->getASTContext();
1304 *Consumer, TU_Complete, completion_consumer));
1305 m_compiler->setASTConsumer(std::move(Consumer));
1307 if (ast_context.getLangOpts().Modules) {
1317 clang::ExternalASTSource *ast_source = decl_map->
CreateProxy();
1321 if (ast_context.getExternalSource()) {
1322 auto *module_wrapper =
1328 ast_context.setExternalSource(multiplexer);
1330 ast_context.setExternalSource(ast_source);
1332 m_compiler->getSema().addExternalSource(ast_source_wrapper);
1337 if (ast_context.getLangOpts().Modules) {
1338 assert(
m_compiler->getASTContext().getExternalSource() &&
1339 "ASTContext doesn't know about the ASTReader?");
1340 assert(
m_compiler->getSema().getExternalSource() &&
1341 "Sema doesn't know about the ASTReader?");
1345 llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(
1347 ParseAST(
m_compiler->getSema(),
false,
false);
1351 if (ast_context.getLangOpts().Modules)
1359 unsigned num_errors = adapter->getNumErrors();
1364 "while importing modules:");
1379static void ApplyFixIt(
const FixItHint &fixit, clang::edit::Commit &commit) {
1381 if (fixit.CodeToInsert.empty()) {
1382 if (fixit.InsertFromRange.isValid()) {
1383 commit.insertFromRange(fixit.RemoveRange.getBegin(),
1384 fixit.InsertFromRange,
false,
1385 fixit.BeforePreviousInsertions);
1388 commit.remove(fixit.RemoveRange);
1391 if (fixit.RemoveRange.isTokenRange() ||
1392 fixit.RemoveRange.getBegin() != fixit.RemoveRange.getEnd()) {
1393 commit.replace(fixit.RemoveRange, fixit.CodeToInsert);
1396 commit.insert(fixit.RemoveRange.getBegin(), fixit.CodeToInsert,
1397 false, fixit.BeforePreviousInsertions);
1402 clang::SourceManager &source_manager =
m_compiler->getSourceManager();
1403 clang::edit::EditedSource editor(source_manager,
m_compiler->getLangOpts(),
1405 clang::edit::Commit commit(editor);
1406 clang::Rewriter rewriter(source_manager,
m_compiler->getLangOpts());
1408 class RewritesReceiver :
public edit::EditsReceiver {
1412 RewritesReceiver(Rewriter &in_rewrite) : rewrite(in_rewrite) {}
1414 void insert(SourceLocation loc, StringRef text)
override {
1415 rewrite.InsertText(loc, text);
1417 void replace(CharSourceRange range, StringRef text)
override {
1418 rewrite.ReplaceText(range.getBegin(), rewrite.getRangeSize(range), text);
1422 RewritesReceiver rewrites_receiver(rewriter);
1425 size_t num_diags = diagnostics.size();
1429 for (
const auto &diag : diagnostic_manager.
Diagnostics()) {
1430 const auto *diagnostic = llvm::dyn_cast<ClangDiagnostic>(diag.get());
1433 if (!diagnostic->HasFixIts())
1435 for (
const FixItHint &fixit : diagnostic->FixIts())
1440 if (!commit.isCommitable())
1442 else if (!editor.commit(commit))
1446 editor.applyRewrites(rewrites_receiver);
1447 RewriteBuffer &main_file_buffer =
1448 rewriter.getEditBuffer(source_manager.getMainFileID());
1450 std::string fixed_expression;
1451 llvm::raw_string_ostream out_stream(fixed_expression);
1453 main_file_buffer.write(out_stream);
1460 llvm::Module *module,
const char *orig_name) {
1461 for (
const auto &func : module->getFunctionList()) {
1462 const StringRef &name = func.getName();
1463 if (name.contains(orig_name)) {
1482 std::unique_ptr<llvm::Module> llvm_module_up(
1485 if (!llvm_module_up) {
1509 sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything);
1517 LLDB_LOGF(log,
"%s - Current expression language is %s\n", __FUNCTION__,
1518 lang.GetDescription().data());
1521 auto runtime = process_sp->GetLanguageRuntime(lang.AsLanguageType());
1523 runtime->GetIRPasses(custom_passes);
1529 "%s - Running Early IR Passes from LanguageRuntime on "
1530 "expression module '%s'",
1536 execution_unit_sp = std::make_shared<IRExecutionUnit>(
1545 type_system_helper->
DeclMap();
1550 *execution_unit_sp, error_stream,
1553 if (!ir_for_target.
runOnModule(*execution_unit_sp->GetModule())) {
1564 bool interpret_function_calls =
1567 *execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(),
1568 interpret_error, interpret_function_calls);
1572 "Can't evaluate the expression without a running target due to: %s",
1580 "Expression needed to run in the target, but the "
1581 "target can't be run");
1587 "Top-level code needs to be inserted into a runnable "
1588 "target, but the target can't be run");
1600 if (
Error Err = dynamic_checkers->
Install(install_diags, exe_ctx))
1606 LLDB_LOGF(log,
"== [ClangExpressionParser::PrepareForExecution] "
1607 "Finished installing dynamic checkers ==");
1610 if (
auto *checker_funcs = llvm::dyn_cast<ClangDynamicCheckerFunctions>(
1615 llvm::Module *module = execution_unit_sp->GetModule();
1616 if (!module || !ir_dynamic_checks.
runOnModule(*module)) {
1618 "Couldn't add dynamic checks to the expression");
1624 "%s - Running Late IR Passes from LanguageRuntime on "
1625 "expression module '%s'",
1636 execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
1639 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 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 SetupLangOpts(CompilerInstance &compiler, ExecutionContextScope &exe_scope, const Expression &expr)
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.
static llvm::Expected< bool > sdkSupportsBuiltinModules(lldb_private::Target &target)
Returns true if the SDK for the specified triple supports builtin modules in system headers.
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
#define LLDB_LOGF(log,...)
#define LLDB_LOG_ERROR(log, error,...)
void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override
void EndSourceFile() override
std::shared_ptr< llvm::raw_string_ostream > m_os
Output stream of m_passthrough.
std::string m_output
Output string filled by m_os.
std::shared_ptr< clang::TextDiagnosticPrinter > m_passthrough
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.
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
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,...
void InstallASTContext(TypeSystemClang &ast_context)
clang::ExternalASTSource * CreateProxy()
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, 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
virtual bool AddModule(const SourceModule &module, ModuleVector *exported_modules, Stream &error_stream)=0
Add a module to the list of modules to search.
"lldb/Expression/ClangPersistentVariables.h" Manages persistent values that need to be preserved betw...
void AddHandLoadedClangModule(ClangModulesDeclVendor::ModuleID module)
"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)
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)
const DiagnosticList & Diagnostics()
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.
"lldb/Expression/ExpressionParser.h" Encapsulates an instance of a compiler that can parse expression...
Expression & m_expr
The expression to be parsed.
Encapsulates a single expression for use in lldb.
virtual bool NeedsValidation()=0
Flags.
virtual const char * Text()=0
Return the string that the parser should parse.
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.
virtual bool NeedsVariableResolution()=0
Return true if external variables in the expression should be resolved.
virtual ExpressionTypeSystemHelper * GetTypeSystemHelper()
virtual const char * FunctionName()=0
Return the function name that should be used for executing the expression.
Wraps an ExternalASTSource into an ExternalSemaSource.
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > GetVirtualFileSystem()
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)
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.
A ExternalSemaSource multiplexer that prioritizes its sources.
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.
lldb::ModuleSP GetExecutableModule()
Gets the module for the main executable.
lldb::PlatformSP GetPlatform()
const ArchSpec & GetArchitecture() const
const char * GetUserText()
Return the string that the user typed.
static bool SDKSupportsBuiltinModules(const llvm::Triple &target_triple, llvm::VersionTuple sdk_version)
Returns true if the SDK for the specified triple supports builtin modules in system headers.
#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.
std::vector< ConstString > path
Something like "Module.Submodule".