clang: lib/Testing/TestAST.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

15#include "llvm/ADT/ScopeExit.h"

16#include "llvm/Support/Error.h"

17#include "llvm/Support/VirtualFileSystem.h"

18

19#include "gtest/gtest.h"

20#include

21

23namespace {

24

25

26class StoreDiagnostics : public DiagnosticConsumer {

27 std::vector &Out;

28 bool ReportErrors;

29 LangOptions LangOpts;

30

31public:

32 StoreDiagnostics(std::vector &Out, bool ReportErrors)

33 : Out(Out), ReportErrors(ReportErrors) {}

34

35 void BeginSourceFile(const LangOptions &LangOpts,

36 const Preprocessor *) override {

37 this->LangOpts = LangOpts;

38 }

39

41 const Diagnostic &Info) override {

42 Out.emplace_back(DiagLevel, Info);

44 std::string Text;

45 llvm::raw_string_ostream OS(Text);

46 TextDiagnostic Renderer(OS, LangOpts,

47 &Info.getDiags()->getDiagnosticOptions());

48 Renderer.emitStoredDiagnostic(Out.back());

49 ADD_FAILURE() << Text;

50 }

51 }

52};

53

54

55

56void createMissingComponents(CompilerInstance &Clang) {

57 if (!Clang.hasDiagnostics())

58 Clang.createDiagnostics(*llvm::vfs::getRealFileSystem());

59 if (!Clang.hasFileManager())

60 Clang.createFileManager();

61 if (!Clang.hasSourceManager())

62 Clang.createSourceManager(Clang.getFileManager());

63 if (!Clang.hasTarget())

64 Clang.createTarget();

65 if (!Clang.hasPreprocessor())

67 if (!Clang.hasASTConsumer())

68 Clang.setASTConsumer(std::make_unique());

69 if (!Clang.hasASTContext())

70 Clang.createASTContext();

71 if (!Clang.hasSema())

72 Clang.createSema(TU_Complete, nullptr);

73}

74

75}

76

78 Clang = std::make_unique(

79 std::make_shared());

80

81

82 auto RecoverFromEarlyExit =

83 llvm::make_scope_exit([&] { createMissingComponents(*Clang); });

84

85 std::string Filename = In.FileName;

88

89

90 auto VFS = llvm::makeIntrusiveRefCntllvm::vfs::InMemoryFileSystem();

91 if (auto Err = VFS->setCurrentWorkingDirectory(In.WorkingDir))

92 ADD_FAILURE() << "Failed to setWD: " << Err.message();

93 VFS->addFile(Filename, 0,

94 llvm::MemoryBuffer::getMemBufferCopy(In.Code, Filename));

95 for (const auto &Extra : In.ExtraFiles)

96 VFS->addFile(

97 Extra.getKey(), 0,

98 llvm::MemoryBuffer::getMemBufferCopy(Extra.getValue(), Extra.getKey()));

99

100

101 bool ErrorOK = In.ErrorOK || llvm::StringRef(In.Code).contains("error-ok");

102 Clang->createDiagnostics(*VFS, new StoreDiagnostics(Diagnostics, !ErrorOK));

103

104

105 std::vector<const char *> Argv;

107 for (const auto &S : LangArgs)

108 Argv.push_back(S.c_str());

109 for (const auto &S : In.ExtraArgs)

110 Argv.push_back(S.c_str());

111 Argv.push_back(Filename.c_str());

112 Clang->setInvocation(std::make_unique());

114 Clang->getDiagnostics(), "clang")) {

115 ADD_FAILURE() << "Failed to create invocation";

116 return;

117 }

118 assert(!Clang->getInvocation().getFrontendOpts().DisableFree);

119

120 Clang->createFileManager(VFS);

121

122

123

124 EXPECT_TRUE(Clang->createTarget());

125 Action =

126 In.MakeAction ? In.MakeAction() : std::make_unique();

127 const FrontendInputFile &Main = Clang->getFrontendOpts().Inputs.front();

128 if (!Action->BeginSourceFile(*Clang, Main)) {

129 ADD_FAILURE() << "Failed to BeginSourceFile()";

130 Action.reset();

131 return;

132 }

133 if (auto Err = Action->Execute())

134 ADD_FAILURE() << "Failed to Execute(): " << llvm::toString(std::move(Err));

135

136

137

138 Clang->getPreprocessor().EndSourceFile();

139

140 Clang->getDiagnosticClient().EndSourceFile();

142 true);

143}

144

145void TestAST::clear() {

146 if (Action) {

147

148

149 auto PP = Clang->getPreprocessorPtr();

150 Clang->setPreprocessor(nullptr);

151 Action->EndSourceFile();

152

153 }

154 Action.reset();

155 Clang.reset();

156 Diagnostics.clear();

157}

158

160 clear();

161 Action = std::move(M.Action);

162 Clang = std::move(M.Clang);

163 Diagnostics = std::move(M.Diagnostics);

164 return *this;

165}

166

168

170

171}

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.

An input file for the front end.

The result of parsing a file specified by TestInputs.

TestAST(const TestInputs &)

Constructing a TestAST parses the virtual file.

TestAST & operator=(TestAST &&)

The JSON file list parser is used to communicate input to InstallAPI.

std::vector< std::string > getCC1ArgsForTesting(TestLanguage Lang)

StringRef getFilenameForTesting(TestLanguage Lang)

@ TU_Complete

The translation unit is a complete translation unit.

Specifies a virtual source file to be parsed as part of a test.