unsigned
ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager,
                                     CodeCompleteConsumer *completion_consumer,
                                     unsigned completion_line,
                                     unsigned completion_column) {
  ClangDiagnosticManagerAdapter *adapter =
      static_cast<ClangDiagnosticManagerAdapter *>(
          m_compiler->getDiagnostics().getClient());
  clang::TextDiagnosticBuffer *diag_buf = adapter->GetPassthrough();
  diag_buf->FlushDiagnostics(m_compiler->getDiagnostics());

  adapter->ResetManager(&diagnostic_manager);

  const char *expr_text = m_expr.Text();

  clang::SourceManager &source_mgr = m_compiler->getSourceManager();
  bool created_main_file = false;

  // Clang wants to do completion on a real file known by Clang's file manager,
  // so we have to create one to make this work.
  // TODO: We probably could also simulate to Clang's file manager that there
  // is a real file that contains our code.
  bool should_create_file = completion_consumer != nullptr;

  // We also want a real file on disk if we generate full debug info.
  should_create_file |= m_compiler->getCodeGenOpts().getDebugInfo() ==
                        codegenoptions::FullDebugInfo;

  if (should_create_file) {
    int temp_fd = -1;
    llvm::SmallString<128> result_path;
    if (FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
      tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr");
      std::string temp_source_path = tmpdir_file_spec.GetPath();
      llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path);
    } else {
      llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path);
    }

    if (temp_fd != -1) {
      lldb_private::File file(temp_fd, true);
      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();
          source_mgr.setMainFileID(
              source_mgr.createFileID(m_file_manager->getFile(result_path),
                                      SourceLocation(), SrcMgr::C_User));
          created_main_file = true;
        }
      }
    }
  }

  if (!created_main_file) {
    std::unique_ptr<MemoryBuffer> memory_buffer =
        MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__);
    source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer)));
  }

  diag_buf->BeginSourceFile(m_compiler->getLangOpts(),
                            &m_compiler->getPreprocessor());

  ClangExpressionHelper *type_system_helper =
      dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());

  ASTConsumer *ast_transformer =
      type_system_helper->ASTTransformer(m_code_generator.get());

  if (ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap())
    decl_map->InstallCodeGenerator(m_code_generator.get());

  // If we want to parse for code completion, we need to attach our code
  // completion consumer to the Sema and specify a completion position.
  // While parsing the Sema will call this consumer with the provided
  // completion suggestions.
  if (completion_consumer) {
    auto main_file = source_mgr.getFileEntryForID(source_mgr.getMainFileID());
    auto &PP = m_compiler->getPreprocessor();
    // Lines and columns start at 1 in Clang, but code completion positions are
    // indexed from 0, so we need to add 1 to the line and column here.
    ++completion_line;
    ++completion_column;
    PP.SetCodeCompletionPoint(main_file, completion_line, completion_column);
  }

  if (ast_transformer) {
    ast_transformer->Initialize(m_compiler->getASTContext());
    ParseAST(m_compiler->getPreprocessor(), ast_transformer,
             m_compiler->getASTContext(), false, TU_Complete,
             completion_consumer);
  } else {
    m_code_generator->Initialize(m_compiler->getASTContext());
    ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(),
             m_compiler->getASTContext(), false, TU_Complete,
             completion_consumer);
  }

  diag_buf->EndSourceFile();

  unsigned num_errors = diag_buf->getNumErrors();

  if (m_pp_callbacks && m_pp_callbacks->hasErrors()) {
    num_errors++;
    diagnostic_manager.PutString(eDiagnosticSeverityError,
                                 "while importing modules:");
    diagnostic_manager.AppendMessageToDiagnostic(
        m_pp_callbacks->getErrorString());
  }

  if (!num_errors) {
    if (type_system_helper->DeclMap() &&
        !type_system_helper->DeclMap()->ResolveUnknownTypes()) {
      diagnostic_manager.Printf(eDiagnosticSeverityError,
                                "Couldn't infer the type of a variable");
      num_errors++;
    }
  }

  if (!num_errors) {
    type_system_helper->CommitPersistentDecls();
  }

  adapter->ResetManager();

  return num_errors;
}
Beispiel #2
0
unsigned
ClangExpressionParser::Parse(DiagnosticManager &diagnostic_manager)
{
    ClangDiagnosticManagerAdapter *adapter =
        static_cast<ClangDiagnosticManagerAdapter *>(m_compiler->getDiagnostics().getClient());
    clang::TextDiagnosticBuffer *diag_buf = adapter->GetPassthrough();
    diag_buf->FlushDiagnostics(m_compiler->getDiagnostics());

    adapter->ResetManager(&diagnostic_manager);

    const char *expr_text = m_expr.Text();

    clang::SourceManager &source_mgr = m_compiler->getSourceManager();
    bool created_main_file = false;
    if (m_compiler->getCodeGenOpts().getDebugInfo() == codegenoptions::FullDebugInfo)
    {
        int temp_fd = -1;
        llvm::SmallString<PATH_MAX> result_path;
        FileSpec tmpdir_file_spec;
        if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
        {
            tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr");
            std::string temp_source_path = tmpdir_file_spec.GetPath();
            llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path);
        }
        else
        {
            llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path);
        }

        if (temp_fd != -1)
        {
            lldb_private::File file(temp_fd, true);
            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();
                    source_mgr.setMainFileID(source_mgr.createFileID(m_file_manager->getFile(result_path),
                                                                     SourceLocation(), SrcMgr::C_User));
                    created_main_file = true;
                }
            }
        }
    }

    if (!created_main_file)
    {
        std::unique_ptr<MemoryBuffer> memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__);
        source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer)));
    }

    diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor());

    ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());

    ASTConsumer *ast_transformer = type_system_helper->ASTTransformer(m_code_generator.get());

    if (ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap())
        decl_map->InstallCodeGenerator(m_code_generator.get());

    if (ast_transformer)
    {
        ast_transformer->Initialize(m_compiler->getASTContext());
        ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext());
    }
    else
    {
        m_code_generator->Initialize(m_compiler->getASTContext());
        ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext());
    }

    diag_buf->EndSourceFile();

    unsigned num_errors = diag_buf->getNumErrors();

    if (m_pp_callbacks && m_pp_callbacks->hasErrors())
    {
        num_errors++;
        diagnostic_manager.PutCString(eDiagnosticSeverityError, "while importing modules:");
        diagnostic_manager.AppendMessageToDiagnostic(m_pp_callbacks->getErrorString().c_str());
    }

    if (!num_errors)
    {
        if (type_system_helper->DeclMap() && !type_system_helper->DeclMap()->ResolveUnknownTypes())
        {
            diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't infer the type of a variable");
            num_errors++;
        }
    }

    if (!num_errors)
    {
        type_system_helper->CommitPersistentDecls();
    }

    adapter->ResetManager();

    return num_errors;
}
unsigned
ClangExpressionParser::Parse (DiagnosticManager &diagnostic_manager,
                              uint32_t first_line,
                              uint32_t last_line,
                              uint32_t line_offset)
{
    ClangDiagnosticManagerAdapter *adapter =
        static_cast<ClangDiagnosticManagerAdapter *>(m_compiler->getDiagnostics().getClient());
    clang::TextDiagnosticBuffer *diag_buf = adapter->GetPassthrough();
    diag_buf->FlushDiagnostics(m_compiler->getDiagnostics());

    adapter->ResetManager(&diagnostic_manager);

    const char *expr_text = m_expr.Text();

    clang::SourceManager &SourceMgr = m_compiler->getSourceManager();
    bool created_main_file = false;
    if (m_expr.GetOptions() && m_expr.GetOptions()->GetPoundLineFilePath() == NULL && m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo)
    {
        std::string temp_source_path;
        if (ExpressionSourceCode::SaveExpressionTextToTempFile(expr_text, *m_expr.GetOptions(), temp_source_path))
        {
            auto file = m_file_manager->getFile(temp_source_path);
            if (file)
            {
                SourceMgr.setMainFileID(SourceMgr.createFileID (file,
                                                                SourceLocation(),
                                                                SrcMgr::C_User));
                created_main_file = true;
            }
        }
    }

    if (!created_main_file)
    {
        std::unique_ptr<MemoryBuffer> memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__);
        SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(memory_buffer)));
    }

    diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor());

    ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());

    ASTConsumer *ast_transformer = type_system_helper->ASTTransformer(m_code_generator.get());

    if (ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap())
        decl_map->InstallCodeGenerator(m_code_generator.get());

    if (ast_transformer)
    {
        ast_transformer->Initialize(m_compiler->getASTContext());
        ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext());
    }
    else
    {
        m_code_generator->Initialize(m_compiler->getASTContext());
        ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext());
    }

    diag_buf->EndSourceFile();

    unsigned num_errors = diag_buf->getNumErrors();

    if (m_pp_callbacks && m_pp_callbacks->hasErrors())
    {
        num_errors++;
        diagnostic_manager.PutCString(eDiagnosticSeverityError, "while importing modules:");
        diagnostic_manager.AppendMessageToDiagnostic(m_pp_callbacks->getErrorString().c_str());
    }

    if (!num_errors)
    {
        if (type_system_helper->DeclMap() && !type_system_helper->DeclMap()->ResolveUnknownTypes())
        {
            diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't infer the type of a variable");
            num_errors++;
        }
    }

    if (!num_errors)
    {
        type_system_helper->CommitPersistentDecls();
    }

    adapter->ResetManager();

    return num_errors;
}