llvm-project/clang/unittests/Driver/SanitizerArgsTest.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

142 lines
5.2 KiB
C++
Raw Normal View History

//===- unittests/Driver/SanitizerArgsTest.cpp -----------------------------===//
//
// 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/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Job.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <cstdlib>
#include <memory>
#include <string>
using namespace clang;
using namespace clang::driver;
using ::testing::Contains;
using ::testing::StrEq;
namespace {
static constexpr const char *ClangBinary = "clang";
static constexpr const char *InputFile = "/sources/foo.c";
std::string concatPaths(llvm::ArrayRef<StringRef> Components) {
llvm::SmallString<128> P;
for (StringRef C : Components)
llvm::sys::path::append(P, C);
return std::string(P);
}
class SanitizerArgsTest : public ::testing::Test {
protected:
const Command &emulateSingleCompilation(std::vector<std::string> ExtraArgs,
std::vector<std::string> ExtraFiles) {
assert(!DriverInstance && "Running twice is not allowed");
llvm::IntrusiveRefCntPtr<DiagnosticOptions> Opts = new DiagnosticOptions;
DiagnosticsEngine Diags(
new DiagnosticIDs, Opts,
new TextDiagnosticPrinter(llvm::errs(), Opts.get()));
DriverInstance.emplace(ClangBinary, "x86_64-unknown-linux-gnu", Diags,
[flang][driver] Add the new flang compiler and frontend drivers Summary: This is the first patch implementing the new Flang driver as outlined in [1], [2] & [3]. It creates Flang driver (`flang-new`) and Flang frontend driver (`flang-new -fc1`). These will be renamed as `flang` and `flang -fc1` once the current Flang throwaway driver, `flang`, can be replaced with `flang-new`. Currently only 2 options are supported: `-help` and `--version`. `flang-new` is implemented in terms of libclangDriver, defaulting the driver mode to `FlangMode` (added to libclangDriver in [4]). This ensures that the driver runs in Flang mode regardless of the name of the binary inferred from argv[0]. The design of the new Flang compiler and frontend drivers is inspired by it counterparts in Clang [3]. Currently, the new Flang compiler and frontend drivers re-use Clang libraries: clangBasic, clangDriver and clangFrontend. To identify Flang options, this patch adds FlangOption/FC1Option enums. Driver::printHelp is updated so that `flang-new` prints only Flang options. The new Flang driver is disabled by default. To enable it, set `-DBUILD_FLANG_NEW_DRIVER=ON` when configuring CMake and add clang to `LLVM_ENABLE_PROJECTS` (e.g. -DLLVM_ENABLE_PROJECTS=“clang;flang;mlir”). [1] “RFC: new Flang driver - next steps” http://lists.llvm.org/pipermail/flang-dev/2020-July/000470.html [2] “RFC: Adding a fortran mode to the clang driver for flang” http://lists.llvm.org/pipermail/cfe-dev/2019-June/062669.html [3] “RFC: refactoring libclangDriver/libclangFrontend to share with Flang” http://lists.llvm.org/pipermail/cfe-dev/2020-July/066393.html [4] https://reviews.llvm.org/rG6bf55804924d5a1d902925ad080b1a2b57c5c75c co-authored-by: Andrzej Warzynski <andrzej.warzynski@arm.com> Reviewed By: richard.barton.arm, sameeranjoshi Differential Revision: https://reviews.llvm.org/D86089
2020-09-11 17:17:31 +08:00
"clang LLVM compiler", prepareFS(ExtraFiles));
std::vector<const char *> Args = {ClangBinary};
for (const auto &A : ExtraArgs)
Args.push_back(A.c_str());
Args.push_back("-c");
Args.push_back(InputFile);
CompilationJob.reset(DriverInstance->BuildCompilation(Args));
if (Diags.hasErrorOccurred())
ADD_FAILURE() << "Error occurred while parsing compilation arguments. "
"See stderr for details.";
const auto &Commands = CompilationJob->getJobs().getJobs();
assert(Commands.size() == 1);
return *Commands.front();
}
private:
llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>
prepareFS(llvm::ArrayRef<std::string> ExtraFiles) {
llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS =
new llvm::vfs::InMemoryFileSystem;
FS->addFile(ClangBinary, time_t(), llvm::MemoryBuffer::getMemBuffer(""));
FS->addFile(InputFile, time_t(), llvm::MemoryBuffer::getMemBuffer(""));
for (llvm::StringRef F : ExtraFiles)
FS->addFile(F, time_t(), llvm::MemoryBuffer::getMemBuffer(""));
return FS;
}
llvm::Optional<Driver> DriverInstance;
std::unique_ptr<driver::Compilation> CompilationJob;
};
TEST_F(SanitizerArgsTest, Ignorelists) {
const std::string ResourceDir = "/opt/llvm/lib/resources";
const std::string UserIgnorelist = "/source/my_ignorelist.txt";
const std::string ASanIgnorelist =
concatPaths({ResourceDir, "share", "asan_ignorelist.txt"});
auto &Command = emulateSingleCompilation(
/*ExtraArgs=*/{"-fsanitize=address", "-resource-dir", ResourceDir,
std::string("-fsanitize-ignorelist=") + UserIgnorelist},
/*ExtraFiles=*/{ASanIgnorelist, UserIgnorelist});
// System ignorelists are added based on resource-dir.
EXPECT_THAT(Command.getArguments(),
Contains(StrEq(std::string("-fsanitize-system-ignorelist=") +
ASanIgnorelist)));
// User ignorelists should also be added.
EXPECT_THAT(
Command.getArguments(),
Contains(StrEq(std::string("-fsanitize-ignorelist=") + UserIgnorelist)));
}
TEST_F(SanitizerArgsTest, XRayLists) {
const std::string XRayWhitelist = "/source/xray_whitelist.txt";
const std::string XRayIgnorelist = "/source/xray_ignorelist.txt";
const std::string XRayAttrList = "/source/xray_attr_list.txt";
auto &Command = emulateSingleCompilation(
/*ExtraArgs=*/
{
"-fxray-instrument",
"-fxray-always-instrument=" + XRayWhitelist,
"-fxray-never-instrument=" + XRayIgnorelist,
"-fxray-attr-list=" + XRayAttrList,
},
/*ExtraFiles=*/{XRayWhitelist, XRayIgnorelist, XRayAttrList});
// Ignorelists exist in the filesystem, so they should be added to the
// compilation command, produced by the driver.
EXPECT_THAT(Command.getArguments(),
Contains(StrEq("-fxray-always-instrument=" + XRayWhitelist)));
EXPECT_THAT(Command.getArguments(),
Contains(StrEq("-fxray-never-instrument=" + XRayIgnorelist)));
EXPECT_THAT(Command.getArguments(),
Contains(StrEq("-fxray-attr-list=" + XRayAttrList)));
}
} // namespace