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"
104using namespace clang;
122 clang::SourceManager &source_mgr)
126 void moduleImport(SourceLocation import_location, clang::ModuleIdPath path,
127 const clang::Module * )
override {
130 llvm::StringRef filename =
131 m_source_mgr.getPresumedLoc(import_location).getFilename();
137 for (
const IdentifierLoc &component : path)
138 module.path.push_back(
139 ConstString(component.getIdentifierInfo()->getName()));
157 for (
auto &fix_it : Info.getFixItHints()) {
170 m_os = std::make_shared<llvm::raw_string_ostream>(
m_output);
172 std::make_shared<clang::TextDiagnosticPrinter>(*
m_os,
m_options);
185 for (
auto it = diags.rbegin(); it != diags.rend(); it++) {
198 const clang::Diagnostic &Info)
override {
207 llvm::SmallVector<char, 32> diag_str;
208 Info.FormatDiagnostic(diag_str);
209 diag_str.push_back(
'\0');
210 const char *plain_diag = diag_str.data();
211 LLDB_LOG(log,
"Received diagnostic outside parsing: {0}", plain_diag);
217 DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
225 case DiagnosticsEngine::Level::Fatal:
226 case DiagnosticsEngine::Level::Error:
229 case DiagnosticsEngine::Level::Warning:
232 case DiagnosticsEngine::Level::Remark:
233 case DiagnosticsEngine::Level::Ignored:
236 case DiagnosticsEngine::Level::Note:
246 if (!clang_diag || clang_diag->HasFixIts())
256 std::string stripped_output =
257 std::string(llvm::StringRef(
m_output).trim());
260 if (Info.hasSourceManager()) {
262 clang::SourceManager &sm = Info.getSourceManager();
263 const clang::SourceLocation sloc = Info.getLocation();
264 if (sloc.isValid()) {
265 const clang::FullSourceLoc fsloc(sloc, sm);
266 clang::PresumedLoc PLoc = fsloc.getPresumedLoc(
true);
268 PLoc.isValid() ? PLoc.getFilename() : StringRef{};
270 loc.
line = fsloc.getSpellingLineNumber();
271 loc.
column = fsloc.getSpellingColumnNumber();
273 loc.
hidden = filename.starts_with(
"<lldb wrapper ");
276 for (
const auto &range : Info.getRanges()) {
277 if (range.getBegin() == sloc) {
279 unsigned end_col = sm.getSpellingColumnNumber(range.getEnd());
288 llvm::SmallString<0> msg;
289 Info.FormatDiagnostic(msg);
292 auto new_diagnostic =
293 std::make_unique<ClangDiagnostic>(detail, Info.getID());
302 m_manager->AddDiagnostic(std::move(new_diagnostic));
316 std::shared_ptr<llvm::raw_string_ostream>
m_os;
323 std::vector<std::string> include_directories,
327 HeaderSearchOptions &search_opts = compiler->getHeaderSearchOpts();
329 for (
const std::string &dir : include_directories) {
330 search_opts.AddPath(dir, frontend::System,
false,
true);
331 LLDB_LOG(log,
"Added user include dir: {0}", dir);
334 llvm::SmallString<128> module_cache;
336 props.GetClangModulesCachePath().GetPath(module_cache);
337 search_opts.ModuleCachePath = std::string(module_cache.str());
338 LLDB_LOG(log,
"Using module cache path: {0}", module_cache.c_str());
342 search_opts.ImplicitModuleMaps =
true;
350 if (token ==
"using")
353 if (token ==
"__null")
356 LangOptions cpp_lang_opts;
357 cpp_lang_opts.CPlusPlus =
true;
358 cpp_lang_opts.CPlusPlus11 =
true;
359 cpp_lang_opts.CPlusPlus20 =
true;
361 clang::IdentifierInfo &ii = idents.get(token);
364 if (!ii.isCPlusPlusKeyword(cpp_lang_opts))
367 if (ii.getTokenID() == clang::tok::identifier)
371 ii.revertTokenIDToIdentifier();
376#define KEYWORD(NAME, FLAGS) RemoveCppKeyword(idents, llvm::StringRef(#NAME));
377#include "clang/Basic/TokenKinds.def"
383 const std::vector<const char *> groupsToIgnore = {
386 "unused-getter-return-value",
388 for (
const char *group : groupsToIgnore) {
389 compiler.getDiagnostics().setSeverityForGroup(
390 clang::diag::Flavor::WarningOrError, group,
391 clang::diag::Severity::Ignored, SourceLocation());
403 if (target_arch.
IsMIPS()) {
416 if (target_arch.
GetTriple().isRISCV64()) {
431 if (target_arch.
GetTriple().isRISCV32()) {
446 if (target_arch.
GetTriple().isLoongArch64()) {
467 const auto target_machine = target_arch.
GetMachine();
469 std::string triple = target_arch.
GetTriple().str();
470 compiler.getTargetOpts().Triple = triple;
471 LLDB_LOGF(log,
"Using %s as the target triple",
472 compiler.getTargetOpts().Triple.c_str());
480 compiler.getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
481 LLDB_LOGF(log,
"Using default target triple of %s",
482 compiler.getTargetOpts().Triple.c_str());
486 if (compiler.getTargetOpts().Triple.find(
"arm64") == std::string::npos &&
487 compiler.getTargetOpts().Triple.find(
"arm") != std::string::npos &&
488 compiler.getTargetOpts().Triple.find(
"ios") != std::string::npos) {
489 compiler.getTargetOpts().ABI =
"apcs-gnu";
492 if (target_machine == llvm::Triple::x86 ||
493 target_machine == llvm::Triple::x86_64) {
494 compiler.getTargetOpts().FeaturesAsWritten.push_back(
"+sse");
495 compiler.getTargetOpts().FeaturesAsWritten.push_back(
"+sse2");
505 compiler.getTargetOpts().ABI = std::move(abi);
507 if ((target_machine == llvm::Triple::riscv64 &&
508 compiler.getTargetOpts().ABI ==
"lp64f") ||
509 (target_machine == llvm::Triple::riscv32 &&
510 compiler.getTargetOpts().ABI ==
"ilp32f"))
511 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+f");
513 if ((target_machine == llvm::Triple::riscv64 &&
514 compiler.getTargetOpts().ABI ==
"lp64d") ||
515 (target_machine == llvm::Triple::riscv32 &&
516 compiler.getTargetOpts().ABI ==
"ilp32d"))
517 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+d");
519 if ((target_machine == llvm::Triple::loongarch64 &&
520 compiler.getTargetOpts().ABI ==
"lp64f"))
521 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+f");
523 if ((target_machine == llvm::Triple::loongarch64 &&
524 compiler.getTargetOpts().ABI ==
"lp64d"))
525 compiler.getTargetOpts().FeaturesAsWritten.emplace_back(
"+d");
544 "Frame has language of type {0}\nPicked {1} for expression evaluation.",
546 frame_sp ? frame_sp->GetLanguage().AsLanguageType()
550 LangOptions &lang_opts = compiler.getLangOpts();
562 lang_opts.CPlusPlus =
true;
565 lang_opts.ObjC =
true;
568 lang_opts.CPlusPlus =
true;
576 lang_opts.CPlusPlus11 =
true;
579 lang_opts.CPlusPlus20 =
true;
585 lang_opts.CPlusPlus14 =
true;
586 lang_opts.CPlusPlus17 =
true;
591 lang_opts.CPlusPlus11 =
true;
592 compiler.getHeaderSearchOpts().UseLibcxx =
true;
595 lang_opts.CPlusPlus =
true;
599 && !(frame_sp && frame_sp->HasDebugInformation()))
606 lang_opts.ObjC =
true;
607 lang_opts.CPlusPlus =
true;
608 lang_opts.CPlusPlus11 =
true;
609 compiler.getHeaderSearchOpts().UseLibcxx =
true;
613 lang_opts.Bool =
true;
614 lang_opts.WChar =
true;
615 lang_opts.Blocks =
true;
616 lang_opts.DebuggerSupport =
619 lang_opts.DebuggerCastResultToId =
true;
621 lang_opts.CharIsSigned =
627 lang_opts.SpellChecking =
false;
629 if (process_sp && lang_opts.ObjC) {
631 switch (runtime->GetRuntimeVersion()) {
633 lang_opts.ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7));
637 lang_opts.ObjCRuntime.set(ObjCRuntime::FragileMacOSX,
638 VersionTuple(10, 7));
641 lang_opts.ObjCRuntime.set(ObjCRuntime::GNUstep, VersionTuple(2, 0));
645 if (runtime->HasNewLiteralsAndIndexing())
646 lang_opts.DebuggerObjCLiteral =
true;
650 lang_opts.ThreadsafeStatics =
false;
651 lang_opts.AccessControl =
false;
652 lang_opts.DollarIdents =
true;
656 lang_opts.NoBuiltin =
true;
661 LangOptions &lang_opts = compiler.getLangOpts();
662 lang_opts.Modules =
true;
664 lang_opts.ImplicitModules =
true;
666 lang_opts.ModulesLocalVisibility =
false;
670 lang_opts.ObjC =
true;
674 lang_opts.GNUMode =
true;
675 lang_opts.GNUKeywords =
true;
676 lang_opts.CPlusPlus11 =
true;
678 lang_opts.BuiltinHeadersInSystemModules =
false;
681 lang_opts.GNUCVersion = 40201;
690 bool generate_debug_info, std::vector<std::string> include_directories,
691 std::string filename)
707 "Can't make an expression parser with a null scope.");
715 "Can't make an expression parser with a null target.");
720 m_compiler = std::make_unique<CompilerInstance>();
735 m_compiler->getDiagnostics().setErrorLimit(target_sp->GetExprErrorLimit());
737 if (
auto *target_info = TargetInfo::CreateTargetInfo(
739 m_compiler->getInvocation().getTargetOpts())) {
741 LLDB_LOGF(log,
"Target datalayout string: '%s'",
742 target_info->getDataLayoutString());
743 LLDB_LOGF(log,
"Target ABI: '%s'", target_info->getABI().str().c_str());
744 LLDB_LOGF(log,
"Target vector alignment: %d",
745 target_info->getMaxVectorAlign());
750 LLDB_LOGF(log,
"Failed to create TargetInfo for '%s'",
753 lldbassert(
false &&
"Failed to create TargetInfo.");
758 auto *clang_expr = dyn_cast<ClangUserExpression>(&
m_expr);
759 if (clang_expr && clang_expr->DidImportCxxModules()) {
760 LLDB_LOG(log,
"Adding lang options for importing C++ modules");
766 m_compiler->getCodeGenOpts().EmitDeclMetadata =
true;
767 m_compiler->getCodeGenOpts().InstrumentFunctions =
false;
769 CodeGenOptions::FramePointerKind::All);
770 if (generate_debug_info)
771 m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
773 m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::NoDebugInfo);
788 m_compiler->getDiagnostics().getDiagnosticOptions(),
789 clang_expr ? clang_expr->GetFilename() : StringRef());
790 m_compiler->getDiagnostics().setClient(diag_mgr);
813 if (
auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(
814 target_sp->GetPersistentExpressionStateForLanguage(
816 if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
817 clang_persistent_vars->GetClangModulesDeclVendor()) {
818 std::unique_ptr<PPCallbacks> pp_callbacks(
823 m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
831 auto &builtin_context = PP.getBuiltinInfo();
832 builtin_context.initializeBuiltins(PP.getIdentifierTable(),
836 clang::ASTContext &ast_context =
m_compiler->getASTContext();
839 "Expression ASTContext for '" +
m_filename +
"'", ast_context);
841 std::string module_name(
"$__lldb_module");
860class CodeComplete :
public CodeCompleteConsumer {
861 CodeCompletionTUInfo m_info;
864 unsigned m_position = 0;
867 clang::PrintingPolicy m_desc_policy;
869 struct CompletionWithPriority {
877 bool operator<(
const CompletionWithPriority &o)
const {
879 if (Priority != o.Priority)
880 return Priority > o.Priority;
883 return completion.
GetUniqueKey() < o.completion.GetUniqueKey();
890 std::vector<CompletionWithPriority> m_completions;
897 static bool IsIdChar(
char c) {
898 return c ==
'_' || std::isalnum(c) || c ==
'$';
903 static bool IsTokenSeparator(
char c) {
return c ==
' ' || c ==
'\t'; }
908 StringRef dropUnrelatedFrontTokens(StringRef cmd)
const {
914 if (IsTokenSeparator(cmd.back()))
919 StringRef to_remove = cmd;
920 while (!to_remove.empty() && !IsTokenSeparator(to_remove.back())) {
921 to_remove = to_remove.drop_back();
923 cmd = cmd.drop_front(to_remove.size());
929 StringRef removeLastToken(StringRef cmd)
const {
930 while (!cmd.empty() && IsIdChar(cmd.back())) {
931 cmd = cmd.drop_back();
939 std::string mergeCompletion(StringRef existing,
unsigned pos,
940 StringRef completion)
const {
941 StringRef existing_command = existing.substr(0, pos);
944 existing_command = removeLastToken(existing_command);
948 existing_command = dropUnrelatedFrontTokens(existing_command);
949 return existing_command.str() + completion.str();
962 CodeComplete(clang::LangOptions ops, std::string expr,
unsigned position)
963 : CodeCompleteConsumer(CodeCompleteOptions()),
964 m_info(std::make_shared<GlobalCodeCompletionAllocator>()), m_expr(expr),
965 m_position(position), m_desc_policy(ops) {
969 m_desc_policy.SuppressScope =
true;
970 m_desc_policy.SuppressTagKeyword =
true;
971 m_desc_policy.FullyQualifiedName =
false;
972 m_desc_policy.TerseOutput =
true;
973 m_desc_policy.IncludeNewlines =
false;
974 m_desc_policy.UseVoidForZeroParams =
false;
975 m_desc_policy.Bool =
true;
980 bool isResultFilteredOut(StringRef Filter,
981 CodeCompletionResult Result)
override {
983 switch (Result.Kind) {
984 case CodeCompletionResult::RK_Declaration:
986 Result.Declaration->getIdentifier() &&
987 Result.Declaration->getIdentifier()->getName().starts_with(Filter));
988 case CodeCompletionResult::RK_Keyword:
989 return !StringRef(Result.Keyword).starts_with(Filter);
990 case CodeCompletionResult::RK_Macro:
991 return !Result.Macro->getName().starts_with(Filter);
992 case CodeCompletionResult::RK_Pattern:
993 return !StringRef(Result.Pattern->getAsString()).starts_with(Filter);
998 assert(
false &&
"Unknown completion result type?");
1013 std::optional<CompletionWithPriority>
1014 getCompletionForResult(
const CodeCompletionResult &R)
const {
1015 std::string ToInsert;
1016 std::string Description;
1019 case CodeCompletionResult::RK_Declaration: {
1020 const NamedDecl *D = R.Declaration;
1021 ToInsert = R.Declaration->getNameAsString();
1025 if (
const FunctionDecl *F = dyn_cast<FunctionDecl>(D)) {
1026 if (F->getNumParams() == 0)
1030 raw_string_ostream
OS(Description);
1031 F->print(
OS, m_desc_policy,
false);
1032 }
else if (
const VarDecl *V = dyn_cast<VarDecl>(D)) {
1033 Description = V->getType().getAsString(m_desc_policy);
1034 }
else if (
const FieldDecl *F = dyn_cast<FieldDecl>(D)) {
1035 Description = F->getType().getAsString(m_desc_policy);
1036 }
else if (
const NamespaceDecl *N = dyn_cast<NamespaceDecl>(D)) {
1039 if (!N->isAnonymousNamespace())
1044 case CodeCompletionResult::RK_Keyword:
1045 ToInsert = R.Keyword;
1047 case CodeCompletionResult::RK_Macro:
1048 ToInsert = R.Macro->getName().str();
1050 case CodeCompletionResult::RK_Pattern:
1051 ToInsert = R.Pattern->getTypedText();
1056 if (llvm::StringRef(ToInsert).starts_with(
"$__lldb_"))
1057 return std::nullopt;
1058 if (ToInsert.empty())
1059 return std::nullopt;
1062 std::string CompletionSuggestion =
1063 mergeCompletion(m_expr, m_position, ToInsert);
1065 CompletionResult::Completion completion(CompletionSuggestion, Description,
1066 CompletionMode::Normal);
1067 return {{completion, R.Priority}};
1072 void GetCompletions(CompletionRequest &request) {
1075 llvm::sort(m_completions);
1077 for (
const CompletionWithPriority &C : m_completions)
1079 C.completion.GetDescription(),
1080 C.completion.GetMode());
1085 void ProcessCodeCompleteResults(Sema &SemaRef, CodeCompletionContext Context,
1086 CodeCompletionResult *Results,
1087 unsigned NumResults)
override {
1091 StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();
1095 for (
unsigned I = 0; I != NumResults; ++I) {
1097 if (!Filter.empty() && isResultFilteredOut(Filter, Results[I]))
1100 CodeCompletionResult &R = Results[I];
1101 std::optional<CompletionWithPriority> CompletionAndPriority =
1102 getCompletionForResult(R);
1103 if (!CompletionAndPriority)
1105 m_completions.push_back(*CompletionAndPriority);
1117 void ProcessOverloadCandidates(Sema &S,
unsigned CurrentArg,
1118 OverloadCandidate *Candidates,
1119 unsigned NumCandidates,
1120 SourceLocation OpenParLoc,
1121 bool Braced)
override {
1125 CodeCompletionAllocator &getAllocator()
override {
1126 return m_info.getAllocator();
1129 CodeCompletionTUInfo &getCodeCompletionTUInfo()
override {
return m_info; }
1134 unsigned pos,
unsigned typed_pos) {
1149 CC.GetCompletions(request);
1159 CodeCompleteConsumer *completion_consumer,
1160 unsigned completion_line,
1161 unsigned completion_column) {
1168 const char *expr_text =
m_expr.Text();
1170 clang::SourceManager &source_mgr =
m_compiler->getSourceManager();
1171 bool created_main_file =
false;
1177 bool should_create_file = completion_consumer !=
nullptr;
1180 should_create_file |=
m_compiler->getCodeGenOpts().getDebugInfo() ==
1181 codegenoptions::FullDebugInfo;
1183 if (should_create_file) {
1185 llvm::SmallString<128> result_path;
1186 if (
FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
1187 tmpdir_file_spec.AppendPathComponent(
"lldb-%%%%%%.expr");
1188 std::string temp_source_path = tmpdir_file_spec.GetPath();
1189 llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path);
1191 llvm::sys::fs::createTemporaryFile(
"lldb",
"expr", temp_fd, result_path);
1194 if (temp_fd != -1) {
1196 const size_t expr_text_len = strlen(expr_text);
1197 size_t bytes_written = expr_text_len;
1199 if (bytes_written == expr_text_len) {
1201 if (
auto fileEntry =
m_compiler->getFileManager().getOptionalFileRef(
1203 source_mgr.setMainFileID(source_mgr.createFileID(
1204 *fileEntry, SourceLocation(), SrcMgr::C_User));
1205 created_main_file =
true;
1212 if (!created_main_file) {
1213 std::unique_ptr<MemoryBuffer> memory_buffer =
1214 MemoryBuffer::getMemBufferCopy(expr_text,
m_filename);
1215 source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer)));
1222 dyn_cast<ClangExpressionHelper>(
m_expr.GetTypeSystemHelper());
1228 if (completion_consumer) {
1230 source_mgr.getFileEntryRefForID(source_mgr.getMainFileID());
1235 ++completion_column;
1236 PP.SetCodeCompletionPoint(*main_file, completion_line, completion_column);
1239 ASTConsumer *ast_transformer =
1242 std::unique_ptr<clang::ASTConsumer> Consumer;
1243 if (ast_transformer) {
1244 Consumer = std::make_unique<ASTConsumerForwarder>(ast_transformer);
1248 Consumer = std::make_unique<ASTConsumer>();
1251 clang::ASTContext &ast_context =
m_compiler->getASTContext();
1254 *Consumer, TU_Complete, completion_consumer));
1255 m_compiler->setASTConsumer(std::move(Consumer));
1257 if (ast_context.getLangOpts().Modules) {
1267 llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source =
1270 auto ast_source_wrapper =
1271 llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(ast_source);
1273 if (ast_context.getExternalSource()) {
1274 auto module_wrapper = llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(
1275 ast_context.getExternalSourcePtr());
1277 auto multiplexer = llvm::makeIntrusiveRefCnt<SemaSourceWithPriorities>(
1278 module_wrapper, ast_source_wrapper);
1280 ast_context.setExternalSource(multiplexer);
1282 ast_context.setExternalSource(ast_source);
1284 m_compiler->getSema().addExternalSource(ast_source_wrapper);
1289 if (ast_context.getLangOpts().Modules) {
1290 assert(
m_compiler->getASTContext().getExternalSource() &&
1291 "ASTContext doesn't know about the ASTReader?");
1292 assert(
m_compiler->getSema().getExternalSource() &&
1293 "Sema doesn't know about the ASTReader?");
1297 llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(
1299 ParseAST(
m_compiler->getSema(),
false,
false);
1303 if (ast_context.getLangOpts().Modules)
1311 unsigned num_errors = adapter->getNumErrors();
1316 "while importing modules:");
1331static void ApplyFixIt(
const FixItHint &fixit, clang::edit::Commit &commit) {
1333 if (fixit.CodeToInsert.empty()) {
1334 if (fixit.InsertFromRange.isValid()) {
1335 commit.insertFromRange(fixit.RemoveRange.getBegin(),
1336 fixit.InsertFromRange,
false,
1337 fixit.BeforePreviousInsertions);
1340 commit.remove(fixit.RemoveRange);
1343 if (fixit.RemoveRange.isTokenRange() ||
1344 fixit.RemoveRange.getBegin() != fixit.RemoveRange.getEnd()) {
1345 commit.replace(fixit.RemoveRange, fixit.CodeToInsert);
1348 commit.insert(fixit.RemoveRange.getBegin(), fixit.CodeToInsert,
1349 false, fixit.BeforePreviousInsertions);
1354 clang::SourceManager &source_manager =
m_compiler->getSourceManager();
1355 clang::edit::EditedSource editor(source_manager,
m_compiler->getLangOpts(),
1357 clang::edit::Commit commit(editor);
1358 clang::Rewriter rewriter(source_manager,
m_compiler->getLangOpts());
1360 class RewritesReceiver :
public edit::EditsReceiver {
1364 RewritesReceiver(Rewriter &in_rewrite) : rewrite(in_rewrite) {}
1366 void insert(SourceLocation loc, StringRef text)
override {
1367 rewrite.InsertText(loc, text);
1369 void replace(CharSourceRange range, StringRef text)
override {
1370 rewrite.ReplaceText(range.getBegin(), rewrite.getRangeSize(range), text);
1374 RewritesReceiver rewrites_receiver(rewriter);
1377 size_t num_diags = diagnostics.size();
1381 for (
const auto &diag : diagnostic_manager.
Diagnostics()) {
1382 const auto *diagnostic = llvm::dyn_cast<ClangDiagnostic>(diag.get());
1385 if (!diagnostic->HasFixIts())
1387 for (
const FixItHint &fixit : diagnostic->FixIts())
1392 if (!commit.isCommitable())
1394 else if (!editor.commit(commit))
1398 editor.applyRewrites(rewrites_receiver);
1399 RewriteBuffer &main_file_buffer =
1400 rewriter.getEditBuffer(source_manager.getMainFileID());
1402 std::string fixed_expression;
1403 llvm::raw_string_ostream out_stream(fixed_expression);
1405 main_file_buffer.write(out_stream);
1412 llvm::Module *module,
const char *orig_name) {
1413 for (
const auto &func : module->getFunctionList()) {
1414 const StringRef &name = func.getName();
1415 if (name.contains(orig_name)) {
1434 std::unique_ptr<llvm::Module> llvm_module_up(
1437 if (!llvm_module_up) {
1448 m_expr.FunctionName())) {
1450 "Couldn't find %s() in the module",
m_expr.FunctionName());
1461 sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything);
1468 auto lang =
m_expr.Language();
1469 LLDB_LOGF(log,
"%s - Current expression language is %s\n", __FUNCTION__,
1470 lang.GetDescription().data());
1473 auto runtime = process_sp->GetLanguageRuntime(lang.AsLanguageType());
1475 runtime->GetIRPasses(custom_passes);
1481 "%s - Running Early IR Passes from LanguageRuntime on "
1482 "expression module '%s'",
1483 __FUNCTION__,
m_expr.FunctionName());
1488 execution_unit_sp = std::make_shared<IRExecutionUnit>(
1494 if (
auto *options =
m_expr.GetOptions())
1495 execution_unit_sp->AppendPreferredSymbolContexts(
1496 options->GetPreferredSymbolContexts());
1499 dyn_cast<ClangExpressionHelper>(
m_expr.GetTypeSystemHelper());
1501 type_system_helper->
DeclMap();
1506 *execution_unit_sp, error_stream,
1509 if (!ir_for_target.
runOnModule(*execution_unit_sp->GetModule())) {
1520 bool interpret_function_calls =
1523 *execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(),
1524 interpret_error, interpret_function_calls);
1528 "Can't evaluate the expression without a running target due to: %s",
1536 "Expression needed to run in the target, but the "
1537 "target can't be run");
1543 "Top-level code needs to be inserted into a runnable "
1544 "target, but the target can't be run");
1550 if (
m_expr.NeedsValidation() && process) {
1556 if (Error Err = dynamic_checkers->
Install(install_diags, exe_ctx))
1562 LLDB_LOGF(log,
"== [ClangExpressionParser::PrepareForExecution] "
1563 "Finished installing dynamic checkers ==");
1566 if (
auto *checker_funcs = llvm::dyn_cast<ClangDynamicCheckerFunctions>(
1571 llvm::Module *module = execution_unit_sp->GetModule();
1572 if (!module || !ir_dynamic_checks.
runOnModule(*module)) {
1574 "Couldn't add dynamic checks to the expression");
1580 "%s - Running Late IR Passes from LanguageRuntime on "
1581 "expression module '%s'",
1582 __FUNCTION__,
m_expr.FunctionName());
1592 execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
1595 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 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 SetupLangOpts(CompilerInstance &compiler, ExecutionContextScope &exe_scope, const Expression &expr)
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, 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)
"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)
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.