<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  <NAME> <<EMAIL>>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "cling/Interpreter/ClangInternalState.h"

#include "clang/AST/ASTContext.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/SourceManager.h"
#include "clang/CodeGen/ModuleBuilder.h"

#include "llvm/ADT/SmallString.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Signals.h"

#include <cstdio>
#include <sstream>
#include <string>
#include <time.h>

#ifdef WIN32
#define popen _popen
#define pclose _pclose
#endif

using namespace clang;

namespace cling {

  ClangInternalState::ClangInternalState(ASTContext& AC, Preprocessor& PP,
                                         llvm::Module* M, CodeGenerator* CG,
                                         const std::string& name)
    : m_ASTContext(AC), m_Preprocessor(PP), m_CodeGen(CG), m_Module(M),
      m_DiffCommand("diff -u --text "), m_Name(name), m_DiffPair(nullptr) {
    store();
  }

  ClangInternalState::~ClangInternalState() {
    // cleanup the temporary files:
    remove(m_LookupTablesFile.c_str());
    remove(m_IncludedFilesFile.c_str());
    remove(m_ASTFile.c_str());
    remove(m_LLVMModuleFile.c_str());
    remove(m_MacrosFile.c_str());
  }

  void ClangInternalState::store() {
    // Cannot use the stack (private copy ctor)
    std::unique_ptr<llvm::raw_fd_ostream> m_LookupTablesOS;
    std::unique_ptr<llvm::raw_fd_ostream> m_IncludedFilesOS;
    std::unique_ptr<llvm::raw_fd_ostream> m_ASTOS;
    std::unique_ptr<llvm::raw_fd_ostream> m_LLVMModuleOS;
    std::unique_ptr<llvm::raw_fd_ostream> m_MacrosOS;

    m_LookupTablesOS.reset(createOutputFile("lookup",
                                            &m_LookupTablesFile));
    m_IncludedFilesOS.reset(createOutputFile("included",
                                             &m_IncludedFilesFile));
    m_ASTOS.reset(createOutputFile("ast", &m_ASTFile));
    m_LLVMModuleOS.reset(createOutputFile("module", &m_LLVMModuleFile));
    m_MacrosOS.reset(createOutputFile("macros", &m_MacrosFile));

    printLookupTables(*m_LookupTablesOS.get(), m_ASTContext);
    printIncludedFiles(*m_IncludedFilesOS.get(),
                       m_ASTContext.getSourceManager());
    printAST(*m_ASTOS.get(), m_ASTContext);
    if (m_Module)
      printLLVMModule(*m_LLVMModuleOS.get(), *m_Module, *m_CodeGen);
    printMacroDefinitions(*m_MacrosOS.get(), m_Preprocessor);
  }
  namespace {
    std::string getCurrentTimeAsString() {
      time_t rawtime;
      struct tm * timeinfo;
      char buffer [80];

      time (&rawtime);
      timeinfo = localtime (&rawtime);

      strftime (buffer, 80, "%I_%M_%S", timeinfo);
      return buffer;
    }
  }

  // Copied with modifications from CompilerInstance.cpp
  llvm::raw_fd_ostream*
  ClangInternalState::createOutputFile(llvm::StringRef OutFile,
                                       std::string *TempPathName/*=0*/,
                                       bool RemoveFileOnSignal/*=true*/) {
    std::unique_ptr<llvm::raw_fd_ostream> OS;
    std::string OSFile;
    llvm::SmallString<256> OutputPath;
    llvm::sys::path::system_temp_directory(/*erasedOnReboot*/false, OutputPath);

    // Only create the temporary if the parent directory exists (or create
    // missing directories is true) and we can actually write to OutPath,
    // otherwise we want to fail early.
    llvm::SmallString<256> TempPath(OutputPath);
    llvm::sys::fs::make_absolute(TempPath);
    assert(llvm::sys::fs::is_directory(TempPath.str()) && "Must be a folder.");
    // Create a temporary file.
    llvm::sys::path::append(TempPath, "cling-" + OutFile);
    TempPath += "-" + getCurrentTimeAsString();
    TempPath += "-%%%%%%%%";
    int fd;
    if (llvm::sys::fs::createUniqueFile(TempPath.str(), fd, TempPath)
        != std::errc::no_such_file_or_directory) {
      OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true));
      OSFile = TempPath.str();
    }

    // Make sure the out stream file gets removed if we crash.
    if (RemoveFileOnSignal)
      llvm::sys::RemoveFileOnSignal(OSFile);

    if (TempPathName)
      *TempPathName = OSFile;

    return OS.release();
  }

  void ClangInternalState::compare(const std::string& name) {
    assert(name == m_Name && "Different names!?");
    m_DiffPair.reset(new ClangInternalState(m_ASTContext, m_Preprocessor,
                                            m_Module, m_CodeGen, name));
    std::string differences = "";
    // Ignore the builtins
    typedef llvm::SmallVector<const char*, 1024> Builtins;
    Builtins builtinNames;
    m_ASTContext.BuiltinInfo.GetBuiltinNames(builtinNames);
    for (Builtins::iterator I = builtinNames.begin();
         I != builtinNames.end();) {
      if (llvm::StringRef(*I).startswith("__builtin"))
        I = builtinNames.erase(I);
      else
        ++I;
    }

    builtinNames.push_back(".*__builtin.*");

    if (differentContent(m_LookupTablesFile, m_DiffPair->m_LookupTablesFile,
                         differences, &builtinNames)) {
      llvm::errs() << "Differences in the lookup tables\n";<commit_msg>llvm upgrade.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  <NAME> <<EMAIL>>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "cling/Interpreter/ClangInternalState.h"

#include "clang/AST/ASTContext.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/ModuleBuilder.h"

#include "llvm/ADT/SmallString.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Signals.h"

#include <cstdio>
#include <sstream>
#include <string>
#include <time.h>

#ifdef WIN32
#define popen _popen
#define pclose _pclose
#endif

using namespace clang;

namespace cling {

  ClangInternalState::ClangInternalState(ASTContext& AC, Preprocessor& PP,
                                         llvm::Module* M, CodeGenerator* CG,
                                         const std::string& name)
    : m_ASTContext(AC), m_Preprocessor(PP), m_CodeGen(CG), m_Module(M),
      m_DiffCommand("diff -u --text "), m_Name(name), m_DiffPair(nullptr) {
    store();
  }

  ClangInternalState::~ClangInternalState() {
    // cleanup the temporary files:
    remove(m_LookupTablesFile.c_str());
    remove(m_IncludedFilesFile.c_str());
    remove(m_ASTFile.c_str());
    remove(m_LLVMModuleFile.c_str());
    remove(m_MacrosFile.c_str());
  }

  void ClangInternalState::store() {
    // Cannot use the stack (private copy ctor)
    std::unique_ptr<llvm::raw_fd_ostream> m_LookupTablesOS;
    std::unique_ptr<llvm::raw_fd_ostream> m_IncludedFilesOS;
    std::unique_ptr<llvm::raw_fd_ostream> m_ASTOS;
    std::unique_ptr<llvm::raw_fd_ostream> m_LLVMModuleOS;
    std::unique_ptr<llvm::raw_fd_ostream> m_MacrosOS;

    m_LookupTablesOS.reset(createOutputFile("lookup",
                                            &m_LookupTablesFile));
    m_IncludedFilesOS.reset(createOutputFile("included",
                                             &m_IncludedFilesFile));
    m_ASTOS.reset(createOutputFile("ast", &m_ASTFile));
    m_LLVMModuleOS.reset(createOutputFile("module", &m_LLVMModuleFile));
    m_MacrosOS.reset(createOutputFile("macros", &m_MacrosFile));

    printLookupTables(*m_LookupTablesOS.get(), m_ASTContext);
    printIncludedFiles(*m_IncludedFilesOS.get(),
                       m_ASTContext.getSourceManager());
    printAST(*m_ASTOS.get(), m_ASTContext);
    if (m_Module)
      printLLVMModule(*m_LLVMModuleOS.get(), *m_Module, *m_CodeGen);
    printMacroDefinitions(*m_MacrosOS.get(), m_Preprocessor);
  }
  namespace {
    std::string getCurrentTimeAsString() {
      time_t rawtime;
      struct tm * timeinfo;
      char buffer [80];

      time (&rawtime);
      timeinfo = localtime (&rawtime);

      strftime (buffer, 80, "%I_%M_%S", timeinfo);
      return buffer;
    }
  }

  // Copied with modifications from CompilerInstance.cpp
  llvm::raw_fd_ostream*
  ClangInternalState::createOutputFile(llvm::StringRef OutFile,
                                       std::string *TempPathName/*=0*/,
                                       bool RemoveFileOnSignal/*=true*/) {
    std::unique_ptr<llvm::raw_fd_ostream> OS;
    std::string OSFile;
    llvm::SmallString<256> OutputPath;
    llvm::sys::path::system_temp_directory(/*erasedOnReboot*/false, OutputPath);

    // Only create the temporary if the parent directory exists (or create
    // missing directories is true) and we can actually write to OutPath,
    // otherwise we want to fail early.
    llvm::SmallString<256> TempPath(OutputPath);
    llvm::sys::fs::make_absolute(TempPath);
    assert(llvm::sys::fs::is_directory(TempPath.str()) && "Must be a folder.");
    // Create a temporary file.
    llvm::sys::path::append(TempPath, "cling-" + OutFile);
    TempPath += "-" + getCurrentTimeAsString();
    TempPath += "-%%%%%%%%";
    int fd;
    if (llvm::sys::fs::createUniqueFile(TempPath.str(), fd, TempPath)
        != std::errc::no_such_file_or_directory) {
      OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true));
      OSFile = TempPath.str();
    }

    // Make sure the out stream file gets removed if we crash.
    if (RemoveFileOnSignal)
      llvm::sys::RemoveFileOnSignal(OSFile);

    if (TempPathName)
      *TempPathName = OSFile;

    return OS.release();
  }

  void ClangInternalState::compare(const std::string& name) {
    assert(name == m_Name && "Different names!?");
    m_DiffPair.reset(new ClangInternalState(m_ASTContext, m_Preprocessor,
                                            m_Module, m_CodeGen, name));
    std::string differences = "";
    // Ignore the builtins
    typedef llvm::SmallVector<const char*, 1024> Builtins;
    Builtins builtinNames;
    const clang::Builtin::Context& BuiltinCtx = m_ASTContext.BuiltinInfo;
    for (unsigned i = clang::Builtin::NotBuiltin+1;
         i != clang::Builtin::FirstTSBuiltin; ++i) {
      const char* Name = BuiltinCtx.getName(i);
      if (!llvm::StringRef(Name).startswith("__builtin"))
        builtinNames.push_back(Name);
    }

    for (auto&& BuiltinInfo: m_ASTContext.getTargetInfo().getTargetBuiltins()) {
      if (!llvm::StringRef(BuiltinInfo.Name).startswith("__builtin"))
        builtinNames.push_back(BuiltinInfo.Name);
    }

    builtinNames.push_back(".*__builtin.*");

    if (differentContent(m_LookupTablesFile, m_DiffPair->m_LookupTablesFile,
                         differences, &builtinNames)) {
      llvm::errs() << "Differences in the lookup tables\n";
{'fraction_non_alphanumeric': 0.15661815661815662, 'fraction_numerical': 0.003031878031878032, 'mean_word_length': 2.983781918564527, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 26, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5548897', 'n_tokens_mistral': 3601, 'n_tokens_neox': 3536, 'n_words': 678}