Skip to content

Commit 539532f

Browse files
committed
merge main into amd-stg-open
Change-Id: I4ec32d2d0228a001ec6527d6dd94920a11d0d975
2 parents ef427fe + 5f782d2 commit 539532f

File tree

16 files changed

+403
-250
lines changed

16 files changed

+403
-250
lines changed

clang/lib/Analysis/FlowSensitive/Transfer.cpp

Lines changed: 63 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,50 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
8787
}
8888

8989
void VisitDeclStmt(const DeclStmt *S) {
90-
// FIXME: Add support for group decls, e.g: `int a, b;`
91-
if (S->isSingleDecl()) {
92-
if (const auto *D = dyn_cast<VarDecl>(S->getSingleDecl())) {
93-
visitVarDecl(*D);
90+
// Group decls are converted into single decls in the CFG so the cast below
91+
// is safe.
92+
const auto &D = *cast<VarDecl>(S->getSingleDecl());
93+
auto &Loc = Env.createStorageLocation(D);
94+
Env.setStorageLocation(D, Loc);
95+
96+
const Expr *InitExpr = D.getInit();
97+
if (InitExpr == nullptr) {
98+
// No initializer expression - associate `Loc` with a new value.
99+
Env.initValueInStorageLocation(Loc, D.getType());
100+
return;
101+
}
102+
103+
// The CFG does not contain `ParenExpr` as top-level statements in basic
104+
// blocks, however sub-expressions can still be of that type.
105+
InitExpr = skipExprWithCleanups(D.getInit()->IgnoreParens());
106+
assert(InitExpr != nullptr);
107+
108+
if (D.getType()->isReferenceType()) {
109+
// Initializing a reference variable - do not create a reference to
110+
// reference.
111+
if (auto *InitExprLoc =
112+
Env.getStorageLocation(*InitExpr, SkipPast::Reference)) {
113+
auto &Val =
114+
Env.takeOwnership(std::make_unique<ReferenceValue>(*InitExprLoc));
115+
Env.setValue(Loc, Val);
116+
} else {
117+
// FIXME: The initializer expression must always be assigned a value.
118+
// Replace this with an assert when we have sufficient coverage of
119+
// language features.
120+
Env.initValueInStorageLocation(Loc, D.getType());
94121
}
122+
return;
123+
}
124+
125+
if (auto *InitExprVal = Env.getValue(*InitExpr, SkipPast::None)) {
126+
Env.setValue(Loc, *InitExprVal);
127+
} else if (!D.getType()->isStructureOrClassType()) {
128+
// FIXME: The initializer expression must always be assigned a value.
129+
// Replace this with an assert when we have sufficient coverage of
130+
// language features.
131+
Env.initValueInStorageLocation(Loc, D.getType());
132+
} else {
133+
llvm_unreachable("structs and classes must always be assigned values");
95134
}
96135
}
97136

@@ -309,57 +348,34 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
309348
Env.setStorageLocation(*S, *SubExprLoc);
310349
}
311350

312-
// FIXME: Add support for:
313-
// - CXXBindTemporaryExpr
314-
// - CXXBoolLiteralExpr
315-
// - CXXStaticCastExpr
316-
317-
private:
318-
void visitVarDecl(const VarDecl &D) {
319-
auto &Loc = Env.createStorageLocation(D);
320-
Env.setStorageLocation(D, Loc);
351+
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *S) {
352+
const Expr *SubExpr = S->getSubExpr();
353+
assert(SubExpr != nullptr);
321354

322-
const Expr *InitExpr = D.getInit();
323-
if (InitExpr == nullptr) {
324-
// No initializer expression - associate `Loc` with a new value.
325-
Env.initValueInStorageLocation(Loc, D.getType());
355+
auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
356+
if (SubExprLoc == nullptr)
326357
return;
327-
}
328358

329-
// The CFG does not contain `ParenExpr` as top-level statements in basic
330-
// blocks, however sub-expressions can still be of that type.
331-
InitExpr = skipExprWithCleanups(D.getInit()->IgnoreParens());
332-
assert(InitExpr != nullptr);
359+
Env.setStorageLocation(*S, *SubExprLoc);
360+
}
333361

334-
if (D.getType()->isReferenceType()) {
335-
// Initializing a reference variable - do not create a reference to
336-
// reference.
337-
if (auto *InitExprLoc =
338-
Env.getStorageLocation(*InitExpr, SkipPast::Reference)) {
339-
auto &Val =
340-
Env.takeOwnership(std::make_unique<ReferenceValue>(*InitExprLoc));
341-
Env.setValue(Loc, Val);
342-
} else {
343-
// FIXME: The initializer expression must always be assigned a value.
344-
// Replace this with an assert when we have sufficient coverage of
345-
// language features.
346-
Env.initValueInStorageLocation(Loc, D.getType());
347-
}
348-
return;
349-
}
362+
void VisitCXXStaticCastExpr(const CXXStaticCastExpr *S) {
363+
if (S->getCastKind() == CK_NoOp) {
364+
const Expr *SubExpr = S->getSubExpr();
365+
assert(SubExpr != nullptr);
350366

351-
if (auto *InitExprVal = Env.getValue(*InitExpr, SkipPast::None)) {
352-
Env.setValue(Loc, *InitExprVal);
353-
} else if (!D.getType()->isStructureOrClassType()) {
354-
// FIXME: The initializer expression must always be assigned a value.
355-
// Replace this with an assert when we have sufficient coverage of
356-
// language features.
357-
Env.initValueInStorageLocation(Loc, D.getType());
358-
} else {
359-
llvm_unreachable("structs and classes must always be assigned values");
367+
auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
368+
if (SubExprLoc == nullptr)
369+
return;
370+
371+
Env.setStorageLocation(*S, *SubExprLoc);
360372
}
361373
}
362374

375+
// FIXME: Add support for:
376+
// - CXXBoolLiteralExpr
377+
378+
private:
363379
Environment &Env;
364380
};
365381

clang/test/Profile/cxx-lambda.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
void lambdas() {
2020
int i = 1;
2121

22-
// LMBGEN-LABEL: define internal{{( [0-9_a-z]*cc)?( noundef zeroext)?}} i1 @"_ZZ7lambdasvENK3$_0clEi"(
23-
// LMBUSE-LABEL: define internal{{( [0-9_a-z]*cc)?( noundef zeroext)?}} i1 @"_ZZ7lambdasvENK3$_0clEi"(
22+
// LMBGEN-LABEL: define internal{{( [0-9_a-z]*cc)?( noundef)?( zeroext)?}} i1 @"_ZZ7lambdasvENK3$_0clEi"(
23+
// LMBUSE-LABEL: define internal{{( [0-9_a-z]*cc)?( noundef)?( zeroext)?}} i1 @"_ZZ7lambdasvENK3$_0clEi"(
2424
// LMBGEN: store {{.*}} @[[LFC]], i32 0, i32 0
2525
auto f = [&i](int k) {
2626
// LMBGEN: store {{.*}} @[[LFC]], i32 0, i32 1

clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,44 @@ TEST_F(TransferTest, SelfReferentialPointerVarDecl) {
489489
});
490490
}
491491

492+
TEST_F(TransferTest, MultipleVarsDecl) {
493+
std::string Code = R"(
494+
void target() {
495+
int Foo, Bar;
496+
(void)0;
497+
// [[p]]
498+
}
499+
)";
500+
runDataflow(Code,
501+
[](llvm::ArrayRef<
502+
std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
503+
Results,
504+
ASTContext &ASTCtx) {
505+
ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
506+
const Environment &Env = Results[0].second.Env;
507+
508+
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
509+
ASSERT_THAT(FooDecl, NotNull());
510+
511+
const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
512+
ASSERT_THAT(BarDecl, NotNull());
513+
514+
const StorageLocation *FooLoc =
515+
Env.getStorageLocation(*FooDecl, SkipPast::None);
516+
ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
517+
518+
const StorageLocation *BarLoc =
519+
Env.getStorageLocation(*BarDecl, SkipPast::None);
520+
ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
521+
522+
const Value *FooVal = Env.getValue(*FooLoc);
523+
EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
524+
525+
const Value *BarVal = Env.getValue(*BarLoc);
526+
EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
527+
});
528+
}
529+
492530
TEST_F(TransferTest, JoinVarDecl) {
493531
std::string Code = R"(
494532
void target(bool B) {
@@ -1589,4 +1627,71 @@ TEST_F(TransferTest, MoveConstructor) {
15891627
});
15901628
}
15911629

1630+
TEST_F(TransferTest, BindTemporary) {
1631+
std::string Code = R"(
1632+
struct A {
1633+
virtual ~A() = default;
1634+
1635+
int Baz;
1636+
};
1637+
1638+
void target(A Foo) {
1639+
int Bar = A(Foo).Baz;
1640+
// [[p]]
1641+
}
1642+
)";
1643+
runDataflow(Code,
1644+
[](llvm::ArrayRef<
1645+
std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1646+
Results,
1647+
ASTContext &ASTCtx) {
1648+
ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1649+
const Environment &Env = Results[0].second.Env;
1650+
1651+
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1652+
ASSERT_THAT(FooDecl, NotNull());
1653+
1654+
const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1655+
ASSERT_THAT(BarDecl, NotNull());
1656+
1657+
const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1658+
ASSERT_THAT(BazDecl, NotNull());
1659+
1660+
const auto &FooVal =
1661+
*cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None));
1662+
const auto *BarVal =
1663+
cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
1664+
EXPECT_EQ(BarVal, &FooVal.getChild(*BazDecl));
1665+
});
1666+
}
1667+
1668+
TEST_F(TransferTest, StaticCast) {
1669+
std::string Code = R"(
1670+
void target(int Foo) {
1671+
int Bar = static_cast<int>(Foo);
1672+
// [[p]]
1673+
}
1674+
)";
1675+
runDataflow(Code,
1676+
[](llvm::ArrayRef<
1677+
std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1678+
Results,
1679+
ASTContext &ASTCtx) {
1680+
ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1681+
const Environment &Env = Results[0].second.Env;
1682+
1683+
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1684+
ASSERT_THAT(FooDecl, NotNull());
1685+
1686+
const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1687+
ASSERT_THAT(BarDecl, NotNull());
1688+
1689+
const auto *FooVal =
1690+
cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None));
1691+
const auto *BarVal =
1692+
cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
1693+
EXPECT_EQ(FooVal, BarVal);
1694+
});
1695+
}
1696+
15921697
} // namespace

compiler-rt/test/msan/noundef_analysis.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// RUN: %clangxx_msan %s -o %t && %run %t >%t.out 2>&1
22
// RUN: FileCheck %s --check-prefix=MISSED --allow-empty < %t.out
3-
// RUN: %clangxx_msan %s -Xclang -enable-noundef-analysis -mllvm -msan-eager-checks=1 -o %t && not %run %t >%t.out 2>&1
3+
// RUN: %clangxx_msan %s -mllvm -msan-eager-checks=1 -o %t && not %run %t >%t.out 2>&1
44
// RUN: FileCheck %s < %t.out
5-
// RUN: %clangxx_msan %s -fsanitize-memory-param-retval -o %t && not %run %t >%t.out 2>&1
5+
// RUN: %clangxx_msan %s -disable-noundef-analysis -s -fsanitize-memory-param-retval -o %t && not %run %t >%t.out 2>&1
66
// RUN: FileCheck %s < %t.out
77

88
struct SimpleStruct {

llvm/include/llvm/IR/Attributes.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,9 +1048,6 @@ class AttrBuilder {
10481048
return removeAttribute(A.getKindAsEnum());
10491049
}
10501050

1051-
/// Remove the attributes from the builder.
1052-
AttrBuilder &removeAttributes(AttributeList A, uint64_t WithoutIndex);
1053-
10541051
/// Add the attributes from the builder.
10551052
AttrBuilder &merge(const AttrBuilder &B);
10561053

@@ -1074,10 +1071,6 @@ class AttrBuilder {
10741071
/// Return true if the builder has IR-level attributes.
10751072
bool hasAttributes() const;
10761073

1077-
/// Return true if the builder has any attribute that's in the
1078-
/// specified attribute.
1079-
bool hasAttributes(AttributeList A, uint64_t Index) const;
1080-
10811074
/// Return true if the builder has an alignment attribute.
10821075
bool hasAlignmentAttr() const;
10831076

0 commit comments

Comments
 (0)