StmtPrinterTest.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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. #include "clang/AST/ASTContext.h"
  22. #include "clang/ASTMatchers/ASTMatchFinder.h"
  23. #include "clang/Tooling/Tooling.h"
  24. #include "llvm/ADT/SmallString.h"
  25. #include "gtest/gtest.h"
  26. using namespace clang;
  27. using namespace ast_matchers;
  28. using namespace tooling;
  29. namespace {
  30. void PrintStmt(raw_ostream &Out, const ASTContext *Context, const Stmt *S) {
  31. assert(S != nullptr && "Expected non-null Stmt");
  32. PrintingPolicy Policy = Context->getPrintingPolicy();
  33. S->printPretty(Out, /*Helper*/ nullptr, Policy);
  34. }
  35. class PrintMatch : public MatchFinder::MatchCallback {
  36. SmallString<1024> Printed;
  37. unsigned NumFoundStmts;
  38. public:
  39. PrintMatch() : NumFoundStmts(0) {}
  40. void run(const MatchFinder::MatchResult &Result) override {
  41. const Stmt *S = Result.Nodes.getNodeAs<Stmt>("id");
  42. if (!S)
  43. return;
  44. NumFoundStmts++;
  45. if (NumFoundStmts > 1)
  46. return;
  47. llvm::raw_svector_ostream Out(Printed);
  48. PrintStmt(Out, Result.Context, S);
  49. }
  50. StringRef getPrinted() const {
  51. return Printed;
  52. }
  53. unsigned getNumFoundStmts() const {
  54. return NumFoundStmts;
  55. }
  56. };
  57. template <typename T>
  58. ::testing::AssertionResult
  59. PrintedStmtMatches(StringRef Code, const std::vector<std::string> &Args,
  60. const T &NodeMatch, StringRef ExpectedPrinted) {
  61. PrintMatch Printer;
  62. MatchFinder Finder;
  63. Finder.addMatcher(NodeMatch, &Printer);
  64. std::unique_ptr<FrontendActionFactory> Factory(
  65. newFrontendActionFactory(&Finder));
  66. if (!runToolOnCodeWithArgs(Factory->create(), Code, Args))
  67. return testing::AssertionFailure()
  68. << "Parsing error in \"" << Code.str() << "\"";
  69. if (Printer.getNumFoundStmts() == 0)
  70. return testing::AssertionFailure()
  71. << "Matcher didn't find any statements";
  72. if (Printer.getNumFoundStmts() > 1)
  73. return testing::AssertionFailure()
  74. << "Matcher should match only one statement "
  75. "(found " << Printer.getNumFoundStmts() << ")";
  76. if (Printer.getPrinted() != ExpectedPrinted)
  77. return ::testing::AssertionFailure()
  78. << "Expected \"" << ExpectedPrinted.str() << "\", "
  79. "got \"" << Printer.getPrinted().str() << "\"";
  80. return ::testing::AssertionSuccess();
  81. }
  82. ::testing::AssertionResult
  83. PrintedStmtCXX98Matches(StringRef Code, const StatementMatcher &NodeMatch,
  84. StringRef ExpectedPrinted) {
  85. std::vector<std::string> Args;
  86. Args.push_back("-std=c++98");
  87. Args.push_back("-Wno-unused-value");
  88. return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted);
  89. }
  90. ::testing::AssertionResult PrintedStmtCXX98Matches(
  91. StringRef Code,
  92. StringRef ContainingFunction,
  93. StringRef ExpectedPrinted) {
  94. std::vector<std::string> Args;
  95. Args.push_back("-std=c++98");
  96. Args.push_back("-Wno-unused-value");
  97. return PrintedStmtMatches(Code,
  98. Args,
  99. functionDecl(hasName(ContainingFunction),
  100. has(compoundStmt(has(stmt().bind("id"))))),
  101. ExpectedPrinted);
  102. }
  103. ::testing::AssertionResult
  104. PrintedStmtCXX11Matches(StringRef Code, const StatementMatcher &NodeMatch,
  105. StringRef ExpectedPrinted) {
  106. std::vector<std::string> Args;
  107. Args.push_back("-std=c++11");
  108. Args.push_back("-Wno-unused-value");
  109. return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted);
  110. }
  111. ::testing::AssertionResult PrintedStmtMSMatches(
  112. StringRef Code,
  113. StringRef ContainingFunction,
  114. StringRef ExpectedPrinted) {
  115. std::vector<std::string> Args;
  116. Args.push_back("-target");
  117. Args.push_back("i686-pc-win32");
  118. Args.push_back("-std=c++98");
  119. Args.push_back("-fms-extensions");
  120. Args.push_back("-Wno-unused-value");
  121. return PrintedStmtMatches(Code,
  122. Args,
  123. functionDecl(hasName(ContainingFunction),
  124. has(compoundStmt(has(stmt().bind("id"))))),
  125. ExpectedPrinted);
  126. }
  127. } // unnamed namespace
  128. TEST(StmtPrinter, TestIntegerLiteral) {
  129. ASSERT_TRUE(PrintedStmtCXX98Matches(
  130. "void A() {"
  131. " 1, -1, 1U, 1u,"
  132. " 1L, 1l, -1L, 1UL, 1ul,"
  133. " 1LL, -1LL, 1ULL;"
  134. "}",
  135. "A",
  136. "1 , -1 , 1U , 1U , "
  137. "1L , 1L , -1L , 1UL , 1UL , "
  138. "1LL , -1LL , 1ULL"));
  139. // Should be: with semicolon
  140. }
  141. TEST(StmtPrinter, TestMSIntegerLiteral) {
  142. ASSERT_TRUE(PrintedStmtMSMatches(
  143. "void A() {"
  144. " 1i8, -1i8, 1ui8, "
  145. " 1i16, -1i16, 1ui16, "
  146. " 1i32, -1i32, 1ui32, "
  147. " 1i64, -1i64, 1ui64;"
  148. "}",
  149. "A",
  150. "1i8 , -1i8 , 1Ui8 , "
  151. "1i16 , -1i16 , 1Ui16 , "
  152. "1 , -1 , 1U , "
  153. "1LL , -1LL , 1ULL"));
  154. // Should be: with semicolon
  155. }
  156. TEST(StmtPrinter, TestFloatingPointLiteral) {
  157. ASSERT_TRUE(PrintedStmtCXX98Matches(
  158. "void A() { 1.0f, -1.0f, 1.0, -1.0, 1.0l, -1.0l; }",
  159. "A",
  160. "1.F , -1.F , 1. , -1. , 1.L , -1.L"));
  161. // Should be: with semicolon
  162. }
  163. TEST(StmtPrinter, TestCXXConversionDeclImplicit) {
  164. ASSERT_TRUE(PrintedStmtCXX98Matches(
  165. "struct A {"
  166. "operator void *();"
  167. "A operator&(A);"
  168. "};"
  169. "void bar(void *);"
  170. "void foo(A a, A b) {"
  171. " bar(a & b);"
  172. "}",
  173. cxxMemberCallExpr(anything()).bind("id"),
  174. "a & b"));
  175. }
  176. TEST(StmtPrinter, TestCXXConversionDeclExplicit) {
  177. ASSERT_TRUE(PrintedStmtCXX11Matches(
  178. "struct A {"
  179. "operator void *();"
  180. "A operator&(A);"
  181. "};"
  182. "void bar(void *);"
  183. "void foo(A a, A b) {"
  184. " auto x = (a & b).operator void *();"
  185. "}",
  186. cxxMemberCallExpr(anything()).bind("id"),
  187. "(a & b)"));
  188. // WRONG; Should be: (a & b).operator void *()
  189. }