//===- unittests/Frontend/CompilerInstanceTest.cpp - CI tests -------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "clang/Frontend/CompilerInstance.h"
#include "clang/Basic/FileManager.h"
#include "clang/Driver/CreateInvocationFromArgs.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "gtest/gtest.h"

using namespace llvm;
using namespace clang;

namespace {

TEST(CompilerInstance, DefaultVFSOverlayFromInvocation) {
  // Create a temporary VFS overlay yaml file.
  int FD;
  SmallString<256> FileName;
  ASSERT_FALSE(sys::fs::createTemporaryFile("vfs", "yaml", FD, FileName));
  ToolOutputFile File(FileName, FD);

  SmallString<256> CurrentPath;
  sys::fs::current_path(CurrentPath);
  sys::path::make_absolute(CurrentPath, FileName);

  // Mount the VFS file itself on the path 'virtual.file'. Makes this test
  // a bit shorter than creating a new dummy file just for this purpose.
  const std::string CurrentPathStr = std::string(CurrentPath.str());
  const std::string FileNameStr = std::string(FileName.str());
  const char *VFSYaml = "{ 'version': 0, 'roots': [\n"
                        "  { 'name': '%s',\n"
                        "    'type': 'directory',\n"
                        "    'contents': [\n"
                        "      { 'name': 'vfs-virtual.file', 'type': 'file',\n"
                        "        'external-contents': '%s'\n"
                        "      }\n"
                        "    ]\n"
                        "  }\n"
                        "]}\n";
  File.os() << format(VFSYaml, CurrentPathStr.c_str(), FileName.c_str());
  File.os().flush();

  // Create a CompilerInvocation that uses this overlay file.
  const std::string VFSArg = "-ivfsoverlay" + FileNameStr;
  const char *Args[] = {"clang", VFSArg.c_str(), "-xc++", "-"};

  DiagnosticOptions DiagOpts;
  IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
      CompilerInstance::createDiagnostics(*llvm::vfs::getRealFileSystem(),
                                          DiagOpts);

  CreateInvocationOptions CIOpts;
  CIOpts.Diags = Diags;
  std::shared_ptr<CompilerInvocation> CInvok =
      createInvocation(Args, std::move(CIOpts));

  if (!CInvok)
    FAIL() << "could not create compiler invocation";
  // Create a minimal CompilerInstance which should use the VFS we specified
  // in the CompilerInvocation (as we don't explicitly set our own).
  CompilerInstance Instance(std::move(CInvok));
  Instance.setDiagnostics(Diags);
  Instance.createVirtualFileSystem();
  Instance.createFileManager();

  // Check if the virtual file exists which means that our VFS is used by the
  // CompilerInstance.
  ASSERT_TRUE(Instance.getFileManager().getOptionalFileRef("vfs-virtual.file"));
}

TEST(CompilerInstance, AllowDiagnosticLogWithUnownedDiagnosticConsumer) {
  DiagnosticOptions DiagOpts;
  // Tell the diagnostics engine to emit the diagnostic log to STDERR. This
  // ensures that a chained diagnostic consumer is created so that the test can
  // exercise the unowned diagnostic consumer in a chained consumer.
  DiagOpts.DiagnosticLogFile = "-";

  // Create the diagnostic engine with unowned consumer.
  std::string DiagnosticOutput;
  llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput);
  auto DiagPrinter =
      std::make_unique<TextDiagnosticPrinter>(DiagnosticsOS, DiagOpts);
  CompilerInstance Instance;
  IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
      Instance.createDiagnostics(*llvm::vfs::getRealFileSystem(), DiagOpts,
                                 DiagPrinter.get(), /*ShouldOwnClient=*/false);

  Diags->Report(diag::err_expected) << "no crash";
  ASSERT_EQ(DiagnosticOutput, "error: expected no crash\n");
}

TEST(CompilerInstance, MultipleInputsCleansFileIDs) {
  auto VFS = makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
  VFS->addFile("a.cc", /*ModificationTime=*/{},
               MemoryBuffer::getMemBuffer(R"cpp(
      #include "a.h"
      )cpp"));
  // Paddings of `void foo();` in the sources below are "important". We're
  // testing against source locations from previous compilations colliding.
  // Hence the `unused` variable in `b.h` needs to be within `#pragma clang
  // diagnostic` block from `a.h`.
  VFS->addFile("a.h", /*ModificationTime=*/{}, MemoryBuffer::getMemBuffer(R"cpp(
      #include "b.h"
      #pragma clang diagnostic push
      #pragma clang diagnostic warning "-Wunused"
      void foo();
      #pragma clang diagnostic pop
      )cpp"));
  VFS->addFile("b.h", /*ModificationTime=*/{}, MemoryBuffer::getMemBuffer(R"cpp(
      void foo(); void foo(); void foo(); void foo();
      inline void foo() { int unused = 2; }
      )cpp"));

  DiagnosticOptions DiagOpts;
  IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
      CompilerInstance::createDiagnostics(*VFS, DiagOpts);

  CreateInvocationOptions CIOpts;
  CIOpts.Diags = Diags;

  const char *Args[] = {"clang", "-xc++", "a.cc"};
  std::shared_ptr<CompilerInvocation> CInvok =
      createInvocation(Args, std::move(CIOpts));
  ASSERT_TRUE(CInvok) << "could not create compiler invocation";

  CompilerInstance Instance(std::move(CInvok));
  Instance.setVirtualFileSystem(VFS);
  Instance.setDiagnostics(Diags);
  Instance.createFileManager();

  // Run once for `a.cc` and then for `a.h`. This makes sure we get the same
  // file ID for `b.h` in the second run as `a.h` from first run.
  const auto &OrigInputKind = Instance.getFrontendOpts().Inputs[0].getKind();
  Instance.getFrontendOpts().Inputs.emplace_back("a.h", OrigInputKind);

  SyntaxOnlyAction Act;
  EXPECT_TRUE(Instance.ExecuteAction(Act)) << "Failed to execute action";
  EXPECT_FALSE(Diags->hasErrorOccurred());
  EXPECT_EQ(Diags->getNumWarnings(), 0u);
}
} // anonymous namespace
