Skip to content

Commit

Permalink
[clang][dataflow]Propagate the result object location for CXXDefaultI…
Browse files Browse the repository at this point in the history
…nitExpr. (#98490)

These are not "original initializers"; the single node underneath
represents the initializing node.
  • Loading branch information
bazuzi authored Jul 13, 2024
1 parent 1fe406f commit 3fed312
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 2 deletions.
10 changes: 8 additions & 2 deletions clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/Type.h"
Expand Down Expand Up @@ -414,8 +415,8 @@ class ResultObjectVisitor : public AnalysisASTVisitor<ResultObjectVisitor> {
// lowest-level AST node that initializes a given object, and nothing
// below them can initialize the same object (or part of it).
if (isa<CXXConstructExpr>(E) || isa<CallExpr>(E) || isa<LambdaExpr>(E) ||
isa<CXXDefaultArgExpr>(E) || isa<CXXDefaultInitExpr>(E) ||
isa<CXXStdInitializerListExpr>(E) || isa<AtomicExpr>(E) ||
isa<CXXDefaultArgExpr>(E) || isa<CXXStdInitializerListExpr>(E) ||
isa<AtomicExpr>(E) ||
// We treat `BuiltinBitCastExpr` as an "original initializer" too as
// it may not even be casting from a record type -- and even if it is,
// the two objects are in general of unrelated type.
Expand Down Expand Up @@ -463,6 +464,11 @@ class ResultObjectVisitor : public AnalysisASTVisitor<ResultObjectVisitor> {
return;
}

if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(E)) {
PropagateResultObject(DIE->getExpr(), Loc);
return;
}

// All other expression nodes that propagate a record prvalue should have
// exactly one child.
SmallVector<Stmt *, 1> Children(E->child_begin(), E->child_end());
Expand Down
37 changes: 37 additions & 0 deletions clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <memory>
#include <string>

namespace {

Expand Down Expand Up @@ -405,6 +406,42 @@ TEST_F(EnvironmentTest,
Contains(Member));
}

// This is a repro of a failure case seen in the wild.
TEST_F(EnvironmentTest, CXXDefaultInitExprResultObjIsWrappedExprResultObj) {
using namespace ast_matchers;

std::string Code = R"cc(
struct Inner {};
struct S {
S() {}
Inner i = {};
};
)cc";

auto Unit =
tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++11"});
auto &Context = Unit->getASTContext();

ASSERT_EQ(Context.getDiagnostics().getClient()->getNumErrors(), 0U);

auto Results =
match(cxxConstructorDecl(
hasAnyConstructorInitializer(cxxCtorInitializer(
withInitializer(expr().bind("default_init_expr")))))
.bind("ctor"),
Context);
const auto *Constructor = selectFirst<CXXConstructorDecl>("ctor", Results);
const auto *DefaultInit =
selectFirst<CXXDefaultInitExpr>("default_init_expr", Results);

Environment Env(DAContext, *Constructor);
Env.initialize();
EXPECT_EQ(&Env.getResultObjectLocation(*DefaultInit),
&Env.getResultObjectLocation(*DefaultInit->getExpr()));
}

TEST_F(EnvironmentTest, Stmt) {
using namespace ast_matchers;

Expand Down

0 comments on commit 3fed312

Please sign in to comment.