Index: projects/clang350-import/contrib/llvm/tools/lldb/source/Expression/ClangExpressionParser.cpp =================================================================== --- projects/clang350-import/contrib/llvm/tools/lldb/source/Expression/ClangExpressionParser.cpp (revision 275126) +++ projects/clang350-import/contrib/llvm/tools/lldb/source/Expression/ClangExpressionParser.cpp (revision 275127) @@ -1,544 +1,544 @@ //===-- ClangExpressionParser.cpp -------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/lldb-python.h" #include "lldb/Expression/ClangExpressionParser.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/Module.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" #include "lldb/Expression/ClangASTSource.h" #include "lldb/Expression/ClangExpression.h" #include "lldb/Expression/ClangExpressionDeclMap.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRDynamicChecks.h" #include "lldb/Expression/IRInterpreter.h" #include "lldb/Host/File.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ExternalASTSource.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Version.h" #include "clang/CodeGen/CodeGenAction.h" #include "clang/CodeGen/ModuleBuilder.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/FrontendPluginRegistry.h" #include "clang/Frontend/TextDiagnosticBuffer.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Lex/Preprocessor.h" #include "clang/Parse/ParseAST.h" #include "clang/Rewrite/Frontend/FrontendActions.h" #include "clang/Sema/SemaConsumer.h" #include "clang/StaticAnalyzer/Frontend/FrontendActions.h" #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/TargetSelect.h" #include "llvm/ExecutionEngine/MCJIT.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/Host.h" #include "llvm/Support/Signals.h" using namespace clang; using namespace llvm; using namespace lldb_private; //===----------------------------------------------------------------------===// // Utility Methods for Clang //===----------------------------------------------------------------------===// std::string GetBuiltinIncludePath(const char *Argv0) { SmallString<128> P(llvm::sys::fs::getMainExecutable( Argv0, (void *)(intptr_t) GetBuiltinIncludePath)); if (!P.empty()) { llvm::sys::path::remove_filename(P); // Remove /clang from foo/bin/clang llvm::sys::path::remove_filename(P); // Remove /bin from foo/bin // Get foo/lib/clang//include llvm::sys::path::append(P, "lib", "clang", CLANG_VERSION_STRING, "include"); } return P.str(); } //===----------------------------------------------------------------------===// // Implementation of ClangExpressionParser //===----------------------------------------------------------------------===// ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, ClangExpression &expr, bool generate_debug_info) : m_expr (expr), m_compiler (), m_code_generator () { // 1. Create a new compiler instance. m_compiler.reset(new CompilerInstance()); // 2. Install the target. lldb::TargetSP target_sp; if (exe_scope) target_sp = exe_scope->CalculateTarget(); // TODO: figure out what to really do when we don't have a valid target. // Sometimes this will be ok to just use the host target triple (when we // evaluate say "2+3", but other expressions like breakpoint conditions // and other things that _are_ target specific really shouldn't just be // using the host triple. This needs to be fixed in a better way. if (target_sp && target_sp->GetArchitecture().IsValid()) { std::string triple = target_sp->GetArchitecture().GetTriple().str(); m_compiler->getTargetOpts().Triple = triple; } else { m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple(); } if (target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86 || target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86_64) { m_compiler->getTargetOpts().Features.push_back("+sse"); m_compiler->getTargetOpts().Features.push_back("+sse2"); } // Any arm32 iOS environment, but not on arm64 if (m_compiler->getTargetOpts().Triple.find("arm64") == std::string::npos && m_compiler->getTargetOpts().Triple.find("arm") != std::string::npos && m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos) { m_compiler->getTargetOpts().ABI = "apcs-gnu"; } m_compiler->createDiagnostics(); // Create the target instance. m_compiler->setTarget(TargetInfo::CreateTargetInfo( m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts)); assert (m_compiler->hasTarget()); // 3. Set options. lldb::LanguageType language = expr.Language(); switch (language) { case lldb::eLanguageTypeC: break; case lldb::eLanguageTypeObjC: m_compiler->getLangOpts().ObjC1 = true; m_compiler->getLangOpts().ObjC2 = true; break; case lldb::eLanguageTypeC_plus_plus: m_compiler->getLangOpts().CPlusPlus = true; m_compiler->getLangOpts().CPlusPlus11 = true; break; case lldb::eLanguageTypeObjC_plus_plus: default: m_compiler->getLangOpts().ObjC1 = true; m_compiler->getLangOpts().ObjC2 = true; m_compiler->getLangOpts().CPlusPlus = true; m_compiler->getLangOpts().CPlusPlus11 = true; break; } m_compiler->getLangOpts().Bool = true; m_compiler->getLangOpts().WChar = true; m_compiler->getLangOpts().Blocks = true; m_compiler->getLangOpts().DebuggerSupport = true; // Features specifically for debugger clients if (expr.DesiredResultType() == ClangExpression::eResultTypeId) m_compiler->getLangOpts().DebuggerCastResultToId = true; // Spell checking is a nice feature, but it ends up completing a // lot of types that we didn't strictly speaking need to complete. // As a result, we spend a long time parsing and importing debug // information. m_compiler->getLangOpts().SpellChecking = false; lldb::ProcessSP process_sp; if (exe_scope) process_sp = exe_scope->CalculateProcess(); if (process_sp && m_compiler->getLangOpts().ObjC1) { if (process_sp->GetObjCLanguageRuntime()) { if (process_sp->GetObjCLanguageRuntime()->GetRuntimeVersion() == eAppleObjC_V2) m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7)); else m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::FragileMacOSX, VersionTuple(10, 7)); if (process_sp->GetObjCLanguageRuntime()->HasNewLiteralsAndIndexing()) m_compiler->getLangOpts().DebuggerObjCLiteral = true; } } m_compiler->getLangOpts().ThreadsafeStatics = false; m_compiler->getLangOpts().AccessControl = false; // Debuggers get universal access m_compiler->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name // Set CodeGen options m_compiler->getCodeGenOpts().EmitDeclMetadata = true; m_compiler->getCodeGenOpts().InstrumentFunctions = false; m_compiler->getCodeGenOpts().DisableFPElim = true; m_compiler->getCodeGenOpts().OmitLeafFramePointer = false; if (generate_debug_info) m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::FullDebugInfo); else m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::NoDebugInfo); // Disable some warnings. m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError, "unused-value", clang::diag::Severity::Ignored, SourceLocation()); m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError, "odr", clang::diag::Severity::Ignored, SourceLocation()); // Inform the target of the language options // // FIXME: We shouldn't need to do this, the target should be immutable once // created. This complexity should be lifted elsewhere. m_compiler->getTarget().adjust(m_compiler->getLangOpts()); // 4. Set up the diagnostic buffer for reporting errors m_compiler->getDiagnostics().setClient(new clang::TextDiagnosticBuffer); // 5. Set up the source management objects inside the compiler clang::FileSystemOptions file_system_options; m_file_manager.reset(new clang::FileManager(file_system_options)); if (!m_compiler->hasSourceManager()) m_compiler->createSourceManager(*m_file_manager.get()); m_compiler->createFileManager(); m_compiler->createPreprocessor(TU_Complete); // 6. Most of this we get from the CompilerInstance, but we // also want to give the context an ExternalASTSource. m_selector_table.reset(new SelectorTable()); m_builtin_context.reset(new Builtin::Context()); std::unique_ptr ast_context(new ASTContext(m_compiler->getLangOpts(), m_compiler->getSourceManager(), m_compiler->getPreprocessor().getIdentifierTable(), *m_selector_table.get(), *m_builtin_context.get())); ast_context->InitBuiltinTypes(m_compiler->getTarget()); ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); if (decl_map) { llvm::IntrusiveRefCntPtr ast_source(decl_map->CreateProxy()); decl_map->InstallASTContext(ast_context.get()); ast_context->setExternalSource(ast_source); } m_compiler->setASTContext(ast_context.release()); std::string module_name("$__lldb_module"); m_llvm_context.reset(new LLVMContext()); m_code_generator.reset(CreateLLVMCodeGen(m_compiler->getDiagnostics(), module_name, m_compiler->getCodeGenOpts(), m_compiler->getTargetOpts(), *m_llvm_context)); } ClangExpressionParser::~ClangExpressionParser() { } unsigned ClangExpressionParser::Parse (Stream &stream) { TextDiagnosticBuffer *diag_buf = static_cast(m_compiler->getDiagnostics().getClient()); diag_buf->FlushDiagnostics (m_compiler->getDiagnostics()); const char *expr_text = m_expr.Text(); clang::SourceManager &SourceMgr = m_compiler->getSourceManager(); bool created_main_file = false; if (m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo) { std::string temp_source_path; FileSpec tmpdir_file_spec; if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) { tmpdir_file_spec.AppendPathComponent("expr.XXXXXX"); temp_source_path = std::move(tmpdir_file_spec.GetPath()); } else { temp_source_path = "/tmp/expr.XXXXXX"; } if (mktemp(&temp_source_path[0])) { lldb_private::File file (temp_source_path.c_str(), File::eOpenOptionWrite | File::eOpenOptionCanCreateNewOnly, lldb::eFilePermissionsFileDefault); const size_t expr_text_len = strlen(expr_text); size_t bytes_written = expr_text_len; if (file.Write(expr_text, bytes_written).Success()) { if (bytes_written == expr_text_len) { file.Close(); SourceMgr.setMainFileID(SourceMgr.createFileID( m_file_manager->getFile(temp_source_path), SourceLocation(), SrcMgr::C_User)); created_main_file = true; } } } } if (!created_main_file) { - std::unique_ptr memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__); - SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(memory_buffer))); + MemoryBuffer *memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__); + SourceMgr.setMainFileID(SourceMgr.createFileID(memory_buffer)); } diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor()); ASTConsumer *ast_transformer = m_expr.ASTTransformer(m_code_generator.get()); if (ast_transformer) ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext()); else ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext()); diag_buf->EndSourceFile(); TextDiagnosticBuffer::const_iterator diag_iterator; int num_errors = 0; for (diag_iterator = diag_buf->warn_begin(); diag_iterator != diag_buf->warn_end(); ++diag_iterator) stream.Printf("warning: %s\n", (*diag_iterator).second.c_str()); num_errors = 0; for (diag_iterator = diag_buf->err_begin(); diag_iterator != diag_buf->err_end(); ++diag_iterator) { num_errors++; stream.Printf("error: %s\n", (*diag_iterator).second.c_str()); } for (diag_iterator = diag_buf->note_begin(); diag_iterator != diag_buf->note_end(); ++diag_iterator) stream.Printf("note: %s\n", (*diag_iterator).second.c_str()); if (!num_errors) { if (m_expr.DeclMap() && !m_expr.DeclMap()->ResolveUnknownTypes()) { stream.Printf("error: Couldn't infer the type of a variable\n"); num_errors++; } } return num_errors; } static bool FindFunctionInModule (ConstString &mangled_name, llvm::Module *module, const char *orig_name) { for (llvm::Module::iterator fi = module->getFunctionList().begin(), fe = module->getFunctionList().end(); fi != fe; ++fi) { if (fi->getName().str().find(orig_name) != std::string::npos) { mangled_name.SetCString(fi->getName().str().c_str()); return true; } } return false; } Error ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, lldb::addr_t &func_end, std::shared_ptr &execution_unit_sp, ExecutionContext &exe_ctx, bool &can_interpret, ExecutionPolicy execution_policy) { func_addr = LLDB_INVALID_ADDRESS; func_end = LLDB_INVALID_ADDRESS; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); Error err; std::unique_ptr llvm_module_ap (m_code_generator->ReleaseModule()); if (!llvm_module_ap.get()) { err.SetErrorToGenericError(); err.SetErrorString("IR doesn't contain a module"); return err; } // Find the actual name of the function (it's often mangled somehow) ConstString function_name; if (!FindFunctionInModule(function_name, llvm_module_ap.get(), m_expr.FunctionName())) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName()); return err; } else { if (log) log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName()); } execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here llvm_module_ap, // handed off here function_name, exe_ctx.GetTargetSP(), m_compiler->getTargetOpts().Features)); ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL if (decl_map) { Stream *error_stream = NULL; Target *target = exe_ctx.GetTargetPtr(); if (target) error_stream = target->GetDebugger().GetErrorFile().get(); IRForTarget ir_for_target(decl_map, m_expr.NeedsVariableResolution(), *execution_unit_sp, error_stream, function_name.AsCString()); bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule()); Error interpret_error; can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error); Process *process = exe_ctx.GetProcessPtr(); if (!ir_can_run) { err.SetErrorString("The expression could not be prepared to run in the target"); return err; } if (!can_interpret && execution_policy == eExecutionPolicyNever) { err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString()); return err; } if (!process && execution_policy == eExecutionPolicyAlways) { err.SetErrorString("Expression needed to run in the target, but the target can't be run"); return err; } if (execution_policy == eExecutionPolicyAlways || !can_interpret) { if (m_expr.NeedsValidation() && process) { if (!process->GetDynamicCheckers()) { DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); StreamString install_errors; if (!dynamic_checkers->Install(install_errors, exe_ctx)) { if (install_errors.GetString().empty()) err.SetErrorString ("couldn't install checkers, unknown error"); else err.SetErrorString (install_errors.GetString().c_str()); return err; } process->SetDynamicCheckers(dynamic_checkers); if (log) log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers =="); } IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString()); if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule())) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't add dynamic checks to the expression"); return err; } } execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); } } else { execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); } return err; } bool ClangExpressionParser::GetGenerateDebugInfo () const { if (m_compiler) return m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo; return false; } Index: projects/clang350-import/contrib/llvm/tools/lldb/source/Expression/IRExecutionUnit.cpp =================================================================== --- projects/clang350-import/contrib/llvm/tools/lldb/source/Expression/IRExecutionUnit.cpp (revision 275126) +++ projects/clang350-import/contrib/llvm/tools/lldb/source/Expression/IRExecutionUnit.cpp (revision 275127) @@ -1,947 +1,951 @@ //===-- IRExecutionUnit.cpp -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/SourceMgr.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Target.h" using namespace lldb_private; IRExecutionUnit::IRExecutionUnit (std::unique_ptr &context_ap, std::unique_ptr &module_ap, ConstString &name, const lldb::TargetSP &target_sp, std::vector &cpu_features) : IRMemoryMap(target_sp), m_context_ap(context_ap.release()), m_module_ap(module_ap.release()), m_module(m_module_ap.get()), m_cpu_features(cpu_features), m_name(name), m_did_jit(false), m_function_load_addr(LLDB_INVALID_ADDRESS), m_function_end_load_addr(LLDB_INVALID_ADDRESS) { } lldb::addr_t IRExecutionUnit::WriteNow (const uint8_t *bytes, size_t size, Error &error) { lldb::addr_t allocation_process_addr = Malloc (size, 8, lldb::ePermissionsWritable | lldb::ePermissionsReadable, eAllocationPolicyMirror, error); if (!error.Success()) return LLDB_INVALID_ADDRESS; WriteMemory(allocation_process_addr, bytes, size, error); if (!error.Success()) { Error err; Free (allocation_process_addr, err); return LLDB_INVALID_ADDRESS; } if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) { DataBufferHeap my_buffer(size, 0); Error err; ReadMemory(my_buffer.GetBytes(), allocation_process_addr, size, err); if (err.Success()) { DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8); my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), allocation_process_addr, 16, DataExtractor::TypeUInt8); } } return allocation_process_addr; } void IRExecutionUnit::FreeNow (lldb::addr_t allocation) { if (allocation == LLDB_INVALID_ADDRESS) return; Error err; Free(allocation, err); } Error IRExecutionUnit::DisassembleFunction (Stream &stream, lldb::ProcessSP &process_wp) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); ExecutionContext exe_ctx(process_wp); Error ret; ret.Clear(); lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS; lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS; for (JittedFunction &function : m_jitted_functions) { if (strstr(function.m_name.c_str(), m_name.AsCString())) { func_local_addr = function.m_local_addr; func_remote_addr = function.m_remote_addr; } } if (func_local_addr == LLDB_INVALID_ADDRESS) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", m_name.AsCString()); return ret; } if (log) log->Printf("Found function, has local address 0x%" PRIx64 " and remote address 0x%" PRIx64, (uint64_t)func_local_addr, (uint64_t)func_remote_addr); std::pair func_range; func_range = GetRemoteRangeForLocal(func_local_addr); if (func_range.first == 0 && func_range.second == 0) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't find code range for function %s", m_name.AsCString()); return ret; } if (log) log->Printf("Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]", func_range.first, func_range.second); Target *target = exe_ctx.GetTargetPtr(); if (!target) { ret.SetErrorToGenericError(); ret.SetErrorString("Couldn't find the target"); return ret; } lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0)); Process *process = exe_ctx.GetProcessPtr(); Error err; process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err); if (!err.Success()) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error")); return ret; } ArchSpec arch(target->GetArchitecture()); const char *plugin_name = NULL; const char *flavor_string = NULL; lldb::DisassemblerSP disassembler_sp = Disassembler::FindPlugin(arch, flavor_string, plugin_name); if (!disassembler_sp) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName()); return ret; } if (!process) { ret.SetErrorToGenericError(); ret.SetErrorString("Couldn't find the process"); return ret; } DataExtractor extractor(buffer_sp, process->GetByteOrder(), target->GetArchitecture().GetAddressByteSize()); if (log) { log->Printf("Function data has contents:"); extractor.PutToLog (log, 0, extractor.GetByteSize(), func_remote_addr, 16, DataExtractor::TypeUInt8); } disassembler_sp->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false, false); InstructionList &instruction_list = disassembler_sp->GetInstructionList(); const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize(); for (size_t instruction_index = 0, num_instructions = instruction_list.GetSize(); instruction_index < num_instructions; ++instruction_index) { Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index).get(); instruction->Dump (&stream, max_opcode_byte_size, true, true, &exe_ctx); stream.PutChar('\n'); } // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions. // I'll fix that but for now, just clear the list and it will go away nicely. disassembler_sp->GetInstructionList().Clear(); return ret; } static void ReportInlineAsmError(const llvm::SMDiagnostic &diagnostic, void *Context, unsigned LocCookie) { Error *err = static_cast(Context); if (err && err->Success()) { err->SetErrorToGenericError(); err->SetErrorStringWithFormat("Inline assembly error: %s", diagnostic.getMessage().str().c_str()); } } void IRExecutionUnit::GetRunnableInfo(Error &error, lldb::addr_t &func_addr, lldb::addr_t &func_end) { lldb::ProcessSP process_sp(GetProcessWP().lock()); static Mutex s_runnable_info_mutex(Mutex::Type::eMutexTypeRecursive); func_addr = LLDB_INVALID_ADDRESS; func_end = LLDB_INVALID_ADDRESS; if (!process_sp) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't write the JIT compiled code into the process because the process is invalid"); return; } if (m_did_jit) { func_addr = m_function_load_addr; func_end = m_function_end_load_addr; return; }; Mutex::Locker runnable_info_mutex_locker(s_runnable_info_mutex); m_did_jit = true; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); std::string error_string; if (log) { std::string s; llvm::raw_string_ostream oss(s); m_module->print(oss, NULL); oss.flush(); log->Printf ("Module being sent to JIT: \n%s", s.c_str()); } llvm::Triple triple(m_module->getTargetTriple()); llvm::Function *function = m_module->getFunction (m_name.AsCString()); llvm::Reloc::Model relocModel; llvm::CodeModel::Model codeModel; if (triple.isOSBinFormatELF()) { relocModel = llvm::Reloc::Static; // This will be small for 32-bit and large for 64-bit. codeModel = llvm::CodeModel::JITDefault; } else { relocModel = llvm::Reloc::PIC_; codeModel = llvm::CodeModel::Small; } m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error); - llvm::EngineBuilder builder(std::move(m_module_ap)); + llvm::EngineBuilder builder(m_module_ap.get()); builder.setEngineKind(llvm::EngineKind::JIT) .setErrorStr(&error_string) .setRelocationModel(relocModel) .setJITMemoryManager(new MemoryManager(*this)) .setOptLevel(llvm::CodeGenOpt::Less) .setAllocateGVsWithCode(true) .setCodeModel(codeModel) .setUseMCJIT(true); llvm::StringRef mArch; llvm::StringRef mCPU; llvm::SmallVector mAttrs; for (std::string &feature : m_cpu_features) mAttrs.push_back(feature); llvm::TargetMachine *target_machine = builder.selectTarget(triple, mArch, mCPU, mAttrs); m_execution_engine_ap.reset(builder.create(target_machine)); if (!m_execution_engine_ap.get()) { error.SetErrorToGenericError(); error.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str()); return; + } + else + { + m_module_ap.release(); // ownership was transferred } // Make sure we see all sections, including ones that don't have relocations... m_execution_engine_ap->setProcessAllSections(true); m_execution_engine_ap->DisableLazyCompilation(); // We don't actually need the function pointer here, this just forces it to get resolved. void *fun_ptr = m_execution_engine_ap->getPointerToFunction(function); if (!error.Success()) { // We got an error through our callback! return; } if (!function) { error.SetErrorToGenericError(); error.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", m_name.AsCString()); return; } if (!fun_ptr) { error.SetErrorToGenericError(); error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", m_name.AsCString()); return; } m_jitted_functions.push_back (JittedFunction(m_name.AsCString(), (lldb::addr_t)fun_ptr)); CommitAllocations(process_sp); ReportAllocations(*m_execution_engine_ap); WriteData(process_sp); for (JittedFunction &jitted_function : m_jitted_functions) { jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr); if (!jitted_function.m_name.compare(m_name.AsCString())) { AddrRange func_range = GetRemoteRangeForLocal(jitted_function.m_local_addr); m_function_end_load_addr = func_range.first + func_range.second; m_function_load_addr = jitted_function.m_remote_addr; } } if (log) { log->Printf("Code can be run in the target."); StreamString disassembly_stream; Error err = DisassembleFunction(disassembly_stream, process_sp); if (!err.Success()) { log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error")); } else { log->Printf("Function disassembly:\n%s", disassembly_stream.GetData()); } log->Printf("Sections: "); for (AllocationRecord &record : m_records) { if (record.m_process_address != LLDB_INVALID_ADDRESS) { record.dump(log); DataBufferHeap my_buffer(record.m_size, 0); Error err; ReadMemory(my_buffer.GetBytes(), record.m_process_address, record.m_size, err); if (err.Success()) { DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8); my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), record.m_process_address, 16, DataExtractor::TypeUInt8); } } } } func_addr = m_function_load_addr; func_end = m_function_end_load_addr; return; } IRExecutionUnit::~IRExecutionUnit () { m_module_ap.reset(); m_execution_engine_ap.reset(); m_context_ap.reset(); } IRExecutionUnit::MemoryManager::MemoryManager (IRExecutionUnit &parent) : m_default_mm_ap (llvm::JITMemoryManager::CreateDefaultMemManager()), m_parent (parent) { } IRExecutionUnit::MemoryManager::~MemoryManager () { } void IRExecutionUnit::MemoryManager::setMemoryWritable () { m_default_mm_ap->setMemoryWritable(); } void IRExecutionUnit::MemoryManager::setMemoryExecutable () { m_default_mm_ap->setMemoryExecutable(); } uint8_t * IRExecutionUnit::MemoryManager::startFunctionBody(const llvm::Function *F, uintptr_t &ActualSize) { return m_default_mm_ap->startFunctionBody(F, ActualSize); } uint8_t * IRExecutionUnit::MemoryManager::allocateStub(const llvm::GlobalValue* F, unsigned StubSize, unsigned Alignment) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); uint8_t *return_value = m_default_mm_ap->allocateStub(F, StubSize, Alignment); m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value, lldb::ePermissionsReadable | lldb::ePermissionsWritable, GetSectionTypeFromSectionName (llvm::StringRef(), AllocationKind::Stub), StubSize, Alignment, eSectionIDInvalid, NULL)); if (log) { log->Printf("IRExecutionUnit::allocateStub (F=%p, StubSize=%u, Alignment=%u) = %p", static_cast(F), StubSize, Alignment, static_cast(return_value)); } return return_value; } void IRExecutionUnit::MemoryManager::endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart, uint8_t *FunctionEnd) { m_default_mm_ap->endFunctionBody(F, FunctionStart, FunctionEnd); } lldb::SectionType IRExecutionUnit::GetSectionTypeFromSectionName (const llvm::StringRef &name, IRExecutionUnit::AllocationKind alloc_kind) { lldb::SectionType sect_type = lldb::eSectionTypeCode; switch (alloc_kind) { case AllocationKind::Stub: sect_type = lldb::eSectionTypeCode; break; case AllocationKind::Code: sect_type = lldb::eSectionTypeCode; break; case AllocationKind::Data: sect_type = lldb::eSectionTypeData; break; case AllocationKind::Global:sect_type = lldb::eSectionTypeData; break; case AllocationKind::Bytes: sect_type = lldb::eSectionTypeOther; break; } if (!name.empty()) { if (name.equals("__text") || name.equals(".text")) sect_type = lldb::eSectionTypeCode; else if (name.equals("__data") || name.equals(".data")) sect_type = lldb::eSectionTypeCode; else if (name.startswith("__debug_") || name.startswith(".debug_")) { const uint32_t name_idx = name[0] == '_' ? 8 : 7; llvm::StringRef dwarf_name(name.substr(name_idx)); switch (dwarf_name[0]) { case 'a': if (dwarf_name.equals("abbrev")) sect_type = lldb::eSectionTypeDWARFDebugAbbrev; else if (dwarf_name.equals("aranges")) sect_type = lldb::eSectionTypeDWARFDebugAranges; break; case 'f': if (dwarf_name.equals("frame")) sect_type = lldb::eSectionTypeDWARFDebugFrame; break; case 'i': if (dwarf_name.equals("info")) sect_type = lldb::eSectionTypeDWARFDebugInfo; break; case 'l': if (dwarf_name.equals("line")) sect_type = lldb::eSectionTypeDWARFDebugLine; else if (dwarf_name.equals("loc")) sect_type = lldb::eSectionTypeDWARFDebugLoc; break; case 'm': if (dwarf_name.equals("macinfo")) sect_type = lldb::eSectionTypeDWARFDebugMacInfo; break; case 'p': if (dwarf_name.equals("pubnames")) sect_type = lldb::eSectionTypeDWARFDebugPubNames; else if (dwarf_name.equals("pubtypes")) sect_type = lldb::eSectionTypeDWARFDebugPubTypes; break; case 's': if (dwarf_name.equals("str")) sect_type = lldb::eSectionTypeDWARFDebugStr; break; case 'r': if (dwarf_name.equals("ranges")) sect_type = lldb::eSectionTypeDWARFDebugRanges; break; default: break; } } else if (name.startswith("__apple_") || name.startswith(".apple_")) { #if 0 const uint32_t name_idx = name[0] == '_' ? 8 : 7; llvm::StringRef apple_name(name.substr(name_idx)); switch (apple_name[0]) { case 'n': if (apple_name.equals("names")) sect_type = lldb::eSectionTypeDWARFAppleNames; else if (apple_name.equals("namespac") || apple_name.equals("namespaces")) sect_type = lldb::eSectionTypeDWARFAppleNamespaces; break; case 't': if (apple_name.equals("types")) sect_type = lldb::eSectionTypeDWARFAppleTypes; break; case 'o': if (apple_name.equals("objc")) sect_type = lldb::eSectionTypeDWARFAppleObjC; break; default: break; } #else sect_type = lldb::eSectionTypeInvalid; #endif } else if (name.equals("__objc_imageinfo")) sect_type = lldb::eSectionTypeOther; } return sect_type; } uint8_t * IRExecutionUnit::MemoryManager::allocateSpace(intptr_t Size, unsigned Alignment) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); uint8_t *return_value = m_default_mm_ap->allocateSpace(Size, Alignment); m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value, lldb::ePermissionsReadable | lldb::ePermissionsWritable, GetSectionTypeFromSectionName (llvm::StringRef(), AllocationKind::Bytes), Size, Alignment, eSectionIDInvalid, NULL)); if (log) { log->Printf("IRExecutionUnit::allocateSpace(Size=%" PRIu64 ", Alignment=%u) = %p", (uint64_t)Size, Alignment, return_value); } return return_value; } uint8_t * IRExecutionUnit::MemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID, SectionName); m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value, lldb::ePermissionsReadable | lldb::ePermissionsExecutable, GetSectionTypeFromSectionName (SectionName, AllocationKind::Code), Size, Alignment, SectionID, SectionName.str().c_str())); if (log) { log->Printf("IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p", (uint64_t)Size, Alignment, SectionID, return_value); } return return_value; } uint8_t * IRExecutionUnit::MemoryManager::allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName, bool IsReadOnly) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID, SectionName, IsReadOnly); m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value, lldb::ePermissionsReadable | (IsReadOnly ? 0 : lldb::ePermissionsWritable), GetSectionTypeFromSectionName (SectionName, AllocationKind::Data), Size, Alignment, SectionID, SectionName.str().c_str())); if (log) { log->Printf("IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p", (uint64_t)Size, Alignment, SectionID, return_value); } return return_value; } uint8_t * IRExecutionUnit::MemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); uint8_t *return_value = m_default_mm_ap->allocateGlobal(Size, Alignment); m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value, lldb::ePermissionsReadable | lldb::ePermissionsWritable, GetSectionTypeFromSectionName (llvm::StringRef(), AllocationKind::Global), Size, Alignment, eSectionIDInvalid, NULL)); if (log) { log->Printf("IRExecutionUnit::allocateGlobal(Size=0x%" PRIx64 ", Alignment=%u) = %p", (uint64_t)Size, Alignment, return_value); } return return_value; } void IRExecutionUnit::MemoryManager::deallocateFunctionBody(void *Body) { m_default_mm_ap->deallocateFunctionBody(Body); } lldb::addr_t IRExecutionUnit::GetRemoteAddressForLocal (lldb::addr_t local_address) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); for (AllocationRecord &record : m_records) { if (local_address >= record.m_host_address && local_address < record.m_host_address + record.m_size) { if (record.m_process_address == LLDB_INVALID_ADDRESS) return LLDB_INVALID_ADDRESS; lldb::addr_t ret = record.m_process_address + (local_address - record.m_host_address); if (log) { log->Printf("IRExecutionUnit::GetRemoteAddressForLocal() found 0x%" PRIx64 " in [0x%" PRIx64 "..0x%" PRIx64 "], and returned 0x%" PRIx64 " from [0x%" PRIx64 "..0x%" PRIx64 "].", local_address, (uint64_t)record.m_host_address, (uint64_t)record.m_host_address + (uint64_t)record.m_size, ret, record.m_process_address, record.m_process_address + record.m_size); } return ret; } } return LLDB_INVALID_ADDRESS; } IRExecutionUnit::AddrRange IRExecutionUnit::GetRemoteRangeForLocal (lldb::addr_t local_address) { for (AllocationRecord &record : m_records) { if (local_address >= record.m_host_address && local_address < record.m_host_address + record.m_size) { if (record.m_process_address == LLDB_INVALID_ADDRESS) return AddrRange(0, 0); return AddrRange(record.m_process_address, record.m_size); } } return AddrRange (0, 0); } bool IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp) { bool ret = true; lldb_private::Error err; for (AllocationRecord &record : m_records) { if (record.m_process_address != LLDB_INVALID_ADDRESS) continue; switch (record.m_sect_type) { case lldb::eSectionTypeInvalid: case lldb::eSectionTypeDWARFDebugAbbrev: case lldb::eSectionTypeDWARFDebugAranges: case lldb::eSectionTypeDWARFDebugFrame: case lldb::eSectionTypeDWARFDebugInfo: case lldb::eSectionTypeDWARFDebugLine: case lldb::eSectionTypeDWARFDebugLoc: case lldb::eSectionTypeDWARFDebugMacInfo: case lldb::eSectionTypeDWARFDebugPubNames: case lldb::eSectionTypeDWARFDebugPubTypes: case lldb::eSectionTypeDWARFDebugRanges: case lldb::eSectionTypeDWARFDebugStr: case lldb::eSectionTypeDWARFAppleNames: case lldb::eSectionTypeDWARFAppleTypes: case lldb::eSectionTypeDWARFAppleNamespaces: case lldb::eSectionTypeDWARFAppleObjC: err.Clear(); break; default: record.m_process_address = Malloc (record.m_size, record.m_alignment, record.m_permissions, eAllocationPolicyProcessOnly, err); break; } if (!err.Success()) { ret = false; break; } } if (!ret) { for (AllocationRecord &record : m_records) { if (record.m_process_address != LLDB_INVALID_ADDRESS) { Free(record.m_process_address, err); record.m_process_address = LLDB_INVALID_ADDRESS; } } } return ret; } void IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine) { for (AllocationRecord &record : m_records) { if (record.m_process_address == LLDB_INVALID_ADDRESS) continue; if (record.m_section_id == eSectionIDInvalid) continue; engine.mapSectionAddress((void*)record.m_host_address, record.m_process_address); } // Trigger re-application of relocations. engine.finalizeObject(); } bool IRExecutionUnit::WriteData (lldb::ProcessSP &process_sp) { bool wrote_something = false; for (AllocationRecord &record : m_records) { if (record.m_process_address != LLDB_INVALID_ADDRESS) { lldb_private::Error err; WriteMemory (record.m_process_address, (uint8_t*)record.m_host_address, record.m_size, err); if (err.Success()) wrote_something = true; } } return wrote_something; } void IRExecutionUnit::AllocationRecord::dump (Log *log) { if (!log) return; log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d)", (unsigned long long)m_host_address, (unsigned long long)m_size, (unsigned long long)m_process_address, (unsigned)m_alignment, (unsigned)m_section_id); } lldb::ByteOrder IRExecutionUnit::GetByteOrder () const { ExecutionContext exe_ctx (GetBestExecutionContextScope()); return exe_ctx.GetByteOrder(); } uint32_t IRExecutionUnit::GetAddressByteSize () const { ExecutionContext exe_ctx (GetBestExecutionContextScope()); return exe_ctx.GetAddressByteSize(); } void IRExecutionUnit::PopulateSymtab (lldb_private::ObjectFile *obj_file, lldb_private::Symtab &symtab) { // No symbols yet... } void IRExecutionUnit::PopulateSectionList (lldb_private::ObjectFile *obj_file, lldb_private::SectionList §ion_list) { for (AllocationRecord &record : m_records) { if (record.m_size > 0) { lldb::SectionSP section_sp (new lldb_private::Section (obj_file->GetModule(), obj_file, record.m_section_id, ConstString(record.m_name), record.m_sect_type, record.m_process_address, record.m_size, record.m_host_address, // file_offset (which is the host address for the data) record.m_size, // file_size 0, record.m_permissions)); // flags section_list.AddSection (section_sp); } } } bool IRExecutionUnit::GetArchitecture (lldb_private::ArchSpec &arch) { ExecutionContext exe_ctx (GetBestExecutionContextScope()); Target *target = exe_ctx.GetTargetPtr(); if (target) arch = target->GetArchitecture(); else arch.Clear(); return arch.IsValid(); } lldb::ModuleSP IRExecutionUnit::GetJITModule () { ExecutionContext exe_ctx (GetBestExecutionContextScope()); Target *target = exe_ctx.GetTargetPtr(); if (target) { lldb::ModuleSP jit_module_sp = lldb_private::Module::CreateJITModule (std::static_pointer_cast(shared_from_this())); if (jit_module_sp) { bool changed = false; jit_module_sp->SetLoadAddress(*target, 0, true, changed); } return jit_module_sp; } return lldb::ModuleSP(); } Index: projects/clang350-import/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp =================================================================== --- projects/clang350-import/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp (revision 275126) +++ projects/clang350-import/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp (revision 275127) @@ -1,2157 +1,2159 @@ //===-- ClangASTContext.cpp -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/Symbol/ClangASTContext.h" // C Includes // C++ Includes #include // Other libraries and framework includes // Clang headers like to use NDEBUG inside of them to enable/disable debug // related features using "#ifndef NDEBUG" preprocessor blocks to do one thing // or another. This is bad because it means that if clang was built in release // mode, it assumes that you are building in release mode which is not always // the case. You can end up with functions that are defined as empty in header // files when NDEBUG is not defined, and this can cause link errors with the // clang .a files that you have since you might be missing functions in the .a // file. So we have to define NDEBUG when including clang headers to avoid any // mismatches. This is covered by rdar://problem/8691220 #if !defined(NDEBUG) && !defined(LLVM_NDEBUG_OFF) #define LLDB_DEFINED_NDEBUG_FOR_CLANG #define NDEBUG // Need to include assert.h so it is as clang would expect it to be (disabled) #include #endif #include "clang/AST/ASTContext.h" #include "clang/AST/ASTImporter.h" #include "clang/AST/Attr.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/Type.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/FileSystemOptions.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" #include "clang/Frontend/FrontendOptions.h" #include "clang/Frontend/LangStandard.h" #ifdef LLDB_DEFINED_NDEBUG_FOR_CLANG #undef NDEBUG #undef LLDB_DEFINED_NDEBUG_FOR_CLANG // Need to re-include assert.h so it is as _we_ would expect it to be (enabled) #include #endif #include "lldb/Core/ArchSpec.h" #include "lldb/Core/dwarf.h" #include "lldb/Core/Flags.h" #include "lldb/Core/Log.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Expression/ASTDumper.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/VerifyDecl.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include #include using namespace lldb; using namespace lldb_private; using namespace llvm; using namespace clang; typedef llvm::DenseMap ClangASTMap; static ClangASTMap & GetASTMap() { static ClangASTMap g_map; return g_map; } clang::AccessSpecifier ClangASTContext::ConvertAccessTypeToAccessSpecifier (AccessType access) { switch (access) { default: break; case eAccessNone: return AS_none; case eAccessPublic: return AS_public; case eAccessPrivate: return AS_private; case eAccessProtected: return AS_protected; } return AS_none; } static void ParseLangArgs ( LangOptions &Opts, InputKind IK ) { // FIXME: Cleanup per-file based stuff. // Set some properties which depend solely on the input kind; it would be nice // to move these to the language standard, and have the driver resolve the // input kind + language standard. if (IK == IK_Asm) { Opts.AsmPreprocessor = 1; } else if (IK == IK_ObjC || IK == IK_ObjCXX || IK == IK_PreprocessedObjC || IK == IK_PreprocessedObjCXX) { Opts.ObjC1 = Opts.ObjC2 = 1; } LangStandard::Kind LangStd = LangStandard::lang_unspecified; if (LangStd == LangStandard::lang_unspecified) { // Based on the base language, pick one. switch (IK) { case IK_None: case IK_AST: case IK_LLVM_IR: assert (!"Invalid input kind!"); case IK_OpenCL: LangStd = LangStandard::lang_opencl; break; case IK_CUDA: LangStd = LangStandard::lang_cuda; break; case IK_Asm: case IK_C: case IK_PreprocessedC: case IK_ObjC: case IK_PreprocessedObjC: LangStd = LangStandard::lang_gnu99; break; case IK_CXX: case IK_PreprocessedCXX: case IK_ObjCXX: case IK_PreprocessedObjCXX: LangStd = LangStandard::lang_gnucxx98; break; } } const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); Opts.LineComment = Std.hasLineComments(); Opts.C99 = Std.isC99(); Opts.CPlusPlus = Std.isCPlusPlus(); Opts.CPlusPlus11 = Std.isCPlusPlus11(); Opts.Digraphs = Std.hasDigraphs(); Opts.GNUMode = Std.isGNUMode(); Opts.GNUInline = !Std.isC99(); Opts.HexFloats = Std.hasHexFloats(); Opts.ImplicitInt = Std.hasImplicitInt(); Opts.WChar = true; // OpenCL has some additional defaults. if (LangStd == LangStandard::lang_opencl) { Opts.OpenCL = 1; Opts.AltiVec = 1; Opts.CXXOperatorNames = 1; Opts.LaxVectorConversions = 1; } // OpenCL and C++ both have bool, true, false keywords. Opts.Bool = Opts.OpenCL || Opts.CPlusPlus; // if (Opts.CPlusPlus) // Opts.CXXOperatorNames = !Args.hasArg(OPT_fno_operator_names); // // if (Args.hasArg(OPT_fobjc_gc_only)) // Opts.setGCMode(LangOptions::GCOnly); // else if (Args.hasArg(OPT_fobjc_gc)) // Opts.setGCMode(LangOptions::HybridGC); // // if (Args.hasArg(OPT_print_ivar_layout)) // Opts.ObjCGCBitmapPrint = 1; // // if (Args.hasArg(OPT_faltivec)) // Opts.AltiVec = 1; // // if (Args.hasArg(OPT_pthread)) // Opts.POSIXThreads = 1; // // llvm::StringRef Vis = getLastArgValue(Args, OPT_fvisibility, // "default"); // if (Vis == "default") Opts.setValueVisibilityMode(DefaultVisibility); // else if (Vis == "hidden") // Opts.setVisibilityMode(LangOptions::Hidden); // else if (Vis == "protected") // Opts.setVisibilityMode(LangOptions::Protected); // else // Diags.Report(diag::err_drv_invalid_value) // << Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis; // Opts.OverflowChecking = Args.hasArg(OPT_ftrapv); // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs // is specified, or -std is set to a conforming mode. Opts.Trigraphs = !Opts.GNUMode; // if (Args.hasArg(OPT_trigraphs)) // Opts.Trigraphs = 1; // // Opts.DollarIdents = Args.hasFlag(OPT_fdollars_in_identifiers, // OPT_fno_dollars_in_identifiers, // !Opts.AsmPreprocessor); // Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings); // Opts.Microsoft = Args.hasArg(OPT_fms_extensions); // Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings); // if (Args.hasArg(OPT_fno_lax_vector_conversions)) // Opts.LaxVectorConversions = 0; // Opts.Exceptions = Args.hasArg(OPT_fexceptions); // Opts.RTTI = !Args.hasArg(OPT_fno_rtti); // Opts.Blocks = Args.hasArg(OPT_fblocks); // Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char); // Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar); // Opts.Freestanding = Args.hasArg(OPT_ffreestanding); // Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; // Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new); // Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions); // Opts.AccessControl = Args.hasArg(OPT_faccess_control); // Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors); // Opts.MathErrno = !Args.hasArg(OPT_fno_math_errno); // Opts.InstantiationDepth = getLastArgIntValue(Args, OPT_ftemplate_depth, 99, // Diags); // Opts.NeXTRuntime = !Args.hasArg(OPT_fgnu_runtime); // Opts.ObjCConstantStringClass = getLastArgValue(Args, // OPT_fconstant_string_class); // Opts.ObjCNonFragileABI = Args.hasArg(OPT_fobjc_nonfragile_abi); // Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior); // Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls); // Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); // Opts.Static = Args.hasArg(OPT_static_define); Opts.OptimizeSize = 0; // FIXME: Eliminate this dependency. // unsigned Opt = // Args.hasArg(OPT_Os) ? 2 : getLastArgIntValue(Args, OPT_O, 0, Diags); // Opts.Optimize = Opt != 0; unsigned Opt = 0; // This is the __NO_INLINE__ define, which just depends on things like the // optimization level and -fno-inline, not actually whether the backend has // inlining enabled. // // FIXME: This is affected by other options (-fno-inline). Opts.NoInlineDefine = !Opt; // unsigned SSP = getLastArgIntValue(Args, OPT_stack_protector, 0, Diags); // switch (SSP) { // default: // Diags.Report(diag::err_drv_invalid_value) // << Args.getLastArg(OPT_stack_protector)->getAsString(Args) << SSP; // break; // case 0: Opts.setStackProtectorMode(LangOptions::SSPOff); break; // case 1: Opts.setStackProtectorMode(LangOptions::SSPOn); break; // case 2: Opts.setStackProtectorMode(LangOptions::SSPReq); break; // } } ClangASTContext::ClangASTContext (const char *target_triple) : m_target_triple(), m_ast_ap(), m_language_options_ap(), m_source_manager_ap(), m_diagnostics_engine_ap(), m_target_options_rp(), m_target_info_ap(), m_identifier_table_ap(), m_selector_table_ap(), m_builtins_ap(), m_callback_tag_decl (nullptr), m_callback_objc_decl (nullptr), m_callback_baton (nullptr), m_pointer_byte_size (0) { if (target_triple && target_triple[0]) SetTargetTriple (target_triple); } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- ClangASTContext::~ClangASTContext() { if (m_ast_ap.get()) { GetASTMap().erase(m_ast_ap.get()); } m_builtins_ap.reset(); m_selector_table_ap.reset(); m_identifier_table_ap.reset(); m_target_info_ap.reset(); m_target_options_rp.reset(); m_diagnostics_engine_ap.reset(); m_source_manager_ap.reset(); m_language_options_ap.reset(); m_ast_ap.reset(); } void ClangASTContext::Clear() { m_ast_ap.reset(); m_language_options_ap.reset(); m_source_manager_ap.reset(); m_diagnostics_engine_ap.reset(); m_target_options_rp.reset(); m_target_info_ap.reset(); m_identifier_table_ap.reset(); m_selector_table_ap.reset(); m_builtins_ap.reset(); m_pointer_byte_size = 0; } const char * ClangASTContext::GetTargetTriple () { return m_target_triple.c_str(); } void ClangASTContext::SetTargetTriple (const char *target_triple) { Clear(); m_target_triple.assign(target_triple); } void ClangASTContext::SetArchitecture (const ArchSpec &arch) { SetTargetTriple(arch.GetTriple().str().c_str()); } bool ClangASTContext::HasExternalSource () { ASTContext *ast = getASTContext(); if (ast) return ast->getExternalSource () != nullptr; return false; } void ClangASTContext::SetExternalSource (llvm::IntrusiveRefCntPtr &ast_source_ap) { ASTContext *ast = getASTContext(); if (ast) { ast->setExternalSource (ast_source_ap); ast->getTranslationUnitDecl()->setHasExternalLexicalStorage(true); //ast->getTranslationUnitDecl()->setHasExternalVisibleStorage(true); } } void ClangASTContext::RemoveExternalSource () { ASTContext *ast = getASTContext(); if (ast) { llvm::IntrusiveRefCntPtr empty_ast_source_ap; ast->setExternalSource (empty_ast_source_ap); ast->getTranslationUnitDecl()->setHasExternalLexicalStorage(false); //ast->getTranslationUnitDecl()->setHasExternalVisibleStorage(false); } } ASTContext * ClangASTContext::getASTContext() { if (m_ast_ap.get() == nullptr) { m_ast_ap.reset(new ASTContext (*getLanguageOptions(), *getSourceManager(), *getIdentifierTable(), *getSelectorTable(), *getBuiltinContext())); m_ast_ap->InitBuiltinTypes(*getTargetInfo()); if ((m_callback_tag_decl || m_callback_objc_decl) && m_callback_baton) { m_ast_ap->getTranslationUnitDecl()->setHasExternalLexicalStorage(); //m_ast_ap->getTranslationUnitDecl()->setHasExternalVisibleStorage(); } m_ast_ap->getDiagnostics().setClient(getDiagnosticConsumer(), false); GetASTMap().insert(std::make_pair(m_ast_ap.get(), this)); } return m_ast_ap.get(); } ClangASTContext* ClangASTContext::GetASTContext (clang::ASTContext* ast) { ClangASTContext *clang_ast = GetASTMap().lookup(ast); return clang_ast; } Builtin::Context * ClangASTContext::getBuiltinContext() { if (m_builtins_ap.get() == nullptr) m_builtins_ap.reset (new Builtin::Context()); return m_builtins_ap.get(); } IdentifierTable * ClangASTContext::getIdentifierTable() { if (m_identifier_table_ap.get() == nullptr) m_identifier_table_ap.reset(new IdentifierTable (*ClangASTContext::getLanguageOptions(), nullptr)); return m_identifier_table_ap.get(); } LangOptions * ClangASTContext::getLanguageOptions() { if (m_language_options_ap.get() == nullptr) { m_language_options_ap.reset(new LangOptions()); ParseLangArgs(*m_language_options_ap, IK_ObjCXX); // InitializeLangOptions(*m_language_options_ap, IK_ObjCXX); } return m_language_options_ap.get(); } SelectorTable * ClangASTContext::getSelectorTable() { if (m_selector_table_ap.get() == nullptr) m_selector_table_ap.reset (new SelectorTable()); return m_selector_table_ap.get(); } clang::FileManager * ClangASTContext::getFileManager() { if (m_file_manager_ap.get() == nullptr) { clang::FileSystemOptions file_system_options; m_file_manager_ap.reset(new clang::FileManager(file_system_options)); } return m_file_manager_ap.get(); } clang::SourceManager * ClangASTContext::getSourceManager() { if (m_source_manager_ap.get() == nullptr) m_source_manager_ap.reset(new clang::SourceManager(*getDiagnosticsEngine(), *getFileManager())); return m_source_manager_ap.get(); } clang::DiagnosticsEngine * ClangASTContext::getDiagnosticsEngine() { if (m_diagnostics_engine_ap.get() == nullptr) { llvm::IntrusiveRefCntPtr diag_id_sp(new DiagnosticIDs()); m_diagnostics_engine_ap.reset(new DiagnosticsEngine(diag_id_sp, new DiagnosticOptions())); } return m_diagnostics_engine_ap.get(); } class NullDiagnosticConsumer : public DiagnosticConsumer { public: NullDiagnosticConsumer () { m_log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); } void HandleDiagnostic (DiagnosticsEngine::Level DiagLevel, const Diagnostic &info) { if (m_log) { llvm::SmallVector diag_str(10); info.FormatDiagnostic(diag_str); diag_str.push_back('\0'); m_log->Printf("Compiler diagnostic: %s\n", diag_str.data()); } } DiagnosticConsumer *clone (DiagnosticsEngine &Diags) const { return new NullDiagnosticConsumer (); } private: Log * m_log; }; DiagnosticConsumer * ClangASTContext::getDiagnosticConsumer() { if (m_diagnostic_consumer_ap.get() == nullptr) m_diagnostic_consumer_ap.reset(new NullDiagnosticConsumer); return m_diagnostic_consumer_ap.get(); } std::shared_ptr & ClangASTContext::getTargetOptions() { if (m_target_options_rp.get() == nullptr && !m_target_triple.empty()) { m_target_options_rp = std::make_shared(); if (m_target_options_rp.get() != nullptr) m_target_options_rp->Triple = m_target_triple; } return m_target_options_rp; } TargetInfo * ClangASTContext::getTargetInfo() { // target_triple should be something like "x86_64-apple-macosx" if (m_target_info_ap.get() == nullptr && !m_target_triple.empty()) m_target_info_ap.reset (TargetInfo::CreateTargetInfo(*getDiagnosticsEngine(), getTargetOptions())); return m_target_info_ap.get(); } #pragma mark Basic Types static inline bool QualTypeMatchesBitSize(const uint64_t bit_size, ASTContext *ast, QualType qual_type) { uint64_t qual_type_bit_size = ast->getTypeSize(qual_type); if (qual_type_bit_size == bit_size) return true; return false; } ClangASTType ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (Encoding encoding, uint32_t bit_size) { return ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (getASTContext(), encoding, bit_size); } ClangASTType ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (ASTContext *ast, Encoding encoding, uint32_t bit_size) { if (!ast) return ClangASTType(); switch (encoding) { case eEncodingInvalid: if (QualTypeMatchesBitSize (bit_size, ast, ast->VoidPtrTy)) return ClangASTType (ast, ast->VoidPtrTy.getAsOpaquePtr()); break; case eEncodingUint: if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) return ClangASTType (ast, ast->UnsignedCharTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) return ClangASTType (ast, ast->UnsignedShortTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) return ClangASTType (ast, ast->UnsignedIntTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongTy)) return ClangASTType (ast, ast->UnsignedLongTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongLongTy)) return ClangASTType (ast, ast->UnsignedLongLongTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedInt128Ty)) return ClangASTType (ast, ast->UnsignedInt128Ty.getAsOpaquePtr()); break; case eEncodingSint: if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) return ClangASTType (ast, ast->CharTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy)) return ClangASTType (ast, ast->ShortTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy)) return ClangASTType (ast, ast->IntTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->LongTy)) return ClangASTType (ast, ast->LongTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->LongLongTy)) return ClangASTType (ast, ast->LongLongTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->Int128Ty)) return ClangASTType (ast, ast->Int128Ty.getAsOpaquePtr()); break; case eEncodingIEEE754: if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy)) return ClangASTType (ast, ast->FloatTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy)) return ClangASTType (ast, ast->DoubleTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleTy)) return ClangASTType (ast, ast->LongDoubleTy.getAsOpaquePtr()); break; case eEncodingVector: // Sanity check that bit_size is a multiple of 8's. if (bit_size && !(bit_size & 0x7u)) return ClangASTType (ast, ast->getExtVectorType (ast->UnsignedCharTy, bit_size/8).getAsOpaquePtr()); break; } return ClangASTType(); } lldb::BasicType ClangASTContext::GetBasicTypeEnumeration (const ConstString &name) { if (name) { typedef UniqueCStringMap TypeNameToBasicTypeMap; static TypeNameToBasicTypeMap g_type_map; static std::once_flag g_once_flag; std::call_once(g_once_flag, [](){ // "void" g_type_map.Append(ConstString("void").GetCString(), eBasicTypeVoid); // "char" g_type_map.Append(ConstString("char").GetCString(), eBasicTypeChar); g_type_map.Append(ConstString("signed char").GetCString(), eBasicTypeSignedChar); g_type_map.Append(ConstString("unsigned char").GetCString(), eBasicTypeUnsignedChar); g_type_map.Append(ConstString("wchar_t").GetCString(), eBasicTypeWChar); g_type_map.Append(ConstString("signed wchar_t").GetCString(), eBasicTypeSignedWChar); g_type_map.Append(ConstString("unsigned wchar_t").GetCString(), eBasicTypeUnsignedWChar); // "short" g_type_map.Append(ConstString("short").GetCString(), eBasicTypeShort); g_type_map.Append(ConstString("short int").GetCString(), eBasicTypeShort); g_type_map.Append(ConstString("unsigned short").GetCString(), eBasicTypeUnsignedShort); g_type_map.Append(ConstString("unsigned short int").GetCString(), eBasicTypeUnsignedShort); // "int" g_type_map.Append(ConstString("int").GetCString(), eBasicTypeInt); g_type_map.Append(ConstString("signed int").GetCString(), eBasicTypeInt); g_type_map.Append(ConstString("unsigned int").GetCString(), eBasicTypeUnsignedInt); g_type_map.Append(ConstString("unsigned").GetCString(), eBasicTypeUnsignedInt); // "long" g_type_map.Append(ConstString("long").GetCString(), eBasicTypeLong); g_type_map.Append(ConstString("long int").GetCString(), eBasicTypeLong); g_type_map.Append(ConstString("unsigned long").GetCString(), eBasicTypeUnsignedLong); g_type_map.Append(ConstString("unsigned long int").GetCString(), eBasicTypeUnsignedLong); // "long long" g_type_map.Append(ConstString("long long").GetCString(), eBasicTypeLongLong); g_type_map.Append(ConstString("long long int").GetCString(), eBasicTypeLongLong); g_type_map.Append(ConstString("unsigned long long").GetCString(), eBasicTypeUnsignedLongLong); g_type_map.Append(ConstString("unsigned long long int").GetCString(), eBasicTypeUnsignedLongLong); // "int128" g_type_map.Append(ConstString("__int128_t").GetCString(), eBasicTypeInt128); g_type_map.Append(ConstString("__uint128_t").GetCString(), eBasicTypeUnsignedInt128); // Miscellaneous g_type_map.Append(ConstString("bool").GetCString(), eBasicTypeBool); g_type_map.Append(ConstString("float").GetCString(), eBasicTypeFloat); g_type_map.Append(ConstString("double").GetCString(), eBasicTypeDouble); g_type_map.Append(ConstString("long double").GetCString(), eBasicTypeLongDouble); g_type_map.Append(ConstString("id").GetCString(), eBasicTypeObjCID); g_type_map.Append(ConstString("SEL").GetCString(), eBasicTypeObjCSel); g_type_map.Append(ConstString("nullptr").GetCString(), eBasicTypeNullPtr); g_type_map.Sort(); }); return g_type_map.Find(name.GetCString(), eBasicTypeInvalid); } return eBasicTypeInvalid; } ClangASTType ClangASTContext::GetBasicType (ASTContext *ast, const ConstString &name) { if (ast) { lldb::BasicType basic_type = ClangASTContext::GetBasicTypeEnumeration (name); return ClangASTContext::GetBasicType (ast, basic_type); } return ClangASTType(); } uint32_t ClangASTContext::GetPointerByteSize () { if (m_pointer_byte_size == 0) m_pointer_byte_size = GetBasicType(lldb::eBasicTypeVoid).GetPointerType().GetByteSize(); return m_pointer_byte_size; } ClangASTType ClangASTContext::GetBasicType (lldb::BasicType basic_type) { return GetBasicType (getASTContext(), basic_type); } ClangASTType ClangASTContext::GetBasicType (ASTContext *ast, lldb::BasicType basic_type) { if (ast) { clang_type_t clang_type = nullptr; switch (basic_type) { case eBasicTypeInvalid: case eBasicTypeOther: break; case eBasicTypeVoid: clang_type = ast->VoidTy.getAsOpaquePtr(); break; case eBasicTypeChar: clang_type = ast->CharTy.getAsOpaquePtr(); break; case eBasicTypeSignedChar: clang_type = ast->SignedCharTy.getAsOpaquePtr(); break; case eBasicTypeUnsignedChar: clang_type = ast->UnsignedCharTy.getAsOpaquePtr(); break; case eBasicTypeWChar: clang_type = ast->getWCharType().getAsOpaquePtr(); break; case eBasicTypeSignedWChar: clang_type = ast->getSignedWCharType().getAsOpaquePtr(); break; case eBasicTypeUnsignedWChar: clang_type = ast->getUnsignedWCharType().getAsOpaquePtr(); break; case eBasicTypeChar16: clang_type = ast->Char16Ty.getAsOpaquePtr(); break; case eBasicTypeChar32: clang_type = ast->Char32Ty.getAsOpaquePtr(); break; case eBasicTypeShort: clang_type = ast->ShortTy.getAsOpaquePtr(); break; case eBasicTypeUnsignedShort: clang_type = ast->UnsignedShortTy.getAsOpaquePtr(); break; case eBasicTypeInt: clang_type = ast->IntTy.getAsOpaquePtr(); break; case eBasicTypeUnsignedInt: clang_type = ast->UnsignedIntTy.getAsOpaquePtr(); break; case eBasicTypeLong: clang_type = ast->LongTy.getAsOpaquePtr(); break; case eBasicTypeUnsignedLong: clang_type = ast->UnsignedLongTy.getAsOpaquePtr(); break; case eBasicTypeLongLong: clang_type = ast->LongLongTy.getAsOpaquePtr(); break; case eBasicTypeUnsignedLongLong: clang_type = ast->UnsignedLongLongTy.getAsOpaquePtr(); break; case eBasicTypeInt128: clang_type = ast->Int128Ty.getAsOpaquePtr(); break; case eBasicTypeUnsignedInt128: clang_type = ast->UnsignedInt128Ty.getAsOpaquePtr(); break; case eBasicTypeBool: clang_type = ast->BoolTy.getAsOpaquePtr(); break; case eBasicTypeHalf: clang_type = ast->HalfTy.getAsOpaquePtr(); break; case eBasicTypeFloat: clang_type = ast->FloatTy.getAsOpaquePtr(); break; case eBasicTypeDouble: clang_type = ast->DoubleTy.getAsOpaquePtr(); break; case eBasicTypeLongDouble: clang_type = ast->LongDoubleTy.getAsOpaquePtr(); break; case eBasicTypeFloatComplex: clang_type = ast->FloatComplexTy.getAsOpaquePtr(); break; case eBasicTypeDoubleComplex: clang_type = ast->DoubleComplexTy.getAsOpaquePtr(); break; case eBasicTypeLongDoubleComplex: clang_type = ast->LongDoubleComplexTy.getAsOpaquePtr(); break; case eBasicTypeObjCID: clang_type = ast->getObjCIdType().getAsOpaquePtr(); break; case eBasicTypeObjCClass: clang_type = ast->getObjCClassType().getAsOpaquePtr(); break; case eBasicTypeObjCSel: clang_type = ast->getObjCSelType().getAsOpaquePtr(); break; case eBasicTypeNullPtr: clang_type = ast->NullPtrTy.getAsOpaquePtr(); break; } if (clang_type) return ClangASTType (ast, clang_type); } return ClangASTType(); } ClangASTType ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize (const char *type_name, uint32_t dw_ate, uint32_t bit_size) { ASTContext *ast = getASTContext(); #define streq(a,b) strcmp(a,b) == 0 assert (ast != nullptr); if (ast) { switch (dw_ate) { default: break; case DW_ATE_address: if (QualTypeMatchesBitSize (bit_size, ast, ast->VoidPtrTy)) return ClangASTType (ast, ast->VoidPtrTy.getAsOpaquePtr()); break; case DW_ATE_boolean: if (QualTypeMatchesBitSize (bit_size, ast, ast->BoolTy)) return ClangASTType (ast, ast->BoolTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) return ClangASTType (ast, ast->UnsignedCharTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) return ClangASTType (ast, ast->UnsignedShortTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) return ClangASTType (ast, ast->UnsignedIntTy.getAsOpaquePtr()); break; case DW_ATE_lo_user: // This has been seen to mean DW_AT_complex_integer if (type_name) { if (::strstr(type_name, "complex")) { ClangASTType complex_int_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ("int", DW_ATE_signed, bit_size/2); return ClangASTType (ast, ast->getComplexType (complex_int_clang_type.GetQualType()).getAsOpaquePtr()); } } break; case DW_ATE_complex_float: if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatComplexTy)) return ClangASTType (ast, ast->FloatComplexTy.getAsOpaquePtr()); else if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleComplexTy)) return ClangASTType (ast, ast->DoubleComplexTy.getAsOpaquePtr()); else if (QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleComplexTy)) return ClangASTType (ast, ast->LongDoubleComplexTy.getAsOpaquePtr()); else { ClangASTType complex_float_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ("float", DW_ATE_float, bit_size/2); return ClangASTType (ast, ast->getComplexType (complex_float_clang_type.GetQualType()).getAsOpaquePtr()); } break; case DW_ATE_float: if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy)) return ClangASTType (ast, ast->FloatTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy)) return ClangASTType (ast, ast->DoubleTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleTy)) return ClangASTType (ast, ast->LongDoubleTy.getAsOpaquePtr()); break; case DW_ATE_signed: if (type_name) { if (streq(type_name, "wchar_t") && QualTypeMatchesBitSize (bit_size, ast, ast->WCharTy)) return ClangASTType (ast, ast->WCharTy.getAsOpaquePtr()); if (streq(type_name, "void") && QualTypeMatchesBitSize (bit_size, ast, ast->VoidTy)) return ClangASTType (ast, ast->VoidTy.getAsOpaquePtr()); if (strstr(type_name, "long long") && QualTypeMatchesBitSize (bit_size, ast, ast->LongLongTy)) return ClangASTType (ast, ast->LongLongTy.getAsOpaquePtr()); if (strstr(type_name, "long") && QualTypeMatchesBitSize (bit_size, ast, ast->LongTy)) return ClangASTType (ast, ast->LongTy.getAsOpaquePtr()); if (strstr(type_name, "short") && QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy)) return ClangASTType (ast, ast->ShortTy.getAsOpaquePtr()); if (strstr(type_name, "char")) { if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) return ClangASTType (ast, ast->CharTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->SignedCharTy)) return ClangASTType (ast, ast->SignedCharTy.getAsOpaquePtr()); } if (strstr(type_name, "int")) { if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy)) return ClangASTType (ast, ast->IntTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->Int128Ty)) return ClangASTType (ast, ast->Int128Ty.getAsOpaquePtr()); } } // We weren't able to match up a type name, just search by size if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) return ClangASTType (ast, ast->CharTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy)) return ClangASTType (ast, ast->ShortTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy)) return ClangASTType (ast, ast->IntTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->LongTy)) return ClangASTType (ast, ast->LongTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->LongLongTy)) return ClangASTType (ast, ast->LongLongTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->Int128Ty)) return ClangASTType (ast, ast->Int128Ty.getAsOpaquePtr()); break; case DW_ATE_signed_char: if (type_name) { if (streq(type_name, "signed char")) { if (QualTypeMatchesBitSize (bit_size, ast, ast->SignedCharTy)) return ClangASTType (ast, ast->SignedCharTy.getAsOpaquePtr()); } } if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) return ClangASTType (ast, ast->CharTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->SignedCharTy)) return ClangASTType (ast, ast->SignedCharTy.getAsOpaquePtr()); break; case DW_ATE_unsigned: if (type_name) { if (strstr(type_name, "long long")) { if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongLongTy)) return ClangASTType (ast, ast->UnsignedLongLongTy.getAsOpaquePtr()); } else if (strstr(type_name, "long")) { if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongTy)) return ClangASTType (ast, ast->UnsignedLongTy.getAsOpaquePtr()); } else if (strstr(type_name, "short")) { if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) return ClangASTType (ast, ast->UnsignedShortTy.getAsOpaquePtr()); } else if (strstr(type_name, "char")) { if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) return ClangASTType (ast, ast->UnsignedCharTy.getAsOpaquePtr()); } else if (strstr(type_name, "int")) { if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) return ClangASTType (ast, ast->UnsignedIntTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedInt128Ty)) return ClangASTType (ast, ast->UnsignedInt128Ty.getAsOpaquePtr()); } } // We weren't able to match up a type name, just search by size if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) return ClangASTType (ast, ast->UnsignedCharTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) return ClangASTType (ast, ast->UnsignedShortTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) return ClangASTType (ast, ast->UnsignedIntTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongTy)) return ClangASTType (ast, ast->UnsignedLongTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongLongTy)) return ClangASTType (ast, ast->UnsignedLongLongTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedInt128Ty)) return ClangASTType (ast, ast->UnsignedInt128Ty.getAsOpaquePtr()); break; case DW_ATE_unsigned_char: if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) return ClangASTType (ast, ast->UnsignedCharTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) return ClangASTType (ast, ast->UnsignedShortTy.getAsOpaquePtr()); break; case DW_ATE_imaginary_float: break; case DW_ATE_UTF: if (type_name) { if (streq(type_name, "char16_t")) { return ClangASTType (ast, ast->Char16Ty.getAsOpaquePtr()); } else if (streq(type_name, "char32_t")) { return ClangASTType (ast, ast->Char32Ty.getAsOpaquePtr()); } } break; } } // This assert should fire for anything that we don't catch above so we know // to fix any issues we run into. if (type_name) { Host::SystemLog (Host::eSystemLogError, "error: need to add support for DW_TAG_base_type '%s' encoded with DW_ATE = 0x%x, bit_size = %u\n", type_name, dw_ate, bit_size); } else { Host::SystemLog (Host::eSystemLogError, "error: need to add support for DW_TAG_base_type encoded with DW_ATE = 0x%x, bit_size = %u\n", dw_ate, bit_size); } return ClangASTType (); } ClangASTType ClangASTContext::GetUnknownAnyType(clang::ASTContext *ast) { if (ast) return ClangASTType (ast, ast->UnknownAnyTy.getAsOpaquePtr()); return ClangASTType(); } ClangASTType ClangASTContext::GetCStringType (bool is_const) { ASTContext *ast = getASTContext(); QualType char_type(ast->CharTy); if (is_const) char_type.addConst(); return ClangASTType (ast, ast->getPointerType(char_type).getAsOpaquePtr()); } clang::DeclContext * ClangASTContext::GetTranslationUnitDecl (clang::ASTContext *ast) { return ast->getTranslationUnitDecl(); } ClangASTType ClangASTContext::CopyType (ASTContext *dst_ast, ClangASTType src) { FileSystemOptions file_system_options; ASTContext *src_ast = src.GetASTContext(); FileManager file_manager (file_system_options); ASTImporter importer(*dst_ast, file_manager, *src_ast, file_manager, false); QualType dst (importer.Import(src.GetQualType())); return ClangASTType (dst_ast, dst.getAsOpaquePtr()); } clang::Decl * ClangASTContext::CopyDecl (ASTContext *dst_ast, ASTContext *src_ast, clang::Decl *source_decl) { FileSystemOptions file_system_options; FileManager file_manager (file_system_options); ASTImporter importer(*dst_ast, file_manager, *src_ast, file_manager, false); return importer.Import(source_decl); } bool ClangASTContext::AreTypesSame (ClangASTType type1, ClangASTType type2, bool ignore_qualifiers) { ASTContext *ast = type1.GetASTContext(); if (ast != type2.GetASTContext()) return false; if (type1.GetOpaqueQualType() == type2.GetOpaqueQualType()) return true; QualType type1_qual = type1.GetQualType(); QualType type2_qual = type2.GetQualType(); if (ignore_qualifiers) { type1_qual = type1_qual.getUnqualifiedType(); type2_qual = type2_qual.getUnqualifiedType(); } return ast->hasSameType (type1_qual, type2_qual); } ClangASTType ClangASTContext::GetTypeForDecl (TagDecl *decl) { // No need to call the getASTContext() accessor (which can create the AST // if it isn't created yet, because we can't have created a decl in this // AST if our AST didn't already exist... ASTContext *ast = m_ast_ap.get(); if (ast) return ClangASTType (ast, ast->getTagDeclType(decl).getAsOpaquePtr()); return ClangASTType(); } ClangASTType ClangASTContext::GetTypeForDecl (ObjCInterfaceDecl *decl) { // No need to call the getASTContext() accessor (which can create the AST // if it isn't created yet, because we can't have created a decl in this // AST if our AST didn't already exist... ASTContext *ast = m_ast_ap.get(); if (ast) return ClangASTType (ast, ast->getObjCInterfaceType(decl).getAsOpaquePtr()); return ClangASTType(); } #pragma mark Structure, Unions, Classes ClangASTType ClangASTContext::CreateRecordType (DeclContext *decl_ctx, AccessType access_type, const char *name, int kind, LanguageType language, ClangASTMetadata *metadata) { ASTContext *ast = getASTContext(); assert (ast != nullptr); if (decl_ctx == nullptr) decl_ctx = ast->getTranslationUnitDecl(); if (language == eLanguageTypeObjC || language == eLanguageTypeObjC_plus_plus) { bool isForwardDecl = true; bool isInternal = false; return CreateObjCClass (name, decl_ctx, isForwardDecl, isInternal, metadata); } // NOTE: Eventually CXXRecordDecl will be merged back into RecordDecl and // we will need to update this code. I was told to currently always use // the CXXRecordDecl class since we often don't know from debug information // if something is struct or a class, so we default to always use the more // complete definition just in case. bool is_anonymous = (!name) || (!name[0]); CXXRecordDecl *decl = CXXRecordDecl::Create (*ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(), SourceLocation(), is_anonymous ? nullptr : &ast->Idents.get(name)); if (is_anonymous) decl->setAnonymousStructOrUnion(true); if (decl) { if (metadata) SetMetadata(ast, decl, *metadata); if (access_type != eAccessNone) decl->setAccess (ConvertAccessTypeToAccessSpecifier (access_type)); if (decl_ctx) decl_ctx->addDecl (decl); return ClangASTType(ast, ast->getTagDeclType(decl).getAsOpaquePtr()); } return ClangASTType(); } static TemplateParameterList * CreateTemplateParameterList (ASTContext *ast, const ClangASTContext::TemplateParameterInfos &template_param_infos, llvm::SmallVector &template_param_decls) { const bool parameter_pack = false; const bool is_typename = false; const unsigned depth = 0; const size_t num_template_params = template_param_infos.GetSize(); for (size_t i=0; iIdents.get(name); if (template_param_infos.args[i].getKind() == TemplateArgument::Integral) { template_param_decls.push_back (NonTypeTemplateParmDecl::Create (*ast, ast->getTranslationUnitDecl(), // Is this the right decl context?, SourceLocation StartLoc, SourceLocation(), SourceLocation(), depth, i, identifier_info, template_param_infos.args[i].getIntegralType(), parameter_pack, nullptr)); } else { template_param_decls.push_back (TemplateTypeParmDecl::Create (*ast, ast->getTranslationUnitDecl(), // Is this the right decl context? SourceLocation(), SourceLocation(), depth, i, identifier_info, is_typename, parameter_pack)); } } TemplateParameterList *template_param_list = TemplateParameterList::Create (*ast, SourceLocation(), SourceLocation(), &template_param_decls.front(), template_param_decls.size(), SourceLocation()); return template_param_list; } clang::FunctionTemplateDecl * ClangASTContext::CreateFunctionTemplateDecl (clang::DeclContext *decl_ctx, clang::FunctionDecl *func_decl, const char *name, const TemplateParameterInfos &template_param_infos) { // /// \brief Create a function template node. ASTContext *ast = getASTContext(); llvm::SmallVector template_param_decls; TemplateParameterList *template_param_list = CreateTemplateParameterList (ast, template_param_infos, template_param_decls); FunctionTemplateDecl *func_tmpl_decl = FunctionTemplateDecl::Create (*ast, decl_ctx, func_decl->getLocation(), func_decl->getDeclName(), template_param_list, func_decl); for (size_t i=0, template_param_decl_count = template_param_decls.size(); i < template_param_decl_count; ++i) { // TODO: verify which decl context we should put template_param_decls into.. template_param_decls[i]->setDeclContext (func_decl); } return func_tmpl_decl; } void ClangASTContext::CreateFunctionTemplateSpecializationInfo (FunctionDecl *func_decl, clang::FunctionTemplateDecl *func_tmpl_decl, const TemplateParameterInfos &infos) { TemplateArgumentList template_args (TemplateArgumentList::OnStack, infos.args.data(), infos.args.size()); func_decl->setFunctionTemplateSpecialization (func_tmpl_decl, &template_args, nullptr); } ClassTemplateDecl * ClangASTContext::CreateClassTemplateDecl (DeclContext *decl_ctx, lldb::AccessType access_type, const char *class_name, int kind, const TemplateParameterInfos &template_param_infos) { ASTContext *ast = getASTContext(); ClassTemplateDecl *class_template_decl = nullptr; if (decl_ctx == nullptr) decl_ctx = ast->getTranslationUnitDecl(); IdentifierInfo &identifier_info = ast->Idents.get(class_name); DeclarationName decl_name (&identifier_info); clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name); for (NamedDecl *decl : result) { class_template_decl = dyn_cast(decl); if (class_template_decl) return class_template_decl; } llvm::SmallVector template_param_decls; TemplateParameterList *template_param_list = CreateTemplateParameterList (ast, template_param_infos, template_param_decls); CXXRecordDecl *template_cxx_decl = CXXRecordDecl::Create (*ast, (TagDecl::TagKind)kind, decl_ctx, // What decl context do we use here? TU? The actual decl context? SourceLocation(), SourceLocation(), &identifier_info); for (size_t i=0, template_param_decl_count = template_param_decls.size(); i < template_param_decl_count; ++i) { template_param_decls[i]->setDeclContext (template_cxx_decl); } // With templated classes, we say that a class is templated with // specializations, but that the bare class has no functions. //template_cxx_decl->startDefinition(); //template_cxx_decl->completeDefinition(); class_template_decl = ClassTemplateDecl::Create (*ast, decl_ctx, // What decl context do we use here? TU? The actual decl context? SourceLocation(), decl_name, template_param_list, template_cxx_decl, nullptr); if (class_template_decl) { if (access_type != eAccessNone) class_template_decl->setAccess (ConvertAccessTypeToAccessSpecifier (access_type)); //if (TagDecl *ctx_tag_decl = dyn_cast(decl_ctx)) // CompleteTagDeclarationDefinition(GetTypeForDecl(ctx_tag_decl)); decl_ctx->addDecl (class_template_decl); #ifdef LLDB_CONFIGURATION_DEBUG VerifyDecl(class_template_decl); #endif } return class_template_decl; } ClassTemplateSpecializationDecl * ClangASTContext::CreateClassTemplateSpecializationDecl (DeclContext *decl_ctx, ClassTemplateDecl *class_template_decl, int kind, const TemplateParameterInfos &template_param_infos) { ASTContext *ast = getASTContext(); ClassTemplateSpecializationDecl *class_template_specialization_decl = ClassTemplateSpecializationDecl::Create (*ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(), SourceLocation(), class_template_decl, &template_param_infos.args.front(), template_param_infos.args.size(), nullptr); class_template_specialization_decl->setSpecializationKind(TSK_ExplicitSpecialization); return class_template_specialization_decl; } ClangASTType ClangASTContext::CreateClassTemplateSpecializationType (ClassTemplateSpecializationDecl *class_template_specialization_decl) { if (class_template_specialization_decl) { ASTContext *ast = getASTContext(); if (ast) return ClangASTType(ast, ast->getTagDeclType(class_template_specialization_decl).getAsOpaquePtr()); } return ClangASTType(); } static inline bool check_op_param (uint32_t op_kind, bool unary, bool binary, uint32_t num_params) { // Special-case call since it can take any number of operands if(op_kind == OO_Call) return true; // The parameter count doesn't include "this" if (num_params == 0) return unary; if (num_params == 1) return binary; else return false; } bool ClangASTContext::CheckOverloadedOperatorKindParameterCount (uint32_t op_kind, uint32_t num_params) { switch (op_kind) { default: break; // C++ standard allows any number of arguments to new/delete case OO_New: case OO_Array_New: case OO_Delete: case OO_Array_Delete: return true; } #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) case OO_##Name: return check_op_param (op_kind, Unary, Binary, num_params); switch (op_kind) { #include "clang/Basic/OperatorKinds.def" default: break; } return false; } clang::AccessSpecifier ClangASTContext::UnifyAccessSpecifiers (clang::AccessSpecifier lhs, clang::AccessSpecifier rhs) { clang::AccessSpecifier ret = lhs; // Make the access equal to the stricter of the field and the nested field's access switch (ret) { case clang::AS_none: break; case clang::AS_private: break; case clang::AS_protected: if (rhs == AS_private) ret = AS_private; break; case clang::AS_public: ret = rhs; break; } return ret; } bool ClangASTContext::FieldIsBitfield (FieldDecl* field, uint32_t& bitfield_bit_size) { return FieldIsBitfield(getASTContext(), field, bitfield_bit_size); } bool ClangASTContext::FieldIsBitfield ( ASTContext *ast, FieldDecl* field, uint32_t& bitfield_bit_size ) { if (ast == nullptr || field == nullptr) return false; if (field->isBitField()) { Expr* bit_width_expr = field->getBitWidth(); if (bit_width_expr) { llvm::APSInt bit_width_apsint; if (bit_width_expr->isIntegerConstantExpr(bit_width_apsint, *ast)) { bitfield_bit_size = bit_width_apsint.getLimitedValue(UINT32_MAX); return true; } } } return false; } bool ClangASTContext::RecordHasFields (const RecordDecl *record_decl) { if (record_decl == nullptr) return false; if (!record_decl->field_empty()) return true; // No fields, lets check this is a CXX record and check the base classes const CXXRecordDecl *cxx_record_decl = dyn_cast(record_decl); if (cxx_record_decl) { CXXRecordDecl::base_class_const_iterator base_class, base_class_end; for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); base_class != base_class_end; ++base_class) { const CXXRecordDecl *base_class_decl = cast(base_class->getType()->getAs()->getDecl()); if (RecordHasFields(base_class_decl)) return true; } } return false; } #pragma mark Objective C Classes ClangASTType ClangASTContext::CreateObjCClass ( const char *name, DeclContext *decl_ctx, bool isForwardDecl, bool isInternal, ClangASTMetadata *metadata ) { ASTContext *ast = getASTContext(); assert (ast != nullptr); assert (name && name[0]); if (decl_ctx == nullptr) decl_ctx = ast->getTranslationUnitDecl(); ObjCInterfaceDecl *decl = ObjCInterfaceDecl::Create (*ast, decl_ctx, SourceLocation(), &ast->Idents.get(name), nullptr, SourceLocation(), /*isForwardDecl,*/ isInternal); if (decl && metadata) SetMetadata(ast, decl, *metadata); return ClangASTType (ast, ast->getObjCInterfaceType(decl)); } static inline bool BaseSpecifierIsEmpty (const CXXBaseSpecifier *b) { return ClangASTContext::RecordHasFields(b->getType()->getAsCXXRecordDecl()) == false; } uint32_t ClangASTContext::GetNumBaseClasses (const CXXRecordDecl *cxx_record_decl, bool omit_empty_base_classes) { uint32_t num_bases = 0; if (cxx_record_decl) { if (omit_empty_base_classes) { CXXRecordDecl::base_class_const_iterator base_class, base_class_end; for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); base_class != base_class_end; ++base_class) { // Skip empty base classes if (omit_empty_base_classes) { if (BaseSpecifierIsEmpty (base_class)) continue; } ++num_bases; } } else num_bases = cxx_record_decl->getNumBases(); } return num_bases; } #pragma mark Namespace Declarations NamespaceDecl * ClangASTContext::GetUniqueNamespaceDeclaration (const char *name, DeclContext *decl_ctx) { NamespaceDecl *namespace_decl = nullptr; ASTContext *ast = getASTContext(); TranslationUnitDecl *translation_unit_decl = ast->getTranslationUnitDecl (); if (decl_ctx == nullptr) decl_ctx = translation_unit_decl; if (name) { IdentifierInfo &identifier_info = ast->Idents.get(name); DeclarationName decl_name (&identifier_info); clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name); for (NamedDecl *decl : result) { namespace_decl = dyn_cast(decl); if (namespace_decl) return namespace_decl; } namespace_decl = NamespaceDecl::Create(*ast, decl_ctx, false, SourceLocation(), SourceLocation(), &identifier_info, nullptr); decl_ctx->addDecl (namespace_decl); } else { if (decl_ctx == translation_unit_decl) { namespace_decl = translation_unit_decl->getAnonymousNamespace(); if (namespace_decl) return namespace_decl; namespace_decl = NamespaceDecl::Create(*ast, decl_ctx, false, SourceLocation(), SourceLocation(), nullptr, nullptr); translation_unit_decl->setAnonymousNamespace (namespace_decl); translation_unit_decl->addDecl (namespace_decl); assert (namespace_decl == translation_unit_decl->getAnonymousNamespace()); } else { NamespaceDecl *parent_namespace_decl = cast(decl_ctx); if (parent_namespace_decl) { namespace_decl = parent_namespace_decl->getAnonymousNamespace(); if (namespace_decl) return namespace_decl; namespace_decl = NamespaceDecl::Create(*ast, decl_ctx, false, SourceLocation(), SourceLocation(), nullptr, nullptr); parent_namespace_decl->setAnonymousNamespace (namespace_decl); parent_namespace_decl->addDecl (namespace_decl); assert (namespace_decl == parent_namespace_decl->getAnonymousNamespace()); } else { // BAD!!! } } if (namespace_decl) { // If we make it here, we are creating the anonymous namespace decl // for the first time, so we need to do the using directive magic // like SEMA does UsingDirectiveDecl* using_directive_decl = UsingDirectiveDecl::Create (*ast, decl_ctx, SourceLocation(), SourceLocation(), NestedNameSpecifierLoc(), SourceLocation(), namespace_decl, decl_ctx); using_directive_decl->setImplicit(); decl_ctx->addDecl(using_directive_decl); } } #ifdef LLDB_CONFIGURATION_DEBUG VerifyDecl(namespace_decl); #endif return namespace_decl; } #pragma mark Function Types FunctionDecl * ClangASTContext::CreateFunctionDeclaration (DeclContext *decl_ctx, const char *name, const ClangASTType &function_clang_type, int storage, bool is_inline) { FunctionDecl *func_decl = nullptr; ASTContext *ast = getASTContext(); if (decl_ctx == nullptr) decl_ctx = ast->getTranslationUnitDecl(); const bool hasWrittenPrototype = true; const bool isConstexprSpecified = false; if (name && name[0]) { func_decl = FunctionDecl::Create (*ast, decl_ctx, SourceLocation(), SourceLocation(), DeclarationName (&ast->Idents.get(name)), function_clang_type.GetQualType(), nullptr, (FunctionDecl::StorageClass)storage, is_inline, hasWrittenPrototype, isConstexprSpecified); } else { func_decl = FunctionDecl::Create (*ast, decl_ctx, SourceLocation(), SourceLocation(), DeclarationName (), function_clang_type.GetQualType(), nullptr, (FunctionDecl::StorageClass)storage, is_inline, hasWrittenPrototype, isConstexprSpecified); } if (func_decl) decl_ctx->addDecl (func_decl); #ifdef LLDB_CONFIGURATION_DEBUG VerifyDecl(func_decl); #endif return func_decl; } ClangASTType ClangASTContext::CreateFunctionType (ASTContext *ast, const ClangASTType& result_type, const ClangASTType *args, unsigned num_args, bool is_variadic, unsigned type_quals) { assert (ast != nullptr); std::vector qual_type_args; for (unsigned i=0; igetFunctionType (result_type.GetQualType(), qual_type_args, proto_info).getAsOpaquePtr()); } ParmVarDecl * ClangASTContext::CreateParameterDeclaration (const char *name, const ClangASTType ¶m_type, int storage) { ASTContext *ast = getASTContext(); assert (ast != nullptr); return ParmVarDecl::Create(*ast, ast->getTranslationUnitDecl(), SourceLocation(), SourceLocation(), name && name[0] ? &ast->Idents.get(name) : nullptr, param_type.GetQualType(), nullptr, (VarDecl::StorageClass)storage, nullptr); } void ClangASTContext::SetFunctionParameters (FunctionDecl *function_decl, ParmVarDecl **params, unsigned num_params) { if (function_decl) function_decl->setParams (ArrayRef(params, num_params)); } #pragma mark Array Types ClangASTType ClangASTContext::CreateArrayType (const ClangASTType &element_type, size_t element_count, bool is_vector) { if (element_type.IsValid()) { ASTContext *ast = getASTContext(); assert (ast != nullptr); if (is_vector) { return ClangASTType (ast, ast->getExtVectorType(element_type.GetQualType(), element_count).getAsOpaquePtr()); } else { llvm::APInt ap_element_count (64, element_count); if (element_count == 0) { return ClangASTType (ast, ast->getIncompleteArrayType (element_type.GetQualType(), ArrayType::Normal, 0).getAsOpaquePtr()); } else { return ClangASTType (ast, ast->getConstantArrayType (element_type.GetQualType(), ap_element_count, ArrayType::Normal, 0).getAsOpaquePtr()); } } } return ClangASTType(); } #pragma mark Enumeration Types ClangASTType ClangASTContext::CreateEnumerationType ( const char *name, DeclContext *decl_ctx, const Declaration &decl, const ClangASTType &integer_clang_type ) { // TODO: Do something intelligent with the Declaration object passed in // like maybe filling in the SourceLocation with it... ASTContext *ast = getASTContext(); // TODO: ask about these... // const bool IsScoped = false; // const bool IsFixed = false; EnumDecl *enum_decl = EnumDecl::Create (*ast, decl_ctx, SourceLocation(), SourceLocation(), name && name[0] ? &ast->Idents.get(name) : nullptr, nullptr, false, // IsScoped false, // IsScopedUsingClassTag false); // IsFixed if (enum_decl) { // TODO: check if we should be setting the promotion type too? enum_decl->setIntegerType(integer_clang_type.GetQualType()); enum_decl->setAccess(AS_public); // TODO respect what's in the debug info return ClangASTType (ast, ast->getTagDeclType(enum_decl).getAsOpaquePtr()); } return ClangASTType(); } // Disable this for now since I can't seem to get a nicely formatted float // out of the APFloat class without just getting the float, double or quad // and then using a formatted print on it which defeats the purpose. We ideally // would like to get perfect string values for any kind of float semantics // so we can support remote targets. The code below also requires a patch to // llvm::APInt. //bool //ClangASTContext::ConvertFloatValueToString (ASTContext *ast, clang_type_t clang_type, const uint8_t* bytes, size_t byte_size, int apint_byte_order, std::string &float_str) //{ // uint32_t count = 0; // bool is_complex = false; // if (ClangASTContext::IsFloatingPointType (clang_type, count, is_complex)) // { // unsigned num_bytes_per_float = byte_size / count; // unsigned num_bits_per_float = num_bytes_per_float * 8; // // float_str.clear(); // uint32_t i; // for (i=0; i 0) // { // if (i > 0) // float_str.append(", "); // float_str.append(s); // if (i == 1 && is_complex) // float_str.append(1, 'i'); // } // } // return !float_str.empty(); // } // return false; //} ClangASTType ClangASTContext::GetIntTypeFromBitSize (clang::ASTContext *ast, size_t bit_size, bool is_signed) { if (ast) { if (is_signed) { if (bit_size == ast->getTypeSize(ast->SignedCharTy)) return ClangASTType(ast, ast->SignedCharTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->ShortTy)) return ClangASTType(ast, ast->ShortTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->IntTy)) return ClangASTType(ast, ast->IntTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->LongTy)) return ClangASTType(ast, ast->LongTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->LongLongTy)) return ClangASTType(ast, ast->LongLongTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->Int128Ty)) return ClangASTType(ast, ast->Int128Ty.getAsOpaquePtr()); } else { if (bit_size == ast->getTypeSize(ast->UnsignedCharTy)) return ClangASTType(ast, ast->UnsignedCharTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->UnsignedShortTy)) return ClangASTType(ast, ast->UnsignedShortTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->UnsignedIntTy)) return ClangASTType(ast, ast->UnsignedIntTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->UnsignedLongTy)) return ClangASTType(ast, ast->UnsignedLongTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->UnsignedLongLongTy)) return ClangASTType(ast, ast->UnsignedLongLongTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->UnsignedInt128Ty)) return ClangASTType(ast, ast->UnsignedInt128Ty.getAsOpaquePtr()); } } return ClangASTType(); } ClangASTType ClangASTContext::GetPointerSizedIntType (clang::ASTContext *ast, bool is_signed) { if (ast) return GetIntTypeFromBitSize(ast, ast->getTypeSize(ast->VoidPtrTy), is_signed); return ClangASTType(); } ClangASTType ClangASTContext::GetFloatTypeFromBitSize (clang::ASTContext *ast, size_t bit_size) { if (ast) { if (bit_size == ast->getTypeSize(ast->FloatTy)) return ClangASTType(ast, ast->FloatTy.getAsOpaquePtr()); else if (bit_size == ast->getTypeSize(ast->DoubleTy)) return ClangASTType(ast, ast->DoubleTy.getAsOpaquePtr()); else if (bit_size == ast->getTypeSize(ast->LongDoubleTy)) return ClangASTType(ast, ast->LongDoubleTy.getAsOpaquePtr()); else if (bit_size == ast->getTypeSize(ast->HalfTy)) return ClangASTType(ast, ast->HalfTy.getAsOpaquePtr()); } return ClangASTType(); } bool ClangASTContext::GetCompleteDecl (clang::ASTContext *ast, clang::Decl *decl) { if (!decl) return false; ExternalASTSource *ast_source = ast->getExternalSource(); if (!ast_source) return false; if (clang::TagDecl *tag_decl = llvm::dyn_cast(decl)) { if (tag_decl->isCompleteDefinition()) return true; if (!tag_decl->hasExternalLexicalStorage()) return false; ast_source->CompleteType(tag_decl); return !tag_decl->getTypeForDecl()->isIncompleteType(); } else if (clang::ObjCInterfaceDecl *objc_interface_decl = llvm::dyn_cast(decl)) { if (objc_interface_decl->getDefinition()) return true; if (!objc_interface_decl->hasExternalLexicalStorage()) return false; ast_source->CompleteType(objc_interface_decl); return !objc_interface_decl->getTypeForDecl()->isIncompleteType(); } else { return false; } } void ClangASTContext::SetMetadataAsUserID (const void *object, user_id_t user_id) { ClangASTMetadata meta_data; meta_data.SetUserID (user_id); SetMetadata (object, meta_data); } void ClangASTContext::SetMetadata (clang::ASTContext *ast, const void *object, ClangASTMetadata &metadata) { ClangExternalASTSourceCommon *external_source = static_cast(ast->getExternalSource()); if (external_source) external_source->SetMetadata(object, metadata); } ClangASTMetadata * ClangASTContext::GetMetadata (clang::ASTContext *ast, const void *object) { ClangExternalASTSourceCommon *external_source = static_cast(ast->getExternalSource()); if (external_source && external_source->HasMetadata(object)) return external_source->GetMetadata(object); else return nullptr; } clang::DeclContext * ClangASTContext::GetAsDeclContext (clang::CXXMethodDecl *cxx_method_decl) { return llvm::dyn_cast(cxx_method_decl); } clang::DeclContext * ClangASTContext::GetAsDeclContext (clang::ObjCMethodDecl *objc_method_decl) { return llvm::dyn_cast(objc_method_decl); } bool ClangASTContext::GetClassMethodInfoForDeclContext (clang::DeclContext *decl_ctx, lldb::LanguageType &language, bool &is_instance_method, ConstString &language_object_name) { language_object_name.Clear(); language = eLanguageTypeUnknown; is_instance_method = false; if (decl_ctx) { if (clang::CXXMethodDecl *method_decl = llvm::dyn_cast(decl_ctx)) { if (method_decl->isStatic()) { is_instance_method = false; } else { language_object_name.SetCString("this"); is_instance_method = true; } language = eLanguageTypeC_plus_plus; return true; } else if (clang::ObjCMethodDecl *method_decl = llvm::dyn_cast(decl_ctx)) { // Both static and instance methods have a "self" object in objective C language_object_name.SetCString("self"); if (method_decl->isInstanceMethod()) { is_instance_method = true; } else { is_instance_method = false; } language = eLanguageTypeObjC; return true; } else if (clang::FunctionDecl *function_decl = llvm::dyn_cast(decl_ctx)) { ClangASTMetadata *metadata = GetMetadata (&decl_ctx->getParentASTContext(), function_decl); if (metadata && metadata->HasObjectPtr()) { language_object_name.SetCString (metadata->GetObjectPtrName()); language = eLanguageTypeObjC; is_instance_method = true; } return true; } } return false; }