This revision was automatically updated to reflect the committed changes.
Closed by commit rGf3700bdb7f00: [clang][dataflow] Account for global variables
in constructor initializers. (authored by ymandel).
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D140501/new/
https://reviews.llvm.org/D140501
Files:
clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
Index: clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
===================================================================
--- clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
@@ -8,6 +8,8 @@
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "TestingSupport.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
#include "clang/Analysis/FlowSensitive/NoopAnalysis.h"
#include "clang/Analysis/FlowSensitive/Value.h"
@@ -21,19 +23,19 @@
using namespace clang;
using namespace dataflow;
using ::testing::ElementsAre;
+using ::testing::NotNull;
using ::testing::Pair;
class EnvironmentTest : public ::testing::Test {
- DataflowAnalysisContext Context;
-
protected:
- EnvironmentTest()
- : Context(std::make_unique<WatchedLiteralsSolver>()), Env(Context) {}
+ EnvironmentTest() : DAContext(std::make_unique<WatchedLiteralsSolver>()) {}
- Environment Env;
+ DataflowAnalysisContext DAContext;
};
TEST_F(EnvironmentTest, FlowCondition) {
+ Environment Env(DAContext);
+
EXPECT_TRUE(Env.flowConditionImplies(Env.getBoolLiteralValue(true)));
EXPECT_FALSE(Env.flowConditionImplies(Env.getBoolLiteralValue(false)));
@@ -76,6 +78,7 @@
// Verify that the struct and the field (`R`) with first appearance of the
// type is created successfully.
+ Environment Env(DAContext);
Value *Val = Env.createValue(*Ty);
ASSERT_NE(Val, nullptr);
StructValue *SVal = clang::dyn_cast<StructValue>(Val);
@@ -86,4 +89,64 @@
EXPECT_NE(PV, nullptr);
}
+TEST_F(EnvironmentTest, InitGlobalVarsFun) {
+ using namespace ast_matchers;
+
+ std::string Code = R"cc(
+ int Global = 0;
+ int Target () { return Global; }
+ )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(decl(anyOf(varDecl(hasName("Global")).bind("global"),
+ functionDecl(hasName("Target")).bind("target"))),
+ Context);
+ const auto *Fun = selectFirst<FunctionDecl>("target", Results);
+ const auto *Var = selectFirst<VarDecl>("global", Results);
+ ASSERT_TRUE(Fun != nullptr);
+ ASSERT_THAT(Var, NotNull());
+
+ // Verify the global variable is populated when we analyze `Target`.
+ Environment Env(DAContext, *Fun);
+ EXPECT_THAT(Env.getValue(*Var, SkipPast::None), NotNull());
+}
+
+TEST_F(EnvironmentTest, InitGlobalVarsConstructor) {
+ using namespace ast_matchers;
+
+ std::string Code = R"cc(
+ int Global = 0;
+ struct Target {
+ Target() : Field(Global) {}
+ int Field;
+ };
+ )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(decl(anyOf(
+ varDecl(hasName("Global")).bind("global"),
+ cxxConstructorDecl(ofClass(hasName("Target"))).bind("target"))),
+ Context);
+ const auto *Ctor = selectFirst<CXXConstructorDecl>("target", Results);
+ const auto *Var = selectFirst<VarDecl>("global", Results);
+ ASSERT_TRUE(Ctor != nullptr);
+ ASSERT_THAT(Var, NotNull());
+
+ // Verify the global variable is populated when we analyze `Target`.
+ Environment Env(DAContext, *Ctor);
+ EXPECT_THAT(Env.getValue(*Var, SkipPast::None), NotNull());
+}
+
} // namespace
Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -233,6 +233,15 @@
}
}
}
+
+ // Look for global variable references in the constructor-initializers.
+ if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(&DeclCtx)) {
+ for (const auto *Init : CtorDecl->inits()) {
+ const Expr *E = Init->getInit();
+ assert(E != nullptr);
+ initGlobalVars(*E, *this);
+ }
+ }
}
bool Environment::canDescend(unsigned MaxDepth,
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits