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;
729 lang_opts.PointerAuthIntrinsics =
true;
730 lang_opts.PointerAuthCalls =
true;
731 lang_opts.PointerAuthReturns =
true;
732 lang_opts.PointerAuthAuthTraps =
true;
733 lang_opts.PointerAuthIndirectGotos =
true;
734 lang_opts.PointerAuthVTPtrAddressDiscrimination =
true;
735 lang_opts.PointerAuthVTPtrTypeDiscrimination =
true;
736 lang_opts.PointerAuthObjcIsa =
true;
737 lang_opts.PointerAuthObjcClassROPointers =
true;
738 lang_opts.PointerAuthObjcInterfaceSel =
true;
744 std::vector<std::string> include_directories, std::string filename,
745 bool force_disable_ptrauth_codegen)
761 "Can't make an expression parser with a null scope.");
769 "Can't make an expression parser with a null target.");
774 m_compiler = std::make_unique<CompilerInstance>();
788 m_compiler->getDiagnostics().setErrorLimit(target_sp->GetExprErrorLimit());
790 if (
auto *target_info = TargetInfo::CreateTargetInfo(
792 m_compiler->getInvocation().getTargetOpts())) {
793 LLDB_LOGF(log,
"Target datalayout string: '%s'",
794 target_info->getDataLayoutString());
795 LLDB_LOGF(log,
"Target ABI: '%s'", target_info->getABI().str().c_str());
796 LLDB_LOGF(log,
"Target vector alignment: %d",
797 target_info->getMaxVectorAlign());
800 LLDB_LOGF(log,
"Failed to create TargetInfo for '%s'",
803 lldbassert(
false &&
"Failed to create TargetInfo.");
809 const llvm::Triple triple = target_sp->GetArchitecture().GetTriple();
810 const bool enable_ptrauth =
811 triple.isArm64e() && !force_disable_ptrauth_codegen;
815 auto *clang_expr = dyn_cast<ClangUserExpression>(&
m_expr);
816 if (clang_expr && clang_expr->DidImportCxxModules()) {
817 LLDB_LOG(log,
"Adding lang options for importing C++ modules");
823 m_compiler->getCodeGenOpts().EmitDeclMetadata =
true;
824 m_compiler->getCodeGenOpts().InstrumentFunctions =
false;
826 CodeGenOptions::FramePointerKind::All);
827 if (generate_debug_info)
828 m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
830 m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::NoDebugInfo);
832 if (enable_ptrauth) {
833 PointerAuthOptions &ptrauth_opts =
m_compiler->getCodeGenOpts().PointerAuth;
834 clang::CompilerInvocation::setDefaultPointerAuthOptions(
835 ptrauth_opts,
m_compiler->getLangOpts(), triple);
851 m_compiler->getDiagnostics().getDiagnosticOptions(),
852 clang_expr ? clang_expr->GetFilename() : StringRef());
853 m_compiler->getDiagnostics().setClient(diag_mgr);
876 if (
auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(
877 target_sp->GetPersistentExpressionStateForLanguage(
879 if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
880 clang_persistent_vars->GetClangModulesDeclVendor()) {
881 std::unique_ptr<PPCallbacks> pp_callbacks(
886 m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
894 auto &builtin_context = PP.getBuiltinInfo();
895 builtin_context.initializeBuiltins(PP.getIdentifierTable(),
899 clang::ASTContext &ast_context =
m_compiler->getASTContext();
902 "Expression ASTContext for '" +
m_filename +
"'", ast_context);
904 std::string module_name(
"$__lldb_module");
920class CodeComplete :
public CodeCompleteConsumer {
921 CodeCompletionTUInfo m_info;
924 unsigned m_position = 0;
927 clang::PrintingPolicy m_desc_policy;
929 struct CompletionWithPriority {
937 bool operator<(
const CompletionWithPriority &o)
const {
939 if (Priority != o.Priority)
940 return Priority > o.Priority;
943 return completion.
GetUniqueKey() < o.completion.GetUniqueKey();
950 std::vector<CompletionWithPriority> m_completions;
957 static bool IsIdChar(
char c) {
958 return c ==
'_' || std::isalnum(c) || c ==
'$';
963 static bool IsTokenSeparator(
char c) {
return c ==
' ' || c ==
'\t'; }
968 StringRef dropUnrelatedFrontTokens(StringRef cmd)
const {
974 if (IsTokenSeparator(cmd.back()))
979 StringRef to_remove = cmd;
980 while (!to_remove.empty() && !IsTokenSeparator(to_remove.back())) {
981 to_remove = to_remove.drop_back();
983 cmd = cmd.drop_front(to_remove.size());
989 StringRef removeLastToken(StringRef cmd)
const {
990 while (!cmd.empty() && IsIdChar(cmd.back())) {
991 cmd = cmd.drop_back();
999 std::string mergeCompletion(StringRef existing,
unsigned pos,
1000 StringRef completion)
const {
1001 StringRef existing_command = existing.substr(0, pos);
1004 existing_command = removeLastToken(existing_command);
1008 existing_command = dropUnrelatedFrontTokens(existing_command);
1009 return existing_command.str() + completion.str();
1022 CodeComplete(clang::LangOptions ops, std::string expr,
unsigned position)
1023 : CodeCompleteConsumer(CodeCompleteOptions()),
1024 m_info(std::make_shared<GlobalCodeCompletionAllocator>()), m_expr(expr),
1025 m_position(position), m_desc_policy(ops) {
1029 m_desc_policy.SuppressScope =
true;
1030 m_desc_policy.SuppressTagKeyword =
true;
1031 m_desc_policy.FullyQualifiedName =
false;
1032 m_desc_policy.TerseOutput =
true;
1033 m_desc_policy.IncludeNewlines =
false;
1034 m_desc_policy.UseVoidForZeroParams =
false;
1035 m_desc_policy.Bool =
true;
1040 bool isResultFilteredOut(StringRef Filter,
1041 CodeCompletionResult Result)
override {
1043 switch (Result.Kind) {
1044 case CodeCompletionResult::RK_Declaration:
1046 Result.Declaration->getIdentifier() &&
1047 Result.Declaration->getIdentifier()->getName().starts_with(Filter));
1048 case CodeCompletionResult::RK_Keyword:
1049 return !StringRef(Result.Keyword).starts_with(Filter);
1050 case CodeCompletionResult::RK_Macro:
1051 return !Result.Macro->getName().starts_with(Filter);
1052 case CodeCompletionResult::RK_Pattern:
1053 return !StringRef(Result.Pattern->getAsString()).starts_with(Filter);
1058 assert(
false &&
"Unknown completion result type?");
1073 std::optional<CompletionWithPriority>
1074 getCompletionForResult(
const CodeCompletionResult &R)
const {
1075 std::string ToInsert;
1076 std::string Description;
1079 case CodeCompletionResult::RK_Declaration: {
1080 const NamedDecl *D = R.Declaration;
1081 ToInsert = R.Declaration->getNameAsString();
1085 if (
const FunctionDecl *F = dyn_cast<FunctionDecl>(D)) {
1086 if (F->getNumParams() == 0)
1090 raw_string_ostream
OS(Description);
1091 F->print(
OS, m_desc_policy,
false);
1092 }
else if (
const VarDecl *V = dyn_cast<VarDecl>(D)) {
1093 Description = V->getType().getAsString(m_desc_policy);
1094 }
else if (
const FieldDecl *F = dyn_cast<FieldDecl>(D)) {
1095 Description = F->getType().getAsString(m_desc_policy);
1096 }
else if (
const NamespaceDecl *N = dyn_cast<NamespaceDecl>(D)) {
1099 if (!N->isAnonymousNamespace())
1104 case CodeCompletionResult::RK_Keyword:
1105 ToInsert = R.Keyword;
1107 case CodeCompletionResult::RK_Macro:
1108 ToInsert = R.Macro->getName().str();
1110 case CodeCompletionResult::RK_Pattern:
1111 ToInsert = R.Pattern->getTypedText();
1116 if (llvm::StringRef(ToInsert).starts_with(
"$__lldb_"))
1117 return std::nullopt;
1118 if (ToInsert.empty())
1119 return std::nullopt;
1122 std::string CompletionSuggestion =
1123 mergeCompletion(m_expr, m_position, ToInsert);
1125 CompletionResult::Completion completion(CompletionSuggestion, Description,
1126 CompletionMode::Normal);
1127 return {{completion, R.Priority}};
1132 void GetCompletions(CompletionRequest &request) {
1135 llvm::sort(m_completions);
1137 for (
const CompletionWithPriority &C : m_completions)
1139 C.completion.GetDescription(),
1140 C.completion.GetMode());
1145 void ProcessCodeCompleteResults(Sema &SemaRef, CodeCompletionContext Context,
1146 CodeCompletionResult *Results,
1147 unsigned NumResults)
override {
1151 StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();
1155 for (
unsigned I = 0; I != NumResults; ++I) {
1157 if (!Filter.empty() && isResultFilteredOut(Filter, Results[I]))
1160 CodeCompletionResult &R = Results[I];
1161 std::optional<CompletionWithPriority> CompletionAndPriority =
1162 getCompletionForResult(R);
1163 if (!CompletionAndPriority)
1165 m_completions.push_back(*CompletionAndPriority);
1177 void ProcessOverloadCandidates(Sema &S,
unsigned CurrentArg,
1178 OverloadCandidate *Candidates,
1179 unsigned NumCandidates,
1180 SourceLocation OpenParLoc,
1181 bool Braced)
override {
1185 CodeCompletionAllocator &getAllocator()
override {
1186 return m_info.getAllocator();
1189 CodeCompletionTUInfo &getCodeCompletionTUInfo()
override {
return m_info; }
1194 unsigned pos,
unsigned typed_pos) {
1209 CC.GetCompletions(request);
1219 CodeCompleteConsumer *completion_consumer,
1220 unsigned completion_line,
1221 unsigned completion_column) {
1228 const char *expr_text =
m_expr.Text();
1230 clang::SourceManager &source_mgr =
m_compiler->getSourceManager();
1231 bool created_main_file =
false;
1237 bool should_create_file = completion_consumer !=
nullptr;
1240 should_create_file |=
m_compiler->getCodeGenOpts().getDebugInfo() ==
1241 codegenoptions::FullDebugInfo;
1243 if (should_create_file) {
1245 llvm::SmallString<128> result_path;
1246 if (
FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
1247 tmpdir_file_spec.AppendPathComponent(
"lldb-%%%%%%.expr");
1248 std::string temp_source_path = tmpdir_file_spec.GetPath();
1249 llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path);
1251 llvm::sys::fs::createTemporaryFile(
"lldb",
"expr", temp_fd, result_path);
1254 if (temp_fd != -1) {
1256 const size_t expr_text_len = strlen(expr_text);
1257 size_t bytes_written = expr_text_len;
1259 if (bytes_written == expr_text_len) {
1261 if (
auto fileEntry =
m_compiler->getFileManager().getOptionalFileRef(
1263 source_mgr.setMainFileID(source_mgr.createFileID(
1264 *fileEntry, SourceLocation(), SrcMgr::C_User));
1265 created_main_file =
true;
1272 if (!created_main_file) {
1273 std::unique_ptr<MemoryBuffer> memory_buffer =
1274 MemoryBuffer::getMemBufferCopy(expr_text,
m_filename);
1275 source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer)));
1282 dyn_cast<ClangExpressionHelper>(
m_expr.GetTypeSystemHelper());
1288 if (completion_consumer) {
1290 source_mgr.getFileEntryRefForID(source_mgr.getMainFileID());
1295 ++completion_column;
1296 PP.SetCodeCompletionPoint(*main_file, completion_line, completion_column);
1299 ASTConsumer *ast_transformer =
1302 std::unique_ptr<clang::ASTConsumer> Consumer;
1303 if (ast_transformer) {
1304 Consumer = std::make_unique<ASTConsumerForwarder>(ast_transformer);
1308 Consumer = std::make_unique<ASTConsumer>();
1311 clang::ASTContext &ast_context =
m_compiler->getASTContext();
1314 *Consumer, TU_Complete, completion_consumer));
1315 m_compiler->setASTConsumer(std::move(Consumer));
1317 if (ast_context.getLangOpts().Modules) {
1327 llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source =
1330 auto ast_source_wrapper =
1331 llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(ast_source);
1333 if (ast_context.getExternalSource()) {
1334 auto module_wrapper = llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(
1335 ast_context.getExternalSourcePtr());
1337 auto multiplexer = llvm::makeIntrusiveRefCnt<SemaSourceWithPriorities>(
1338 module_wrapper, ast_source_wrapper);
1340 ast_context.setExternalSource(multiplexer);
1342 ast_context.setExternalSource(ast_source);
1344 m_compiler->getSema().addExternalSource(ast_source_wrapper);
1349 if (ast_context.getLangOpts().Modules) {
1350 assert(
m_compiler->getASTContext().getExternalSource() &&
1351 "ASTContext doesn't know about the ASTReader?");
1352 assert(
m_compiler->getSema().getExternalSource() &&
1353 "Sema doesn't know about the ASTReader?");
1357 llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(
1359 ParseAST(
m_compiler->getSema(),
false,
false);
1363 if (ast_context.getLangOpts().Modules)
1375 unsigned num_errors = adapter->getNumErrors();
1380 "while importing modules:");
1393static void ApplyFixIt(
const FixItHint &fixit, clang::edit::Commit &commit) {
1395 if (fixit.CodeToInsert.empty()) {
1396 if (fixit.InsertFromRange.isValid()) {
1397 commit.insertFromRange(fixit.RemoveRange.getBegin(),
1398 fixit.InsertFromRange,
false,
1399 fixit.BeforePreviousInsertions);
1402 commit.remove(fixit.RemoveRange);
1405 if (fixit.RemoveRange.isTokenRange() ||
1406 fixit.RemoveRange.getBegin() != fixit.RemoveRange.getEnd()) {
1407 commit.replace(fixit.RemoveRange, fixit.CodeToInsert);
1410 commit.insert(fixit.RemoveRange.getBegin(), fixit.CodeToInsert,
1411 false, fixit.BeforePreviousInsertions);
1416 clang::SourceManager &source_manager =
m_compiler->getSourceManager();
1417 clang::edit::EditedSource editor(source_manager,
m_compiler->getLangOpts(),
1419 clang::edit::Commit commit(editor);
1420 clang::Rewriter rewriter(source_manager,
m_compiler->getLangOpts());
1422 class RewritesReceiver :
public edit::EditsReceiver {
1426 RewritesReceiver(Rewriter &in_rewrite) : rewrite(in_rewrite) {}
1428 void insert(SourceLocation loc, StringRef text)
override {
1429 rewrite.InsertText(loc, text);
1431 void replace(CharSourceRange range, StringRef text)
override {
1432 rewrite.ReplaceText(range.getBegin(), rewrite.getRangeSize(range), text);
1436 RewritesReceiver rewrites_receiver(rewriter);
1439 size_t num_diags = diagnostics.size();
1443 for (
const auto &diag : diagnostic_manager.
Diagnostics()) {
1444 const auto *diagnostic = llvm::dyn_cast<ClangDiagnostic>(diag.get());
1447 if (!diagnostic->HasFixIts())
1449 for (
const FixItHint &fixit : diagnostic->FixIts())
1454 if (!commit.isCommitable())
1456 else if (!editor.commit(commit))
1460 editor.applyRewrites(rewrites_receiver);
1461 RewriteBuffer &main_file_buffer =
1462 rewriter.getEditBuffer(source_manager.getMainFileID());
1464 std::string fixed_expression;
1465 llvm::raw_string_ostream out_stream(fixed_expression);
1467 main_file_buffer.write(out_stream);
1474 llvm::Module *module,
const char *orig_name) {
1475 for (
const auto &func : module->getFunctionList()) {
1476 const StringRef &name = func.getName();
1477 if (name.contains(orig_name)) {
1496 std::unique_ptr<llvm::Module> llvm_module_up(
1499 if (!llvm_module_up) {
1510 m_expr.FunctionName())) {
1512 "Couldn't find %s() in the module",
m_expr.FunctionName());
1523 sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything);
1530 auto lang =
m_expr.Language();
1531 LLDB_LOGF(log,
"%s - Current expression language is %s\n", __FUNCTION__,
1532 lang.GetDescription().data());
1534 if (process_sp && lang) {
1535 auto runtime = process_sp->GetLanguageRuntime(lang.AsLanguageType());
1537 runtime->GetIRPasses(custom_passes);
1543 "%s - Running Early IR Passes from LanguageRuntime on "
1544 "expression module '%s'",
1545 __FUNCTION__,
m_expr.FunctionName());
1550 execution_unit_sp = std::make_shared<IRExecutionUnit>(
1556 if (
auto *options =
m_expr.GetOptions())
1557 execution_unit_sp->AppendPreferredSymbolContexts(
1558 options->GetPreferredSymbolContexts());
1561 dyn_cast<ClangExpressionHelper>(
m_expr.GetTypeSystemHelper());
1563 type_system_helper->
DeclMap();
1568 *execution_unit_sp, error_stream,
1569 execution_policy, function_name.
AsCString());
1571 if (!ir_for_target.
runOnModule(*execution_unit_sp->GetModule())) {
1582 bool interpret_function_calls =
1585 *execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(),
1586 interpret_error, interpret_function_calls);
1590 "Can't evaluate the expression without a running target due to: %s",
1598 "Expression needed to run in the target, but the "
1599 "target can't be run");
1605 "Top-level code needs to be inserted into a runnable "
1606 "target, but the target can't be run");
1612 if (
m_expr.NeedsValidation() && process) {
1618 if (Error Err = dynamic_checkers->
Install(install_diags, exe_ctx))
1624 LLDB_LOGF(log,
"== [ClangExpressionParser::PrepareForExecution] "
1625 "Finished installing dynamic checkers ==");
1628 if (
auto *checker_funcs = llvm::dyn_cast<ClangDynamicCheckerFunctions>(
1633 llvm::Module *module = execution_unit_sp->GetModule();
1634 if (!module || !ir_dynamic_checks.
runOnModule(*module)) {
1636 "Couldn't add dynamic checks to the expression");
1642 "%s - Running Late IR Passes from LanguageRuntime on "
1643 "expression module '%s'",
1644 __FUNCTION__,
m_expr.FunctionName());
1654 execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
1657 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 void SetPointerAuthOptionsForArm64e(LangOptions &lang_opts)
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.
ClangExpressionParser(ExecutionContextScope *exe_scope, Expression &expr, bool generate_debug_info, DiagnosticManager &diagnostic_manager, std::vector< std::string > include_directories={}, std::string filename="<clang expression>", bool force_disable_ptrauth_codegen=false)
Constructor.
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.
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.