Skip to content

Commit 5323cdb

Browse files
committed
Address review comments and add another test.
Inline a function instead of needing a good name for it, rewrite explanatory comments, and add a test to demonstrate lack of behavior change for common circumstances.
1 parent a755b29 commit 5323cdb

File tree

3 files changed

+45
-23
lines changed

3 files changed

+45
-23
lines changed

clang/include/clang/Analysis/FlowSensitive/ASTOps.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -155,13 +155,16 @@ struct ReferencedDecls {
155155
/// the surrounding function) that the lambda captures. Captured local
156156
/// variables are already included in `Locals` above.
157157
///
158-
/// This set also includes any referenced parameters of functions other than
159-
/// the function whose body is targeted for visitation. When calling
160-
/// `getReferencedDecls(const Stmt& S)`, there is no such targeted function,
161-
/// so any referenced function parameters are included in this set. This
162-
/// supports the collection of ReferencedDecls from a DeclStmt constructed for
163-
/// lambda init-capture VarDecls for the purpose of performing a dataflow
164-
/// analysis on the declaration/initialization.
158+
/// When analyzing a standalone `Stmt` directly, this set includes any
159+
/// referenced function parameters. This supports the collection of
160+
/// ReferencedDecls from a DeclStmt constructed for lambda init-capture
161+
/// VarDecls for the purpose of performing a dataflow analysis on the
162+
/// declaration/initialization. When analyzing any `FunctionDecl`, this set
163+
/// would also include any parameters of other functions that are referenced
164+
/// in the analyzed function's body, though there is no known case where this
165+
/// happens. If other (especially non-lambda-related) cases are found, this
166+
/// group of parameters could be moved out of `LambdaCapturedParams` into a
167+
/// separate set.
165168
llvm::SetVector<const ParmVarDecl *> LambdaCapturedParams;
166169
};
167170

clang/lib/Analysis/FlowSensitive/ASTOps.cpp

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -183,17 +183,6 @@ static void insertIfFunction(const Decl &D,
183183
Funcs.insert(FD);
184184
}
185185

186-
static void insertIfParamOfNotThePrimaryFunction(
187-
const Decl &D, llvm::SetVector<const ParmVarDecl *> &Locals,
188-
const FunctionDecl *PrimaryFunction) {
189-
if (auto *PVD = dyn_cast<ParmVarDecl>(&D)) {
190-
if (!PrimaryFunction ||
191-
PVD->getParentFunctionOrMethod() != PrimaryFunction) {
192-
Locals.insert(PVD);
193-
}
194-
}
195-
}
196-
197186
static MemberExpr *getMemberForAccessor(const CXXMemberCallExpr &C) {
198187
// Use getCalleeDecl instead of getMethodDecl in order to handle
199188
// pointer-to-member calls.
@@ -212,8 +201,8 @@ static MemberExpr *getMemberForAccessor(const CXXMemberCallExpr &C) {
212201
class ReferencedDeclsVisitor : public AnalysisASTVisitor {
213202
public:
214203
ReferencedDeclsVisitor(ReferencedDecls &Referenced,
215-
const FunctionDecl *PrimaryFunction)
216-
: Referenced(Referenced), PrimaryFunction(PrimaryFunction) {}
204+
const FunctionDecl *AnalyzedFunction)
205+
: Referenced(Referenced), AnalyzedFunction(AnalyzedFunction) {}
217206

218207
void traverseConstructorInits(const CXXConstructorDecl *Ctor) {
219208
for (const CXXCtorInitializer *Init : Ctor->inits()) {
@@ -247,8 +236,17 @@ class ReferencedDeclsVisitor : public AnalysisASTVisitor {
247236
insertIfGlobal(*E->getDecl(), Referenced.Globals);
248237
insertIfLocal(*E->getDecl(), Referenced.Locals);
249238
insertIfFunction(*E->getDecl(), Referenced.Functions);
250-
insertIfParamOfNotThePrimaryFunction(
251-
*E->getDecl(), Referenced.LambdaCapturedParams, PrimaryFunction);
239+
240+
// Collect referenced parameters of functions other than the function being
241+
// analyzed, or of any function if we are analyzing a standalone statement.
242+
// See comments on `LambdaCapturedParams` for motivations.
243+
if (auto *P = dyn_cast<ParmVarDecl>(E->getDecl())) {
244+
if (!AnalyzedFunction ||
245+
P->getParentFunctionOrMethod() != AnalyzedFunction) {
246+
Referenced.LambdaCapturedParams.insert(P);
247+
}
248+
}
249+
252250
return true;
253251
}
254252

@@ -286,7 +284,7 @@ class ReferencedDeclsVisitor : public AnalysisASTVisitor {
286284
private:
287285
ReferencedDecls &Referenced;
288286
// May be null, if we are visiting a statement that is not a function body.
289-
const FunctionDecl *const PrimaryFunction;
287+
const FunctionDecl *const AnalyzedFunction;
290288
};
291289

292290
ReferencedDecls getReferencedDecls(const FunctionDecl &FD) {

clang/unittests/Analysis/FlowSensitive/ASTOpsTest.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,4 +180,25 @@ TEST(ASTOpsTest, LambdaInitCapture) {
180180
UnorderedElementsAre(IDecl));
181181
}
182182

183+
TEST(ASTOpsTest, NoLambdaCapturedParamsWhenAnalyzingFunctionNotLambdaOperator) {
184+
std::string Code = R"cc(
185+
void func(int I) {
186+
I++; // Parameters of the function being analyzed don't get included in `LambdaCapturedParams`.
187+
auto Lambda = [&I](int L) { // We don't see the capture of `I` when analyzing `func`.
188+
L++; // We don't see the lambda body when analyzing `func`.
189+
I++; // This is a parameter of the function being analyzed, and it's not seen when analyzing `func`.
190+
};
191+
}
192+
)cc";
193+
std::unique_ptr<ASTUnit> Unit =
194+
tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++17"});
195+
auto &ASTCtx = Unit->getASTContext();
196+
197+
ASSERT_EQ(ASTCtx.getDiagnostics().getClient()->getNumErrors(), 0U);
198+
199+
auto *Func = cast<FunctionDecl>(findValueDecl(ASTCtx, "func"));
200+
ASSERT_NE(Func, nullptr);
201+
EXPECT_THAT(getReferencedDecls(*Func).LambdaCapturedParams, IsEmpty());
202+
}
203+
183204
} // namespace

0 commit comments

Comments
 (0)