Skip to content

Commit 75a1198

Browse files
committed
[clang][dataflow] Don't propagate result objects inside decltype.
Trying to do so can cause crashes -- see newly added test and the comments in the fix. We're starting to see a repeating pattern here: We're getting crashes because `ResultObjectVisitor` and `getReferencedDecls()` don't agree on which parts of the AST to visit and, hence, which fields should be modeled. I think we should ensure consistency between these two parts of the code by using a `RecursiveASTVisitor` in `getReferencedDecls()`[^1]; the `Traverse...()` functions that control which parts of the AST we visit would go in a common base class that would be used for both `ResultObjectVisitor` and `getReferencedDecls()`. I'd like to focus this PR, however, on a targeted fix for the current crash and postpone the refactoring to a later PR (which will be easier to revert if there are unintended side-effects). [^1]: As an added bonus, this would make the code better structured and more efficient than the current sequence of `if (dyn_cast<T>(...))` statements).
1 parent fefac5d commit 75a1198

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,13 @@ class ResultObjectVisitor : public RecursiveASTVisitor<ResultObjectVisitor> {
350350
return RecursiveASTVisitor<ResultObjectVisitor>::TraverseDecl(D);
351351
}
352352

353+
bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node) {
354+
// Don't traverse `decltype` because we don't analyze its argument (as it
355+
// isn't executed) and hence don't model fields that are only used in the
356+
// argument of a `decltype`.
357+
return true;
358+
}
359+
353360
bool TraverseBindingDecl(BindingDecl *BD) {
354361
// `RecursiveASTVisitor` doesn't traverse holding variables for
355362
// `BindingDecl`s by itself, so we need to tell it to.

clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3331,6 +3331,23 @@ TEST(TransferTest, ResultObjectLocationDontVisitNestedRecordDecl) {
33313331
ASTContext &ASTCtx) {});
33323332
}
33333333

3334+
TEST(TransferTest, ResultObjectLocationDontVisitDeclTypeArg) {
3335+
// This is a crash repro.
3336+
// We used to crash because when propagating result objects, we would visit
3337+
// the argument of `decltype()`, but we don't model fields used only in these.
3338+
std::string Code = R"cc(
3339+
struct S1 {};
3340+
struct S2 { S1 s1; };
3341+
void target() {
3342+
decltype(S2{ S1() }) Dummy;
3343+
}
3344+
)cc";
3345+
runDataflow(
3346+
Code,
3347+
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3348+
ASTContext &ASTCtx) {});
3349+
}
3350+
33343351
TEST(TransferTest, StaticCast) {
33353352
std::string Code = R"(
33363353
void target(int Foo) {

0 commit comments

Comments
 (0)