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"
105using namespace clang;
124 clang::SourceManager &source_mgr)
128 void moduleImport(SourceLocation import_location, clang::ModuleIdPath path,
129 const clang::Module * )
override {
132 llvm::StringRef filename =
133 m_source_mgr.getPresumedLoc(import_location).getFilename();
139 for (
const IdentifierLoc &component : path)
140 module.path.push_back(
141 ConstString(component.getIdentifierInfo()->getName()));
144 if (
auto err =
m_decl_vendor.AddModule(module, &exported_modules)) {
160 for (
auto &fix_it : Info.getFixItHints()) {
173 m_os = std::make_unique<llvm::raw_string_ostream>(
m_output);
175 std::make_unique<clang::TextDiagnosticPrinter>(*
m_os,
m_options);
188 for (
auto it = diags.rbegin(); it != diags.rend(); it++) {
201 const clang::Diagnostic &Info)
override {
210 llvm::SmallVector<char, 32> diag_str;
211 Info.FormatDiagnostic(diag_str);
212 diag_str.push_back(
'\0');
213 const char *plain_diag = diag_str.data();
214 LLDB_LOG(log,
"Received diagnostic outside parsing: {0}", plain_diag);
220 DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
228 case DiagnosticsEngine::Level::Fatal:
229 case DiagnosticsEngine::Level::Error:
232 case DiagnosticsEngine::Level::Warning:
235 case DiagnosticsEngine::Level::Remark:
236 case DiagnosticsEngine::Level::Ignored:
239 case DiagnosticsEngine::Level::Note:
249 if (!clang_diag || clang_diag->HasFixIts())
259 std::string stripped_output =
260 std::string(llvm::StringRef(
m_output).trim());
263 if (Info.hasSourceManager()) {
265 clang::SourceManager &sm = Info.getSourceManager();
266 const clang::SourceLocation sloc = Info.getLocation();
267 if (sloc.isValid()) {
268 const clang::FullSourceLoc fsloc(sloc, sm);
269 clang::PresumedLoc PLoc = fsloc.getPresumedLoc(
true);
271 PLoc.isValid() ? PLoc.getFilename() : StringRef{};
273 loc.
line = fsloc.getSpellingLineNumber();
274 loc.
column = fsloc.getSpellingColumnNumber();
276 loc.
hidden = filename.starts_with(
"<lldb wrapper ");
279 for (
const auto &range : Info.getRanges()) {
280 if (range.getBegin() != sloc)
282 SourceLocation end = range.getEnd();
283 if (range.isTokenRange())
284 end = clang::Lexer::getLocForEndOfToken(end, 0, sm,
m_lang_opts);
286 unsigned end_col = sm.getSpellingColumnNumber(end);
288 if (end_col != sm.getSpellingLineNumber(sloc))
294 detail.source_location = loc;
297 llvm::SmallString<0> msg;
298 Info.FormatDiagnostic(msg);
299 detail.message = msg.str();
300 detail.rendered = stripped_output;
301 auto new_diagnostic =
302 std::make_unique<ClangDiagnostic>(
detail, Info.getID());
311 m_manager->AddDiagnostic(std::move(new_diagnostic));
328 std::unique_ptr<llvm::raw_string_ostream>
m_os;
334 std::vector<std::string> include_directories,
338 HeaderSearchOptions &search_opts = compiler->getHeaderSearchOpts();
340 for (
const std::string &dir : include_directories) {
341 search_opts.AddPath(dir, frontend::System,
false,
true);
342 LLDB_LOG(log,
"Added user include dir: {0}", dir);
345 llvm::SmallString<128> module_cache;
347 props.GetClangModulesCachePath().GetPath(module_cache);
348 search_opts.ModuleCachePath = std::string(module_cache.str());
349 LLDB_LOG(log,
"Using module cache path: {0}", module_cache.c_str());
353 search_opts.ImplicitModuleMaps =
true;
361 if (token ==
"using")
364 if (token ==
"__null")
367 LangOptions cpp_lang_opts;
368 cpp_lang_opts.CPlusPlus =
true;
369 cpp_lang_opts.CPlusPlus11 =
true;
370 cpp_lang_opts.CPlusPlus20 =
true;
372 clang::IdentifierInfo &ii = idents.get(token);
375 if (!ii.isCPlusPlusKeyword(cpp_lang_opts))
378 if (ii.getTokenID() == clang::tok::identifier)
382 ii.revertTokenIDToIdentifier();
387#define KEYWORD(NAME, FLAGS) RemoveCppKeyword(idents, llvm::StringRef(#NAME));
388#include "clang/Basic/TokenKinds.def"
394 const std::vector<const char *> groupsToIgnore = {
397 "unused-getter-return-value",
399 for (
const char *group : groupsToIgnore) {
400 compiler.getDiagnostics().setSeverityForGroup(
401 clang::diag::Flavor::WarningOrError, group,
402 clang::diag::Severity::Ignored, SourceLocation());
414 if (target_arch.
IsMIPS()) {
427 if (target_arch.
GetTriple().isRISCV64()) {
442 if (target_arch.
GetTriple().isRISCV32()) {
457 if (target_arch.
GetTriple().isLoongArch64()) {
478 const auto target_machine = target_arch.
GetMachine();
480 std::string triple = target_arch.
GetTriple().str();
481 compiler.getTargetOpts().Triple = triple;
482 LLDB_LOGF(log,
"Using %s as the target triple",
483 compiler.getTargetOpts().Triple.c_str());
491 compiler.getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
492 LLDB_LOGF(log,
"Using default target triple of %s",
493 compiler.getTargetOpts().Triple.c_str());
497 if (compiler.getTargetOpts().Triple.find(
"arm64") == std::string::npos &&
498 compiler.getTargetOpts().Triple.find(
"arm") != std::string::npos &&
499 compiler.getTargetOpts().Triple.find(
"ios") != std::string::npos) {
500 compiler.getTargetOpts().ABI =
"apcs-gnu";
503 if (target_machine == llvm::Triple::x86 ||
504 target_machine == llvm::Triple::x86_64) {
505 compiler.getTargetOpts().FeaturesAsWritten.push_back(
"+sse");
506 compiler.getTargetOpts().FeaturesAsWritten.push_back(
"+sse2");
516 compiler.getTargetOpts().ABI = std::move(abi);
518 if ((target_machine == llvm::Triple::riscv64 &&
519 compiler.getTargetOpts().ABI ==
"lp64f") ||
520 (target_machine == llvm::Triple::riscv32 &&
521 compiler.getTargetOpts().ABI ==
"ilp32f"))
522 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+f");
524 if ((target_machine == llvm::Triple::riscv64 &&
525 compiler.getTargetOpts().ABI ==
"lp64d") ||
526 (target_machine == llvm::Triple::riscv32 &&
527 compiler.getTargetOpts().ABI ==
"ilp32d"))
528 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+d");
530 if ((target_machine == llvm::Triple::loongarch64 &&
531 compiler.getTargetOpts().ABI ==
"lp64f"))
532 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+f");
534 if ((target_machine == llvm::Triple::loongarch64 &&
535 compiler.getTargetOpts().ABI ==
"lp64d"))
536 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+d");
556 "Frame has language of type {0}\nPicked {1} for expression evaluation.",
558 frame_sp ? frame_sp->GetLanguage().AsLanguageType()
563 std::string language_fallback_reason;
565 LangOptions &lang_opts = compiler.getLangOpts();
577 lang_opts.CPlusPlus =
true;
580 language_fallback_reason =
581 "Expression evaluation in pure C not supported. ";
584 lang_opts.ObjC =
true;
587 lang_opts.CPlusPlus =
true;
590 language_fallback_reason =
591 "Expression evaluation in pure Objective-C not supported. ";
599 lang_opts.CPlusPlus11 =
true;
602 lang_opts.CPlusPlus20 =
true;
608 lang_opts.CPlusPlus14 =
true;
609 lang_opts.CPlusPlus17 =
true;
614 lang_opts.CPlusPlus11 =
true;
615 compiler.getHeaderSearchOpts().UseLibcxx =
true;
618 lang_opts.CPlusPlus =
true;
622 && !(frame_sp && frame_sp->HasDebugInformation())) {
625 if (lang_opts.ObjC) {
627 language_fallback_reason =
"Possibly stopped inside system library, so "
628 "speculatively enabled Objective-C. ";
635 lang_opts.ObjC =
true;
636 lang_opts.CPlusPlus =
true;
637 lang_opts.CPlusPlus11 =
true;
638 compiler.getHeaderSearchOpts().UseLibcxx =
true;
641 if (language != language_for_note) {
643 language_fallback_reason = llvm::formatv(
644 "Expression evaluation in {0} not supported. ",
647 language_fallback_reason +=
648 llvm::formatv(
"Falling back to default language. ");
656 ArchSpec(compiler.getTargetOpts().Triple)))
657 lang_opts.ObjC =
false;
660 llvm::formatv(
"{0}Ran expression as '{1}'.", language_fallback_reason,
666 lang_opts.Bool =
true;
667 lang_opts.WChar =
true;
668 lang_opts.Blocks =
true;
669 lang_opts.DebuggerSupport =
672 lang_opts.DebuggerCastResultToId =
true;
674 lang_opts.CharIsSigned =
680 lang_opts.SpellChecking =
false;
682 if (process_sp && lang_opts.ObjC) {
684 switch (runtime->GetRuntimeVersion()) {
686 lang_opts.ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7));
690 lang_opts.ObjCRuntime.set(ObjCRuntime::FragileMacOSX,
691 VersionTuple(10, 7));
694 lang_opts.ObjCRuntime.set(ObjCRuntime::GNUstep, VersionTuple(2, 0));
698 if (runtime->HasNewLiteralsAndIndexing())
699 lang_opts.DebuggerObjCLiteral =
true;
703 lang_opts.ThreadsafeStatics =
false;
704 lang_opts.AccessControl =
false;
705 lang_opts.DollarIdents =
true;
709 lang_opts.NoBuiltin =
true;
714 LangOptions &lang_opts = compiler.getLangOpts();
715 lang_opts.Modules =
true;
717 lang_opts.ImplicitModules =
true;
719 lang_opts.ModulesLocalVisibility =
false;
723 lang_opts.ObjC =
true;
727 lang_opts.GNUMode =
true;
728 lang_opts.GNUKeywords =
true;
729 lang_opts.CPlusPlus11 =
true;
731 lang_opts.BuiltinHeadersInSystemModules =
false;
734 lang_opts.GNUCVersion = 40201;
742 lang_opts.PointerAuthIntrinsics =
true;
743 lang_opts.PointerAuthCalls =
true;
744 lang_opts.PointerAuthReturns =
true;
745 lang_opts.PointerAuthAuthTraps =
true;
746 lang_opts.PointerAuthIndirectGotos =
true;
747 lang_opts.PointerAuthVTPtrAddressDiscrimination =
true;
748 lang_opts.PointerAuthVTPtrTypeDiscrimination =
true;
749 lang_opts.PointerAuthObjcIsa =
true;
750 lang_opts.PointerAuthObjcClassROPointers =
true;
751 lang_opts.PointerAuthObjcInterfaceSel =
true;
757 std::vector<std::string> include_directories, std::string filename,
758 bool force_disable_ptrauth_codegen)
774 "Can't make an expression parser with a null scope.");
782 "Can't make an expression parser with a null target.");
787 m_compiler = std::make_unique<CompilerInstance>();
801 m_compiler->getDiagnostics().setErrorLimit(target_sp->GetExprErrorLimit());
803 if (
auto *target_info = TargetInfo::CreateTargetInfo(
805 m_compiler->getInvocation().getTargetOpts())) {
806 LLDB_LOGF(log,
"Target datalayout string: '%s'",
807 target_info->getDataLayoutString());
808 LLDB_LOGF(log,
"Target ABI: '%s'", target_info->getABI().str().c_str());
809 LLDB_LOGF(log,
"Target vector alignment: %d",
810 target_info->getMaxVectorAlign());
813 LLDB_LOGF(log,
"Failed to create TargetInfo for '%s'",
816 lldbassert(
false &&
"Failed to create TargetInfo.");
822 const llvm::Triple triple = target_sp->GetArchitecture().GetTriple();
823 const bool enable_ptrauth =
824 triple.isArm64e() && !force_disable_ptrauth_codegen;
828 auto *clang_expr = dyn_cast<ClangUserExpression>(&
m_expr);
829 if (clang_expr && clang_expr->DidImportCxxModules()) {
830 LLDB_LOG(log,
"Adding lang options for importing C++ modules");
836 m_compiler->getCodeGenOpts().EmitDeclMetadata =
true;
837 m_compiler->getCodeGenOpts().InstrumentFunctions =
false;
839 CodeGenOptions::FramePointerKind::All);
840 if (generate_debug_info)
841 m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
843 m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::NoDebugInfo);
845 if (enable_ptrauth) {
846 PointerAuthOptions &ptrauth_opts =
m_compiler->getCodeGenOpts().PointerAuth;
847 clang::CompilerInvocation::setDefaultPointerAuthOptions(
848 ptrauth_opts,
m_compiler->getLangOpts(), triple);
864 m_compiler->getDiagnostics().getDiagnosticOptions(),
865 clang_expr ? clang_expr->GetFilename() : StringRef());
866 m_compiler->getDiagnostics().setClient(diag_mgr);
889 if (
auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(
890 target_sp->GetPersistentExpressionStateForLanguage(
892 if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
893 clang_persistent_vars->GetClangModulesDeclVendor()) {
894 std::unique_ptr<PPCallbacks> pp_callbacks(
899 m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
907 auto &builtin_context = PP.getBuiltinInfo();
908 builtin_context.initializeBuiltins(PP.getIdentifierTable(),
912 clang::ASTContext &ast_context =
m_compiler->getASTContext();
915 "Expression ASTContext for '" +
m_filename +
"'", ast_context);
917 std::string module_name(
"$__lldb_module");
933class CodeComplete :
public CodeCompleteConsumer {
934 CodeCompletionTUInfo m_info;
937 unsigned m_position = 0;
940 clang::PrintingPolicy m_desc_policy;
942 struct CompletionWithPriority {
950 bool operator<(
const CompletionWithPriority &o)
const {
952 if (Priority != o.Priority)
953 return Priority > o.Priority;
956 return completion.
GetUniqueKey() < o.completion.GetUniqueKey();
963 std::vector<CompletionWithPriority> m_completions;
970 static bool IsIdChar(
char c) {
971 return c ==
'_' || std::isalnum(c) || c ==
'$';
976 static bool IsTokenSeparator(
char c) {
return c ==
' ' || c ==
'\t'; }
981 StringRef dropUnrelatedFrontTokens(StringRef cmd)
const {
987 if (IsTokenSeparator(cmd.back()))
992 StringRef to_remove = cmd;
993 while (!to_remove.empty() && !IsTokenSeparator(to_remove.back())) {
994 to_remove = to_remove.drop_back();
996 cmd = cmd.drop_front(to_remove.size());
1002 StringRef removeLastToken(StringRef cmd)
const {
1003 while (!cmd.empty() && IsIdChar(cmd.back())) {
1004 cmd = cmd.drop_back();
1012 std::string mergeCompletion(StringRef existing,
unsigned pos,
1013 StringRef completion)
const {
1014 StringRef existing_command = existing.substr(0, pos);
1017 existing_command = removeLastToken(existing_command);
1021 existing_command = dropUnrelatedFrontTokens(existing_command);
1022 return existing_command.str() + completion.str();
1035 CodeComplete(clang::LangOptions ops, std::string expr,
unsigned position)
1036 : CodeCompleteConsumer(CodeCompleteOptions()),
1037 m_info(std::make_shared<GlobalCodeCompletionAllocator>()), m_expr(expr),
1038 m_position(position), m_desc_policy(ops) {
1042 m_desc_policy.SuppressScope =
true;
1043 m_desc_policy.SuppressTagKeyword =
true;
1044 m_desc_policy.FullyQualifiedName =
false;
1045 m_desc_policy.TerseOutput =
true;
1046 m_desc_policy.IncludeNewlines =
false;
1047 m_desc_policy.UseVoidForZeroParams =
false;
1048 m_desc_policy.Bool =
true;
1053 bool isResultFilteredOut(StringRef Filter,
1054 CodeCompletionResult Result)
override {
1056 switch (Result.Kind) {
1057 case CodeCompletionResult::RK_Declaration:
1059 Result.Declaration->getIdentifier() &&
1060 Result.Declaration->getIdentifier()->getName().starts_with(Filter));
1061 case CodeCompletionResult::RK_Keyword:
1062 return !StringRef(Result.Keyword).starts_with(Filter);
1063 case CodeCompletionResult::RK_Macro:
1064 return !Result.Macro->getName().starts_with(Filter);
1065 case CodeCompletionResult::RK_Pattern:
1066 return !StringRef(Result.Pattern->getAsString()).starts_with(Filter);
1071 assert(
false &&
"Unknown completion result type?");
1086 std::optional<CompletionWithPriority>
1087 getCompletionForResult(
const CodeCompletionResult &R)
const {
1088 std::string ToInsert;
1089 std::string Description;
1092 case CodeCompletionResult::RK_Declaration: {
1093 const NamedDecl *D = R.Declaration;
1094 ToInsert = R.Declaration->getNameAsString();
1098 if (
const FunctionDecl *F = dyn_cast<FunctionDecl>(D)) {
1099 if (F->getNumParams() == 0)
1103 raw_string_ostream
OS(Description);
1104 F->print(
OS, m_desc_policy,
false);
1105 }
else if (
const VarDecl *V = dyn_cast<VarDecl>(D)) {
1106 Description = V->getType().getAsString(m_desc_policy);
1107 }
else if (
const FieldDecl *F = dyn_cast<FieldDecl>(D)) {
1108 Description = F->getType().getAsString(m_desc_policy);
1109 }
else if (
const NamespaceDecl *N = dyn_cast<NamespaceDecl>(D)) {
1112 if (!N->isAnonymousNamespace())
1117 case CodeCompletionResult::RK_Keyword:
1118 ToInsert = R.Keyword;
1120 case CodeCompletionResult::RK_Macro:
1121 ToInsert = R.Macro->getName().str();
1123 case CodeCompletionResult::RK_Pattern:
1124 ToInsert = R.Pattern->getTypedText();
1129 if (llvm::StringRef(ToInsert).starts_with(
"$__lldb_"))
1130 return std::nullopt;
1131 if (ToInsert.empty())
1132 return std::nullopt;
1135 std::string CompletionSuggestion =
1136 mergeCompletion(m_expr, m_position, ToInsert);
1138 CompletionResult::Completion completion(CompletionSuggestion, Description,
1139 CompletionMode::Normal);
1140 return {{completion, R.Priority}};
1145 void GetCompletions(CompletionRequest &request) {
1148 llvm::sort(m_completions);
1150 for (
const CompletionWithPriority &C : m_completions)
1152 C.completion.GetDescription(),
1153 C.completion.GetMode());
1158 void ProcessCodeCompleteResults(Sema &SemaRef, CodeCompletionContext Context,
1159 CodeCompletionResult *Results,
1160 unsigned NumResults)
override {
1164 StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();
1168 for (
unsigned I = 0; I != NumResults; ++I) {
1170 if (!Filter.empty() && isResultFilteredOut(Filter, Results[I]))
1173 CodeCompletionResult &R = Results[I];
1174 std::optional<CompletionWithPriority> CompletionAndPriority =
1175 getCompletionForResult(R);
1176 if (!CompletionAndPriority)
1178 m_completions.push_back(*CompletionAndPriority);
1190 void ProcessOverloadCandidates(Sema &S,
unsigned CurrentArg,
1191 OverloadCandidate *Candidates,
1192 unsigned NumCandidates,
1193 SourceLocation OpenParLoc,
1194 bool Braced)
override {
1198 CodeCompletionAllocator &getAllocator()
override {
1199 return m_info.getAllocator();
1202 CodeCompletionTUInfo &getCodeCompletionTUInfo()
override {
return m_info; }
1207 unsigned pos,
unsigned typed_pos) {
1222 CC.GetCompletions(request);
1232 CodeCompleteConsumer *completion_consumer,
1233 unsigned completion_line,
1234 unsigned completion_column) {
1241 const char *expr_text =
m_expr.Text();
1243 clang::SourceManager &source_mgr =
m_compiler->getSourceManager();
1244 bool created_main_file =
false;
1250 bool should_create_file = completion_consumer !=
nullptr;
1253 should_create_file |=
m_compiler->getCodeGenOpts().getDebugInfo() ==
1254 codegenoptions::FullDebugInfo;
1256 if (should_create_file) {
1258 llvm::SmallString<128> result_path;
1259 if (
FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
1260 tmpdir_file_spec.AppendPathComponent(
"lldb-%%%%%%.expr");
1261 std::string temp_source_path = tmpdir_file_spec.GetPath();
1262 llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path);
1264 llvm::sys::fs::createTemporaryFile(
"lldb",
"expr", temp_fd, result_path);
1267 if (temp_fd != -1) {
1269 const size_t expr_text_len = strlen(expr_text);
1270 size_t bytes_written = expr_text_len;
1272 if (bytes_written == expr_text_len) {
1274 if (
auto fileEntry =
m_compiler->getFileManager().getOptionalFileRef(
1276 source_mgr.setMainFileID(source_mgr.createFileID(
1277 *fileEntry, SourceLocation(), SrcMgr::C_User));
1278 created_main_file =
true;
1285 if (!created_main_file) {
1286 std::unique_ptr<MemoryBuffer> memory_buffer =
1287 MemoryBuffer::getMemBufferCopy(expr_text,
m_filename);
1288 source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer)));
1295 dyn_cast<ClangExpressionHelper>(
m_expr.GetTypeSystemHelper());
1301 if (completion_consumer) {
1303 source_mgr.getFileEntryRefForID(source_mgr.getMainFileID());
1308 ++completion_column;
1309 PP.SetCodeCompletionPoint(*main_file, completion_line, completion_column);
1312 ASTConsumer *ast_transformer =
1315 std::unique_ptr<clang::ASTConsumer> Consumer;
1316 if (ast_transformer) {
1317 Consumer = std::make_unique<ASTConsumerForwarder>(ast_transformer);
1321 Consumer = std::make_unique<ASTConsumer>();
1324 clang::ASTContext &ast_context =
m_compiler->getASTContext();
1327 *Consumer, TU_Complete, completion_consumer));
1328 m_compiler->setASTConsumer(std::move(Consumer));
1330 if (ast_context.getLangOpts().Modules) {
1340 llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source =
1343 auto ast_source_wrapper =
1344 llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(ast_source);
1346 if (ast_context.getExternalSource()) {
1347 auto module_wrapper = llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(
1348 ast_context.getExternalSourcePtr());
1350 auto multiplexer = llvm::makeIntrusiveRefCnt<SemaSourceWithPriorities>(
1351 module_wrapper, ast_source_wrapper);
1353 ast_context.setExternalSource(multiplexer);
1355 ast_context.setExternalSource(ast_source);
1357 m_compiler->getSema().addExternalSource(ast_source_wrapper);
1362 if (ast_context.getLangOpts().Modules) {
1363 assert(
m_compiler->getASTContext().getExternalSource() &&
1364 "ASTContext doesn't know about the ASTReader?");
1365 assert(
m_compiler->getSema().getExternalSource() &&
1366 "Sema doesn't know about the ASTReader?");
1370 llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(
1372 ParseAST(
m_compiler->getSema(),
false,
false);
1376 if (ast_context.getLangOpts().Modules)
1388 unsigned num_errors = adapter->getNumErrors();
1393 "while importing modules:");
1406static void ApplyFixIt(
const FixItHint &fixit, clang::edit::Commit &commit) {
1408 if (fixit.CodeToInsert.empty()) {
1409 if (fixit.InsertFromRange.isValid()) {
1410 commit.insertFromRange(fixit.RemoveRange.getBegin(),
1411 fixit.InsertFromRange,
false,
1412 fixit.BeforePreviousInsertions);
1415 commit.remove(fixit.RemoveRange);
1418 if (fixit.RemoveRange.isTokenRange() ||
1419 fixit.RemoveRange.getBegin() != fixit.RemoveRange.getEnd()) {
1420 commit.replace(fixit.RemoveRange, fixit.CodeToInsert);
1423 commit.insert(fixit.RemoveRange.getBegin(), fixit.CodeToInsert,
1424 false, fixit.BeforePreviousInsertions);
1429 clang::SourceManager &source_manager =
m_compiler->getSourceManager();
1430 clang::edit::EditedSource editor(source_manager,
m_compiler->getLangOpts(),
1432 clang::edit::Commit commit(editor);
1433 clang::Rewriter rewriter(source_manager,
m_compiler->getLangOpts());
1435 class RewritesReceiver :
public edit::EditsReceiver {
1439 RewritesReceiver(Rewriter &in_rewrite) : rewrite(in_rewrite) {}
1441 void insert(SourceLocation loc, StringRef text)
override {
1442 rewrite.InsertText(loc, text);
1444 void replace(CharSourceRange range, StringRef text)
override {
1445 rewrite.ReplaceText(range.getBegin(), rewrite.getRangeSize(range), text);
1449 RewritesReceiver rewrites_receiver(rewriter);
1452 size_t num_diags = diagnostics.size();
1456 for (
const auto &diag : diagnostic_manager.
Diagnostics()) {
1457 const auto *diagnostic = llvm::dyn_cast<ClangDiagnostic>(diag.get());
1460 if (!diagnostic->HasFixIts())
1462 for (
const FixItHint &fixit : diagnostic->FixIts())
1467 if (!commit.isCommitable())
1469 else if (!editor.commit(commit))
1473 editor.applyRewrites(rewrites_receiver);
1474 RewriteBuffer &main_file_buffer =
1475 rewriter.getEditBuffer(source_manager.getMainFileID());
1477 std::string fixed_expression;
1478 llvm::raw_string_ostream out_stream(fixed_expression);
1480 main_file_buffer.write(out_stream);
1487 llvm::Module *module,
const char *orig_name) {
1488 for (
const auto &func : module->getFunctionList()) {
1489 const StringRef &name = func.getName();
1490 if (name.contains(orig_name)) {
1509 std::unique_ptr<llvm::Module> llvm_module_up(
1512 if (!llvm_module_up) {
1523 m_expr.FunctionName())) {
1525 "Couldn't find %s() in the module",
m_expr.FunctionName());
1528 LLDB_LOG(log,
"Found function {0} for {1}", function_name,
1536 sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything);
1543 auto lang =
m_expr.Language();
1544 LLDB_LOGF(log,
"%s - Current expression language is %s\n", __FUNCTION__,
1545 lang.GetDescription().data());
1547 if (process_sp && lang) {
1548 auto runtime = process_sp->GetLanguageRuntime(lang.AsLanguageType());
1550 runtime->GetIRPasses(custom_passes);
1556 "%s - Running Early IR Passes from LanguageRuntime on "
1557 "expression module '%s'",
1558 __FUNCTION__,
m_expr.FunctionName());
1563 execution_unit_sp = std::make_shared<IRExecutionUnit>(
1569 if (
auto *options =
m_expr.GetOptions())
1570 execution_unit_sp->AppendPreferredSymbolContexts(
1571 options->GetPreferredSymbolContexts());
1574 dyn_cast<ClangExpressionHelper>(
m_expr.GetTypeSystemHelper());
1576 type_system_helper->
DeclMap();
1581 decl_map,
m_expr.NeedsVariableResolution(), *execution_unit_sp,
1582 error_stream, execution_policy, function_name.
AsCString(
nullptr));
1584 if (!ir_for_target.
runOnModule(*execution_unit_sp->GetModule())) {
1595 bool interpret_function_calls =
1598 *execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(),
1599 interpret_error, interpret_function_calls);
1603 "Can't evaluate the expression without a running target due to: %s",
1611 "Expression needed to run in the target, but the "
1612 "target can't be run");
1618 "Top-level code needs to be inserted into a runnable "
1619 "target, but the target can't be run");
1625 if (
m_expr.NeedsValidation() && process) {
1631 if (Error Err = dynamic_checkers->
Install(install_diags, exe_ctx))
1637 LLDB_LOGF(log,
"== [ClangExpressionParser::PrepareForExecution] "
1638 "Finished installing dynamic checkers ==");
1641 if (
auto *checker_funcs = llvm::dyn_cast<ClangDynamicCheckerFunctions>(
1646 llvm::Module *module = execution_unit_sp->GetModule();
1647 if (!module || !ir_dynamic_checks.
runOnModule(*module)) {
1649 "Couldn't add dynamic checks to the expression");
1655 "%s - Running Late IR Passes from LanguageRuntime on "
1656 "expression module '%s'",
1657 __FUNCTION__,
m_expr.FunctionName());
1667 execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
1670 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.