15#include "llvm/ADT/ScopeExit.h"
16#include "llvm/Support/VirtualFileSystem.h"
18#include "gtest/gtest.h"
25class StoreDiagnostics :
public DiagnosticConsumer {
26 std::vector<StoredDiagnostic> &Out;
31 StoreDiagnostics(std::vector<StoredDiagnostic> &Out,
bool ReportErrors)
32 : Out(Out), ReportErrors(ReportErrors) {}
34 void BeginSourceFile(
const LangOptions &LangOpts,
35 const Preprocessor *)
override {
36 this->LangOpts = LangOpts;
40 const Diagnostic &Info)
override {
41 Out.emplace_back(DiagLevel, Info);
44 llvm::raw_string_ostream
OS(
Text);
45 TextDiagnostic Renderer(
OS, LangOpts,
46 &Info.getDiags()->getDiagnosticOptions());
47 Renderer.emitStoredDiagnostic(Out.back());
48 ADD_FAILURE() <<
Text;
55void createMissingComponents(CompilerInstance &Clang) {
56 if (!Clang.hasDiagnostics())
57 Clang.createDiagnostics();
58 if (!Clang.hasFileManager())
59 Clang.createFileManager();
60 if (!Clang.hasSourceManager())
61 Clang.createSourceManager(Clang.getFileManager());
62 if (!Clang.hasTarget())
64 if (!Clang.hasPreprocessor())
66 if (!Clang.hasASTConsumer())
67 Clang.setASTConsumer(std::make_unique<ASTConsumer>());
68 if (!Clang.hasASTContext())
69 Clang.createASTContext();
77 Clang = std::make_unique<CompilerInstance>(
78 std::make_shared<PCHContainerOperations>());
81 auto RecoverFromEarlyExit =
82 llvm::make_scope_exit([&] { createMissingComponents(*Clang); });
85 bool ErrorOK = In.
ErrorOK || llvm::StringRef(In.
Code).contains(
"error-ok");
86 Clang->createDiagnostics(
new StoreDiagnostics(Diagnostics, !ErrorOK));
89 std::vector<const char *> Argv;
91 for (
const auto &S : LangArgs)
92 Argv.push_back(S.c_str());
94 Argv.push_back(S.c_str());
99 Clang->setInvocation(std::make_unique<CompilerInvocation>());
101 Clang->getDiagnostics(),
"clang")) {
102 ADD_FAILURE() <<
"Failed to create invocation";
105 assert(!Clang->getInvocation().getFrontendOpts().DisableFree);
108 auto VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
110 llvm::MemoryBuffer::getMemBufferCopy(In.
Code,
Filename));
114 llvm::MemoryBuffer::getMemBufferCopy(Extra.getValue(), Extra.getKey()));
115 Clang->createFileManager(VFS);
119 EXPECT_TRUE(Clang->createTarget());
123 if (!Action->BeginSourceFile(*Clang, Main)) {
124 ADD_FAILURE() <<
"Failed to BeginSourceFile()";
128 if (
auto Err = Action->Execute())
129 ADD_FAILURE() <<
"Failed to Execute(): " << llvm::toString(std::move(Err));
133 Clang->getPreprocessor().EndSourceFile();
135 Clang->getDiagnosticClient().EndSourceFile();
140void TestAST::clear() {
144 auto PP = Clang->getPreprocessorPtr();
145 Clang->setPreprocessor(
nullptr);
146 Action->EndSourceFile();
156 Action = std::move(M.Action);
157 Clang = std::move(M.Clang);
158 Diagnostics = std::move(M.Diagnostics);
Defines the Diagnostic-related interfaces.
Defines the clang::LangOptions interface.
static bool CreateFromArgs(CompilerInvocation &Res, ArrayRef< const char * > CommandLineArgs, DiagnosticsEngine &Diags, const char *Argv0=nullptr)
Create a compiler invocation from a list of input options.
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
Level
The level of the diagnostic, after it has been through mapping.
The result of parsing a file specified by TestInputs.
TestAST(const TestInputs &)
Constructing a TestAST parses the virtual file.
TestAST & operator=(TestAST &&)
std::vector< std::string > getCC1ArgsForTesting(TestLanguage Lang)
StringRef getFilenameForTesting(TestLanguage Lang)
@ TU_Complete
The translation unit is a complete translation unit.