12
12
#include " SourceCode.h"
13
13
#include " refactor/Tweak.h"
14
14
#include " clang/AST/ASTContext.h"
15
+ #include " clang/AST/Decl.h"
16
+ #include " clang/AST/DeclCXX.h"
15
17
#include " clang/AST/Expr.h"
16
18
#include " clang/AST/ExprCXX.h"
19
+ #include " clang/AST/LambdaCapture.h"
17
20
#include " clang/AST/OperationKinds.h"
18
21
#include " clang/AST/RecursiveASTVisitor.h"
19
22
#include " clang/AST/Stmt.h"
@@ -74,10 +77,52 @@ computeReferencedDecls(const clang::Expr *Expr) {
74
77
public:
75
78
std::vector<Decl *> ReferencedDecls;
76
79
bool VisitDeclRefExpr (DeclRefExpr *DeclRef) { // NOLINT
80
+ // Stop the call operator of lambdas from being marked as a referenced
81
+ // DeclRefExpr in immediately invoked lambdas.
82
+ if (const auto *const Method =
83
+ llvm::dyn_cast<CXXMethodDecl>(DeclRef->getDecl ());
84
+ Method != nullptr && Method->getParent ()->isLambda ()) {
85
+ return true ;
86
+ }
77
87
ReferencedDecls.push_back (DeclRef->getDecl ());
78
88
return true ;
79
89
}
90
+
91
+ // Local variables declared inside of the selected lambda cannot go out of
92
+ // scope. The DeclRefExprs that are important are the variables captured,
93
+ // the DeclRefExprs inside the initializers of init-capture variables,
94
+ // variables mentioned in trailing return types, constraints and explicit
95
+ // defaulted template parameters.
96
+ bool TraverseLambdaExpr (LambdaExpr *LExpr) {
97
+ for (const auto &[Capture, Initializer] :
98
+ llvm::zip (LExpr->captures (), LExpr->capture_inits ())) {
99
+ TraverseLambdaCapture (LExpr, &Capture, Initializer);
100
+ }
101
+
102
+ if (clang::Expr *const RequiresClause =
103
+ LExpr->getTrailingRequiresClause ()) {
104
+ TraverseStmt (RequiresClause);
105
+ }
106
+
107
+ for (auto *const TemplateParam : LExpr->getExplicitTemplateParameters ())
108
+ TraverseDecl (TemplateParam);
109
+
110
+ if (auto *const CallOperator = LExpr->getCallOperator ()) {
111
+ TraverseType (CallOperator->getDeclaredReturnType ());
112
+
113
+ for (auto *const Param : CallOperator->parameters ()) {
114
+ TraverseParmVarDecl (Param);
115
+ }
116
+
117
+ for (auto *const Attr : CallOperator->attrs ()) {
118
+ TraverseAttr (Attr);
119
+ }
120
+ }
121
+
122
+ return true ;
123
+ }
80
124
};
125
+
81
126
FindDeclRefsVisitor Visitor;
82
127
Visitor.TraverseStmt (const_cast <Stmt *>(cast<Stmt>(Expr)));
83
128
return Visitor.ReferencedDecls ;
@@ -152,10 +197,16 @@ const clang::Stmt *ExtractionContext::computeInsertionPoint() const {
152
197
auto CanExtractOutside =
153
198
[](const SelectionTree::Node *InsertionPoint) -> bool {
154
199
if (const clang::Stmt *Stmt = InsertionPoint->ASTNode .get <clang::Stmt>()) {
155
- // Allow all expressions except LambdaExpr since we don't want to extract
156
- // from the captures/default arguments of a lambda
157
- if (isa<clang::Expr>(Stmt))
158
- return !isa<LambdaExpr>(Stmt);
200
+ if (isa<clang::Expr>(Stmt)) {
201
+ // Do not allow extraction from the initializer of a defaulted parameter
202
+ // to a local variable (e.g. a function-local lambda).
203
+ if (InsertionPoint->Parent ->ASTNode .get <ParmVarDecl>() != nullptr ) {
204
+ return false ;
205
+ }
206
+
207
+ return true ;
208
+ }
209
+
159
210
// We don't yet allow extraction from switch/case stmt as we would need to
160
211
// jump over the switch stmt even if there is a CompoundStmt inside the
161
212
// switch. And there are other Stmts which we don't care about (e.g.
@@ -240,7 +291,7 @@ struct ParsedBinaryOperator {
240
291
SelectedOperands.clear ();
241
292
242
293
if (const BinaryOperator *Op =
243
- llvm::dyn_cast_or_null<BinaryOperator>(N.ASTNode .get <Expr>())) {
294
+ llvm::dyn_cast_or_null<BinaryOperator>(N.ASTNode .get <Expr>())) {
244
295
Kind = Op->getOpcode ();
245
296
ExprLoc = Op->getExprLoc ();
246
297
SelectedOperands = N.Children ;
@@ -255,7 +306,7 @@ struct ParsedBinaryOperator {
255
306
Kind = BinaryOperator::getOverloadedOpcode (Op->getOperator ());
256
307
ExprLoc = Op->getExprLoc ();
257
308
// Not all children are args, there's also the callee (operator).
258
- for (const auto * Child : N.Children ) {
309
+ for (const auto * Child : N.Children ) {
259
310
const Expr *E = Child->ASTNode .get <Expr>();
260
311
assert (E && " callee and args should be Exprs!" );
261
312
if (E == Op->getArg (0 ) || E == Op->getArg (1 ))
@@ -376,15 +427,15 @@ bool childExprIsStmt(const Stmt *Outer, const Expr *Inner) {
376
427
if (llvm::isa<SwitchCase>(Outer))
377
428
return true ;
378
429
// Control flow statements use condition etc, but not the body.
379
- if (const auto * WS = llvm::dyn_cast<WhileStmt>(Outer))
430
+ if (const auto * WS = llvm::dyn_cast<WhileStmt>(Outer))
380
431
return Inner == WS->getBody ();
381
- if (const auto * DS = llvm::dyn_cast<DoStmt>(Outer))
432
+ if (const auto * DS = llvm::dyn_cast<DoStmt>(Outer))
382
433
return Inner == DS->getBody ();
383
- if (const auto * FS = llvm::dyn_cast<ForStmt>(Outer))
434
+ if (const auto * FS = llvm::dyn_cast<ForStmt>(Outer))
384
435
return Inner == FS->getBody ();
385
- if (const auto * FS = llvm::dyn_cast<CXXForRangeStmt>(Outer))
436
+ if (const auto * FS = llvm::dyn_cast<CXXForRangeStmt>(Outer))
386
437
return Inner == FS->getBody ();
387
- if (const auto * IS = llvm::dyn_cast<IfStmt>(Outer))
438
+ if (const auto * IS = llvm::dyn_cast<IfStmt>(Outer))
388
439
return Inner == IS->getThen () || Inner == IS->getElse ();
389
440
// Assume all other cases may be actual expressions.
390
441
// This includes the important case of subexpressions (where Outer is Expr).
0 commit comments