1 //===- unittests/Frontend/FrontendActionTest.cpp - FrontendAction tests ---===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "clang/Frontend/FrontendAction.h" 11 #include "clang/AST/ASTConsumer.h" 12 #include "clang/AST/ASTContext.h" 13 #include "clang/AST/RecursiveASTVisitor.h" 14 #include "clang/Frontend/CompilerInstance.h" 15 #include "clang/Frontend/CompilerInvocation.h" 16 #include "clang/Lex/Preprocessor.h" 17 #include "llvm/ADT/Triple.h" 18 #include "llvm/Support/MemoryBuffer.h" 19 #include "gtest/gtest.h" 20 21 using namespace llvm; 22 using namespace clang; 23 24 namespace { 25 26 class TestASTFrontendAction : public ASTFrontendAction { 27 public: 28 TestASTFrontendAction(bool enableIncrementalProcessing = false) 29 : EnableIncrementalProcessing(enableIncrementalProcessing) { } 30 31 bool EnableIncrementalProcessing; 32 std::vector<std::string> decl_names; 33 34 virtual bool BeginSourceFileAction(CompilerInstance &ci, StringRef filename) { 35 if (EnableIncrementalProcessing) 36 ci.getPreprocessor().enableIncrementalProcessing(); 37 38 return ASTFrontendAction::BeginSourceFileAction(ci, filename); 39 } 40 41 virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, 42 StringRef InFile) { 43 return new Visitor(decl_names); 44 } 45 46 private: 47 class Visitor : public ASTConsumer, public RecursiveASTVisitor<Visitor> { 48 public: 49 Visitor(std::vector<std::string> &decl_names) : decl_names_(decl_names) {} 50 51 virtual void HandleTranslationUnit(ASTContext &context) { 52 TraverseDecl(context.getTranslationUnitDecl()); 53 } 54 55 virtual bool VisitNamedDecl(NamedDecl *Decl) { 56 decl_names_.push_back(Decl->getQualifiedNameAsString()); 57 return true; 58 } 59 60 private: 61 std::vector<std::string> &decl_names_; 62 }; 63 }; 64 65 TEST(ASTFrontendAction, Sanity) { 66 CompilerInvocation *invocation = new CompilerInvocation; 67 invocation->getPreprocessorOpts().addRemappedFile( 68 "test.cc", MemoryBuffer::getMemBuffer("int main() { float x; }")); 69 invocation->getFrontendOpts().Inputs.push_back(FrontendInputFile("test.cc", 70 IK_CXX)); 71 invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly; 72 invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; 73 CompilerInstance compiler; 74 compiler.setInvocation(invocation); 75 compiler.createDiagnostics(); 76 77 TestASTFrontendAction test_action; 78 ASSERT_TRUE(compiler.ExecuteAction(test_action)); 79 ASSERT_EQ(2U, test_action.decl_names.size()); 80 EXPECT_EQ("main", test_action.decl_names[0]); 81 EXPECT_EQ("x", test_action.decl_names[1]); 82 } 83 84 TEST(ASTFrontendAction, IncrementalParsing) { 85 CompilerInvocation *invocation = new CompilerInvocation; 86 invocation->getPreprocessorOpts().addRemappedFile( 87 "test.cc", MemoryBuffer::getMemBuffer("int main() { float x; }")); 88 invocation->getFrontendOpts().Inputs.push_back(FrontendInputFile("test.cc", 89 IK_CXX)); 90 invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly; 91 invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; 92 CompilerInstance compiler; 93 compiler.setInvocation(invocation); 94 compiler.createDiagnostics(); 95 96 TestASTFrontendAction test_action(/*enableIncrementalProcessing=*/true); 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]); 101 } 102 103 } // anonymous namespace 104