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