1 //===- unittests/AST/StmtPrinterTest.cpp --- Statement printer 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 // This file contains tests for Stmt::printPretty() and related methods. 11 // 12 // Search this file for WRONG to see test cases that are producing something 13 // completely wrong, invalid C++ or just misleading. 14 // 15 // These tests have a coding convention: 16 // * statements to be printed should be contained within a function named 'A' 17 // unless it should have some special name (e.g., 'operator+'); 18 // * additional helper declarations are 'Z', 'Y', 'X' and so on. 19 // 20 //===----------------------------------------------------------------------===// 21 22 #include "clang/AST/ASTContext.h" 23 #include "clang/ASTMatchers/ASTMatchFinder.h" 24 #include "clang/Tooling/Tooling.h" 25 #include "llvm/ADT/SmallString.h" 26 #include "gtest/gtest.h" 27 28 using namespace clang; 29 using namespace ast_matchers; 30 using namespace tooling; 31 32 namespace { 33 34 using PolicyAdjusterType = 35 Optional<llvm::function_ref<void(PrintingPolicy &Policy)>>; 36 37 void PrintStmt(raw_ostream &Out, const ASTContext *Context, const Stmt *S, 38 PolicyAdjusterType PolicyAdjuster) { 39 assert(S != nullptr && "Expected non-null Stmt"); 40 PrintingPolicy Policy = Context->getPrintingPolicy(); 41 if (PolicyAdjuster) 42 (*PolicyAdjuster)(Policy); 43 S->printPretty(Out, /*Helper*/ nullptr, Policy); 44 } 45 46 class PrintMatch : public MatchFinder::MatchCallback { 47 SmallString<1024> Printed; 48 unsigned NumFoundStmts; 49 PolicyAdjusterType PolicyAdjuster; 50 51 public: 52 PrintMatch(PolicyAdjusterType PolicyAdjuster) 53 : NumFoundStmts(0), PolicyAdjuster(PolicyAdjuster) {} 54 55 void run(const MatchFinder::MatchResult &Result) override { 56 const Stmt *S = Result.Nodes.getNodeAs<Stmt>("id"); 57 if (!S) 58 return; 59 NumFoundStmts++; 60 if (NumFoundStmts > 1) 61 return; 62 63 llvm::raw_svector_ostream Out(Printed); 64 PrintStmt(Out, Result.Context, S, PolicyAdjuster); 65 } 66 67 StringRef getPrinted() const { 68 return Printed; 69 } 70 71 unsigned getNumFoundStmts() const { 72 return NumFoundStmts; 73 } 74 }; 75 76 template <typename T> 77 ::testing::AssertionResult 78 PrintedStmtMatches(StringRef Code, const std::vector<std::string> &Args, 79 const T &NodeMatch, StringRef ExpectedPrinted, 80 PolicyAdjusterType PolicyAdjuster = None) { 81 82 PrintMatch Printer(PolicyAdjuster); 83 MatchFinder Finder; 84 Finder.addMatcher(NodeMatch, &Printer); 85 std::unique_ptr<FrontendActionFactory> Factory( 86 newFrontendActionFactory(&Finder)); 87 88 if (!runToolOnCodeWithArgs(Factory->create(), Code, Args)) 89 return testing::AssertionFailure() 90 << "Parsing error in \"" << Code.str() << "\""; 91 92 if (Printer.getNumFoundStmts() == 0) 93 return testing::AssertionFailure() 94 << "Matcher didn't find any statements"; 95 96 if (Printer.getNumFoundStmts() > 1) 97 return testing::AssertionFailure() 98 << "Matcher should match only one statement " 99 "(found " << Printer.getNumFoundStmts() << ")"; 100 101 if (Printer.getPrinted() != ExpectedPrinted) 102 return ::testing::AssertionFailure() 103 << "Expected \"" << ExpectedPrinted.str() << "\", " 104 "got \"" << Printer.getPrinted().str() << "\""; 105 106 return ::testing::AssertionSuccess(); 107 } 108 109 enum class StdVer { CXX98, CXX11, CXX14, CXX17, CXX2a }; 110 111 DeclarationMatcher FunctionBodyMatcher(StringRef ContainingFunction) { 112 return functionDecl(hasName(ContainingFunction), 113 has(compoundStmt(has(stmt().bind("id"))))); 114 } 115 116 template <typename T> 117 ::testing::AssertionResult 118 PrintedStmtCXXMatches(StdVer Standard, StringRef Code, const T &NodeMatch, 119 StringRef ExpectedPrinted, 120 PolicyAdjusterType PolicyAdjuster = None) { 121 const char *StdOpt; 122 switch (Standard) { 123 case StdVer::CXX98: StdOpt = "-std=c++98"; break; 124 case StdVer::CXX11: StdOpt = "-std=c++11"; break; 125 case StdVer::CXX14: StdOpt = "-std=c++14"; break; 126 case StdVer::CXX17: StdOpt = "-std=c++17"; break; 127 case StdVer::CXX2a: StdOpt = "-std=c++2a"; break; 128 } 129 130 std::vector<std::string> Args = { 131 StdOpt, 132 "-Wno-unused-value", 133 }; 134 return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted, 135 PolicyAdjuster); 136 } 137 138 template <typename T> 139 ::testing::AssertionResult 140 PrintedStmtMSMatches(StringRef Code, const T &NodeMatch, 141 StringRef ExpectedPrinted, 142 PolicyAdjusterType PolicyAdjuster = None) { 143 std::vector<std::string> Args = { 144 "-std=c++98", 145 "-target", "i686-pc-win32", 146 "-fms-extensions", 147 "-Wno-unused-value", 148 }; 149 return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted, 150 PolicyAdjuster); 151 } 152 153 template <typename T> 154 ::testing::AssertionResult 155 PrintedStmtObjCMatches(StringRef Code, const T &NodeMatch, 156 StringRef ExpectedPrinted, 157 PolicyAdjusterType PolicyAdjuster = None) { 158 std::vector<std::string> Args = { 159 "-ObjC", 160 "-fobjc-runtime=macosx-10.12.0", 161 }; 162 return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted, 163 PolicyAdjuster); 164 } 165 166 } // unnamed namespace 167 168 TEST(StmtPrinter, TestIntegerLiteral) { 169 ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX98, 170 "void A() {" 171 " 1, -1, 1U, 1u," 172 " 1L, 1l, -1L, 1UL, 1ul," 173 " 1LL, -1LL, 1ULL;" 174 "}", 175 FunctionBodyMatcher("A"), 176 "1 , -1 , 1U , 1U , " 177 "1L , 1L , -1L , 1UL , 1UL , " 178 "1LL , -1LL , 1ULL")); 179 // Should be: with semicolon 180 } 181 182 TEST(StmtPrinter, TestMSIntegerLiteral) { 183 ASSERT_TRUE(PrintedStmtMSMatches( 184 "void A() {" 185 " 1i8, -1i8, 1ui8, " 186 " 1i16, -1i16, 1ui16, " 187 " 1i32, -1i32, 1ui32, " 188 " 1i64, -1i64, 1ui64;" 189 "}", 190 FunctionBodyMatcher("A"), 191 "1i8 , -1i8 , 1Ui8 , " 192 "1i16 , -1i16 , 1Ui16 , " 193 "1 , -1 , 1U , " 194 "1LL , -1LL , 1ULL")); 195 // Should be: with semicolon 196 } 197 198 TEST(StmtPrinter, TestFloatingPointLiteral) { 199 ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX98, 200 "void A() { 1.0f, -1.0f, 1.0, -1.0, 1.0l, -1.0l; }", 201 FunctionBodyMatcher("A"), 202 "1.F , -1.F , 1. , -1. , 1.L , -1.L")); 203 // Should be: with semicolon 204 } 205 206 TEST(StmtPrinter, TestCXXConversionDeclImplicit) { 207 ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX98, 208 "struct A {" 209 "operator void *();" 210 "A operator&(A);" 211 "};" 212 "void bar(void *);" 213 "void foo(A a, A b) {" 214 " bar(a & b);" 215 "}", 216 cxxMemberCallExpr(anything()).bind("id"), 217 "a & b")); 218 } 219 220 TEST(StmtPrinter, TestCXXConversionDeclExplicit) { 221 ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX11, 222 "struct A {" 223 "operator void *();" 224 "A operator&(A);" 225 "};" 226 "void bar(void *);" 227 "void foo(A a, A b) {" 228 " auto x = (a & b).operator void *();" 229 "}", 230 cxxMemberCallExpr(anything()).bind("id"), 231 "(a & b)")); 232 // WRONG; Should be: (a & b).operator void *() 233 } 234 235 TEST(StmtPrinter, TestNoImplicitBases) { 236 const char *CPPSource = R"( 237 class A { 238 int field; 239 int member() { return field; } 240 }; 241 )"; 242 // No implicit 'this'. 243 ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX11, 244 CPPSource, memberExpr(anything()).bind("id"), "field", 245 PolicyAdjusterType( 246 [](PrintingPolicy &PP) { PP.SuppressImplicitBase = true; }))); 247 // Print implicit 'this'. 248 ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX11, 249 CPPSource, memberExpr(anything()).bind("id"), "this->field")); 250 251 const char *ObjCSource = R"( 252 @interface I { 253 int ivar; 254 } 255 @end 256 @implementation I 257 - (int) method { 258 return ivar; 259 } 260 @end 261 )"; 262 // No implicit 'self'. 263 ASSERT_TRUE(PrintedStmtObjCMatches(ObjCSource, returnStmt().bind("id"), 264 "return ivar;\n", 265 PolicyAdjusterType([](PrintingPolicy &PP) { 266 PP.SuppressImplicitBase = true; 267 }))); 268 // Print implicit 'self'. 269 ASSERT_TRUE(PrintedStmtObjCMatches(ObjCSource, returnStmt().bind("id"), 270 "return self->ivar;\n")); 271 } 272