xref: /aosp_15_r20/external/clang/unittests/Frontend/FrontendActionTest.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===- unittests/Frontend/FrontendActionTest.cpp - FrontendAction tests ---===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li 
10*67e74705SXin Li #include "clang/Frontend/FrontendAction.h"
11*67e74705SXin Li #include "clang/AST/ASTConsumer.h"
12*67e74705SXin Li #include "clang/AST/ASTContext.h"
13*67e74705SXin Li #include "clang/AST/RecursiveASTVisitor.h"
14*67e74705SXin Li #include "clang/Frontend/CompilerInstance.h"
15*67e74705SXin Li #include "clang/Frontend/CompilerInvocation.h"
16*67e74705SXin Li #include "clang/Lex/Preprocessor.h"
17*67e74705SXin Li #include "clang/Sema/Sema.h"
18*67e74705SXin Li #include "llvm/ADT/Triple.h"
19*67e74705SXin Li #include "llvm/Support/MemoryBuffer.h"
20*67e74705SXin Li #include "gtest/gtest.h"
21*67e74705SXin Li 
22*67e74705SXin Li using namespace llvm;
23*67e74705SXin Li using namespace clang;
24*67e74705SXin Li 
25*67e74705SXin Li namespace {
26*67e74705SXin Li 
27*67e74705SXin Li class TestASTFrontendAction : public ASTFrontendAction {
28*67e74705SXin Li public:
TestASTFrontendAction(bool enableIncrementalProcessing=false,bool actOnEndOfTranslationUnit=false)29*67e74705SXin Li   TestASTFrontendAction(bool enableIncrementalProcessing = false,
30*67e74705SXin Li                         bool actOnEndOfTranslationUnit = false)
31*67e74705SXin Li     : EnableIncrementalProcessing(enableIncrementalProcessing),
32*67e74705SXin Li       ActOnEndOfTranslationUnit(actOnEndOfTranslationUnit) { }
33*67e74705SXin Li 
34*67e74705SXin Li   bool EnableIncrementalProcessing;
35*67e74705SXin Li   bool ActOnEndOfTranslationUnit;
36*67e74705SXin Li   std::vector<std::string> decl_names;
37*67e74705SXin Li 
BeginSourceFileAction(CompilerInstance & ci,StringRef filename)38*67e74705SXin Li   bool BeginSourceFileAction(CompilerInstance &ci,
39*67e74705SXin Li                              StringRef filename) override {
40*67e74705SXin Li     if (EnableIncrementalProcessing)
41*67e74705SXin Li       ci.getPreprocessor().enableIncrementalProcessing();
42*67e74705SXin Li 
43*67e74705SXin Li     return ASTFrontendAction::BeginSourceFileAction(ci, filename);
44*67e74705SXin Li   }
45*67e74705SXin Li 
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)46*67e74705SXin Li   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
47*67e74705SXin Li                                                  StringRef InFile) override {
48*67e74705SXin Li     return llvm::make_unique<Visitor>(CI, ActOnEndOfTranslationUnit,
49*67e74705SXin Li                                       decl_names);
50*67e74705SXin Li   }
51*67e74705SXin Li 
52*67e74705SXin Li private:
53*67e74705SXin Li   class Visitor : public ASTConsumer, public RecursiveASTVisitor<Visitor> {
54*67e74705SXin Li   public:
Visitor(CompilerInstance & CI,bool ActOnEndOfTranslationUnit,std::vector<std::string> & decl_names)55*67e74705SXin Li     Visitor(CompilerInstance &CI, bool ActOnEndOfTranslationUnit,
56*67e74705SXin Li             std::vector<std::string> &decl_names) :
57*67e74705SXin Li       CI(CI), ActOnEndOfTranslationUnit(ActOnEndOfTranslationUnit),
58*67e74705SXin Li       decl_names_(decl_names) {}
59*67e74705SXin Li 
HandleTranslationUnit(ASTContext & context)60*67e74705SXin Li     void HandleTranslationUnit(ASTContext &context) override {
61*67e74705SXin Li       if (ActOnEndOfTranslationUnit) {
62*67e74705SXin Li         CI.getSema().ActOnEndOfTranslationUnit();
63*67e74705SXin Li       }
64*67e74705SXin Li       TraverseDecl(context.getTranslationUnitDecl());
65*67e74705SXin Li     }
66*67e74705SXin Li 
VisitNamedDecl(NamedDecl * Decl)67*67e74705SXin Li     virtual bool VisitNamedDecl(NamedDecl *Decl) {
68*67e74705SXin Li       decl_names_.push_back(Decl->getQualifiedNameAsString());
69*67e74705SXin Li       return true;
70*67e74705SXin Li     }
71*67e74705SXin Li 
72*67e74705SXin Li   private:
73*67e74705SXin Li     CompilerInstance &CI;
74*67e74705SXin Li     bool ActOnEndOfTranslationUnit;
75*67e74705SXin Li     std::vector<std::string> &decl_names_;
76*67e74705SXin Li   };
77*67e74705SXin Li };
78*67e74705SXin Li 
TEST(ASTFrontendAction,Sanity)79*67e74705SXin Li TEST(ASTFrontendAction, Sanity) {
80*67e74705SXin Li   CompilerInvocation *invocation = new CompilerInvocation;
81*67e74705SXin Li   invocation->getPreprocessorOpts().addRemappedFile(
82*67e74705SXin Li       "test.cc",
83*67e74705SXin Li       MemoryBuffer::getMemBuffer("int main() { float x; }").release());
84*67e74705SXin Li   invocation->getFrontendOpts().Inputs.push_back(FrontendInputFile("test.cc",
85*67e74705SXin Li                                                                    IK_CXX));
86*67e74705SXin Li   invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly;
87*67e74705SXin Li   invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
88*67e74705SXin Li   CompilerInstance compiler;
89*67e74705SXin Li   compiler.setInvocation(invocation);
90*67e74705SXin Li   compiler.createDiagnostics();
91*67e74705SXin Li 
92*67e74705SXin Li   TestASTFrontendAction test_action;
93*67e74705SXin Li   ASSERT_TRUE(compiler.ExecuteAction(test_action));
94*67e74705SXin Li   ASSERT_EQ(2U, test_action.decl_names.size());
95*67e74705SXin Li   EXPECT_EQ("main", test_action.decl_names[0]);
96*67e74705SXin Li   EXPECT_EQ("x", test_action.decl_names[1]);
97*67e74705SXin Li }
98*67e74705SXin Li 
TEST(ASTFrontendAction,IncrementalParsing)99*67e74705SXin Li TEST(ASTFrontendAction, IncrementalParsing) {
100*67e74705SXin Li   CompilerInvocation *invocation = new CompilerInvocation;
101*67e74705SXin Li   invocation->getPreprocessorOpts().addRemappedFile(
102*67e74705SXin Li       "test.cc",
103*67e74705SXin Li       MemoryBuffer::getMemBuffer("int main() { float x; }").release());
104*67e74705SXin Li   invocation->getFrontendOpts().Inputs.push_back(FrontendInputFile("test.cc",
105*67e74705SXin Li                                                                    IK_CXX));
106*67e74705SXin Li   invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly;
107*67e74705SXin Li   invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
108*67e74705SXin Li   CompilerInstance compiler;
109*67e74705SXin Li   compiler.setInvocation(invocation);
110*67e74705SXin Li   compiler.createDiagnostics();
111*67e74705SXin Li 
112*67e74705SXin Li   TestASTFrontendAction test_action(/*enableIncrementalProcessing=*/true);
113*67e74705SXin Li   ASSERT_TRUE(compiler.ExecuteAction(test_action));
114*67e74705SXin Li   ASSERT_EQ(2U, test_action.decl_names.size());
115*67e74705SXin Li   EXPECT_EQ("main", test_action.decl_names[0]);
116*67e74705SXin Li   EXPECT_EQ("x", test_action.decl_names[1]);
117*67e74705SXin Li }
118*67e74705SXin Li 
TEST(ASTFrontendAction,LateTemplateIncrementalParsing)119*67e74705SXin Li TEST(ASTFrontendAction, LateTemplateIncrementalParsing) {
120*67e74705SXin Li   CompilerInvocation *invocation = new CompilerInvocation;
121*67e74705SXin Li   invocation->getLangOpts()->CPlusPlus = true;
122*67e74705SXin Li   invocation->getLangOpts()->DelayedTemplateParsing = true;
123*67e74705SXin Li   invocation->getPreprocessorOpts().addRemappedFile(
124*67e74705SXin Li     "test.cc", MemoryBuffer::getMemBuffer(
125*67e74705SXin Li       "template<typename T> struct A { A(T); T data; };\n"
126*67e74705SXin Li       "template<typename T> struct B: public A<T> {\n"
127*67e74705SXin Li       "  B();\n"
128*67e74705SXin Li       "  B(B const& b): A<T>(b.data) {}\n"
129*67e74705SXin Li       "};\n"
130*67e74705SXin Li       "B<char> c() { return B<char>(); }\n").release());
131*67e74705SXin Li   invocation->getFrontendOpts().Inputs.push_back(FrontendInputFile("test.cc",
132*67e74705SXin Li                                                                    IK_CXX));
133*67e74705SXin Li   invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly;
134*67e74705SXin Li   invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
135*67e74705SXin Li   CompilerInstance compiler;
136*67e74705SXin Li   compiler.setInvocation(invocation);
137*67e74705SXin Li   compiler.createDiagnostics();
138*67e74705SXin Li 
139*67e74705SXin Li   TestASTFrontendAction test_action(/*enableIncrementalProcessing=*/true,
140*67e74705SXin Li                                     /*actOnEndOfTranslationUnit=*/true);
141*67e74705SXin Li   ASSERT_TRUE(compiler.ExecuteAction(test_action));
142*67e74705SXin Li   ASSERT_EQ(13U, test_action.decl_names.size());
143*67e74705SXin Li   EXPECT_EQ("A", test_action.decl_names[0]);
144*67e74705SXin Li   EXPECT_EQ("c", test_action.decl_names[12]);
145*67e74705SXin Li }
146*67e74705SXin Li 
147*67e74705SXin Li struct TestPPCallbacks : public PPCallbacks {
TestPPCallbacks__anond125b09b0111::TestPPCallbacks148*67e74705SXin Li   TestPPCallbacks() : SeenEnd(false) {}
149*67e74705SXin Li 
EndOfMainFile__anond125b09b0111::TestPPCallbacks150*67e74705SXin Li   void EndOfMainFile() override { SeenEnd = true; }
151*67e74705SXin Li 
152*67e74705SXin Li   bool SeenEnd;
153*67e74705SXin Li };
154*67e74705SXin Li 
155*67e74705SXin Li class TestPPCallbacksFrontendAction : public PreprocessorFrontendAction {
156*67e74705SXin Li   TestPPCallbacks *Callbacks;
157*67e74705SXin Li 
158*67e74705SXin Li public:
TestPPCallbacksFrontendAction(TestPPCallbacks * C)159*67e74705SXin Li   TestPPCallbacksFrontendAction(TestPPCallbacks *C)
160*67e74705SXin Li       : Callbacks(C), SeenEnd(false) {}
161*67e74705SXin Li 
ExecuteAction()162*67e74705SXin Li   void ExecuteAction() override {
163*67e74705SXin Li     Preprocessor &PP = getCompilerInstance().getPreprocessor();
164*67e74705SXin Li     PP.addPPCallbacks(std::unique_ptr<TestPPCallbacks>(Callbacks));
165*67e74705SXin Li     PP.EnterMainSourceFile();
166*67e74705SXin Li   }
EndSourceFileAction()167*67e74705SXin Li   void EndSourceFileAction() override { SeenEnd = Callbacks->SeenEnd; }
168*67e74705SXin Li 
169*67e74705SXin Li   bool SeenEnd;
170*67e74705SXin Li };
171*67e74705SXin Li 
TEST(PreprocessorFrontendAction,EndSourceFile)172*67e74705SXin Li TEST(PreprocessorFrontendAction, EndSourceFile) {
173*67e74705SXin Li   CompilerInvocation *Invocation = new CompilerInvocation;
174*67e74705SXin Li   Invocation->getPreprocessorOpts().addRemappedFile(
175*67e74705SXin Li       "test.cc",
176*67e74705SXin Li       MemoryBuffer::getMemBuffer("int main() { float x; }").release());
177*67e74705SXin Li   Invocation->getFrontendOpts().Inputs.push_back(
178*67e74705SXin Li       FrontendInputFile("test.cc", IK_CXX));
179*67e74705SXin Li   Invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly;
180*67e74705SXin Li   Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
181*67e74705SXin Li   CompilerInstance Compiler;
182*67e74705SXin Li   Compiler.setInvocation(Invocation);
183*67e74705SXin Li   Compiler.createDiagnostics();
184*67e74705SXin Li 
185*67e74705SXin Li   TestPPCallbacks *Callbacks = new TestPPCallbacks;
186*67e74705SXin Li   TestPPCallbacksFrontendAction TestAction(Callbacks);
187*67e74705SXin Li   ASSERT_FALSE(Callbacks->SeenEnd);
188*67e74705SXin Li   ASSERT_FALSE(TestAction.SeenEnd);
189*67e74705SXin Li   ASSERT_TRUE(Compiler.ExecuteAction(TestAction));
190*67e74705SXin Li   // Check that EndOfMainFile was called before EndSourceFileAction.
191*67e74705SXin Li   ASSERT_TRUE(TestAction.SeenEnd);
192*67e74705SXin Li }
193*67e74705SXin Li 
194*67e74705SXin Li } // anonymous namespace
195