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");
896class CodeComplete :
public CodeCompleteConsumer {
897 CodeCompletionTUInfo m_info;
900 unsigned m_position = 0;
903 clang::PrintingPolicy m_desc_policy;
905 struct CompletionWithPriority {
913 bool operator<(
const CompletionWithPriority &o)
const {
915 if (Priority != o.Priority)
916 return Priority > o.Priority;
919 return completion.
GetUniqueKey() < o.completion.GetUniqueKey();
926 std::vector<CompletionWithPriority> m_completions;
933 static bool IsIdChar(
char c) {
934 return c ==
'_' || std::isalnum(c) || c ==
'$';
939 static bool IsTokenSeparator(
char c) {
return c ==
' ' || c ==
'\t'; }
944 StringRef dropUnrelatedFrontTokens(StringRef cmd)
const {
950 if (IsTokenSeparator(cmd.back()))
955 StringRef to_remove = cmd;
956 while (!to_remove.empty() && !IsTokenSeparator(to_remove.back())) {
957 to_remove = to_remove.drop_back();
959 cmd = cmd.drop_front(to_remove.size());
965 StringRef removeLastToken(StringRef cmd)
const {
966 while (!cmd.empty() && IsIdChar(cmd.back())) {
967 cmd = cmd.drop_back();
975 std::string mergeCompletion(StringRef existing,
unsigned pos,
976 StringRef completion)
const {
977 StringRef existing_command = existing.substr(0, pos);
980 existing_command = removeLastToken(existing_command);
984 existing_command = dropUnrelatedFrontTokens(existing_command);
985 return existing_command.str() + completion.str();
998 CodeComplete(clang::LangOptions ops, std::string expr,
unsigned position)
999 : CodeCompleteConsumer(CodeCompleteOptions()),
1000 m_info(std::make_shared<GlobalCodeCompletionAllocator>()), m_expr(expr),
1001 m_position(position), m_desc_policy(ops) {
1005 m_desc_policy.SuppressScope =
true;
1006 m_desc_policy.SuppressTagKeyword =
true;
1007 m_desc_policy.FullyQualifiedName =
false;
1008 m_desc_policy.TerseOutput =
true;
1009 m_desc_policy.IncludeNewlines =
false;
1010 m_desc_policy.UseVoidForZeroParams =
false;
1011 m_desc_policy.Bool =
true;
1016 bool isResultFilteredOut(StringRef Filter,
1017 CodeCompletionResult Result)
override {
1019 switch (Result.Kind) {
1020 case CodeCompletionResult::RK_Declaration:
1022 Result.Declaration->getIdentifier() &&
1023 Result.Declaration->getIdentifier()->getName().starts_with(Filter));
1024 case CodeCompletionResult::RK_Keyword:
1025 return !StringRef(Result.Keyword).starts_with(Filter);
1026 case CodeCompletionResult::RK_Macro:
1027 return !Result.Macro->getName().starts_with(Filter);
1028 case CodeCompletionResult::RK_Pattern:
1029 return !StringRef(Result.Pattern->getAsString()).starts_with(Filter);
1034 assert(
false &&
"Unknown completion result type?");
1049 std::optional<CompletionWithPriority>
1050 getCompletionForResult(
const CodeCompletionResult &R)
const {
1051 std::string ToInsert;
1052 std::string Description;
1055 case CodeCompletionResult::RK_Declaration: {
1056 const NamedDecl *D = R.Declaration;
1057 ToInsert = R.Declaration->getNameAsString();
1061 if (
const FunctionDecl *F = dyn_cast<FunctionDecl>(D)) {
1062 if (F->getNumParams() == 0)
1066 raw_string_ostream
OS(Description);
1067 F->print(
OS, m_desc_policy,
false);
1068 }
else if (
const VarDecl *V = dyn_cast<VarDecl>(D)) {
1069 Description = V->getType().getAsString(m_desc_policy);
1070 }
else if (
const FieldDecl *F = dyn_cast<FieldDecl>(D)) {
1071 Description = F->getType().getAsString(m_desc_policy);
1072 }
else if (
const NamespaceDecl *N = dyn_cast<NamespaceDecl>(D)) {
1075 if (!N->isAnonymousNamespace())
1080 case CodeCompletionResult::RK_Keyword:
1081 ToInsert = R.Keyword;
1083 case CodeCompletionResult::RK_Macro:
1084 ToInsert = R.Macro->getName().str();
1086 case CodeCompletionResult::RK_Pattern:
1087 ToInsert = R.Pattern->getTypedText();
1092 if (llvm::StringRef(ToInsert).starts_with(
"$__lldb_"))
1093 return std::nullopt;
1094 if (ToInsert.empty())
1095 return std::nullopt;
1098 std::string CompletionSuggestion =
1099 mergeCompletion(m_expr, m_position, ToInsert);
1101 CompletionResult::Completion completion(CompletionSuggestion, Description,
1102 CompletionMode::Normal);
1103 return {{completion, R.Priority}};
1108 void GetCompletions(CompletionRequest &request) {
1111 llvm::sort(m_completions);
1113 for (
const CompletionWithPriority &C : m_completions)
1115 C.completion.GetDescription(),
1116 C.completion.GetMode());
1121 void ProcessCodeCompleteResults(Sema &SemaRef, CodeCompletionContext Context,
1122 CodeCompletionResult *Results,
1123 unsigned NumResults)
override {
1127 StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();
1131 for (
unsigned I = 0; I != NumResults; ++I) {
1133 if (!Filter.empty() && isResultFilteredOut(Filter, Results[I]))
1136 CodeCompletionResult &R = Results[I];
1137 std::optional<CompletionWithPriority> CompletionAndPriority =
1138 getCompletionForResult(R);
1139 if (!CompletionAndPriority)
1141 m_completions.push_back(*CompletionAndPriority);
1153 void ProcessOverloadCandidates(Sema &S,
unsigned CurrentArg,
1154 OverloadCandidate *Candidates,
1155 unsigned NumCandidates,
1156 SourceLocation OpenParLoc,
1157 bool Braced)
override {
1161 CodeCompletionAllocator &getAllocator()
override {
1162 return m_info.getAllocator();
1165 CodeCompletionTUInfo &getCodeCompletionTUInfo()
override {
return m_info; }
1170 unsigned pos,
unsigned typed_pos) {
1185 CC.GetCompletions(request);
1195 CodeCompleteConsumer *completion_consumer,
1196 unsigned completion_line,
1197 unsigned completion_column) {
1204 const char *expr_text =
m_expr.Text();
1206 clang::SourceManager &source_mgr =
m_compiler->getSourceManager();
1207 bool created_main_file =
false;
1213 bool should_create_file = completion_consumer !=
nullptr;
1216 should_create_file |=
m_compiler->getCodeGenOpts().getDebugInfo() ==
1217 codegenoptions::FullDebugInfo;
1219 if (should_create_file) {
1221 llvm::SmallString<128> result_path;
1222 if (
FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
1223 tmpdir_file_spec.AppendPathComponent(
"lldb-%%%%%%.expr");
1224 std::string temp_source_path = tmpdir_file_spec.GetPath();
1225 llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path);
1227 llvm::sys::fs::createTemporaryFile(
"lldb",
"expr", temp_fd, result_path);
1230 if (temp_fd != -1) {
1232 const size_t expr_text_len = strlen(expr_text);
1233 size_t bytes_written = expr_text_len;
1235 if (bytes_written == expr_text_len) {
1237 if (
auto fileEntry =
m_compiler->getFileManager().getOptionalFileRef(
1239 source_mgr.setMainFileID(source_mgr.createFileID(
1240 *fileEntry, SourceLocation(), SrcMgr::C_User));
1241 created_main_file =
true;
1248 if (!created_main_file) {
1249 std::unique_ptr<MemoryBuffer> memory_buffer =
1250 MemoryBuffer::getMemBufferCopy(expr_text,
m_filename);
1251 source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer)));
1258 dyn_cast<ClangExpressionHelper>(
m_expr.GetTypeSystemHelper());
1264 if (completion_consumer) {
1266 source_mgr.getFileEntryRefForID(source_mgr.getMainFileID());
1271 ++completion_column;
1272 PP.SetCodeCompletionPoint(*main_file, completion_line, completion_column);
1275 ASTConsumer *ast_transformer =
1278 std::unique_ptr<clang::ASTConsumer> Consumer;
1279 if (ast_transformer) {
1280 Consumer = std::make_unique<ASTConsumerForwarder>(ast_transformer);
1284 Consumer = std::make_unique<ASTConsumer>();
1287 clang::ASTContext &ast_context =
m_compiler->getASTContext();
1290 *Consumer, TU_Complete, completion_consumer));
1291 m_compiler->setASTConsumer(std::move(Consumer));
1293 if (ast_context.getLangOpts().Modules) {
1303 llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source =
1306 auto ast_source_wrapper =
1307 llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(ast_source);
1309 if (ast_context.getExternalSource()) {
1310 auto module_wrapper = llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(
1311 ast_context.getExternalSourcePtr());
1313 auto multiplexer = llvm::makeIntrusiveRefCnt<SemaSourceWithPriorities>(
1314 module_wrapper, ast_source_wrapper);
1316 ast_context.setExternalSource(multiplexer);
1318 ast_context.setExternalSource(ast_source);
1320 m_compiler->getSema().addExternalSource(ast_source_wrapper);
1325 if (ast_context.getLangOpts().Modules) {
1326 assert(
m_compiler->getASTContext().getExternalSource() &&
1327 "ASTContext doesn't know about the ASTReader?");
1328 assert(
m_compiler->getSema().getExternalSource() &&
1329 "Sema doesn't know about the ASTReader?");
1333 llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(
1335 ParseAST(
m_compiler->getSema(),
false,
false);
1339 if (ast_context.getLangOpts().Modules)
1351 unsigned num_errors = adapter->getNumErrors();
1356 "while importing modules:");
1369static void ApplyFixIt(
const FixItHint &fixit, clang::edit::Commit &commit) {
1371 if (fixit.CodeToInsert.empty()) {
1372 if (fixit.InsertFromRange.isValid()) {
1373 commit.insertFromRange(fixit.RemoveRange.getBegin(),
1374 fixit.InsertFromRange,
false,
1375 fixit.BeforePreviousInsertions);
1378 commit.remove(fixit.RemoveRange);
1381 if (fixit.RemoveRange.isTokenRange() ||
1382 fixit.RemoveRange.getBegin() != fixit.RemoveRange.getEnd()) {
1383 commit.replace(fixit.RemoveRange, fixit.CodeToInsert);
1386 commit.insert(fixit.RemoveRange.getBegin(), fixit.CodeToInsert,
1387 false, fixit.BeforePreviousInsertions);
1392 clang::SourceManager &source_manager =
m_compiler->getSourceManager();
1393 clang::edit::EditedSource editor(source_manager,
m_compiler->getLangOpts(),
1395 clang::edit::Commit commit(editor);
1396 clang::Rewriter rewriter(source_manager,
m_compiler->getLangOpts());
1398 class RewritesReceiver :
public edit::EditsReceiver {
1402 RewritesReceiver(Rewriter &in_rewrite) : rewrite(in_rewrite) {}
1404 void insert(SourceLocation loc, StringRef text)
override {
1405 rewrite.InsertText(loc, text);
1407 void replace(CharSourceRange range, StringRef text)
override {
1408 rewrite.ReplaceText(range.getBegin(), rewrite.getRangeSize(range), text);
1412 RewritesReceiver rewrites_receiver(rewriter);
1415 size_t num_diags = diagnostics.size();
1419 for (
const auto &diag : diagnostic_manager.
Diagnostics()) {
1420 const auto *diagnostic = llvm::dyn_cast<ClangDiagnostic>(diag.get());
1423 if (!diagnostic->HasFixIts())
1425 for (
const FixItHint &fixit : diagnostic->FixIts())
1430 if (!commit.isCommitable())
1432 else if (!editor.commit(commit))
1436 editor.applyRewrites(rewrites_receiver);
1437 RewriteBuffer &main_file_buffer =
1438 rewriter.getEditBuffer(source_manager.getMainFileID());
1440 std::string fixed_expression;
1441 llvm::raw_string_ostream out_stream(fixed_expression);
1443 main_file_buffer.write(out_stream);
1450 llvm::Module *module,
const char *orig_name) {
1451 for (
const auto &func : module->getFunctionList()) {
1452 const StringRef &name = func.getName();
1453 if (name.contains(orig_name)) {
1472 std::unique_ptr<llvm::Module> llvm_module_up(
1475 if (!llvm_module_up) {
1486 m_expr.FunctionName())) {
1488 "Couldn't find %s() in the module",
m_expr.FunctionName());
1499 sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything);
1506 auto lang =
m_expr.Language();
1507 LLDB_LOGF(log,
"%s - Current expression language is %s\n", __FUNCTION__,
1508 lang.GetDescription().data());
1510 if (process_sp && lang) {
1511 auto runtime = process_sp->GetLanguageRuntime(lang.AsLanguageType());
1513 runtime->GetIRPasses(custom_passes);
1519 "%s - Running Early IR Passes from LanguageRuntime on "
1520 "expression module '%s'",
1521 __FUNCTION__,
m_expr.FunctionName());
1526 execution_unit_sp = std::make_shared<IRExecutionUnit>(
1532 if (
auto *options =
m_expr.GetOptions())
1533 execution_unit_sp->AppendPreferredSymbolContexts(
1534 options->GetPreferredSymbolContexts());
1537 dyn_cast<ClangExpressionHelper>(
m_expr.GetTypeSystemHelper());
1539 type_system_helper->
DeclMap();
1544 *execution_unit_sp, error_stream,
1547 if (!ir_for_target.
runOnModule(*execution_unit_sp->GetModule())) {
1558 bool interpret_function_calls =
1561 *execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(),
1562 interpret_error, interpret_function_calls);
1566 "Can't evaluate the expression without a running target due to: %s",
1574 "Expression needed to run in the target, but the "
1575 "target can't be run");
1581 "Top-level code needs to be inserted into a runnable "
1582 "target, but the target can't be run");
1588 if (
m_expr.NeedsValidation() && process) {
1594 if (Error Err = dynamic_checkers->
Install(install_diags, exe_ctx))
1600 LLDB_LOGF(log,
"== [ClangExpressionParser::PrepareForExecution] "
1601 "Finished installing dynamic checkers ==");
1604 if (
auto *checker_funcs = llvm::dyn_cast<ClangDynamicCheckerFunctions>(
1609 llvm::Module *module = execution_unit_sp->GetModule();
1610 if (!module || !ir_dynamic_checks.
runOnModule(*module)) {
1612 "Couldn't add dynamic checks to the expression");
1618 "%s - Running Late IR Passes from LanguageRuntime on "
1619 "expression module '%s'",
1620 __FUNCTION__,
m_expr.FunctionName());
1630 execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
1633 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.