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/DiagnosticIDs.h"
16#include "clang/Basic/IdentifierTable.h"
17#include "clang/Basic/SourceLocation.h"
18#include "clang/Basic/TargetInfo.h"
19#include "clang/Basic/Version.h"
20#include "clang/CodeGen/CodeGenAction.h"
21#include "clang/CodeGen/ModuleBuilder.h"
22#include "clang/Edit/Commit.h"
23#include "clang/Edit/EditedSource.h"
24#include "clang/Edit/EditsReceiver.h"
25#include "clang/Frontend/CompilerInstance.h"
26#include "clang/Frontend/CompilerInvocation.h"
27#include "clang/Frontend/FrontendActions.h"
28#include "clang/Frontend/FrontendDiagnostic.h"
29#include "clang/Frontend/FrontendPluginRegistry.h"
30#include "clang/Frontend/TextDiagnostic.h"
31#include "clang/Frontend/TextDiagnosticBuffer.h"
32#include "clang/Frontend/TextDiagnosticPrinter.h"
33#include "clang/Lex/Preprocessor.h"
34#include "clang/Parse/ParseAST.h"
35#include "clang/Rewrite/Core/Rewriter.h"
36#include "clang/Rewrite/Frontend/FrontendActions.h"
37#include "clang/Sema/CodeCompleteConsumer.h"
38#include "clang/Sema/Sema.h"
39#include "clang/Sema/SemaConsumer.h"
41#include "llvm/ADT/StringRef.h"
42#include "llvm/ExecutionEngine/ExecutionEngine.h"
43#include "llvm/Support/CrashRecoveryContext.h"
44#include "llvm/Support/Debug.h"
45#include "llvm/Support/Error.h"
46#include "llvm/Support/FileSystem.h"
47#include "llvm/Support/TargetSelect.h"
48#include "llvm/TargetParser/Triple.h"
50#include "llvm/IR/LLVMContext.h"
51#include "llvm/IR/Module.h"
52#include "llvm/Support/DynamicLibrary.h"
53#include "llvm/Support/ErrorHandling.h"
54#include "llvm/Support/MemoryBuffer.h"
55#include "llvm/Support/Signals.h"
56#include "llvm/TargetParser/Host.h"
106using namespace clang;
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()));
159 for (
auto &fix_it : Info.getFixItHints()) {
172 m_os = std::make_shared<llvm::raw_string_ostream>(
m_output);
174 std::make_shared<clang::TextDiagnosticPrinter>(*
m_os,
m_options);
187 for (
auto it = diags.rbegin(); it != diags.rend(); it++) {
200 const clang::Diagnostic &Info)
override {
209 llvm::SmallVector<char, 32> diag_str;
210 Info.FormatDiagnostic(diag_str);
211 diag_str.push_back(
'\0');
212 const char *plain_diag = diag_str.data();
213 LLDB_LOG(log,
"Received diagnostic outside parsing: {0}", plain_diag);
219 DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
227 case DiagnosticsEngine::Level::Fatal:
228 case DiagnosticsEngine::Level::Error:
231 case DiagnosticsEngine::Level::Warning:
234 case DiagnosticsEngine::Level::Remark:
235 case DiagnosticsEngine::Level::Ignored:
238 case DiagnosticsEngine::Level::Note:
248 if (!clang_diag || clang_diag->HasFixIts())
258 std::string stripped_output =
259 std::string(llvm::StringRef(
m_output).trim());
262 if (Info.hasSourceManager()) {
264 clang::SourceManager &sm = Info.getSourceManager();
265 const clang::SourceLocation sloc = Info.getLocation();
266 if (sloc.isValid()) {
267 const clang::FullSourceLoc fsloc(sloc, sm);
268 clang::PresumedLoc PLoc = fsloc.getPresumedLoc(
true);
270 PLoc.isValid() ? PLoc.getFilename() : StringRef{};
272 loc.
line = fsloc.getSpellingLineNumber();
273 loc.
column = fsloc.getSpellingColumnNumber();
275 loc.
hidden = filename.starts_with(
"<lldb wrapper ");
278 for (
const auto &range : Info.getRanges()) {
279 if (range.getBegin() == sloc) {
281 unsigned end_col = sm.getSpellingColumnNumber(range.getEnd());
290 llvm::SmallString<0> msg;
291 Info.FormatDiagnostic(msg);
294 auto new_diagnostic =
295 std::make_unique<ClangDiagnostic>(detail, Info.getID());
304 m_manager->AddDiagnostic(std::move(new_diagnostic));
318 std::shared_ptr<llvm::raw_string_ostream>
m_os;
325 std::vector<std::string> include_directories,
329 HeaderSearchOptions &search_opts = compiler->getHeaderSearchOpts();
331 for (
const std::string &dir : include_directories) {
332 search_opts.AddPath(dir, frontend::System,
false,
true);
333 LLDB_LOG(log,
"Added user include dir: {0}", dir);
336 llvm::SmallString<128> module_cache;
338 props.GetClangModulesCachePath().GetPath(module_cache);
339 search_opts.ModuleCachePath = std::string(module_cache.str());
340 LLDB_LOG(log,
"Using module cache path: {0}", module_cache.c_str());
344 search_opts.ImplicitModuleMaps =
true;
352 if (token ==
"using")
355 if (token ==
"__null")
358 LangOptions cpp_lang_opts;
359 cpp_lang_opts.CPlusPlus =
true;
360 cpp_lang_opts.CPlusPlus11 =
true;
361 cpp_lang_opts.CPlusPlus20 =
true;
363 clang::IdentifierInfo &ii = idents.get(token);
366 if (!ii.isCPlusPlusKeyword(cpp_lang_opts))
369 if (ii.getTokenID() == clang::tok::identifier)
373 ii.revertTokenIDToIdentifier();
378#define KEYWORD(NAME, FLAGS) RemoveCppKeyword(idents, llvm::StringRef(#NAME));
379#include "clang/Basic/TokenKinds.def"
385 const std::vector<const char *> groupsToIgnore = {
388 "unused-getter-return-value",
390 for (
const char *group : groupsToIgnore) {
391 compiler.getDiagnostics().setSeverityForGroup(
392 clang::diag::Flavor::WarningOrError, group,
393 clang::diag::Severity::Ignored, SourceLocation());
405 if (target_arch.
IsMIPS()) {
418 if (target_arch.
GetTriple().isRISCV64()) {
433 if (target_arch.
GetTriple().isRISCV32()) {
448 if (target_arch.
GetTriple().isLoongArch64()) {
469 const auto target_machine = target_arch.
GetMachine();
471 std::string triple = target_arch.
GetTriple().str();
472 compiler.getTargetOpts().Triple = triple;
473 LLDB_LOGF(log,
"Using %s as the target triple",
474 compiler.getTargetOpts().Triple.c_str());
482 compiler.getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
483 LLDB_LOGF(log,
"Using default target triple of %s",
484 compiler.getTargetOpts().Triple.c_str());
488 if (compiler.getTargetOpts().Triple.find(
"arm64") == std::string::npos &&
489 compiler.getTargetOpts().Triple.find(
"arm") != std::string::npos &&
490 compiler.getTargetOpts().Triple.find(
"ios") != std::string::npos) {
491 compiler.getTargetOpts().ABI =
"apcs-gnu";
494 if (target_machine == llvm::Triple::x86 ||
495 target_machine == llvm::Triple::x86_64) {
496 compiler.getTargetOpts().FeaturesAsWritten.push_back(
"+sse");
497 compiler.getTargetOpts().FeaturesAsWritten.push_back(
"+sse2");
507 compiler.getTargetOpts().ABI = std::move(abi);
509 if ((target_machine == llvm::Triple::riscv64 &&
510 compiler.getTargetOpts().ABI ==
"lp64f") ||
511 (target_machine == llvm::Triple::riscv32 &&
512 compiler.getTargetOpts().ABI ==
"ilp32f"))
513 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+f");
515 if ((target_machine == llvm::Triple::riscv64 &&
516 compiler.getTargetOpts().ABI ==
"lp64d") ||
517 (target_machine == llvm::Triple::riscv32 &&
518 compiler.getTargetOpts().ABI ==
"ilp32d"))
519 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+d");
521 if ((target_machine == llvm::Triple::loongarch64 &&
522 compiler.getTargetOpts().ABI ==
"lp64f"))
523 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+f");
525 if ((target_machine == llvm::Triple::loongarch64 &&
526 compiler.getTargetOpts().ABI ==
"lp64d"))
527 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+d");
547 "Frame has language of type {0}\nPicked {1} for expression evaluation.",
549 frame_sp ? frame_sp->GetLanguage().AsLanguageType()
554 std::string language_fallback_reason;
556 LangOptions &lang_opts = compiler.getLangOpts();
568 lang_opts.CPlusPlus =
true;
571 language_fallback_reason =
572 "Expression evaluation in pure C not supported. ";
575 lang_opts.ObjC =
true;
578 lang_opts.CPlusPlus =
true;
581 language_fallback_reason =
582 "Expression evaluation in pure Objective-C not supported. ";
590 lang_opts.CPlusPlus11 =
true;
593 lang_opts.CPlusPlus20 =
true;
599 lang_opts.CPlusPlus14 =
true;
600 lang_opts.CPlusPlus17 =
true;
605 lang_opts.CPlusPlus11 =
true;
606 compiler.getHeaderSearchOpts().UseLibcxx =
true;
609 lang_opts.CPlusPlus =
true;
613 && !(frame_sp && frame_sp->HasDebugInformation()))
620 lang_opts.ObjC =
true;
621 lang_opts.CPlusPlus =
true;
622 lang_opts.CPlusPlus11 =
true;
623 compiler.getHeaderSearchOpts().UseLibcxx =
true;
626 if (language != language_for_note) {
628 language_fallback_reason = llvm::formatv(
629 "Expression evaluation in {0} not supported. ",
632 language_fallback_reason +=
633 llvm::formatv(
"Falling back to default language. ");
639 llvm::formatv(
"{0}Ran expression as '{1}'.", language_fallback_reason,
645 lang_opts.Bool =
true;
646 lang_opts.WChar =
true;
647 lang_opts.Blocks =
true;
648 lang_opts.DebuggerSupport =
651 lang_opts.DebuggerCastResultToId =
true;
653 lang_opts.CharIsSigned =
659 lang_opts.SpellChecking =
false;
661 if (process_sp && lang_opts.ObjC) {
663 switch (runtime->GetRuntimeVersion()) {
665 lang_opts.ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7));
669 lang_opts.ObjCRuntime.set(ObjCRuntime::FragileMacOSX,
670 VersionTuple(10, 7));
673 lang_opts.ObjCRuntime.set(ObjCRuntime::GNUstep, VersionTuple(2, 0));
677 if (runtime->HasNewLiteralsAndIndexing())
678 lang_opts.DebuggerObjCLiteral =
true;
682 lang_opts.ThreadsafeStatics =
false;
683 lang_opts.AccessControl =
false;
684 lang_opts.DollarIdents =
true;
688 lang_opts.NoBuiltin =
true;
693 LangOptions &lang_opts = compiler.getLangOpts();
694 lang_opts.Modules =
true;
696 lang_opts.ImplicitModules =
true;
698 lang_opts.ModulesLocalVisibility =
false;
702 lang_opts.ObjC =
true;
706 lang_opts.GNUMode =
true;
707 lang_opts.GNUKeywords =
true;
708 lang_opts.CPlusPlus11 =
true;
710 lang_opts.BuiltinHeadersInSystemModules =
false;
713 lang_opts.GNUCVersion = 40201;
723 std::vector<std::string> include_directories, std::string filename)
739 "Can't make an expression parser with a null scope.");
747 "Can't make an expression parser with a null target.");
752 m_compiler = std::make_unique<CompilerInstance>();
766 m_compiler->getDiagnostics().setErrorLimit(target_sp->GetExprErrorLimit());
768 if (
auto *target_info = TargetInfo::CreateTargetInfo(
770 m_compiler->getInvocation().getTargetOpts())) {
772 LLDB_LOGF(log,
"Target datalayout string: '%s'",
773 target_info->getDataLayoutString());
774 LLDB_LOGF(log,
"Target ABI: '%s'", target_info->getABI().str().c_str());
775 LLDB_LOGF(log,
"Target vector alignment: %d",
776 target_info->getMaxVectorAlign());
781 LLDB_LOGF(log,
"Failed to create TargetInfo for '%s'",
784 lldbassert(
false &&
"Failed to create TargetInfo.");
789 auto *clang_expr = dyn_cast<ClangUserExpression>(&
m_expr);
790 if (clang_expr && clang_expr->DidImportCxxModules()) {
791 LLDB_LOG(log,
"Adding lang options for importing C++ modules");
797 m_compiler->getCodeGenOpts().EmitDeclMetadata =
true;
798 m_compiler->getCodeGenOpts().InstrumentFunctions =
false;
800 CodeGenOptions::FramePointerKind::All);
801 if (generate_debug_info)
802 m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
804 m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::NoDebugInfo);
819 m_compiler->getDiagnostics().getDiagnosticOptions(),
820 clang_expr ? clang_expr->GetFilename() : StringRef());
821 m_compiler->getDiagnostics().setClient(diag_mgr);
844 if (
auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(
845 target_sp->GetPersistentExpressionStateForLanguage(
847 if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
848 clang_persistent_vars->GetClangModulesDeclVendor()) {
849 std::unique_ptr<PPCallbacks> pp_callbacks(
854 m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
862 auto &builtin_context = PP.getBuiltinInfo();
863 builtin_context.initializeBuiltins(PP.getIdentifierTable(),
867 clang::ASTContext &ast_context =
m_compiler->getASTContext();
870 "Expression ASTContext for '" +
m_filename +
"'", ast_context);
872 std::string module_name(
"$__lldb_module");
891class CodeComplete :
public CodeCompleteConsumer {
892 CodeCompletionTUInfo m_info;
895 unsigned m_position = 0;
898 clang::PrintingPolicy m_desc_policy;
900 struct CompletionWithPriority {
908 bool operator<(
const CompletionWithPriority &o)
const {
910 if (Priority != o.Priority)
911 return Priority > o.Priority;
914 return completion.
GetUniqueKey() < o.completion.GetUniqueKey();
921 std::vector<CompletionWithPriority> m_completions;
928 static bool IsIdChar(
char c) {
929 return c ==
'_' || std::isalnum(c) || c ==
'$';
934 static bool IsTokenSeparator(
char c) {
return c ==
' ' || c ==
'\t'; }
939 StringRef dropUnrelatedFrontTokens(StringRef cmd)
const {
945 if (IsTokenSeparator(cmd.back()))
950 StringRef to_remove = cmd;
951 while (!to_remove.empty() && !IsTokenSeparator(to_remove.back())) {
952 to_remove = to_remove.drop_back();
954 cmd = cmd.drop_front(to_remove.size());
960 StringRef removeLastToken(StringRef cmd)
const {
961 while (!cmd.empty() && IsIdChar(cmd.back())) {
962 cmd = cmd.drop_back();
970 std::string mergeCompletion(StringRef existing,
unsigned pos,
971 StringRef completion)
const {
972 StringRef existing_command = existing.substr(0, pos);
975 existing_command = removeLastToken(existing_command);
979 existing_command = dropUnrelatedFrontTokens(existing_command);
980 return existing_command.str() + completion.str();
993 CodeComplete(clang::LangOptions ops, std::string expr,
unsigned position)
994 : CodeCompleteConsumer(CodeCompleteOptions()),
995 m_info(std::make_shared<GlobalCodeCompletionAllocator>()), m_expr(expr),
996 m_position(position), m_desc_policy(ops) {
1000 m_desc_policy.SuppressScope =
true;
1001 m_desc_policy.SuppressTagKeyword =
true;
1002 m_desc_policy.FullyQualifiedName =
false;
1003 m_desc_policy.TerseOutput =
true;
1004 m_desc_policy.IncludeNewlines =
false;
1005 m_desc_policy.UseVoidForZeroParams =
false;
1006 m_desc_policy.Bool =
true;
1011 bool isResultFilteredOut(StringRef Filter,
1012 CodeCompletionResult Result)
override {
1014 switch (Result.Kind) {
1015 case CodeCompletionResult::RK_Declaration:
1017 Result.Declaration->getIdentifier() &&
1018 Result.Declaration->getIdentifier()->getName().starts_with(Filter));
1019 case CodeCompletionResult::RK_Keyword:
1020 return !StringRef(Result.Keyword).starts_with(Filter);
1021 case CodeCompletionResult::RK_Macro:
1022 return !Result.Macro->getName().starts_with(Filter);
1023 case CodeCompletionResult::RK_Pattern:
1024 return !StringRef(Result.Pattern->getAsString()).starts_with(Filter);
1029 assert(
false &&
"Unknown completion result type?");
1044 std::optional<CompletionWithPriority>
1045 getCompletionForResult(
const CodeCompletionResult &R)
const {
1046 std::string ToInsert;
1047 std::string Description;
1050 case CodeCompletionResult::RK_Declaration: {
1051 const NamedDecl *D = R.Declaration;
1052 ToInsert = R.Declaration->getNameAsString();
1056 if (
const FunctionDecl *F = dyn_cast<FunctionDecl>(D)) {
1057 if (F->getNumParams() == 0)
1061 raw_string_ostream
OS(Description);
1062 F->print(
OS, m_desc_policy,
false);
1063 }
else if (
const VarDecl *V = dyn_cast<VarDecl>(D)) {
1064 Description = V->getType().getAsString(m_desc_policy);
1065 }
else if (
const FieldDecl *F = dyn_cast<FieldDecl>(D)) {
1066 Description = F->getType().getAsString(m_desc_policy);
1067 }
else if (
const NamespaceDecl *N = dyn_cast<NamespaceDecl>(D)) {
1070 if (!N->isAnonymousNamespace())
1075 case CodeCompletionResult::RK_Keyword:
1076 ToInsert = R.Keyword;
1078 case CodeCompletionResult::RK_Macro:
1079 ToInsert = R.Macro->getName().str();
1081 case CodeCompletionResult::RK_Pattern:
1082 ToInsert = R.Pattern->getTypedText();
1087 if (llvm::StringRef(ToInsert).starts_with(
"$__lldb_"))
1088 return std::nullopt;
1089 if (ToInsert.empty())
1090 return std::nullopt;
1093 std::string CompletionSuggestion =
1094 mergeCompletion(m_expr, m_position, ToInsert);
1096 CompletionResult::Completion completion(CompletionSuggestion, Description,
1097 CompletionMode::Normal);
1098 return {{completion, R.Priority}};
1103 void GetCompletions(CompletionRequest &request) {
1106 llvm::sort(m_completions);
1108 for (
const CompletionWithPriority &C : m_completions)
1110 C.completion.GetDescription(),
1111 C.completion.GetMode());
1116 void ProcessCodeCompleteResults(Sema &SemaRef, CodeCompletionContext Context,
1117 CodeCompletionResult *Results,
1118 unsigned NumResults)
override {
1122 StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();
1126 for (
unsigned I = 0; I != NumResults; ++I) {
1128 if (!Filter.empty() && isResultFilteredOut(Filter, Results[I]))
1131 CodeCompletionResult &R = Results[I];
1132 std::optional<CompletionWithPriority> CompletionAndPriority =
1133 getCompletionForResult(R);
1134 if (!CompletionAndPriority)
1136 m_completions.push_back(*CompletionAndPriority);
1148 void ProcessOverloadCandidates(Sema &S,
unsigned CurrentArg,
1149 OverloadCandidate *Candidates,
1150 unsigned NumCandidates,
1151 SourceLocation OpenParLoc,
1152 bool Braced)
override {
1156 CodeCompletionAllocator &getAllocator()
override {
1157 return m_info.getAllocator();
1160 CodeCompletionTUInfo &getCodeCompletionTUInfo()
override {
return m_info; }
1165 unsigned pos,
unsigned typed_pos) {
1180 CC.GetCompletions(request);
1190 CodeCompleteConsumer *completion_consumer,
1191 unsigned completion_line,
1192 unsigned completion_column) {
1199 const char *expr_text =
m_expr.Text();
1201 clang::SourceManager &source_mgr =
m_compiler->getSourceManager();
1202 bool created_main_file =
false;
1208 bool should_create_file = completion_consumer !=
nullptr;
1211 should_create_file |=
m_compiler->getCodeGenOpts().getDebugInfo() ==
1212 codegenoptions::FullDebugInfo;
1214 if (should_create_file) {
1216 llvm::SmallString<128> result_path;
1217 if (
FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
1218 tmpdir_file_spec.AppendPathComponent(
"lldb-%%%%%%.expr");
1219 std::string temp_source_path = tmpdir_file_spec.GetPath();
1220 llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path);
1222 llvm::sys::fs::createTemporaryFile(
"lldb",
"expr", temp_fd, result_path);
1225 if (temp_fd != -1) {
1227 const size_t expr_text_len = strlen(expr_text);
1228 size_t bytes_written = expr_text_len;
1230 if (bytes_written == expr_text_len) {
1232 if (
auto fileEntry =
m_compiler->getFileManager().getOptionalFileRef(
1234 source_mgr.setMainFileID(source_mgr.createFileID(
1235 *fileEntry, SourceLocation(), SrcMgr::C_User));
1236 created_main_file =
true;
1243 if (!created_main_file) {
1244 std::unique_ptr<MemoryBuffer> memory_buffer =
1245 MemoryBuffer::getMemBufferCopy(expr_text,
m_filename);
1246 source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer)));
1253 dyn_cast<ClangExpressionHelper>(
m_expr.GetTypeSystemHelper());
1259 if (completion_consumer) {
1261 source_mgr.getFileEntryRefForID(source_mgr.getMainFileID());
1266 ++completion_column;
1267 PP.SetCodeCompletionPoint(*main_file, completion_line, completion_column);
1270 ASTConsumer *ast_transformer =
1273 std::unique_ptr<clang::ASTConsumer> Consumer;
1274 if (ast_transformer) {
1275 Consumer = std::make_unique<ASTConsumerForwarder>(ast_transformer);
1279 Consumer = std::make_unique<ASTConsumer>();
1282 clang::ASTContext &ast_context =
m_compiler->getASTContext();
1285 *Consumer, TU_Complete, completion_consumer));
1286 m_compiler->setASTConsumer(std::move(Consumer));
1288 if (ast_context.getLangOpts().Modules) {
1298 llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source =
1301 auto ast_source_wrapper =
1302 llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(ast_source);
1304 if (ast_context.getExternalSource()) {
1305 auto module_wrapper = llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(
1306 ast_context.getExternalSourcePtr());
1308 auto multiplexer = llvm::makeIntrusiveRefCnt<SemaSourceWithPriorities>(
1309 module_wrapper, ast_source_wrapper);
1311 ast_context.setExternalSource(multiplexer);
1313 ast_context.setExternalSource(ast_source);
1315 m_compiler->getSema().addExternalSource(ast_source_wrapper);
1320 if (ast_context.getLangOpts().Modules) {
1321 assert(
m_compiler->getASTContext().getExternalSource() &&
1322 "ASTContext doesn't know about the ASTReader?");
1323 assert(
m_compiler->getSema().getExternalSource() &&
1324 "Sema doesn't know about the ASTReader?");
1328 llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(
1330 ParseAST(
m_compiler->getSema(),
false,
false);
1334 if (ast_context.getLangOpts().Modules)
1346 unsigned num_errors = adapter->getNumErrors();
1351 "while importing modules:");
1364static void ApplyFixIt(
const FixItHint &fixit, clang::edit::Commit &commit) {
1366 if (fixit.CodeToInsert.empty()) {
1367 if (fixit.InsertFromRange.isValid()) {
1368 commit.insertFromRange(fixit.RemoveRange.getBegin(),
1369 fixit.InsertFromRange,
false,
1370 fixit.BeforePreviousInsertions);
1373 commit.remove(fixit.RemoveRange);
1376 if (fixit.RemoveRange.isTokenRange() ||
1377 fixit.RemoveRange.getBegin() != fixit.RemoveRange.getEnd()) {
1378 commit.replace(fixit.RemoveRange, fixit.CodeToInsert);
1381 commit.insert(fixit.RemoveRange.getBegin(), fixit.CodeToInsert,
1382 false, fixit.BeforePreviousInsertions);
1387 clang::SourceManager &source_manager =
m_compiler->getSourceManager();
1388 clang::edit::EditedSource editor(source_manager,
m_compiler->getLangOpts(),
1390 clang::edit::Commit commit(editor);
1391 clang::Rewriter rewriter(source_manager,
m_compiler->getLangOpts());
1393 class RewritesReceiver :
public edit::EditsReceiver {
1397 RewritesReceiver(Rewriter &in_rewrite) : rewrite(in_rewrite) {}
1399 void insert(SourceLocation loc, StringRef text)
override {
1400 rewrite.InsertText(loc, text);
1402 void replace(CharSourceRange range, StringRef text)
override {
1403 rewrite.ReplaceText(range.getBegin(), rewrite.getRangeSize(range), text);
1407 RewritesReceiver rewrites_receiver(rewriter);
1410 size_t num_diags = diagnostics.size();
1414 for (
const auto &diag : diagnostic_manager.
Diagnostics()) {
1415 const auto *diagnostic = llvm::dyn_cast<ClangDiagnostic>(diag.get());
1418 if (!diagnostic->HasFixIts())
1420 for (
const FixItHint &fixit : diagnostic->FixIts())
1425 if (!commit.isCommitable())
1427 else if (!editor.commit(commit))
1431 editor.applyRewrites(rewrites_receiver);
1432 RewriteBuffer &main_file_buffer =
1433 rewriter.getEditBuffer(source_manager.getMainFileID());
1435 std::string fixed_expression;
1436 llvm::raw_string_ostream out_stream(fixed_expression);
1438 main_file_buffer.write(out_stream);
1445 llvm::Module *module,
const char *orig_name) {
1446 for (
const auto &func : module->getFunctionList()) {
1447 const StringRef &name = func.getName();
1448 if (name.contains(orig_name)) {
1467 std::unique_ptr<llvm::Module> llvm_module_up(
1470 if (!llvm_module_up) {
1481 m_expr.FunctionName())) {
1483 "Couldn't find %s() in the module",
m_expr.FunctionName());
1494 sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything);
1501 auto lang =
m_expr.Language();
1502 LLDB_LOGF(log,
"%s - Current expression language is %s\n", __FUNCTION__,
1503 lang.GetDescription().data());
1506 auto runtime = process_sp->GetLanguageRuntime(lang.AsLanguageType());
1508 runtime->GetIRPasses(custom_passes);
1514 "%s - Running Early IR Passes from LanguageRuntime on "
1515 "expression module '%s'",
1516 __FUNCTION__,
m_expr.FunctionName());
1521 execution_unit_sp = std::make_shared<IRExecutionUnit>(
1527 if (
auto *options =
m_expr.GetOptions())
1528 execution_unit_sp->AppendPreferredSymbolContexts(
1529 options->GetPreferredSymbolContexts());
1532 dyn_cast<ClangExpressionHelper>(
m_expr.GetTypeSystemHelper());
1534 type_system_helper->
DeclMap();
1539 *execution_unit_sp, error_stream,
1542 if (!ir_for_target.
runOnModule(*execution_unit_sp->GetModule())) {
1553 bool interpret_function_calls =
1556 *execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(),
1557 interpret_error, interpret_function_calls);
1561 "Can't evaluate the expression without a running target due to: %s",
1569 "Expression needed to run in the target, but the "
1570 "target can't be run");
1576 "Top-level code needs to be inserted into a runnable "
1577 "target, but the target can't be run");
1583 if (
m_expr.NeedsValidation() && process) {
1589 if (Error Err = dynamic_checkers->
Install(install_diags, exe_ctx))
1595 LLDB_LOGF(log,
"== [ClangExpressionParser::PrepareForExecution] "
1596 "Finished installing dynamic checkers ==");
1599 if (
auto *checker_funcs = llvm::dyn_cast<ClangDynamicCheckerFunctions>(
1604 llvm::Module *module = execution_unit_sp->GetModule();
1605 if (!module || !ir_dynamic_checks.
runOnModule(*module)) {
1607 "Couldn't add dynamic checks to the expression");
1613 "%s - Running Late IR Passes from LanguageRuntime on "
1614 "expression module '%s'",
1615 __FUNCTION__,
m_expr.FunctionName());
1625 execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
1628 execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
static void SetupModuleHeaderPaths(CompilerInstance *compiler, std::vector< std::string > include_directories, lldb::TargetSP target_sp)
static void RemoveAllCppKeywords(IdentifierTable &idents)
Remove all C++ keywords from the given identifier table.
static void SetupLangOpts(CompilerInstance &compiler, ExecutionContextScope &exe_scope, const Expression &expr, DiagnosticManager &diagnostic_manager)
static void ApplyFixIt(const FixItHint &fixit, clang::edit::Commit &commit)
Applies the given Fix-It hint to the given commit.
static void SetupImportStdModuleLangOpts(CompilerInstance &compiler, lldb_private::Target &target)
static void AddAllFixIts(ClangDiagnostic *diag, const clang::Diagnostic &Info)
static void SetupDefaultClangDiagnostics(CompilerInstance &compiler)
Configures Clang diagnostics for the expression parser.
static void SetupTargetOpts(CompilerInstance &compiler, lldb_private::Target const &target)
static void RemoveCppKeyword(IdentifierTable &idents, llvm::StringRef token)
Iff the given identifier is a C++ keyword, remove it from the identifier table (i....
static bool FindFunctionInModule(ConstString &mangled_name, llvm::Module *module, const char *orig_name)
static std::string GetClangTargetABI(const ArchSpec &target_arch)
Returns a string representing current ABI.
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
#define LLDB_LOGF(log,...)
void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override
DiagnosticOptions m_options
void EndSourceFile() override
std::shared_ptr< llvm::raw_string_ostream > m_os
Output stream of m_passthrough.
std::string m_output
Output string filled by m_os.
std::shared_ptr< clang::TextDiagnosticPrinter > m_passthrough
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.
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
Transforms the IR for a function to run in the target.
bool runOnModule(llvm::Module &llvm_module)
Run this IR transformer on a single module.
static bool CanInterpret(llvm::Module &module, llvm::Function &function, lldb_private::Status &error, const bool support_function_calls)
An architecture specification class.
bool IsValid() const
Tests if this ArchSpec is valid.
llvm::Triple & GetTriple()
Architecture triple accessor.
@ eLoongArch_abi_single_float
soft float
@ eLoongArch_abi_soft_float
@ eLoongArch_abi_mask
double precision floating point, +d
@ eLoongArch_abi_double_float
single precision floating point, +f
bool IsMIPS() const
if MIPS architecture return true.
bool CharIsSignedByDefault() const
Returns true if 'char' is a signed type by default in the architecture false otherwise.
uint32_t GetFlags() const
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
@ eRISCV_float_abi_double
single precision floating point, +f
@ eRISCV_float_abi_soft
RVC, +c.
@ eRISCV_float_abi_quad
double precision floating point, +d
@ eRISCV_float_abi_mask
quad precision floating point, +q
@ eRISCV_float_abi_single
soft float
std::string GetClangTargetCPU() const
Returns a string representing current architecture as a target CPU for tools like compiler,...
llvm::IntrusiveRefCntPtr< clang::ExternalASTSource > CreateProxy()
void InstallASTContext(TypeSystemClang &ast_context)
void AddFixitHint(const clang::FixItHint &fixit)
llvm::Error Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) override
Install the utility functions into a process.
"lldb/Expression/ClangExpressionDeclMap.h" Manages named entities that are defined in LLDB's debug in...
void InstallDiagnosticManager(DiagnosticManager &diag_manager)
void InstallCodeGenerator(clang::ASTConsumer *code_gen)
virtual void CommitPersistentDecls()
virtual clang::ASTConsumer * ASTTransformer(clang::ASTConsumer *passthrough)=0
Return the object that the parser should allow to access ASTs.
virtual ClangExpressionDeclMap * DeclMap()=0
Return the object that the parser should use when resolving external values.
std::string m_filename
File name used for the user expression.
bool RewriteExpression(DiagnosticManager &diagnostic_manager) override
Try to use the FixIts in the diagnostic_manager to rewrite the expression.
unsigned ParseInternal(DiagnosticManager &diagnostic_manager, clang::CodeCompleteConsumer *completion=nullptr, unsigned completion_line=0, unsigned completion_column=0)
Parses the expression.
ClangExpressionParser(ExecutionContextScope *exe_scope, Expression &expr, bool generate_debug_info, DiagnosticManager &diagnostic_manager, std::vector< std::string > include_directories={}, std::string filename="<clang expression>")
Constructor.
std::unique_ptr< clang::CompilerInstance > m_compiler
The Clang compiler used to parse expressions into IR.
Status DoPrepareForExecution(lldb::addr_t &func_addr, lldb::addr_t &func_end, lldb::IRExecutionUnitSP &execution_unit_sp, ExecutionContext &exe_ctx, bool &can_interpret, lldb_private::ExecutionPolicy execution_policy) override
Ready an already-parsed expression for execution, possibly evaluating it statically.
unsigned Parse(DiagnosticManager &diagnostic_manager)
Parse a single expression and convert it to IR using Clang.
bool Complete(CompletionRequest &request, unsigned line, unsigned pos, unsigned typed_pos) override
Attempts to find possible command line completions for the given expression.
~ClangExpressionParser() override
Destructor.
std::unique_ptr< llvm::LLVMContext > m_llvm_context
The LLVM context to generate IR into.
std::unique_ptr< clang::CodeGenerator > m_code_generator
The Clang object that generates IR.
LLDBPreprocessorCallbacks * m_pp_callbacks
Called when the preprocessor encounters module imports.
std::vector< std::string > m_include_directories
std::shared_ptr< TypeSystemClang > m_ast_context
static const llvm::StringRef g_prefix_file_name
The file name we use for the wrapper code that we inject before the user expression.
std::vector< ModuleID > ModuleVector
"lldb/Expression/ClangPersistentVariables.h" Manages persistent values that need to be preserved betw...
"lldb/Expression/ClangUserExpression.h" Encapsulates a single expression for use with Clang
"lldb/Utility/ArgCompletionRequest.h"
void AddCompletion(llvm::StringRef completion, llvm::StringRef description="", CompletionMode mode=CompletionMode::Normal)
Adds a possible completion string.
A single completion and all associated data.
std::string GetUniqueKey() const
Generates a string that uniquely identifies this completion result.
A uniqued constant string class.
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
void SetString(llvm::StringRef s)
size_t void PutString(lldb::Severity severity, llvm::StringRef str)
const DiagnosticList & Diagnostics() const
llvm::Error GetAsError(lldb::ExpressionResults result, llvm::Twine message={}) const
Returns an ExpressionError with arg as error code.
void SetFixedExpression(std::string fixed_expression)
void AppendMessageToDiagnostic(llvm::StringRef str)
void AddDiagnostic(llvm::StringRef message, lldb::Severity severity, DiagnosticOrigin origin, uint32_t compiler_id=LLDB_INVALID_COMPILER_ID)
"lldb/Target/ExecutionContextScope.h" Inherit from this if your object can reconstruct its execution ...
virtual lldb::StackFrameSP CalculateStackFrame()=0
virtual lldb::ProcessSP CalculateProcess()=0
virtual lldb::TargetSP CalculateTarget()=0
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
const lldb::TargetSP & GetTargetSP() const
Get accessor to get the target shared pointer.
const lldb::ProcessSP & GetProcessSP() const
Get accessor to get the process shared pointer.
const lldb::StackFrameSP & GetFrameSP() const
Get accessor to get the frame shared pointer.
Process * GetProcessPtr() const
Returns a pointer to the process object.
ExpressionParser(ExecutionContextScope *exe_scope, Expression &expr, bool generate_debug_info)
Constructor.
Expression & m_expr
The expression to be parsed.
Encapsulates a single expression for use in lldb.
virtual SourceLanguage Language() const
Return the language that should be used when parsing.
virtual ResultType DesiredResultType() const
Return the desired result type of the function, or eResultTypeAny if indifferent.
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
static FileSystem & Instance()
"lldb/Expression/IRDynamicChecks.h" Adds dynamic checks to a user-entered expression to reduce its li...
bool runOnModule(llvm::Module &M) override
Run this IR transformer on a single module.
static const char * GetNameForLanguageType(lldb::LanguageType language)
Returns the internal LLDB name for the specified language.
static llvm::StringRef GetDisplayNameForLanguageType(lldb::LanguageType language)
Returns a user-friendly name for the specified language.
static ModuleListProperties & GetGlobalModuleListProperties()
Status Close() override
Flush any buffers and release any resources owned by the file.
Status Write(const void *buf, size_t &num_bytes) override
Write bytes from buf to a file at the current file position.
static ObjCLanguageRuntime * Get(Process &process)
A plug-in interface definition class for debugging a process.
void SetDynamicCheckers(DynamicCheckerFunctions *dynamic_checkers)
DynamicCheckerFunctions * GetDynamicCheckers()
bool CanInterpretFunctionCalls()
Determines whether executing function calls using the interpreter is possible for this process.
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
static Status FromErrorString(const char *str)
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
bool Success() const
Test for success condition.
llvm::StringRef GetString() const
Defines a symbol context baton that can be handed other debug core functions.
lldb::TargetSP target_sp
The Target for a given query.
const ArchSpec & GetArchitecture() const
const char * GetUserText()
Return the string that the user typed.
#define LLDB_INVALID_ADDRESS
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
FileSpec GetClangResourceDir()
ExecutionPolicy
Expression execution policies.
@ eExecutionPolicyTopLevel
std::vector< std::unique_ptr< Diagnostic > > DiagnosticList
bool operator<(const Address &lhs, const Address &rhs)
std::shared_ptr< lldb_private::IRExecutionUnit > IRExecutionUnitSP
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
LanguageType
Programming language type.
@ eLanguageTypeC_plus_plus_20
ISO C++:2020.
@ eLanguageTypeC_plus_plus_14
ISO C++:2014.
@ eLanguageTypeC11
ISO C:2011.
@ eLanguageTypeC99
ISO C:1999.
@ eLanguageTypeC_plus_plus_03
ISO C++:2003.
@ eLanguageTypeUnknown
Unknown or invalid language value.
@ eLanguageTypeC_plus_plus_17
ISO C++:2017.
@ eLanguageTypeObjC_plus_plus
Objective-C++.
@ eLanguageTypeC_plus_plus_11
ISO C++:2011.
@ eLanguageTypeC89
ISO C:1989.
@ eLanguageTypeC
Non-standardized C, such as K&R.
@ eLanguageTypeObjC
Objective-C.
@ eLanguageTypeC_plus_plus
ISO C++:1998.
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::Target > TargetSP
A source location consisting of a file name and position.
unsigned line
1 in the example above.
bool in_user_input
Whether this source location refers to something the user typed as part of the command,...
FileSpec file
"<user expression 0>" in the example above.
uint16_t length
3 in the example above.
uint16_t column
5 in the example above.
bool hidden
Whether this source location should be surfaced to the user.
A compiler-independent representation of an lldb_private::Diagnostic.
std::optional< SourceLocation > source_location
Contains this diagnostic's source location, if applicable.
lldb::Severity severity
Contains eSeverityError in the example above.
std::string rendered
Contains the fully rendered error message, without "error: ", but including the source context.
std::string message
Contains "use of undeclared identifier 'foo'" in the example above.
std::shared_ptr< llvm::legacy::PassManager > EarlyPasses
std::shared_ptr< llvm::legacy::PassManager > LatePasses
lldb::LanguageType AsLanguageType() const
Information needed to import a source-language module.