@@ -53,16 +53,72 @@ AST_MATCHER(ParmVarDecl, isTemplateTypeParameter) {
53
53
FuncTemplate->getTemplateParameters ()->getDepth ();
54
54
}
55
55
56
+ AST_MATCHER_P (NamedDecl, hasSameNameAsBoundNode, std::string, BindingID) {
57
+ IdentifierInfo *II = Node.getIdentifier ();
58
+ if (nullptr == II)
59
+ return false ;
60
+ StringRef Name = II->getName ();
61
+
62
+ return Builder->removeBindings (
63
+ [this , Name](const ast_matchers::internal::BoundNodesMap &Nodes) {
64
+ const DynTypedNode &BN = Nodes.getNode (this ->BindingID );
65
+ if (const auto *ND = BN.get <NamedDecl>()) {
66
+ if (!isa<FieldDecl, CXXMethodDecl, VarDecl>(ND))
67
+ return true ;
68
+ return ND->getName () != Name;
69
+ }
70
+ return true ;
71
+ });
72
+ }
73
+
74
+ AST_MATCHER_P (LambdaCapture, hasCaptureKind, LambdaCaptureKind, Kind) {
75
+ return Node.getCaptureKind () == Kind;
76
+ }
77
+
78
+ AST_MATCHER_P (LambdaExpr, hasCaptureDefaultKind, LambdaCaptureDefault, Kind) {
79
+ return Node.getCaptureDefault () == Kind;
80
+ }
81
+
56
82
} // namespace
57
83
58
84
void MissingStdForwardCheck::registerMatchers (MatchFinder *Finder) {
85
+ auto RefToParmImplicit = allOf (
86
+ equalsBoundNode (" var" ), hasInitializer (ignoringParenImpCasts (
87
+ declRefExpr (to (equalsBoundNode (" param" ))))));
88
+ auto RefToParm = capturesVar (
89
+ varDecl (anyOf (hasSameNameAsBoundNode (" param" ), RefToParmImplicit)));
90
+ auto HasRefToParm = hasAnyCapture (RefToParm);
91
+
92
+ auto CaptureInRef =
93
+ allOf (hasCaptureDefaultKind (LambdaCaptureDefault::LCD_ByRef),
94
+ unless (hasAnyCapture (
95
+ capturesVar (varDecl (hasSameNameAsBoundNode (" param" ))))));
96
+ auto CaptureInCopy = allOf (
97
+ hasCaptureDefaultKind (LambdaCaptureDefault::LCD_ByCopy), HasRefToParm);
98
+ auto CaptureByRefExplicit = hasAnyCapture (
99
+ allOf (hasCaptureKind (LambdaCaptureKind::LCK_ByRef), RefToParm));
100
+
101
+ auto CapturedInBody =
102
+ lambdaExpr (anyOf (CaptureInRef, CaptureInCopy, CaptureByRefExplicit));
103
+ auto CapturedInCaptureList = hasAnyCapture (capturesVar (
104
+ varDecl (hasInitializer (ignoringParenImpCasts (equalsBoundNode (" call" ))))));
105
+
106
+ auto CapturedInLambda = hasDeclContext (cxxRecordDecl (
107
+ isLambda (),
108
+ hasParent (lambdaExpr (forCallable (equalsBoundNode (" func" )),
109
+ anyOf (CapturedInCaptureList, CapturedInBody)))));
110
+
59
111
auto ToParam = hasAnyParameter (parmVarDecl (equalsBoundNode (" param" )));
60
112
61
113
auto ForwardCallMatcher = callExpr (
62
- forCallable (equalsBoundNode (" func" )), argumentCountIs (1 ),
114
+ callExpr ().bind (" call" ), argumentCountIs (1 ),
115
+ hasArgument (
116
+ 0 , declRefExpr (to (
117
+ varDecl (optionally (equalsBoundNode (" param" ))).bind (" var" )))),
118
+ forCallable (anyOf (equalsBoundNode (" func" ), CapturedInLambda)),
63
119
callee (unresolvedLookupExpr (hasAnyDeclaration (
64
120
namedDecl (hasUnderlyingDecl (hasName (" ::std::forward" )))))),
65
- hasArgument ( 0 , declRefExpr ( to ( equalsBoundNode ( " param " ))). bind ( " ref " )),
121
+
66
122
unless (anyOf (hasAncestor (typeLoc ()),
67
123
hasAncestor (expr (hasUnevaluatedContext ())))));
68
124
0 commit comments