[mlir][tensor] fix typo in pad tiling comment
[llvm-project.git] / clang / unittests / Frontend / FrontendActionTest.cpp
blob75e166767c6678915c16dcbd6f4a22958d1f0935
1 //===- unittests/Frontend/FrontendActionTest.cpp - FrontendAction tests ---===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "clang/Frontend/FrontendAction.h"
10 #include "clang/AST/ASTConsumer.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/AST/DynamicRecursiveASTVisitor.h"
13 #include "clang/Basic/LangStandard.h"
14 #include "clang/Frontend/CompilerInstance.h"
15 #include "clang/Frontend/CompilerInvocation.h"
16 #include "clang/Frontend/FrontendActions.h"
17 #include "clang/Lex/Preprocessor.h"
18 #include "clang/Lex/PreprocessorOptions.h"
19 #include "clang/Sema/Sema.h"
20 #include "clang/Serialization/InMemoryModuleCache.h"
21 #include "llvm/Support/MemoryBuffer.h"
22 #include "llvm/Support/ToolOutputFile.h"
23 #include "llvm/Support/VirtualFileSystem.h"
24 #include "llvm/TargetParser/Triple.h"
25 #include "gtest/gtest.h"
27 using namespace llvm;
28 using namespace clang;
30 namespace {
32 class TestASTFrontendAction : public ASTFrontendAction {
33 public:
34 TestASTFrontendAction(bool enableIncrementalProcessing = false,
35 bool actOnEndOfTranslationUnit = false)
36 : EnableIncrementalProcessing(enableIncrementalProcessing),
37 ActOnEndOfTranslationUnit(actOnEndOfTranslationUnit) { }
39 bool EnableIncrementalProcessing;
40 bool ActOnEndOfTranslationUnit;
41 std::vector<std::string> decl_names;
43 bool BeginSourceFileAction(CompilerInstance &ci) override {
44 if (EnableIncrementalProcessing)
45 ci.getPreprocessor().enableIncrementalProcessing();
47 return ASTFrontendAction::BeginSourceFileAction(ci);
50 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
51 StringRef InFile) override {
52 return std::make_unique<Visitor>(CI, ActOnEndOfTranslationUnit,
53 decl_names);
56 private:
57 class Visitor : public ASTConsumer, public DynamicRecursiveASTVisitor {
58 public:
59 Visitor(CompilerInstance &CI, bool ActOnEndOfTranslationUnit,
60 std::vector<std::string> &decl_names) :
61 CI(CI), ActOnEndOfTranslationUnit(ActOnEndOfTranslationUnit),
62 decl_names_(decl_names) {}
64 void HandleTranslationUnit(ASTContext &context) override {
65 if (ActOnEndOfTranslationUnit) {
66 CI.getSema().ActOnEndOfTranslationUnit();
68 TraverseDecl(context.getTranslationUnitDecl());
71 bool VisitNamedDecl(NamedDecl *Decl) override {
72 decl_names_.push_back(Decl->getQualifiedNameAsString());
73 return true;
76 private:
77 CompilerInstance &CI;
78 bool ActOnEndOfTranslationUnit;
79 std::vector<std::string> &decl_names_;
83 TEST(ASTFrontendAction, Sanity) {
84 auto invocation = std::make_shared<CompilerInvocation>();
85 invocation->getPreprocessorOpts().addRemappedFile(
86 "test.cc",
87 MemoryBuffer::getMemBuffer("int main() { float x; }").release());
88 invocation->getFrontendOpts().Inputs.push_back(
89 FrontendInputFile("test.cc", Language::CXX));
90 invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly;
91 invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
92 CompilerInstance compiler;
93 compiler.setInvocation(std::move(invocation));
94 compiler.createDiagnostics(*llvm::vfs::getRealFileSystem());
96 TestASTFrontendAction test_action;
97 ASSERT_TRUE(compiler.ExecuteAction(test_action));
98 ASSERT_EQ(2U, test_action.decl_names.size());
99 EXPECT_EQ("main", test_action.decl_names[0]);
100 EXPECT_EQ("x", test_action.decl_names[1]);
103 TEST(ASTFrontendAction, IncrementalParsing) {
104 auto invocation = std::make_shared<CompilerInvocation>();
105 invocation->getPreprocessorOpts().addRemappedFile(
106 "test.cc",
107 MemoryBuffer::getMemBuffer("int main() { float x; }").release());
108 invocation->getFrontendOpts().Inputs.push_back(
109 FrontendInputFile("test.cc", Language::CXX));
110 invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly;
111 invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
112 CompilerInstance compiler;
113 compiler.setInvocation(std::move(invocation));
114 compiler.createDiagnostics(*llvm::vfs::getRealFileSystem());
116 TestASTFrontendAction test_action(/*enableIncrementalProcessing=*/true);
117 ASSERT_TRUE(compiler.ExecuteAction(test_action));
118 ASSERT_EQ(2U, test_action.decl_names.size());
119 EXPECT_EQ("main", test_action.decl_names[0]);
120 EXPECT_EQ("x", test_action.decl_names[1]);
123 TEST(ASTFrontendAction, LateTemplateIncrementalParsing) {
124 auto invocation = std::make_shared<CompilerInvocation>();
125 invocation->getLangOpts().CPlusPlus = true;
126 invocation->getLangOpts().DelayedTemplateParsing = true;
127 invocation->getPreprocessorOpts().addRemappedFile(
128 "test.cc", MemoryBuffer::getMemBuffer(
129 "template<typename T> struct A { A(T); T data; };\n"
130 "template<typename T> struct B: public A<T> {\n"
131 " B();\n"
132 " B(B const& b): A<T>(b.data) {}\n"
133 "};\n"
134 "B<char> c() { return B<char>(); }\n").release());
135 invocation->getFrontendOpts().Inputs.push_back(
136 FrontendInputFile("test.cc", Language::CXX));
137 invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly;
138 invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
139 CompilerInstance compiler;
140 compiler.setInvocation(std::move(invocation));
141 compiler.createDiagnostics(*llvm::vfs::getRealFileSystem());
143 TestASTFrontendAction test_action(/*enableIncrementalProcessing=*/true,
144 /*actOnEndOfTranslationUnit=*/true);
145 ASSERT_TRUE(compiler.ExecuteAction(test_action));
146 ASSERT_EQ(13U, test_action.decl_names.size());
147 EXPECT_EQ("A", test_action.decl_names[0]);
148 EXPECT_EQ("c", test_action.decl_names[12]);
151 struct TestPPCallbacks : public PPCallbacks {
152 TestPPCallbacks() : SeenEnd(false) {}
154 void EndOfMainFile() override { SeenEnd = true; }
156 bool SeenEnd;
159 class TestPPCallbacksFrontendAction : public PreprocessorFrontendAction {
160 TestPPCallbacks *Callbacks;
162 public:
163 TestPPCallbacksFrontendAction(TestPPCallbacks *C)
164 : Callbacks(C), SeenEnd(false) {}
166 void ExecuteAction() override {
167 Preprocessor &PP = getCompilerInstance().getPreprocessor();
168 PP.addPPCallbacks(std::unique_ptr<TestPPCallbacks>(Callbacks));
169 PP.EnterMainSourceFile();
171 void EndSourceFileAction() override { SeenEnd = Callbacks->SeenEnd; }
173 bool SeenEnd;
176 TEST(PreprocessorFrontendAction, EndSourceFile) {
177 auto Invocation = std::make_shared<CompilerInvocation>();
178 Invocation->getPreprocessorOpts().addRemappedFile(
179 "test.cc",
180 MemoryBuffer::getMemBuffer("int main() { float x; }").release());
181 Invocation->getFrontendOpts().Inputs.push_back(
182 FrontendInputFile("test.cc", Language::CXX));
183 Invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly;
184 Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
185 CompilerInstance Compiler;
186 Compiler.setInvocation(std::move(Invocation));
187 Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem());
189 TestPPCallbacks *Callbacks = new TestPPCallbacks;
190 TestPPCallbacksFrontendAction TestAction(Callbacks);
191 ASSERT_FALSE(Callbacks->SeenEnd);
192 ASSERT_FALSE(TestAction.SeenEnd);
193 ASSERT_TRUE(Compiler.ExecuteAction(TestAction));
194 // Check that EndOfMainFile was called before EndSourceFileAction.
195 ASSERT_TRUE(TestAction.SeenEnd);
198 class TypoExternalSemaSource : public ExternalSemaSource {
199 CompilerInstance &CI;
201 public:
202 TypoExternalSemaSource(CompilerInstance &CI) : CI(CI) {}
204 TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, int LookupKind,
205 Scope *S, CXXScopeSpec *SS,
206 CorrectionCandidateCallback &CCC,
207 DeclContext *MemberContext, bool EnteringContext,
208 const ObjCObjectPointerType *OPT) override {
209 // Generate a fake typo correction with one attached note.
210 ASTContext &Ctx = CI.getASTContext();
211 TypoCorrection TC(DeclarationName(&Ctx.Idents.get("moo")));
212 unsigned DiagID = Ctx.getDiagnostics().getCustomDiagID(
213 DiagnosticsEngine::Note, "This is a note");
214 TC.addExtraDiagnostic(PartialDiagnostic(DiagID, Ctx.getDiagAllocator()));
215 return TC;
219 struct TypoDiagnosticConsumer : public DiagnosticConsumer {
220 void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
221 const Diagnostic &Info) override {
222 // Capture errors and notes. There should be one of each.
223 if (DiagLevel == DiagnosticsEngine::Error) {
224 assert(Error.empty());
225 Info.FormatDiagnostic(Error);
226 } else {
227 assert(Note.empty());
228 Info.FormatDiagnostic(Note);
231 SmallString<32> Error;
232 SmallString<32> Note;
235 TEST(ASTFrontendAction, ExternalSemaSource) {
236 auto Invocation = std::make_shared<CompilerInvocation>();
237 Invocation->getLangOpts().CPlusPlus = true;
238 Invocation->getPreprocessorOpts().addRemappedFile(
239 "test.cc", MemoryBuffer::getMemBuffer("void fooo();\n"
240 "int main() { foo(); }")
241 .release());
242 Invocation->getFrontendOpts().Inputs.push_back(
243 FrontendInputFile("test.cc", Language::CXX));
244 Invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly;
245 Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
246 CompilerInstance Compiler;
247 Compiler.setInvocation(std::move(Invocation));
248 auto *TDC = new TypoDiagnosticConsumer;
249 Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem(), TDC,
250 /*ShouldOwnClient=*/true);
251 Compiler.setExternalSemaSource(new TypoExternalSemaSource(Compiler));
253 SyntaxOnlyAction TestAction;
254 ASSERT_TRUE(Compiler.ExecuteAction(TestAction));
255 // There should be one error correcting to 'moo' and a note attached to it.
256 EXPECT_EQ("use of undeclared identifier 'foo'; did you mean 'moo'?",
257 std::string(TDC->Error));
258 EXPECT_EQ("This is a note", std::string(TDC->Note));
261 TEST(GeneratePCHFrontendAction, CacheGeneratedPCH) {
262 // Create a temporary file for writing out the PCH that will be cleaned up.
263 int PCHFD;
264 llvm::SmallString<128> PCHFilename;
265 ASSERT_FALSE(
266 llvm::sys::fs::createTemporaryFile("test.h", "pch", PCHFD, PCHFilename));
267 llvm::ToolOutputFile PCHFile(PCHFilename, PCHFD);
269 for (bool ShouldCache : {false, true}) {
270 auto Invocation = std::make_shared<CompilerInvocation>();
271 Invocation->getLangOpts().CacheGeneratedPCH = ShouldCache;
272 Invocation->getPreprocessorOpts().addRemappedFile(
273 "test.h",
274 MemoryBuffer::getMemBuffer("int foo(void) { return 1; }\n").release());
275 Invocation->getFrontendOpts().Inputs.push_back(
276 FrontendInputFile("test.h", Language::C));
277 Invocation->getFrontendOpts().OutputFile = PCHFilename.str().str();
278 Invocation->getFrontendOpts().ProgramAction = frontend::GeneratePCH;
279 Invocation->getTargetOpts().Triple = "x86_64-apple-darwin19.0.0";
280 CompilerInstance Compiler;
281 Compiler.setInvocation(std::move(Invocation));
282 Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem());
284 GeneratePCHAction TestAction;
285 ASSERT_TRUE(Compiler.ExecuteAction(TestAction));
287 // Check whether the PCH was cached.
288 if (ShouldCache)
289 EXPECT_EQ(InMemoryModuleCache::Final,
290 Compiler.getModuleCache().getPCMState(PCHFilename));
291 else
292 EXPECT_EQ(InMemoryModuleCache::Unknown,
293 Compiler.getModuleCache().getPCMState(PCHFilename));
297 } // anonymous namespace