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/Lexer.h"
34#include "clang/Lex/Preprocessor.h"
35#include "clang/Parse/ParseAST.h"
36#include "clang/Rewrite/Core/Rewriter.h"
37#include "clang/Rewrite/Frontend/FrontendActions.h"
38#include "clang/Sema/CodeCompleteConsumer.h"
39#include "clang/Sema/Sema.h"
40#include "clang/Sema/SemaConsumer.h"
42#include "llvm/ADT/StringRef.h"
43#include "llvm/ExecutionEngine/ExecutionEngine.h"
44#include "llvm/Support/CrashRecoveryContext.h"
45#include "llvm/Support/Debug.h"
46#include "llvm/Support/Error.h"
47#include "llvm/Support/FileSystem.h"
48#include "llvm/Support/TargetSelect.h"
49#include "llvm/TargetParser/Triple.h"
51#include "llvm/IR/LLVMContext.h"
52#include "llvm/IR/Module.h"
53#include "llvm/Support/DynamicLibrary.h"
54#include "llvm/Support/ErrorHandling.h"
55#include "llvm/Support/MemoryBuffer.h"
56#include "llvm/Support/Signals.h"
57#include "llvm/TargetParser/Host.h"
107using namespace clang;
126 clang::SourceManager &source_mgr)
130 void moduleImport(SourceLocation import_location, clang::ModuleIdPath path,
131 const clang::Module * )
override {
134 llvm::StringRef filename =
135 m_source_mgr.getPresumedLoc(import_location).getFilename();
141 for (
const IdentifierLoc &component : path)
142 module.path.push_back(
143 ConstString(component.getIdentifierInfo()->getName()));
146 if (
auto err =
m_decl_vendor.AddModule(module, &exported_modules)) {
162 for (
auto &fix_it : Info.getFixItHints()) {
175 m_os = std::make_unique<llvm::raw_string_ostream>(
m_output);
177 std::make_unique<clang::TextDiagnosticPrinter>(*
m_os,
m_options);
190 for (
auto it = diags.rbegin(); it != diags.rend(); it++) {
203 const clang::Diagnostic &Info)
override {
212 llvm::SmallVector<char, 32> diag_str;
213 Info.FormatDiagnostic(diag_str);
214 diag_str.push_back(
'\0');
215 const char *plain_diag = diag_str.data();
216 LLDB_LOG(log,
"Received diagnostic outside parsing: {0}", plain_diag);
222 DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
230 case DiagnosticsEngine::Level::Fatal:
231 case DiagnosticsEngine::Level::Error:
234 case DiagnosticsEngine::Level::Warning:
237 case DiagnosticsEngine::Level::Remark:
238 case DiagnosticsEngine::Level::Ignored:
241 case DiagnosticsEngine::Level::Note:
251 if (!clang_diag || clang_diag->HasFixIts())
261 std::string stripped_output =
262 std::string(llvm::StringRef(
m_output).trim());
265 if (Info.hasSourceManager()) {
267 clang::SourceManager &sm = Info.getSourceManager();
268 const clang::SourceLocation sloc = Info.getLocation();
269 if (sloc.isValid()) {
270 const clang::FullSourceLoc fsloc(sloc, sm);
271 clang::PresumedLoc PLoc = fsloc.getPresumedLoc(
true);
273 PLoc.isValid() ? PLoc.getFilename() : StringRef{};
275 loc.
line = fsloc.getSpellingLineNumber();
276 loc.
column = fsloc.getSpellingColumnNumber();
278 loc.
hidden = filename.starts_with(
"<lldb wrapper ");
281 for (
const auto &range : Info.getRanges()) {
282 if (range.getBegin() != sloc)
284 SourceLocation end = range.getEnd();
285 if (range.isTokenRange())
286 end = clang::Lexer::getLocForEndOfToken(end, 0, sm,
m_lang_opts);
288 unsigned end_col = sm.getSpellingColumnNumber(end);
290 if (end_col != sm.getSpellingLineNumber(sloc))
296 detail.source_location = loc;
299 llvm::SmallString<0> msg;
300 Info.FormatDiagnostic(msg);
301 detail.message = msg.str();
302 detail.rendered = stripped_output;
303 auto new_diagnostic =
304 std::make_unique<ClangDiagnostic>(
detail, Info.getID());
313 m_manager->AddDiagnostic(std::move(new_diagnostic));
330 std::unique_ptr<llvm::raw_string_ostream>
m_os;
336 std::vector<std::string> include_directories,
340 HeaderSearchOptions &search_opts = compiler->getHeaderSearchOpts();
342 for (
const std::string &dir : include_directories) {
343 search_opts.AddPath(dir, frontend::System,
false,
true);
344 LLDB_LOG(log,
"Added user include dir: {0}", dir);
347 llvm::SmallString<128> module_cache;
349 props.GetClangModulesCachePath().GetPath(module_cache);
350 search_opts.ModuleCachePath = std::string(module_cache.str());
351 LLDB_LOG(log,
"Using module cache path: {0}", module_cache.c_str());
355 search_opts.ImplicitModuleMaps =
true;
363 if (token ==
"using")
366 if (token ==
"__null")
369 LangOptions cpp_lang_opts;
370 cpp_lang_opts.CPlusPlus =
true;
371 cpp_lang_opts.CPlusPlus11 =
true;
372 cpp_lang_opts.CPlusPlus20 =
true;
374 clang::IdentifierInfo &ii = idents.get(token);
377 if (!ii.isCPlusPlusKeyword(cpp_lang_opts))
380 if (ii.getTokenID() == clang::tok::identifier)
384 ii.revertTokenIDToIdentifier();
389#define KEYWORD(NAME, FLAGS) RemoveCppKeyword(idents, llvm::StringRef(#NAME));
390#include "clang/Basic/TokenKinds.def"
396 const std::vector<const char *> groupsToIgnore = {
399 "unused-getter-return-value",
401 for (
const char *group : groupsToIgnore) {
402 compiler.getDiagnostics().setSeverityForGroup(
403 clang::diag::Flavor::WarningOrError, group,
404 clang::diag::Severity::Ignored, SourceLocation());
416 if (target_arch.
IsMIPS()) {
429 if (target_arch.
GetTriple().isRISCV64()) {
444 if (target_arch.
GetTriple().isRISCV32()) {
459 if (target_arch.
GetTriple().isLoongArch64()) {
480 const auto target_machine = target_arch.
GetMachine();
482 std::string triple = target_arch.
GetTriple().str();
483 compiler.getTargetOpts().Triple = triple;
484 LLDB_LOGF(log,
"Using %s as the target triple",
485 compiler.getTargetOpts().Triple.c_str());
493 compiler.getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
494 LLDB_LOGF(log,
"Using default target triple of %s",
495 compiler.getTargetOpts().Triple.c_str());
499 if (compiler.getTargetOpts().Triple.find(
"arm64") == std::string::npos &&
500 compiler.getTargetOpts().Triple.find(
"arm") != std::string::npos &&
501 compiler.getTargetOpts().Triple.find(
"ios") != std::string::npos) {
502 compiler.getTargetOpts().ABI =
"apcs-gnu";
505 if (target_machine == llvm::Triple::x86 ||
506 target_machine == llvm::Triple::x86_64) {
507 compiler.getTargetOpts().FeaturesAsWritten.push_back(
"+sse");
508 compiler.getTargetOpts().FeaturesAsWritten.push_back(
"+sse2");
518 compiler.getTargetOpts().ABI = std::move(abi);
520 if ((target_machine == llvm::Triple::riscv64 &&
521 compiler.getTargetOpts().ABI ==
"lp64f") ||
522 (target_machine == llvm::Triple::riscv32 &&
523 compiler.getTargetOpts().ABI ==
"ilp32f"))
524 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+f");
526 if ((target_machine == llvm::Triple::riscv64 &&
527 compiler.getTargetOpts().ABI ==
"lp64d") ||
528 (target_machine == llvm::Triple::riscv32 &&
529 compiler.getTargetOpts().ABI ==
"ilp32d"))
530 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+d");
532 if ((target_machine == llvm::Triple::loongarch64 &&
533 compiler.getTargetOpts().ABI ==
"lp64f"))
534 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+f");
536 if ((target_machine == llvm::Triple::loongarch64 &&
537 compiler.getTargetOpts().ABI ==
"lp64d"))
538 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+d");
558 "Frame has language of type {0}\nPicked {1} for expression evaluation.",
560 frame_sp ? frame_sp->GetLanguage().AsLanguageType()
565 std::string language_fallback_reason;
567 LangOptions &lang_opts = compiler.getLangOpts();
579 lang_opts.CPlusPlus =
true;
582 language_fallback_reason =
583 "Expression evaluation in pure C not supported. ";
586 lang_opts.ObjC =
true;
589 lang_opts.CPlusPlus =
true;
592 language_fallback_reason =
593 "Expression evaluation in pure Objective-C not supported. ";
601 lang_opts.CPlusPlus11 =
true;
604 lang_opts.CPlusPlus20 =
true;
610 lang_opts.CPlusPlus14 =
true;
611 lang_opts.CPlusPlus17 =
true;
616 lang_opts.CPlusPlus11 =
true;
617 compiler.getHeaderSearchOpts().UseLibcxx =
true;
620 lang_opts.CPlusPlus =
true;
624 && !(frame_sp && frame_sp->HasDebugInformation())) {
627 if (lang_opts.ObjC) {
629 language_fallback_reason =
"Possibly stopped inside system library, so "
630 "speculatively enabled Objective-C. ";
637 lang_opts.ObjC =
true;
638 lang_opts.CPlusPlus =
true;
639 lang_opts.CPlusPlus11 =
true;
640 compiler.getHeaderSearchOpts().UseLibcxx =
true;
643 if (language != language_for_note) {
645 language_fallback_reason = llvm::formatv(
646 "Expression evaluation in {0} not supported. ",
649 language_fallback_reason +=
650 llvm::formatv(
"Falling back to default language. ");
656 llvm::formatv(
"{0}Ran expression as '{1}'.", language_fallback_reason,
662 lang_opts.Bool =
true;
663 lang_opts.WChar =
true;
664 lang_opts.Blocks =
true;
665 lang_opts.DebuggerSupport =
668 lang_opts.DebuggerCastResultToId =
true;
670 lang_opts.CharIsSigned =
676 lang_opts.SpellChecking =
false;
678 if (process_sp && lang_opts.ObjC) {
680 switch (runtime->GetRuntimeVersion()) {
682 lang_opts.ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7));
686 lang_opts.ObjCRuntime.set(ObjCRuntime::FragileMacOSX,
687 VersionTuple(10, 7));
690 lang_opts.ObjCRuntime.set(ObjCRuntime::GNUstep, VersionTuple(2, 0));
694 if (runtime->HasNewLiteralsAndIndexing())
695 lang_opts.DebuggerObjCLiteral =
true;
699 lang_opts.ThreadsafeStatics =
false;
700 lang_opts.AccessControl =
false;
701 lang_opts.DollarIdents =
true;
705 lang_opts.NoBuiltin =
true;
710 LangOptions &lang_opts = compiler.getLangOpts();
711 lang_opts.Modules =
true;
713 lang_opts.ImplicitModules =
true;
715 lang_opts.ModulesLocalVisibility =
false;
719 lang_opts.ObjC =
true;
723 lang_opts.GNUMode =
true;
724 lang_opts.GNUKeywords =
true;
725 lang_opts.CPlusPlus11 =
true;
727 lang_opts.BuiltinHeadersInSystemModules =
false;
730 lang_opts.GNUCVersion = 40201;
738 lang_opts.PointerAuthIntrinsics =
true;
739 lang_opts.PointerAuthCalls =
true;
740 lang_opts.PointerAuthReturns =
true;
741 lang_opts.PointerAuthAuthTraps =
true;
742 lang_opts.PointerAuthIndirectGotos =
true;
743 lang_opts.PointerAuthVTPtrAddressDiscrimination =
true;
744 lang_opts.PointerAuthVTPtrTypeDiscrimination =
true;
745 lang_opts.PointerAuthObjcIsa =
true;
746 lang_opts.PointerAuthObjcClassROPointers =
true;
747 lang_opts.PointerAuthObjcInterfaceSel =
true;
753 std::vector<std::string> include_directories, std::string filename,
754 bool force_disable_ptrauth_codegen)
770 "Can't make an expression parser with a null scope.");
778 "Can't make an expression parser with a null target.");
783 m_compiler = std::make_unique<CompilerInstance>();
797 m_compiler->getDiagnostics().setErrorLimit(target_sp->GetExprErrorLimit());
799 if (
auto *target_info = TargetInfo::CreateTargetInfo(
801 m_compiler->getInvocation().getTargetOpts())) {
802 LLDB_LOGF(log,
"Target datalayout string: '%s'",
803 target_info->getDataLayoutString());
804 LLDB_LOGF(log,
"Target ABI: '%s'", target_info->getABI().str().c_str());
805 LLDB_LOGF(log,
"Target vector alignment: %d",
806 target_info->getMaxVectorAlign());
809 LLDB_LOGF(log,
"Failed to create TargetInfo for '%s'",
812 lldbassert(
false &&
"Failed to create TargetInfo.");
818 const llvm::Triple triple = target_sp->GetArchitecture().GetTriple();
819 const bool enable_ptrauth =
820 triple.isArm64e() && !force_disable_ptrauth_codegen;
824 auto *clang_expr = dyn_cast<ClangUserExpression>(&
m_expr);
825 if (clang_expr && clang_expr->DidImportCxxModules()) {
826 LLDB_LOG(log,
"Adding lang options for importing C++ modules");
832 m_compiler->getCodeGenOpts().EmitDeclMetadata =
true;
833 m_compiler->getCodeGenOpts().InstrumentFunctions =
false;
835 CodeGenOptions::FramePointerKind::All);
836 if (generate_debug_info)
837 m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
839 m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::NoDebugInfo);
841 if (enable_ptrauth) {
842 PointerAuthOptions &ptrauth_opts =
m_compiler->getCodeGenOpts().PointerAuth;
843 clang::CompilerInvocation::setDefaultPointerAuthOptions(
844 ptrauth_opts,
m_compiler->getLangOpts(), triple);
860 m_compiler->getDiagnostics().getDiagnosticOptions(),
861 clang_expr ? clang_expr->GetFilename() : StringRef());
862 m_compiler->getDiagnostics().setClient(diag_mgr);
885 if (
auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(
886 target_sp->GetPersistentExpressionStateForLanguage(
888 if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
889 clang_persistent_vars->GetClangModulesDeclVendor()) {
890 std::unique_ptr<PPCallbacks> pp_callbacks(
895 m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
903 auto &builtin_context = PP.getBuiltinInfo();
904 builtin_context.initializeBuiltins(PP.getIdentifierTable(),
908 clang::ASTContext &ast_context =
m_compiler->getASTContext();
911 "Expression ASTContext for '" +
m_filename +
"'", ast_context);
913 std::string module_name(
"$__lldb_module");
929class CodeComplete :
public CodeCompleteConsumer {
930 CodeCompletionTUInfo m_info;
933 unsigned m_position = 0;
936 clang::PrintingPolicy m_desc_policy;
938 struct CompletionWithPriority {
946 bool operator<(
const CompletionWithPriority &o)
const {
948 if (Priority != o.Priority)
949 return Priority > o.Priority;
952 return completion.
GetUniqueKey() < o.completion.GetUniqueKey();
959 std::vector<CompletionWithPriority> m_completions;
966 static bool IsIdChar(
char c) {
967 return c ==
'_' || std::isalnum(c) || c ==
'$';
972 static bool IsTokenSeparator(
char c) {
return c ==
' ' || c ==
'\t'; }
977 StringRef dropUnrelatedFrontTokens(StringRef cmd)
const {
983 if (IsTokenSeparator(cmd.back()))
988 StringRef to_remove = cmd;
989 while (!to_remove.empty() && !IsTokenSeparator(to_remove.back())) {
990 to_remove = to_remove.drop_back();
992 cmd = cmd.drop_front(to_remove.size());
998 StringRef removeLastToken(StringRef cmd)
const {
999 while (!cmd.empty() && IsIdChar(cmd.back())) {
1000 cmd = cmd.drop_back();
1008 std::string mergeCompletion(StringRef existing,
unsigned pos,
1009 StringRef completion)
const {
1010 StringRef existing_command = existing.substr(0, pos);
1013 existing_command = removeLastToken(existing_command);
1017 existing_command = dropUnrelatedFrontTokens(existing_command);
1018 return existing_command.str() + completion.str();
1031 CodeComplete(clang::LangOptions ops, std::string expr,
unsigned position)
1032 : CodeCompleteConsumer(CodeCompleteOptions()),
1033 m_info(std::make_shared<GlobalCodeCompletionAllocator>()), m_expr(expr),
1034 m_position(position), m_desc_policy(ops) {
1038 m_desc_policy.SuppressScope =
true;
1039 m_desc_policy.SuppressTagKeyword =
true;
1040 m_desc_policy.FullyQualifiedName =
false;
1041 m_desc_policy.TerseOutput =
true;
1042 m_desc_policy.IncludeNewlines =
false;
1043 m_desc_policy.UseVoidForZeroParams =
false;
1044 m_desc_policy.Bool =
true;
1049 bool isResultFilteredOut(StringRef Filter,
1050 CodeCompletionResult Result)
override {
1052 switch (Result.Kind) {
1053 case CodeCompletionResult::RK_Declaration:
1055 Result.Declaration->getIdentifier() &&
1056 Result.Declaration->getIdentifier()->getName().starts_with(Filter));
1057 case CodeCompletionResult::RK_Keyword:
1058 return !StringRef(Result.Keyword).starts_with(Filter);
1059 case CodeCompletionResult::RK_Macro:
1060 return !Result.Macro->getName().starts_with(Filter);
1061 case CodeCompletionResult::RK_Pattern:
1062 return !StringRef(Result.Pattern->getAsString()).starts_with(Filter);
1067 assert(
false &&
"Unknown completion result type?");
1082 std::optional<CompletionWithPriority>
1083 getCompletionForResult(
const CodeCompletionResult &R)
const {
1084 std::string ToInsert;
1085 std::string Description;
1088 case CodeCompletionResult::RK_Declaration: {
1089 const NamedDecl *D = R.Declaration;
1090 ToInsert = R.Declaration->getNameAsString();
1094 if (
const FunctionDecl *F = dyn_cast<FunctionDecl>(D)) {
1095 if (F->getNumParams() == 0)
1099 raw_string_ostream
OS(Description);
1100 F->print(
OS, m_desc_policy,
false);
1101 }
else if (
const VarDecl *V = dyn_cast<VarDecl>(D)) {
1102 Description = V->getType().getAsString(m_desc_policy);
1103 }
else if (
const FieldDecl *F = dyn_cast<FieldDecl>(D)) {
1104 Description = F->getType().getAsString(m_desc_policy);
1105 }
else if (
const NamespaceDecl *N = dyn_cast<NamespaceDecl>(D)) {
1108 if (!N->isAnonymousNamespace())
1113 case CodeCompletionResult::RK_Keyword:
1114 ToInsert = R.Keyword;
1116 case CodeCompletionResult::RK_Macro:
1117 ToInsert = R.Macro->getName().str();
1119 case CodeCompletionResult::RK_Pattern:
1120 ToInsert = R.Pattern->getTypedText();
1125 if (llvm::StringRef(ToInsert).starts_with(
"$__lldb_"))
1126 return std::nullopt;
1127 if (ToInsert.empty())
1128 return std::nullopt;
1131 std::string CompletionSuggestion =
1132 mergeCompletion(m_expr, m_position, ToInsert);
1134 CompletionResult::Completion completion(CompletionSuggestion, Description,
1135 CompletionMode::Normal);
1136 return {{completion, R.Priority}};
1141 void GetCompletions(CompletionRequest &request) {
1144 llvm::sort(m_completions);
1146 for (
const CompletionWithPriority &C : m_completions)
1148 C.completion.GetDescription(),
1149 C.completion.GetMode());
1154 void ProcessCodeCompleteResults(Sema &SemaRef, CodeCompletionContext Context,
1155 CodeCompletionResult *Results,
1156 unsigned NumResults)
override {
1160 StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();
1164 for (
unsigned I = 0; I != NumResults; ++I) {
1166 if (!Filter.empty() && isResultFilteredOut(Filter, Results[I]))
1169 CodeCompletionResult &R = Results[I];
1170 std::optional<CompletionWithPriority> CompletionAndPriority =
1171 getCompletionForResult(R);
1172 if (!CompletionAndPriority)
1174 m_completions.push_back(*CompletionAndPriority);
1186 void ProcessOverloadCandidates(Sema &S,
unsigned CurrentArg,
1187 OverloadCandidate *Candidates,
1188 unsigned NumCandidates,
1189 SourceLocation OpenParLoc,
1190 bool Braced)
override {
1194 CodeCompletionAllocator &getAllocator()
override {
1195 return m_info.getAllocator();
1198 CodeCompletionTUInfo &getCodeCompletionTUInfo()
override {
return m_info; }
1203 unsigned pos,
unsigned typed_pos) {
1218 CC.GetCompletions(request);
1228 CodeCompleteConsumer *completion_consumer,
1229 unsigned completion_line,
1230 unsigned completion_column) {
1237 const char *expr_text =
m_expr.Text();
1239 clang::SourceManager &source_mgr =
m_compiler->getSourceManager();
1240 bool created_main_file =
false;
1246 bool should_create_file = completion_consumer !=
nullptr;
1249 should_create_file |=
m_compiler->getCodeGenOpts().getDebugInfo() ==
1250 codegenoptions::FullDebugInfo;
1252 if (should_create_file) {
1254 llvm::SmallString<128> result_path;
1255 if (
FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
1256 tmpdir_file_spec.AppendPathComponent(
"lldb-%%%%%%.expr");
1257 std::string temp_source_path = tmpdir_file_spec.GetPath();
1258 llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path);
1260 llvm::sys::fs::createTemporaryFile(
"lldb",
"expr", temp_fd, result_path);
1263 if (temp_fd != -1) {
1265 const size_t expr_text_len = strlen(expr_text);
1266 size_t bytes_written = expr_text_len;
1268 if (bytes_written == expr_text_len) {
1270 if (
auto fileEntry =
m_compiler->getFileManager().getOptionalFileRef(
1272 source_mgr.setMainFileID(source_mgr.createFileID(
1273 *fileEntry, SourceLocation(), SrcMgr::C_User));
1274 created_main_file =
true;
1281 if (!created_main_file) {
1282 std::unique_ptr<MemoryBuffer> memory_buffer =
1283 MemoryBuffer::getMemBufferCopy(expr_text,
m_filename);
1284 source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer)));
1291 dyn_cast<ClangExpressionHelper>(
m_expr.GetTypeSystemHelper());
1297 if (completion_consumer) {
1299 source_mgr.getFileEntryRefForID(source_mgr.getMainFileID());
1304 ++completion_column;
1305 PP.SetCodeCompletionPoint(*main_file, completion_line, completion_column);
1308 ASTConsumer *ast_transformer =
1311 std::unique_ptr<clang::ASTConsumer> Consumer;
1312 if (ast_transformer) {
1313 Consumer = std::make_unique<ASTConsumerForwarder>(ast_transformer);
1317 Consumer = std::make_unique<ASTConsumer>();
1320 clang::ASTContext &ast_context =
m_compiler->getASTContext();
1323 *Consumer, TU_Complete, completion_consumer));
1324 m_compiler->setASTConsumer(std::move(Consumer));
1326 if (ast_context.getLangOpts().Modules) {
1336 llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source =
1339 auto ast_source_wrapper =
1340 llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(ast_source);
1342 if (ast_context.getExternalSource()) {
1343 auto module_wrapper = llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(
1344 ast_context.getExternalSourcePtr());
1346 auto multiplexer = llvm::makeIntrusiveRefCnt<SemaSourceWithPriorities>(
1347 module_wrapper, ast_source_wrapper);
1349 ast_context.setExternalSource(multiplexer);
1351 ast_context.setExternalSource(ast_source);
1353 m_compiler->getSema().addExternalSource(ast_source_wrapper);
1358 if (ast_context.getLangOpts().Modules) {
1359 assert(
m_compiler->getASTContext().getExternalSource() &&
1360 "ASTContext doesn't know about the ASTReader?");
1361 assert(
m_compiler->getSema().getExternalSource() &&
1362 "Sema doesn't know about the ASTReader?");
1366 llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(
1368 ParseAST(
m_compiler->getSema(),
false,
false);
1372 if (ast_context.getLangOpts().Modules)
1384 unsigned num_errors = adapter->getNumErrors();
1389 "while importing modules:");
1402static void ApplyFixIt(
const FixItHint &fixit, clang::edit::Commit &commit) {
1404 if (fixit.CodeToInsert.empty()) {
1405 if (fixit.InsertFromRange.isValid()) {
1406 commit.insertFromRange(fixit.RemoveRange.getBegin(),
1407 fixit.InsertFromRange,
false,
1408 fixit.BeforePreviousInsertions);
1411 commit.remove(fixit.RemoveRange);
1414 if (fixit.RemoveRange.isTokenRange() ||
1415 fixit.RemoveRange.getBegin() != fixit.RemoveRange.getEnd()) {
1416 commit.replace(fixit.RemoveRange, fixit.CodeToInsert);
1419 commit.insert(fixit.RemoveRange.getBegin(), fixit.CodeToInsert,
1420 false, fixit.BeforePreviousInsertions);
1425 clang::SourceManager &source_manager =
m_compiler->getSourceManager();
1426 clang::edit::EditedSource editor(source_manager,
m_compiler->getLangOpts(),
1428 clang::edit::Commit commit(editor);
1429 clang::Rewriter rewriter(source_manager,
m_compiler->getLangOpts());
1431 class RewritesReceiver :
public edit::EditsReceiver {
1435 RewritesReceiver(Rewriter &in_rewrite) : rewrite(in_rewrite) {}
1437 void insert(SourceLocation loc, StringRef text)
override {
1438 rewrite.InsertText(loc, text);
1440 void replace(CharSourceRange range, StringRef text)
override {
1441 rewrite.ReplaceText(range.getBegin(), rewrite.getRangeSize(range), text);
1445 RewritesReceiver rewrites_receiver(rewriter);
1448 size_t num_diags = diagnostics.size();
1452 for (
const auto &diag : diagnostic_manager.
Diagnostics()) {
1453 const auto *diagnostic = llvm::dyn_cast<ClangDiagnostic>(diag.get());
1456 if (!diagnostic->HasFixIts())
1458 for (
const FixItHint &fixit : diagnostic->FixIts())
1463 if (!commit.isCommitable())
1465 else if (!editor.commit(commit))
1469 editor.applyRewrites(rewrites_receiver);
1470 RewriteBuffer &main_file_buffer =
1471 rewriter.getEditBuffer(source_manager.getMainFileID());
1473 std::string fixed_expression;
1474 llvm::raw_string_ostream out_stream(fixed_expression);
1476 main_file_buffer.write(out_stream);
1483 llvm::Module *module,
const char *orig_name) {
1484 for (
const auto &func : module->getFunctionList()) {
1485 const StringRef &name = func.getName();
1486 if (name.contains(orig_name)) {
1505 std::unique_ptr<llvm::Module> llvm_module_up(
1508 if (!llvm_module_up) {
1519 m_expr.FunctionName())) {
1521 "Couldn't find %s() in the module",
m_expr.FunctionName());
1524 LLDB_LOG(log,
"Found function {0} for {1}", function_name,
1532 sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything);
1539 auto lang =
m_expr.Language();
1540 LLDB_LOGF(log,
"%s - Current expression language is %s\n", __FUNCTION__,
1541 lang.GetDescription().data());
1543 if (process_sp && lang) {
1544 auto runtime = process_sp->GetLanguageRuntime(lang.AsLanguageType());
1546 runtime->GetIRPasses(custom_passes);
1552 "%s - Running Early IR Passes from LanguageRuntime on "
1553 "expression module '%s'",
1554 __FUNCTION__,
m_expr.FunctionName());
1559 execution_unit_sp = std::make_shared<IRExecutionUnit>(
1565 if (
auto *options =
m_expr.GetOptions())
1566 execution_unit_sp->AppendPreferredSymbolContexts(
1567 options->GetPreferredSymbolContexts());
1570 dyn_cast<ClangExpressionHelper>(
m_expr.GetTypeSystemHelper());
1572 type_system_helper->
DeclMap();
1577 decl_map,
m_expr.NeedsVariableResolution(), *execution_unit_sp,
1578 error_stream, execution_policy, function_name.
AsCString(
nullptr));
1580 if (!ir_for_target.
runOnModule(*execution_unit_sp->GetModule())) {
1591 bool interpret_function_calls =
1594 *execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(),
1595 interpret_error, interpret_function_calls);
1599 "Can't evaluate the expression without a running target due to: %s",
1607 "Expression needed to run in the target, but the "
1608 "target can't be run");
1614 "Top-level code needs to be inserted into a runnable "
1615 "target, but the target can't be run");
1621 if (
m_expr.NeedsValidation() && process) {
1627 if (Error Err = dynamic_checkers->
Install(install_diags, exe_ctx))
1633 LLDB_LOGF(log,
"== [ClangExpressionParser::PrepareForExecution] "
1634 "Finished installing dynamic checkers ==");
1637 if (
auto *checker_funcs = llvm::dyn_cast<ClangDynamicCheckerFunctions>(
1642 llvm::Module *module = execution_unit_sp->GetModule();
1643 if (!module || !ir_dynamic_checks.
runOnModule(*module)) {
1645 "Couldn't add dynamic checks to the expression");
1651 "%s - Running Late IR Passes from LanguageRuntime on "
1652 "expression module '%s'",
1653 __FUNCTION__,
m_expr.FunctionName());
1663 execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
1666 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.
void SetString(llvm::StringRef s)
const char * AsCString(const char *value_if_empty) const
Get the string value as a C string.
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 *src, size_t &num_bytes, off_t &offset) override
Write bytes to a file at the specified file offset.
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
NativeFilePosix NativeFile
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::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.