1*f4a2713aSLionel Sambuc //===- unittests/AST/StmtPrinterTest.cpp --- Statement printer tests ------===// 2*f4a2713aSLionel Sambuc // 3*f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure 4*f4a2713aSLionel Sambuc // 5*f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source 6*f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details. 7*f4a2713aSLionel Sambuc // 8*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 9*f4a2713aSLionel Sambuc // 10*f4a2713aSLionel Sambuc // This file contains tests for Stmt::printPretty() and related methods. 11*f4a2713aSLionel Sambuc // 12*f4a2713aSLionel Sambuc // Search this file for WRONG to see test cases that are producing something 13*f4a2713aSLionel Sambuc // completely wrong, invalid C++ or just misleading. 14*f4a2713aSLionel Sambuc // 15*f4a2713aSLionel Sambuc // These tests have a coding convention: 16*f4a2713aSLionel Sambuc // * statements to be printed should be contained within a function named 'A' 17*f4a2713aSLionel Sambuc // unless it should have some special name (e.g., 'operator+'); 18*f4a2713aSLionel Sambuc // * additional helper declarations are 'Z', 'Y', 'X' and so on. 19*f4a2713aSLionel Sambuc // 20*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 21*f4a2713aSLionel Sambuc 22*f4a2713aSLionel Sambuc #include "clang/AST/ASTContext.h" 23*f4a2713aSLionel Sambuc #include "clang/ASTMatchers/ASTMatchFinder.h" 24*f4a2713aSLionel Sambuc #include "clang/Tooling/Tooling.h" 25*f4a2713aSLionel Sambuc #include "llvm/ADT/SmallString.h" 26*f4a2713aSLionel Sambuc #include "gtest/gtest.h" 27*f4a2713aSLionel Sambuc 28*f4a2713aSLionel Sambuc using namespace clang; 29*f4a2713aSLionel Sambuc using namespace ast_matchers; 30*f4a2713aSLionel Sambuc using namespace tooling; 31*f4a2713aSLionel Sambuc 32*f4a2713aSLionel Sambuc namespace { 33*f4a2713aSLionel Sambuc 34*f4a2713aSLionel Sambuc void PrintStmt(raw_ostream &Out, const ASTContext *Context, const Stmt *S) { 35*f4a2713aSLionel Sambuc PrintingPolicy Policy = Context->getPrintingPolicy(); 36*f4a2713aSLionel Sambuc S->printPretty(Out, /*Helper*/ 0, Policy); 37*f4a2713aSLionel Sambuc } 38*f4a2713aSLionel Sambuc 39*f4a2713aSLionel Sambuc class PrintMatch : public MatchFinder::MatchCallback { 40*f4a2713aSLionel Sambuc SmallString<1024> Printed; 41*f4a2713aSLionel Sambuc unsigned NumFoundStmts; 42*f4a2713aSLionel Sambuc 43*f4a2713aSLionel Sambuc public: 44*f4a2713aSLionel Sambuc PrintMatch() : NumFoundStmts(0) {} 45*f4a2713aSLionel Sambuc 46*f4a2713aSLionel Sambuc virtual void run(const MatchFinder::MatchResult &Result) { 47*f4a2713aSLionel Sambuc const Stmt *S = Result.Nodes.getStmtAs<Stmt>("id"); 48*f4a2713aSLionel Sambuc if (!S) 49*f4a2713aSLionel Sambuc return; 50*f4a2713aSLionel Sambuc NumFoundStmts++; 51*f4a2713aSLionel Sambuc if (NumFoundStmts > 1) 52*f4a2713aSLionel Sambuc return; 53*f4a2713aSLionel Sambuc 54*f4a2713aSLionel Sambuc llvm::raw_svector_ostream Out(Printed); 55*f4a2713aSLionel Sambuc PrintStmt(Out, Result.Context, S); 56*f4a2713aSLionel Sambuc } 57*f4a2713aSLionel Sambuc 58*f4a2713aSLionel Sambuc StringRef getPrinted() const { 59*f4a2713aSLionel Sambuc return Printed; 60*f4a2713aSLionel Sambuc } 61*f4a2713aSLionel Sambuc 62*f4a2713aSLionel Sambuc unsigned getNumFoundStmts() const { 63*f4a2713aSLionel Sambuc return NumFoundStmts; 64*f4a2713aSLionel Sambuc } 65*f4a2713aSLionel Sambuc }; 66*f4a2713aSLionel Sambuc 67*f4a2713aSLionel Sambuc ::testing::AssertionResult PrintedStmtMatches( 68*f4a2713aSLionel Sambuc StringRef Code, 69*f4a2713aSLionel Sambuc const std::vector<std::string> &Args, 70*f4a2713aSLionel Sambuc const DeclarationMatcher &NodeMatch, 71*f4a2713aSLionel Sambuc StringRef ExpectedPrinted) { 72*f4a2713aSLionel Sambuc 73*f4a2713aSLionel Sambuc PrintMatch Printer; 74*f4a2713aSLionel Sambuc MatchFinder Finder; 75*f4a2713aSLionel Sambuc Finder.addMatcher(NodeMatch, &Printer); 76*f4a2713aSLionel Sambuc OwningPtr<FrontendActionFactory> Factory(newFrontendActionFactory(&Finder)); 77*f4a2713aSLionel Sambuc 78*f4a2713aSLionel Sambuc if (!runToolOnCodeWithArgs(Factory->create(), Code, Args)) 79*f4a2713aSLionel Sambuc return testing::AssertionFailure() << "Parsing error in \"" << Code << "\""; 80*f4a2713aSLionel Sambuc 81*f4a2713aSLionel Sambuc if (Printer.getNumFoundStmts() == 0) 82*f4a2713aSLionel Sambuc return testing::AssertionFailure() 83*f4a2713aSLionel Sambuc << "Matcher didn't find any statements"; 84*f4a2713aSLionel Sambuc 85*f4a2713aSLionel Sambuc if (Printer.getNumFoundStmts() > 1) 86*f4a2713aSLionel Sambuc return testing::AssertionFailure() 87*f4a2713aSLionel Sambuc << "Matcher should match only one statement " 88*f4a2713aSLionel Sambuc "(found " << Printer.getNumFoundStmts() << ")"; 89*f4a2713aSLionel Sambuc 90*f4a2713aSLionel Sambuc if (Printer.getPrinted() != ExpectedPrinted) 91*f4a2713aSLionel Sambuc return ::testing::AssertionFailure() 92*f4a2713aSLionel Sambuc << "Expected \"" << ExpectedPrinted << "\", " 93*f4a2713aSLionel Sambuc "got \"" << Printer.getPrinted() << "\""; 94*f4a2713aSLionel Sambuc 95*f4a2713aSLionel Sambuc return ::testing::AssertionSuccess(); 96*f4a2713aSLionel Sambuc } 97*f4a2713aSLionel Sambuc 98*f4a2713aSLionel Sambuc ::testing::AssertionResult PrintedStmtCXX98Matches( 99*f4a2713aSLionel Sambuc StringRef Code, 100*f4a2713aSLionel Sambuc StringRef ContainingFunction, 101*f4a2713aSLionel Sambuc StringRef ExpectedPrinted) { 102*f4a2713aSLionel Sambuc std::vector<std::string> Args; 103*f4a2713aSLionel Sambuc Args.push_back("-std=c++98"); 104*f4a2713aSLionel Sambuc Args.push_back("-Wno-unused-value"); 105*f4a2713aSLionel Sambuc return PrintedStmtMatches(Code, 106*f4a2713aSLionel Sambuc Args, 107*f4a2713aSLionel Sambuc functionDecl(hasName(ContainingFunction), 108*f4a2713aSLionel Sambuc has(compoundStmt(has(stmt().bind("id"))))), 109*f4a2713aSLionel Sambuc ExpectedPrinted); 110*f4a2713aSLionel Sambuc } 111*f4a2713aSLionel Sambuc 112*f4a2713aSLionel Sambuc ::testing::AssertionResult PrintedStmtMSMatches( 113*f4a2713aSLionel Sambuc StringRef Code, 114*f4a2713aSLionel Sambuc StringRef ContainingFunction, 115*f4a2713aSLionel Sambuc StringRef ExpectedPrinted) { 116*f4a2713aSLionel Sambuc std::vector<std::string> Args; 117*f4a2713aSLionel Sambuc Args.push_back("-std=c++98"); 118*f4a2713aSLionel Sambuc Args.push_back("-fms-extensions"); 119*f4a2713aSLionel Sambuc Args.push_back("-Wno-unused-value"); 120*f4a2713aSLionel Sambuc return PrintedStmtMatches(Code, 121*f4a2713aSLionel Sambuc Args, 122*f4a2713aSLionel Sambuc functionDecl(hasName(ContainingFunction), 123*f4a2713aSLionel Sambuc has(compoundStmt(has(stmt().bind("id"))))), 124*f4a2713aSLionel Sambuc ExpectedPrinted); 125*f4a2713aSLionel Sambuc } 126*f4a2713aSLionel Sambuc 127*f4a2713aSLionel Sambuc } // unnamed namespace 128*f4a2713aSLionel Sambuc 129*f4a2713aSLionel Sambuc TEST(StmtPrinter, TestIntegerLiteral) { 130*f4a2713aSLionel Sambuc ASSERT_TRUE(PrintedStmtCXX98Matches( 131*f4a2713aSLionel Sambuc "void A() {" 132*f4a2713aSLionel Sambuc " 1, -1, 1U, 1u," 133*f4a2713aSLionel Sambuc " 1L, 1l, -1L, 1UL, 1ul," 134*f4a2713aSLionel Sambuc " 1LL, -1LL, 1ULL;" 135*f4a2713aSLionel Sambuc "}", 136*f4a2713aSLionel Sambuc "A", 137*f4a2713aSLionel Sambuc "1 , -1 , 1U , 1U , " 138*f4a2713aSLionel Sambuc "1L , 1L , -1L , 1UL , 1UL , " 139*f4a2713aSLionel Sambuc "1LL , -1LL , 1ULL")); 140*f4a2713aSLionel Sambuc // Should be: with semicolon 141*f4a2713aSLionel Sambuc } 142*f4a2713aSLionel Sambuc 143*f4a2713aSLionel Sambuc TEST(StmtPrinter, TestMSIntegerLiteral) { 144*f4a2713aSLionel Sambuc ASSERT_TRUE(PrintedStmtMSMatches( 145*f4a2713aSLionel Sambuc "void A() {" 146*f4a2713aSLionel Sambuc " 1i8, -1i8, 1ui8, " 147*f4a2713aSLionel Sambuc " 1i16, -1i16, 1ui16, " 148*f4a2713aSLionel Sambuc " 1i32, -1i32, 1ui32, " 149*f4a2713aSLionel Sambuc " 1i64, -1i64, 1ui64;" 150*f4a2713aSLionel Sambuc "}", 151*f4a2713aSLionel Sambuc "A", 152*f4a2713aSLionel Sambuc "1 , -1 , 1U , " 153*f4a2713aSLionel Sambuc "1 , -1 , 1U , " 154*f4a2713aSLionel Sambuc "1L , -1L , 1UL , " 155*f4a2713aSLionel Sambuc "1LL , -1LL , 1ULL")); 156*f4a2713aSLionel Sambuc // Should be: with semicolon 157*f4a2713aSLionel Sambuc } 158*f4a2713aSLionel Sambuc 159*f4a2713aSLionel Sambuc TEST(StmtPrinter, TestFloatingPointLiteral) { 160*f4a2713aSLionel Sambuc ASSERT_TRUE(PrintedStmtCXX98Matches( 161*f4a2713aSLionel Sambuc "void A() { 1.0f, -1.0f, 1.0, -1.0, 1.0l, -1.0l; }", 162*f4a2713aSLionel Sambuc "A", 163*f4a2713aSLionel Sambuc "1.F , -1.F , 1. , -1. , 1.L , -1.L")); 164*f4a2713aSLionel Sambuc // Should be: with semicolon 165*f4a2713aSLionel Sambuc } 166