check nocapture ptrs passed as fn parameters
fixes
MODIFY
ir/attrs.cpp
ir/attrs.cpp
@@ -97,12 +97,14 @@ static void
encodePtrAttrs(const State &s, const expr &ptrvalue,
AndExpr &UB, expr &non_poison,
uint64_t derefBytes, uint64_t derefOrNullBytes, uint64_t align,
- bool nonnull) {
+ bool nonnull, bool nocapture) {
Pointer p(s.getMemory(), ptrvalue);
if (nonnull)
non_poison &= !p.isNull();
+ non_poison &= p.isNocapture().implies(nocapture);
+
if (derefBytes || derefOrNullBytes) {
// dereferenceable, byval (ParamAttrs), dereferenceable_or_null
if (derefBytes)
@@ -120,8 +122,8 @@ ParamAttrs::encode(const State &s, const StateValue &val, const Type &ty) const
expr new_non_poison = val.non_poison;
if (ty.isPtrType())
- encodePtrAttrs(s, val.value, UB, new_non_poison,
- getDerefBytes(), derefOrNullBytes, align, has(NonNull));
+ encodePtrAttrs(s, val.value, UB, new_non_poison, getDerefBytes(),
+ derefOrNullBytes, align, has(NonNull), has(NoCapture));
if (poisonImpliesUB()) {
UB.add(move(new_non_poison));
@@ -154,8 +156,8 @@ FnAttrs::encode(const State &s, const StateValue &val, const Type &ty) const {
}
if (ty.isPtrType())
- encodePtrAttrs(s, val.value, UB, new_non_poison,
- derefBytes, derefOrNullBytes, align, has(NonNull));
+ encodePtrAttrs(s, val.value, UB, new_non_poison, derefBytes,
+ derefOrNullBytes, align, has(NonNull), false);
if (poisonImpliesUB()) {
UB.add(move(new_non_poison));

ADD
tests/alive-tv/attrs/nocapture-call-fail.srctgt.ll
+; ERROR: Source is more defined
+
+define void @src(i8* nocapture %p) {
+ call i8* @g(i8* %p)
+ ret void
+}
+
+define void @tgt(i8* nocapture %p) {
+ call i8* @g(i8* poison)
+ ret void
+}
+
+declare i8* @g(i8* nocapture)

ADD
tests/alive-tv/attrs/nocapture-call.srctgt.ll
+define void @src(i8* nocapture %p) {
+ call i8* @g(i8* %p)
+ ret void
+}
+
+define void @tgt(i8* nocapture %p) {
+ call i8* @g(i8* poison)
+ ret void
+}
+
+declare i8* @g(i8*)

check nocapture ptrs passed as fn parameters
fixes #682