Skip to content

Commit 9b0651f

Browse files
authored
[clang][dataflow] Don't propagate result objects in nested declarations. (#89903)
Trying to do so can cause crashes -- see newly added test and the comments in the fix.
1 parent 8bfdbb9 commit 9b0651f

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,18 @@ class ResultObjectVisitor : public RecursiveASTVisitor<ResultObjectVisitor> {
333333
}
334334
}
335335

336+
bool TraverseDecl(Decl *D) {
337+
// Don't traverse nested record or function declarations.
338+
// - We won't be analyzing code contained in these anyway
339+
// - We don't model fields that are used only in these nested declaration,
340+
// so trying to propagate a result object to initializers of such fields
341+
// would cause an error.
342+
if (isa_and_nonnull<RecordDecl>(D) || isa_and_nonnull<FunctionDecl>(D))
343+
return true;
344+
345+
return RecursiveASTVisitor<ResultObjectVisitor>::TraverseDecl(D);
346+
}
347+
336348
bool TraverseBindingDecl(BindingDecl *BD) {
337349
// `RecursiveASTVisitor` doesn't traverse holding variables for
338350
// `BindingDecl`s by itself, so we need to tell it to.

clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3309,6 +3309,28 @@ TEST(TransferTest, ResultObjectLocationPropagatesThroughConditionalOperator) {
33093309
});
33103310
}
33113311

3312+
TEST(TransferTest, ResultObjectLocationDontVisitNestedRecordDecl) {
3313+
// This is a crash repro.
3314+
// We used to crash because when propagating result objects, we would visit
3315+
// nested record and function declarations, but we don't model fields used
3316+
// only in these.
3317+
std::string Code = R"(
3318+
struct S1 {};
3319+
struct S2 { S1 s1; };
3320+
void target() {
3321+
struct Nested {
3322+
void f() {
3323+
S2 s2 = { S1() };
3324+
}
3325+
};
3326+
}
3327+
)";
3328+
runDataflow(
3329+
Code,
3330+
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3331+
ASTContext &ASTCtx) {});
3332+
}
3333+
33123334
TEST(TransferTest, StaticCast) {
33133335
std::string Code = R"(
33143336
void target(int Foo) {

0 commit comments

Comments
 (0)