Skip to content

Add two ownership verifier tests #6953

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 20, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions lib/SIL/SILOwnershipVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class OwnershipCompatibilityUseChecker
llvm::errs() << "Function: '" << User->getFunction()->getName() << "'\n"
<< "Have operand with incompatible ownership?!\n"
<< "Value: " << *getValue() << "User: " << *User
<< "Conv: " << getOwnershipKind() << "\n";
<< "Conv: " << getOwnershipKind() << "\n\n";
if (PrintMessageInsteadOfAssert)
return false;
llvm_unreachable("triggering standard assertion failure routine");
Expand Down Expand Up @@ -662,8 +662,8 @@ bool SILValueOwnershipChecker::doesBlockContainUseAfterFree(
[&NonLifetimeEndingUser](const SILInstruction &I) -> bool {
return NonLifetimeEndingUser == &I;
}) != UserBlock->end()) {
llvm::errs() << "Found use after free?!\n"
<< "Function: '" << Value->getFunction()->getName() << "'\n"
llvm::errs() << "Function: '" << Value->getFunction()->getName() << "'\n"
<< "Found use after free?!\n"
<< "Value: " << *Value
<< "Consuming User: " << *LifetimeEndingUser
<< "Non Consuming User: " << *Iter->second << "Block: bb"
Expand Down Expand Up @@ -756,9 +756,9 @@ static bool checkFunctionArgWithoutLifetimeEndingUses(SILFunctionArgument *Arg,
break;
}

llvm::errs() << " Owned function parameter without life "
llvm::errs() << "Function: '" << Arg->getFunction()->getName() << "'\n"
<< " Owned function parameter without life "
"ending uses!\n"
<< "Function: '" << Arg->getFunction()->getName() << "'\n"
<< "Value: " << *Arg << '\n';
if (PrintMessageInsteadOfAssert)
return true;
Expand All @@ -774,10 +774,10 @@ bool SILValueOwnershipChecker::checkValueWithoutLifetimeEndingUses() {
}

if (!isValueAddressOrTrivial(Value, Mod)) {
llvm::errs() << "Non trivial values, non address values, and non "
llvm::errs() << "Function: '" << Value->getFunction()->getName() << "'\n"
<< "Non trivial values, non address values, and non "
"guaranteed function args must have at least one "
"lifetime ending use?!\n"
<< "Function: '" << Value->getFunction()->getName() << "'\n"
<< "Value: " << *Value << '\n';
if (PrintMessageInsteadOfAssert)
return true;
Expand All @@ -793,8 +793,8 @@ static bool isGuaranteedFunctionArgWithLifetimeEndingUses(
if (Arg->getOwnershipKind() != ValueOwnershipKind::Guaranteed)
return true;

llvm::errs() << " Guaranteed function parameter with life ending uses!\n"
<< " Function: '" << Arg->getFunction()->getName() << "'\n"
llvm::errs() << " Function: '" << Arg->getFunction()->getName() << "'\n"
<< " Guaranteed function parameter with life ending uses!\n"
<< " Value: " << *Arg;
for (auto *U : LifetimeEndingUsers) {
llvm::errs() << " Lifetime Ending User: " << *U;
Expand Down Expand Up @@ -982,8 +982,8 @@ void SILValueOwnershipChecker::checkDataflow() {
// make sure we didn't leak.
if (!SuccessorBlocksThatMustBeVisited.empty()) {
llvm::errs()
<< "Error! Found a leak due to a consuming post-dominance failure!\n"
<< "Function: '" << Value->getFunction()->getName() << "'\n"
<< "Error! Found a leak due to a consuming post-dominance failure!\n"
<< " Value: " << *Value << " Post Dominating Failure Blocks:\n";
for (auto *BB : SuccessorBlocksThatMustBeVisited) {
llvm::errs() << "bb" << BB->getDebugID();
Expand All @@ -999,8 +999,8 @@ void SILValueOwnershipChecker::checkDataflow() {
// blocks implying a use-after free.
if (!BlocksWithNonLifetimeEndingUses.empty()) {
llvm::errs()
<< "Found use after free due to unvisited non lifetime ending uses?!\n"
<< "Function: '" << Value->getFunction()->getName() << "'\n"
<< "Found use after free due to unvisited non lifetime ending uses?!\n"
<< "Value: " << *Value << " Remaining Users:\n";
for (auto &Pair : BlocksWithNonLifetimeEndingUses) {
llvm::errs() << "User:" << *Pair.second << "Block: bb"
Expand Down
40 changes: 40 additions & 0 deletions test/SIL/ownership-verifier/over_consume.sil
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ sil_stage canonical

import Builtin

sil @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()

// This checks if the dataflow verifier asserts when we have two consuming users
// in the same block.
// CHECK-LABEL: Function: 'double_consume_same_bb'
Expand Down Expand Up @@ -83,3 +85,41 @@ bb0(%0 : $Builtin.NativeObject):
return %9999 : $()
}

// We have a use of a borrowed value after an end_borrow. This is effectively a
// use after consume.
//
// CHECK-LABEL: Function: 'use_after_end_borrow'
// CHECK: Found use after free?!
// CHECK: Value: %1 = begin_borrow %0 : $Builtin.NativeObject
// CHECK: Consuming User: end_borrow %1 from %0 : $Builtin.NativeObject, $Builtin.NativeObject
// CHECK: Non Consuming User: %4 = apply %2(%1) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
// CHECK: Block: bb0
sil @use_after_end_borrow : $@convention(thin) (@owned Builtin.NativeObject) -> () {
bb0(%0 : $Builtin.NativeObject):
%1 = begin_borrow %0 : $Builtin.NativeObject
%2 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
end_borrow %1 from %0 : $Builtin.NativeObject, $Builtin.NativeObject
apply %2(%1) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
destroy_value %0 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}

// We have a destroy value of an owned value before a borrow of the owned value
// has finished.
//
// CHECK-LABEL: Function: 'destroy_before_end_borrow'
// CHECK: Found use after free?!
// CHECK: Value: %0 = argument of bb0 : $Builtin.NativeObject
// CHECK: Consuming User: destroy_value %0 : $Builtin.NativeObject
// CHECK: Non Consuming User: end_borrow %1 from %0 : $Builtin.NativeObject, $Builtin.NativeObject
// CHECK: Block: bb0
sil @destroy_before_end_borrow : $@convention(thin) (@owned Builtin.NativeObject) -> () {
bb0(%0 : $Builtin.NativeObject):
%1 = begin_borrow %0 : $Builtin.NativeObject
%2 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
destroy_value %0 : $Builtin.NativeObject
end_borrow %1 from %0 : $Builtin.NativeObject, $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}