Skip to content

Commit 0c34615

Browse files
committed
fix(aggr): fix aggr decl with ExprWithCleanups
1 parent 7d6889c commit 0c34615

11 files changed

Lines changed: 128 additions & 16 deletions

File tree

.github/workflows/ci-macos-local.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
strategy:
1313
matrix:
1414
build_type: [ Release ]
15-
os: [macos-12]
15+
os: [macos-latest]
1616
compiler:
1717
- cc: cc
1818
cxx: c++
@@ -32,6 +32,10 @@ jobs:
3232
with:
3333
fetch-depth: 0
3434

35+
- uses: actions/setup-python@v5
36+
with:
37+
python-version: '3.13'
38+
3539
- name: Install llvm@17
3640
run: |
3741
brew install llvm@17

.github/workflows/ci-macos.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
strategy:
1717
matrix:
1818
build_type: [ Release ]
19-
os: [macos-12]
19+
os: [macos-13, macos-14, macos-15]
2020
compiler:
2121
- cc: cc
2222
cxx: c++
@@ -34,6 +34,10 @@ jobs:
3434
steps:
3535
- uses: actions/checkout@v3
3636

37+
- uses: actions/setup-python@v5
38+
with:
39+
python-version: '3.13'
40+
3741
- name: Install conan
3842
run: pip3 install conan
3943

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ Note that cppsafe will detect system includes via `c++`, you can override it via
7070
CXX=/opt/homebrew/opt/llvm/bin/clang cppsafe example.cpp -- -std=c++20
7171
```
7272

73+
> Note: cppship should be used with std17 or above, since cpp17 has changed the rule for temporaries.
74+
7375
### With compile\_commands.json
7476
Generally, you should use cppsafe with compile\_commands.json.
7577

include/cppsafe/lifetime/LifetimePsetBuilder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ class PSBuilder {
3232

3333
DISALLOW_COPY_AND_MOVE(PSBuilder);
3434

35+
virtual const Expr* ignoreTransparentExprs(const Expr* E, bool IgnoreLValueToRValue = false) const = 0;
36+
3537
virtual void setPSet(const Expr* E, const PSet& PS) = 0;
3638
virtual void setPSet(const PSet& LHS, PSet RHS, SourceRange Range) = 0;
3739

integration_test/case/elements_view_cxx17.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,12 @@ int main()
124124

125125
__lifetime_type_category<T1>(); // expected-warning {{lifetime type category is Pointer with pointee const int}}
126126
__lifetime_type_category<T1_iter>(); // expected-warning {{lifetime type category is Pointer with pointee const int}}
127-
__lifetime_type_category<T2>(); // expected-warning {{lifetime type category is Pointer with pointee std::string}}
128-
__lifetime_type_category<T2_iter>(); // expected-warning {{lifetime type category is Pointer with pointee std::string}}
127+
__lifetime_type_category<T2>(); // expected-warning {{lifetime type category is Pointer with pointee}}
128+
__lifetime_type_category<T2_iter>(); // expected-warning {{lifetime type category is Pointer with pointee}}
129129
__lifetime_type_category<T3>(); // expected-warning {{lifetime type category is Pointer with pointee const int}}
130130
__lifetime_type_category<T3_iter>(); // expected-warning {{lifetime type category is Pointer with pointee const int}}
131-
__lifetime_type_category<T4>(); // expected-warning {{lifetime type category is Pointer with pointee std::string}}
132-
__lifetime_type_category<T4_iter>(); // expected-warning {{lifetime type category is Pointer with pointee std::string}}
131+
__lifetime_type_category<T4>(); // expected-warning {{lifetime type category is Pointer with pointee}}
132+
__lifetime_type_category<T4_iter>(); // expected-warning {{lifetime type category is Pointer with pointee}}
133133

134134
map<int, string> mp{{1, "one"}, {2, "two"}, {3, "three"}, {4, "four"}};
135135

integration_test/feature/structureal_binding.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ int main()
3636

3737
const auto& [x3, y3] = get1();
3838
__lifetime_pset(x3); // expected-warning {{(unknown)}}
39-
__lifetime_pset(y3); // expected-warning {{(unknown)}}
39+
__lifetime_pset(y3); // expected-warning {{(global)}}
4040

4141
auto& [x4, y4] = get2(d);
4242
__lifetime_pset(x4); // expected-warning {{(unknown)}}

integration_test/safety/contract_return.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,17 @@ void test()
1919
Derive d;
2020
auto* p2 = d.foo(&x);
2121
__lifetime_pset(p2); // expected-warning {{pset(p2) = (x)}}
22+
}
23+
24+
int* get()
25+
{
26+
static int x = 0;
27+
return &x;
28+
}
29+
30+
int* get2()
31+
{
32+
static int x;
33+
static int* y = &x;
34+
return y;
2235
}

integration_test/safety/contract_return_aggr.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ struct A {
1010
Inner i;
1111
};
1212

13+
struct B {
14+
int* x;
15+
};
16+
1317
A foo(int* x);
18+
B get();
1419

1520
void test_contract_return()
1621
{
@@ -27,4 +32,72 @@ void test_contract_return()
2732
__lifetime_pset(m.y); // expected-warning {{pset(m.y) = ((global))}}
2833
__lifetime_pset(m.i); // expected-warning {{pset(m.i) = (m.i)}}
2934
__lifetime_pset(m.i.m); // expected-warning {{pset(m.i.m) = (x)}}
35+
36+
A n = foo(get().x);
37+
__lifetime_pset(n); // expected-warning {{pset(n) = (n)}}
38+
__lifetime_pset(n.x); // expected-warning {{pset(n.x) = ((global))}}
39+
__lifetime_pset(n.y); // expected-warning {{pset(n.y) = ((global))}}
40+
__lifetime_pset(n.i); // expected-warning {{pset(n.i) = (n.i)}}
41+
__lifetime_pset(n.i.m); // expected-warning {{pset(n.i.m) = ((global))}}
42+
43+
int y = 0;
44+
m = foo(&y);
45+
__lifetime_pset(m); // expected-warning {{pset(m) = (m)}}
46+
__lifetime_pset(m.x); // expected-warning {{pset(m.x) = (y)}}
47+
__lifetime_pset(m.y); // expected-warning {{pset(m.y) = ((global))}}
48+
__lifetime_pset(m.i); // expected-warning {{pset(m.i) = (m.i)}}
49+
__lifetime_pset(m.i.m); // expected-warning {{pset(m.i.m) = (y)}}
50+
51+
n = foo(B{&y}.x);
52+
__lifetime_pset(n); // expected-warning {{pset(n) = (n)}}
53+
__lifetime_pset(n.x); // expected-warning {{pset(n.x) = (y)}}
54+
__lifetime_pset(n.y); // expected-warning {{pset(n.y) = ((global))}}
55+
__lifetime_pset(n.i); // expected-warning {{pset(n.i) = (n.i)}}
56+
__lifetime_pset(n.i.m); // expected-warning {{pset(n.i.m) = (y)}}
57+
58+
n = foo(B{}.x);
59+
__lifetime_pset(n); // expected-warning {{pset(n) = (n)}}
60+
__lifetime_pset(n.x); // expected-warning {{pset(n.x) = ((global))}}
61+
__lifetime_pset(n.y); // expected-warning {{pset(n.y) = ((global))}}
62+
__lifetime_pset(n.i); // expected-warning {{pset(n.i) = (n.i)}}
63+
__lifetime_pset(n.i.m); // expected-warning {{pset(n.i.m) = ((global))}}
64+
65+
int* z = B{}.x;
66+
__lifetime_pset(z); // expected-warning {{pset(z) = ((null))}}
67+
}
68+
69+
B createB()
70+
{
71+
const B b { .x = nullptr };
72+
return b;
73+
}
74+
75+
B createStaticB()
76+
{
77+
static int t = 0;
78+
static const B b { .x = &t };
79+
__lifetime_pmap();
80+
return b;
81+
}
82+
83+
struct [[gsl::Owner(char)]] String {};
84+
struct [[gsl::Pointer(char)]] StringView {
85+
StringView(const String&);
86+
87+
void Foo();
88+
};
89+
90+
struct Wrapper {
91+
StringView s1;
92+
StringView s2;
93+
};
94+
95+
Wrapper get(StringView);
96+
97+
void test_string_view()
98+
{
99+
auto s = get(String{}); // expected-note {{temporary was destroyed at the end of the full expression}}
100+
__lifetime_pset(s.s1); // expected-warning {{pset(s.s1) = ((invalid))}}
101+
__lifetime_pset(s.s2); // expected-warning {{pset(s.s2) = ((invalid))}}
102+
s.s1.Foo(); // expected-warning {{passing a dangling pointer as argument}}
30103
}

integration_test/safety/type_aggr_init.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ void test_default_init()
5151
__lifetime_pset(b.c); // expected-warning {{pset(b.c) = (*b.c)}}
5252
}
5353

54+
void test_list_init()
55+
{
56+
int t = 0;
57+
Aggr a = {.y = &t };
58+
__lifetime_pset(a); // expected-warning {{pset(a) = (a)}}
59+
__lifetime_pset(a.y); // expected-warning {{pset(a.y) = (t)}}
60+
}
61+
5462
void test_copy_init()
5563
{
5664
int m = 0;

lib/lifetime/LifetimePsetBuilder.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class PSetsBuilder final : public ConstStmtVisitor<PSetsBuilder, void>, public P
107107
/// Does not ignore MaterializeTemporaryExpr as Expr::IgnoreParenImpCasts
108108
/// would.
109109
// NOLINTBEGIN(readability-else-after-return)
110-
static const Expr* ignoreTransparentExprs(const Expr* E, bool IgnoreLValueToRValue = false)
110+
const Expr* ignoreTransparentExprs(const Expr* E, bool IgnoreLValueToRValue = false) const override
111111
{
112112
while (true) {
113113
E = E->IgnoreParens();
@@ -150,7 +150,7 @@ class PSetsBuilder final : public ConstStmtVisitor<PSetsBuilder, void>, public P
150150
// NOLINTEND(readability-else-after-return)
151151
}
152152

153-
static bool isIgnoredStmt(const Stmt* S)
153+
bool isIgnoredStmt(const Stmt* S)
154154
{
155155
const Expr* E = dyn_cast<Expr>(S);
156156
return E && ignoreTransparentExprs(E) != E;
@@ -1068,14 +1068,19 @@ class PSetsBuilder final : public ConstStmtVisitor<PSetsBuilder, void>, public P
10681068
// NOLINTNEXTLINE(readability-identifier-naming): required by parent
10691069
void VisitVarDecl(const VarDecl* VD)
10701070
{
1071-
if (const auto* DD = dyn_cast<DecompositionDecl>(VD)) {
1071+
if (const auto* DD = dyn_cast_if_present<DecompositionDecl>(VD)) {
10721072
visitDecompositionDecl(DD);
10731073
return;
10741074
}
10751075

10761076
const Expr* Initializer = VD->getInit();
10771077
const SourceRange Range = VD->getSourceRange();
10781078

1079+
// NB. clang don't generage ExprWithCleanups node in CFG
1080+
if (const auto* E = dyn_cast_if_present<ExprWithCleanups>(Initializer)) {
1081+
Initializer = E->getSubExpr();
1082+
}
1083+
10791084
switch (classifyTypeCategory(VD->getType())) {
10801085
case TypeCategory::Pointer: {
10811086
PSet PS;

0 commit comments

Comments
 (0)