}
getFieldsAndGlobalVars(*FuncDecl->getBody(), Fields, Vars);
- initVars(Vars);
- // These have to be set before the lines that follow to ensure that create*
- // work correctly for structs.
+ // These have to be added before the lines that follow to ensure that
+ // `create*` work correctly for structs.
DACtx.addModeledFields(Fields);
+ initVars(Vars);
+
for (const auto *ParamDecl : FuncDecl->parameters()) {
assert(ParamDecl != nullptr);
auto &ParamLoc = createStorageLocation(*ParamDecl);
}
}
getFieldsAndGlobalVars(*FuncDecl->getBody(), Fields, Vars);
- initVars(Vars);
+
+ // These have to be added before the lines that follow to ensure that
+ // `create*` work correctly for structs.
DACtx->addModeledFields(Fields);
+ initVars(Vars);
+
const auto *ParamIt = FuncDecl->param_begin();
// FIXME: Parameters don't always map to arguments 1:1; examples include
Context);
const auto *Fun = selectFirst<FunctionDecl>("target", Results);
const auto *Var = selectFirst<VarDecl>("global", Results);
- ASSERT_TRUE(Fun != nullptr);
+ ASSERT_THAT(Fun, NotNull());
ASSERT_THAT(Var, NotNull());
// Verify the global variable is populated when we analyze `Target`.
EXPECT_THAT(Env.getValue(*Var, SkipPast::None), NotNull());
}
+TEST_F(EnvironmentTest, InitGlobalVarsFieldFun) {
+ using namespace ast_matchers;
+
+ std::string Code = R"cc(
+ struct S { int Bar; };
+ S Global = {0};
+ int Target () { return Global.Bar; }
+ )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 *GlobalDecl = selectFirst<VarDecl>("global", Results);
+ ASSERT_THAT(Fun, NotNull());
+ ASSERT_THAT(GlobalDecl, NotNull());
+
+ ASSERT_TRUE(GlobalDecl->getType()->isStructureType());
+ auto GlobalFields = GlobalDecl->getType()->getAsRecordDecl()->fields();
+
+ FieldDecl *BarDecl = nullptr;
+ for (FieldDecl *Field : GlobalFields) {
+ if (Field->getNameAsString() == "Bar") {
+ BarDecl = Field;
+ break;
+ }
+ FAIL() << "Unexpected field: " << Field->getNameAsString();
+ }
+ ASSERT_THAT(BarDecl, NotNull());
+
+ // Verify the global variable is populated when we analyze `Target`.
+ Environment Env(DAContext, *Fun);
+ const auto *GlobalLoc = cast<AggregateStorageLocation>(
+ Env.getStorageLocation(*GlobalDecl, SkipPast::None));
+ const auto *GlobalVal = cast<StructValue>(Env.getValue(*GlobalLoc));
+ const auto *BarVal = GlobalVal->getChild(*BarDecl);
+ ASSERT_THAT(BarVal, NotNull());
+ EXPECT_TRUE(isa<IntegerValue>(BarVal));
+}
+
TEST_F(EnvironmentTest, InitGlobalVarsConstructor) {
using namespace ast_matchers;