173
|
1 //===- GtestMatchers.cpp - AST Matchers for Gtest ---------------*- C++ -*-===//
|
|
2 //
|
|
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
4 // See https://llvm.org/LICENSE.txt for license information.
|
|
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
6 //
|
|
7 //===----------------------------------------------------------------------===//
|
|
8
|
|
9 #include "clang/ASTMatchers/GtestMatchers.h"
|
|
10 #include "clang/ASTMatchers/ASTMatchFinder.h"
|
|
11 #include "clang/AST/ASTConsumer.h"
|
|
12 #include "clang/AST/ASTContext.h"
|
|
13 #include "clang/AST/RecursiveASTVisitor.h"
|
|
14 #include "llvm/ADT/DenseMap.h"
|
|
15 #include "llvm/ADT/StringMap.h"
|
|
16 #include "llvm/Support/Timer.h"
|
|
17 #include <deque>
|
|
18 #include <memory>
|
|
19 #include <set>
|
|
20
|
|
21 namespace clang {
|
|
22 namespace ast_matchers {
|
|
23
|
|
24 static DeclarationMatcher getComparisonDecl(GtestCmp Cmp) {
|
|
25 switch (Cmp) {
|
|
26 case GtestCmp::Eq:
|
|
27 return cxxMethodDecl(hasName("Compare"),
|
|
28 ofClass(cxxRecordDecl(isSameOrDerivedFrom(
|
|
29 hasName("::testing::internal::EqHelper")))));
|
|
30 case GtestCmp::Ne:
|
|
31 return functionDecl(hasName("::testing::internal::CmpHelperNE"));
|
|
32 case GtestCmp::Ge:
|
|
33 return functionDecl(hasName("::testing::internal::CmpHelperGE"));
|
|
34 case GtestCmp::Gt:
|
|
35 return functionDecl(hasName("::testing::internal::CmpHelperGT"));
|
|
36 case GtestCmp::Le:
|
|
37 return functionDecl(hasName("::testing::internal::CmpHelperLE"));
|
|
38 case GtestCmp::Lt:
|
|
39 return functionDecl(hasName("::testing::internal::CmpHelperLT"));
|
|
40 }
|
|
41 llvm_unreachable("Unhandled GtestCmp enum");
|
|
42 }
|
|
43
|
|
44 static llvm::StringRef getAssertMacro(GtestCmp Cmp) {
|
|
45 switch (Cmp) {
|
|
46 case GtestCmp::Eq:
|
|
47 return "ASSERT_EQ";
|
|
48 case GtestCmp::Ne:
|
|
49 return "ASSERT_NE";
|
|
50 case GtestCmp::Ge:
|
|
51 return "ASSERT_GE";
|
|
52 case GtestCmp::Gt:
|
|
53 return "ASSERT_GT";
|
|
54 case GtestCmp::Le:
|
|
55 return "ASSERT_LE";
|
|
56 case GtestCmp::Lt:
|
|
57 return "ASSERT_LT";
|
|
58 }
|
|
59 llvm_unreachable("Unhandled GtestCmp enum");
|
|
60 }
|
|
61
|
|
62 static llvm::StringRef getExpectMacro(GtestCmp Cmp) {
|
|
63 switch (Cmp) {
|
|
64 case GtestCmp::Eq:
|
|
65 return "EXPECT_EQ";
|
|
66 case GtestCmp::Ne:
|
|
67 return "EXPECT_NE";
|
|
68 case GtestCmp::Ge:
|
|
69 return "EXPECT_GE";
|
|
70 case GtestCmp::Gt:
|
|
71 return "EXPECT_GT";
|
|
72 case GtestCmp::Le:
|
|
73 return "EXPECT_LE";
|
|
74 case GtestCmp::Lt:
|
|
75 return "EXPECT_LT";
|
|
76 }
|
|
77 llvm_unreachable("Unhandled GtestCmp enum");
|
|
78 }
|
|
79
|
|
80 // In general, AST matchers cannot match calls to macros. However, we can
|
|
81 // simulate such matches if the macro definition has identifiable elements that
|
|
82 // themselves can be matched. In that case, we can match on those elements and
|
|
83 // then check that the match occurs within an expansion of the desired
|
|
84 // macro. The more uncommon the identified elements, the more efficient this
|
|
85 // process will be.
|
|
86 //
|
|
87 // We use this approach to implement the derived matchers gtestAssert and
|
|
88 // gtestExpect.
|
|
89 internal::BindableMatcher<Stmt> gtestAssert(GtestCmp Cmp, StatementMatcher Left,
|
|
90 StatementMatcher Right) {
|
|
91 return callExpr(callee(getComparisonDecl(Cmp)),
|
|
92 isExpandedFromMacro(getAssertMacro(Cmp)),
|
|
93 hasArgument(2, Left), hasArgument(3, Right));
|
|
94 }
|
|
95
|
|
96 internal::BindableMatcher<Stmt> gtestExpect(GtestCmp Cmp, StatementMatcher Left,
|
|
97 StatementMatcher Right) {
|
|
98 return callExpr(callee(getComparisonDecl(Cmp)),
|
|
99 isExpandedFromMacro(getExpectMacro(Cmp)),
|
|
100 hasArgument(2, Left), hasArgument(3, Right));
|
|
101 }
|
|
102
|
|
103 } // end namespace ast_matchers
|
|
104 } // end namespace clang
|