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. ");
658 ArchSpec(compiler.getTargetOpts().Triple)))
659 lang_opts.ObjC =
false;
662 llvm::formatv(
"{0}Ran expression as '{1}'.", language_fallback_reason,
668 lang_opts.Bool =
true;
669 lang_opts.WChar =
true;
670 lang_opts.Blocks =
true;
671 lang_opts.DebuggerSupport =
674 lang_opts.DebuggerCastResultToId =
true;
676 lang_opts.CharIsSigned =
682 lang_opts.SpellChecking =
false;
684 if (process_sp && lang_opts.ObjC) {
686 switch (runtime->GetRuntimeVersion()) {
688 lang_opts.ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7));
692 lang_opts.ObjCRuntime.set(ObjCRuntime::FragileMacOSX,
693 VersionTuple(10, 7));
696 lang_opts.ObjCRuntime.set(ObjCRuntime::GNUstep, VersionTuple(2, 0));
700 if (runtime->HasNewLiteralsAndIndexing())
701 lang_opts.DebuggerObjCLiteral =
true;
705 lang_opts.ThreadsafeStatics =
false;
706 lang_opts.AccessControl =
false;
707 lang_opts.DollarIdents =
true;
711 lang_opts.NoBuiltin =
true;
716 LangOptions &lang_opts = compiler.getLangOpts();
717 lang_opts.Modules =
true;
719 lang_opts.ImplicitModules =
true;
721 lang_opts.ModulesLocalVisibility =
false;
725 lang_opts.ObjC =
true;
729 lang_opts.GNUMode =
true;
730 lang_opts.GNUKeywords =
true;
731 lang_opts.CPlusPlus11 =
true;
733 lang_opts.BuiltinHeadersInSystemModules =
false;
736 lang_opts.GNUCVersion = 40201;
744 lang_opts.PointerAuthIntrinsics =
true;
745 lang_opts.PointerAuthCalls =
true;
746 lang_opts.PointerAuthReturns =
true;
747 lang_opts.PointerAuthAuthTraps =
true;
748 lang_opts.PointerAuthIndirectGotos =
true;
749 lang_opts.PointerAuthVTPtrAddressDiscrimination =
true;
750 lang_opts.PointerAuthVTPtrTypeDiscrimination =
true;
751 lang_opts.PointerAuthObjcIsa =
true;
752 lang_opts.PointerAuthObjcClassROPointers =
true;
753 lang_opts.PointerAuthObjcInterfaceSel =
true;
759 std::vector<std::string> include_directories, std::string filename,
760 bool force_disable_ptrauth_codegen)
776 "Can't make an expression parser with a null scope.");
784 "Can't make an expression parser with a null target.");
789 m_compiler = std::make_unique<CompilerInstance>();
803 m_compiler->getDiagnostics().setErrorLimit(target_sp->GetExprErrorLimit());
805 if (
auto *target_info = TargetInfo::CreateTargetInfo(
807 m_compiler->getInvocation().getTargetOpts())) {
808 LLDB_LOGF(log,
"Target datalayout string: '%s'",
809 target_info->getDataLayoutString());
810 LLDB_LOGF(log,
"Target ABI: '%s'", target_info->getABI().str().c_str());
811 LLDB_LOGF(log,
"Target vector alignment: %d",
812 target_info->getMaxVectorAlign());
815 LLDB_LOGF(log,
"Failed to create TargetInfo for '%s'",
818 lldbassert(
false &&
"Failed to create TargetInfo.");
824 const llvm::Triple triple = target_sp->GetArchitecture().GetTriple();
825 const bool enable_ptrauth =
826 triple.isArm64e() && !force_disable_ptrauth_codegen;
830 auto *clang_expr = dyn_cast<ClangUserExpression>(&
m_expr);
831 if (clang_expr && clang_expr->DidImportCxxModules()) {
832 LLDB_LOG(log,
"Adding lang options for importing C++ modules");
838 m_compiler->getCodeGenOpts().EmitDeclMetadata =
true;
839 m_compiler->getCodeGenOpts().InstrumentFunctions =
false;
841 CodeGenOptions::FramePointerKind::All);
842 if (generate_debug_info)
843 m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
845 m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::NoDebugInfo);
847 if (enable_ptrauth) {
848 PointerAuthOptions &ptrauth_opts =
m_compiler->getCodeGenOpts().PointerAuth;
849 clang::CompilerInvocation::setDefaultPointerAuthOptions(
850 ptrauth_opts,
m_compiler->getLangOpts(), triple);
866 m_compiler->getDiagnostics().getDiagnosticOptions(),
867 clang_expr ? clang_expr->GetFilename() : StringRef());
868 m_compiler->getDiagnostics().setClient(diag_mgr);
891 if (
auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(
892 target_sp->GetPersistentExpressionStateForLanguage(
894 if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
895 clang_persistent_vars->GetClangModulesDeclVendor()) {
896 std::unique_ptr<PPCallbacks> pp_callbacks(
901 m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
909 auto &builtin_context = PP.getBuiltinInfo();
910 builtin_context.initializeBuiltins(PP.getIdentifierTable(),
914 clang::ASTContext &ast_context =
m_compiler->getASTContext();
917 "Expression ASTContext for '" +
m_filename +
"'", ast_context);
919 std::string module_name(
"$__lldb_module");
935class CodeComplete :
public CodeCompleteConsumer {
936 CodeCompletionTUInfo m_info;
939 unsigned m_position = 0;
942 clang::PrintingPolicy m_desc_policy;
944 struct CompletionWithPriority {
952 bool operator<(
const CompletionWithPriority &o)
const {
954 if (Priority != o.Priority)
955 return Priority > o.Priority;
958 return completion.
GetUniqueKey() < o.completion.GetUniqueKey();
965 std::vector<CompletionWithPriority> m_completions;
972 static bool IsIdChar(
char c) {
973 return c ==
'_' || std::isalnum(c) || c ==
'$';
978 static bool IsTokenSeparator(
char c) {
return c ==
' ' || c ==
'\t'; }
983 StringRef dropUnrelatedFrontTokens(StringRef cmd)
const {
989 if (IsTokenSeparator(cmd.back()))
994 StringRef to_remove = cmd;
995 while (!to_remove.empty() && !IsTokenSeparator(to_remove.back())) {
996 to_remove = to_remove.drop_back();
998 cmd = cmd.drop_front(to_remove.size());
1004 StringRef removeLastToken(StringRef cmd)
const {
1005 while (!cmd.empty() && IsIdChar(cmd.back())) {
1006 cmd = cmd.drop_back();
1014 std::string mergeCompletion(StringRef existing,
unsigned pos,
1015 StringRef completion)
const {
1016 StringRef existing_command = existing.substr(0, pos);
1019 existing_command = removeLastToken(existing_command);
1023 existing_command = dropUnrelatedFrontTokens(existing_command);
1024 return existing_command.str() + completion.str();
1037 CodeComplete(clang::LangOptions ops, std::string expr,
unsigned position)
1038 : CodeCompleteConsumer(CodeCompleteOptions()),
1039 m_info(std::make_shared<GlobalCodeCompletionAllocator>()), m_expr(expr),
1040 m_position(position), m_desc_policy(ops) {
1044 m_desc_policy.SuppressScope =
true;
1045 m_desc_policy.SuppressTagKeyword =
true;
1046 m_desc_policy.FullyQualifiedName =
false;
1047 m_desc_policy.TerseOutput =
true;
1048 m_desc_policy.IncludeNewlines =
false;
1049 m_desc_policy.UseVoidForZeroParams =
false;
1050 m_desc_policy.Bool =
true;
1055 bool isResultFilteredOut(StringRef Filter,
1056 CodeCompletionResult Result)
override {
1058 switch (Result.Kind) {
1059 case CodeCompletionResult::RK_Declaration:
1061 Result.Declaration->getIdentifier() &&
1062 Result.Declaration->getIdentifier()->getName().starts_with(Filter));
1063 case CodeCompletionResult::RK_Keyword:
1064 return !StringRef(Result.Keyword).starts_with(Filter);
1065 case CodeCompletionResult::RK_Macro:
1066 return !Result.Macro->getName().starts_with(Filter);
1067 case CodeCompletionResult::RK_Pattern:
1068 return !StringRef(Result.Pattern->getAsString()).starts_with(Filter);
1073 assert(
false &&
"Unknown completion result type?");
1088 std::optional<CompletionWithPriority>
1089 getCompletionForResult(
const CodeCompletionResult &R)
const {
1090 std::string ToInsert;
1091 std::string Description;
1094 case CodeCompletionResult::RK_Declaration: {
1095 const NamedDecl *D = R.Declaration;
1096 ToInsert = R.Declaration->getNameAsString();
1100 if (
const FunctionDecl *F = dyn_cast<FunctionDecl>(D)) {
1101 if (F->getNumParams() == 0)
1105 raw_string_ostream
OS(Description);
1106 F->print(
OS, m_desc_policy,
false);
1107 }
else if (
const VarDecl *V = dyn_cast<VarDecl>(D)) {
1108 Description = V->getType().getAsString(m_desc_policy);
1109 }
else if (
const FieldDecl *F = dyn_cast<FieldDecl>(D)) {
1110 Description = F->getType().getAsString(m_desc_policy);
1111 }
else if (
const NamespaceDecl *N = dyn_cast<NamespaceDecl>(D)) {
1114 if (!N->isAnonymousNamespace())
1119 case CodeCompletionResult::RK_Keyword:
1120 ToInsert = R.Keyword;
1122 case CodeCompletionResult::RK_Macro:
1123 ToInsert = R.Macro->getName().str();
1125 case CodeCompletionResult::RK_Pattern:
1126 ToInsert = R.Pattern->getTypedText();
1131 if (llvm::StringRef(ToInsert).starts_with(
"$__lldb_"))
1132 return std::nullopt;
1133 if (ToInsert.empty())
1134 return std::nullopt;
1137 std::string CompletionSuggestion =
1138 mergeCompletion(m_expr, m_position, ToInsert);
1140 CompletionResult::Completion completion(CompletionSuggestion, Description,
1141 CompletionMode::Normal);
1142 return {{completion, R.Priority}};
1147 void GetCompletions(CompletionRequest &request) {
1150 llvm::sort(m_completions);
1152 for (
const CompletionWithPriority &C : m_completions)
1154 C.completion.GetDescription(),
1155 C.completion.GetMode());
1160 void ProcessCodeCompleteResults(Sema &SemaRef, CodeCompletionContext Context,
1161 CodeCompletionResult *Results,
1162 unsigned NumResults)
override {
1166 StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();
1170 for (
unsigned I = 0; I != NumResults; ++I) {
1172 if (!Filter.empty() && isResultFilteredOut(Filter, Results[I]))
1175 CodeCompletionResult &R = Results[I];
1176 std::optional<CompletionWithPriority> CompletionAndPriority =
1177 getCompletionForResult(R);
1178 if (!CompletionAndPriority)
1180 m_completions.push_back(*CompletionAndPriority);
1192 void ProcessOverloadCandidates(Sema &S,
unsigned CurrentArg,
1193 OverloadCandidate *Candidates,
1194 unsigned NumCandidates,
1195 SourceLocation OpenParLoc,
1196 bool Braced)
override {
1200 CodeCompletionAllocator &getAllocator()
override {
1201 return m_info.getAllocator();
1204 CodeCompletionTUInfo &getCodeCompletionTUInfo()
override {
return m_info; }
1209 unsigned pos,
unsigned typed_pos) {
1224 CC.GetCompletions(request);
1234 CodeCompleteConsumer *completion_consumer,
1235 unsigned completion_line,
1236 unsigned completion_column) {
1243 const char *expr_text =
m_expr.Text();
1245 clang::SourceManager &source_mgr =
m_compiler->getSourceManager();
1246 bool created_main_file =
false;
1252 bool should_create_file = completion_consumer !=
nullptr;
1255 should_create_file |=
m_compiler->getCodeGenOpts().getDebugInfo() ==
1256 codegenoptions::FullDebugInfo;
1258 if (should_create_file) {
1260 llvm::SmallString<128> result_path;
1261 if (
FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
1262 tmpdir_file_spec.AppendPathComponent(
"lldb-%%%%%%.expr");
1263 std::string temp_source_path = tmpdir_file_spec.GetPath();
1264 llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path);
1266 llvm::sys::fs::createTemporaryFile(
"lldb",
"expr", temp_fd, result_path);
1269 if (temp_fd != -1) {
1271 const size_t expr_text_len = strlen(expr_text);
1272 size_t bytes_written = expr_text_len;
1274 if (bytes_written == expr_text_len) {
1276 if (
auto fileEntry =
m_compiler->getFileManager().getOptionalFileRef(
1278 source_mgr.setMainFileID(source_mgr.createFileID(
1279 *fileEntry, SourceLocation(), SrcMgr::C_User));
1280 created_main_file =
true;
1287 if (!created_main_file) {
1288 std::unique_ptr<MemoryBuffer> memory_buffer =
1289 MemoryBuffer::getMemBufferCopy(expr_text,
m_filename);
1290 source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer)));
1297 dyn_cast<ClangExpressionHelper>(
m_expr.GetTypeSystemHelper());
1303 if (completion_consumer) {
1305 source_mgr.getFileEntryRefForID(source_mgr.getMainFileID());
1310 ++completion_column;
1311 PP.SetCodeCompletionPoint(*main_file, completion_line, completion_column);
1314 ASTConsumer *ast_transformer =
1317 std::unique_ptr<clang::ASTConsumer> Consumer;
1318 if (ast_transformer) {
1319 Consumer = std::make_unique<ASTConsumerForwarder>(ast_transformer);
1323 Consumer = std::make_unique<ASTConsumer>();
1326 clang::ASTContext &ast_context =
m_compiler->getASTContext();
1329 *Consumer, TU_Complete, completion_consumer));
1330 m_compiler->setASTConsumer(std::move(Consumer));
1332 if (ast_context.getLangOpts().Modules) {
1342 llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source =
1345 auto ast_source_wrapper =
1346 llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(ast_source);
1348 if (ast_context.getExternalSource()) {
1349 auto module_wrapper = llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(
1350 ast_context.getExternalSourcePtr());
1352 auto multiplexer = llvm::makeIntrusiveRefCnt<SemaSourceWithPriorities>(
1353 module_wrapper, ast_source_wrapper);
1355 ast_context.setExternalSource(multiplexer);
1357 ast_context.setExternalSource(ast_source);
1359 m_compiler->getSema().addExternalSource(ast_source_wrapper);
1364 if (ast_context.getLangOpts().Modules) {
1365 assert(
m_compiler->getASTContext().getExternalSource() &&
1366 "ASTContext doesn't know about the ASTReader?");
1367 assert(
m_compiler->getSema().getExternalSource() &&
1368 "Sema doesn't know about the ASTReader?");
1372 llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(
1374 ParseAST(
m_compiler->getSema(),
false,
false);
1378 if (ast_context.getLangOpts().Modules)
1390 unsigned num_errors = adapter->getNumErrors();
1395 "while importing modules:");
1408static void ApplyFixIt(
const FixItHint &fixit, clang::edit::Commit &commit) {
1410 if (fixit.CodeToInsert.empty()) {
1411 if (fixit.InsertFromRange.isValid()) {
1412 commit.insertFromRange(fixit.RemoveRange.getBegin(),
1413 fixit.InsertFromRange,
false,
1414 fixit.BeforePreviousInsertions);
1417 commit.remove(fixit.RemoveRange);
1420 if (fixit.RemoveRange.isTokenRange() ||
1421 fixit.RemoveRange.getBegin() != fixit.RemoveRange.getEnd()) {
1422 commit.replace(fixit.RemoveRange, fixit.CodeToInsert);
1425 commit.insert(fixit.RemoveRange.getBegin(), fixit.CodeToInsert,
1426 false, fixit.BeforePreviousInsertions);
1431 clang::SourceManager &source_manager =
m_compiler->getSourceManager();
1432 clang::edit::EditedSource editor(source_manager,
m_compiler->getLangOpts(),
1434 clang::edit::Commit commit(editor);
1435 clang::Rewriter rewriter(source_manager,
m_compiler->getLangOpts());
1437 class RewritesReceiver :
public edit::EditsReceiver {
1441 RewritesReceiver(Rewriter &in_rewrite) : rewrite(in_rewrite) {}
1443 void insert(SourceLocation loc, StringRef text)
override {
1444 rewrite.InsertText(loc, text);
1446 void replace(CharSourceRange range, StringRef text)
override {
1447 rewrite.ReplaceText(range.getBegin(), rewrite.getRangeSize(range), text);
1451 RewritesReceiver rewrites_receiver(rewriter);
1454 size_t num_diags = diagnostics.size();
1458 for (
const auto &diag : diagnostic_manager.
Diagnostics()) {
1459 const auto *diagnostic = llvm::dyn_cast<ClangDiagnostic>(diag.get());
1462 if (!diagnostic->HasFixIts())
1464 for (
const FixItHint &fixit : diagnostic->FixIts())
1469 if (!commit.isCommitable())
1471 else if (!editor.commit(commit))
1475 editor.applyRewrites(rewrites_receiver);
1476 RewriteBuffer &main_file_buffer =
1477 rewriter.getEditBuffer(source_manager.getMainFileID());
1479 std::string fixed_expression;
1480 llvm::raw_string_ostream out_stream(fixed_expression);
1482 main_file_buffer.write(out_stream);
1489 llvm::Module *module,
const char *orig_name) {
1490 for (
const auto &func : module->getFunctionList()) {
1491 const StringRef &name = func.getName();
1492 if (name.contains(orig_name)) {
1511 std::unique_ptr<llvm::Module> llvm_module_up(
1514 if (!llvm_module_up) {
1525 m_expr.FunctionName())) {
1527 "Couldn't find %s() in the module",
m_expr.FunctionName());
1530 LLDB_LOG(log,
"Found function {0} for {1}", function_name,
1538 sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything);
1545 auto lang =
m_expr.Language();
1546 LLDB_LOGF(log,
"%s - Current expression language is %s\n", __FUNCTION__,
1547 lang.GetDescription().data());
1549 if (process_sp && lang) {
1550 auto runtime = process_sp->GetLanguageRuntime(lang.AsLanguageType());
1552 runtime->GetIRPasses(custom_passes);
1558 "%s - Running Early IR Passes from LanguageRuntime on "
1559 "expression module '%s'",
1560 __FUNCTION__,
m_expr.FunctionName());
1565 execution_unit_sp = std::make_shared<IRExecutionUnit>(
1571 if (
auto *options =
m_expr.GetOptions())
1572 execution_unit_sp->AppendPreferredSymbolContexts(
1573 options->GetPreferredSymbolContexts());
1576 dyn_cast<ClangExpressionHelper>(
m_expr.GetTypeSystemHelper());
1578 type_system_helper->
DeclMap();
1583 decl_map,
m_expr.NeedsVariableResolution(), *execution_unit_sp,
1584 error_stream, execution_policy, function_name.
AsCString(
nullptr));
1586 if (!ir_for_target.
runOnModule(*execution_unit_sp->GetModule())) {
1597 bool interpret_function_calls =
1600 *execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(),
1601 interpret_error, interpret_function_calls);
1605 "Can't evaluate the expression without a running target due to: %s",
1613 "Expression needed to run in the target, but the "
1614 "target can't be run");
1620 "Top-level code needs to be inserted into a runnable "
1621 "target, but the target can't be run");
1627 if (
m_expr.NeedsValidation() && process) {
1633 if (Error Err = dynamic_checkers->
Install(install_diags, exe_ctx))
1639 LLDB_LOGF(log,
"== [ClangExpressionParser::PrepareForExecution] "
1640 "Finished installing dynamic checkers ==");
1643 if (
auto *checker_funcs = llvm::dyn_cast<ClangDynamicCheckerFunctions>(
1648 llvm::Module *module = execution_unit_sp->GetModule();
1649 if (!module || !ir_dynamic_checks.
runOnModule(*module)) {
1651 "Couldn't add dynamic checks to the expression");
1657 "%s - Running Late IR Passes from LanguageRuntime on "
1658 "expression module '%s'",
1659 __FUNCTION__,
m_expr.FunctionName());
1669 execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
1672 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 bool IsSupportedForArchitecture(const ArchSpec &arch)
Returns whether the architecture's object file format supports Objective-C code generation.
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.