@@ -44,6 +44,8 @@ struct LifetimeCheckPass : public LifetimeCheckBase<LifetimeCheckPass> {
44
44
45
45
void checkCtor (CallOp callOp, const clang::CXXConstructorDecl *ctor);
46
46
void checkMoveAssignment (CallOp callOp, const clang::CXXMethodDecl *m);
47
+ void checkCopyAssignment (CallOp callOp, const clang::CXXMethodDecl *m);
48
+ void checkNonConstUseOfOwner (CallOp callOp);
47
49
void checkOperatorStar (CallOp callOp);
48
50
49
51
// Tracks current module.
@@ -140,13 +142,13 @@ struct LifetimeCheckPass : public LifetimeCheckBase<LifetimeCheckPass> {
140
142
bool operator <(const State &RHS) const {
141
143
// FIXME: note that this makes the ordering non-deterministic, do
142
144
// we really care?
143
- if (val. getInt () == LocalValue && RHS.val . getInt () == LocalValue )
145
+ if (hasValue () && RHS.hasValue () )
144
146
return val.getPointer ().getAsOpaquePointer () <
145
147
RHS.val .getPointer ().getAsOpaquePointer ();
146
148
return val.getInt () < RHS.val .getInt ();
147
149
}
148
150
bool operator ==(const State &RHS) const {
149
- if (val. getInt () == LocalValue && RHS.val . getInt () == LocalValue )
151
+ if (hasValue () && RHS.hasValue () )
150
152
return val.getPointer () == RHS.val .getPointer ();
151
153
return val.getInt () == RHS.val .getInt ();
152
154
}
@@ -968,6 +970,7 @@ void LifetimeCheckPass::checkMoveAssignment(CallOp callOp,
968
970
auto src = callOp.getOperand (1 );
969
971
970
972
// Currently only handle move assignments between pointer categories.
973
+ // TODO: add Owner category
971
974
if (!(ptrs.count (dst) && ptrs.count (src)))
972
975
return ;
973
976
@@ -982,6 +985,20 @@ void LifetimeCheckPass::checkMoveAssignment(CallOp callOp,
982
985
getPmap ()[src].insert (State::getInvalid ());
983
986
}
984
987
988
+ void LifetimeCheckPass::checkCopyAssignment (CallOp callOp,
989
+ const clang::CXXMethodDecl *m) {
990
+ // MyIntOwner::operator=(MyIntOwner&)(%dst, %src)
991
+ auto dst = callOp.getOperand (0 );
992
+ auto src = callOp.getOperand (1 );
993
+
994
+ // Currently only handle copy assignments between owner categories.
995
+ // TODO: add Ptr category
996
+ if (!(owners.count (dst) && owners.count (src)))
997
+ return ;
998
+
999
+ checkNonConstUseOfOwner (callOp);
1000
+ }
1001
+
985
1002
// User defined ctors that initialize from owner types is one
986
1003
// way of tracking owned pointers.
987
1004
//
@@ -1083,6 +1100,23 @@ bool LifetimeCheckPass::isNonConstUseOfOwner(CallOp callOp,
1083
1100
return false ;
1084
1101
}
1085
1102
1103
+ void LifetimeCheckPass::checkNonConstUseOfOwner (CallOp callOp) {
1104
+ auto ownerAddr = callOp.getOperand (0 );
1105
+ // 2.4.2 - On every non-const use of a local Owner o:
1106
+ //
1107
+ // - For each entry e in pset(s): Remove e from pset(s), and if no other
1108
+ // Owner’s pset contains only e, then KILL(e).
1109
+ kill (State::getOwnedBy (ownerAddr), InvalidStyle::NonConstUseOfOwner,
1110
+ callOp.getLoc ());
1111
+
1112
+ // - Set pset(o) = {o__N'}, where N is one higher than the highest
1113
+ // previously used suffix. For example, initially pset(o) is {o__1'}, on
1114
+ // o’s first non-const use pset(o) becomes {o__2'}, on o’s second non-const
1115
+ // use pset(o) becomes {o__3'}, and so on.
1116
+ incOwner (ownerAddr);
1117
+ return ;
1118
+ }
1119
+
1086
1120
void LifetimeCheckPass::checkCall (CallOp callOp) {
1087
1121
if (callOp.getNumOperands () == 0 )
1088
1122
return ;
@@ -1096,7 +1130,7 @@ void LifetimeCheckPass::checkCall(CallOp callOp) {
1096
1130
if (methodDecl->isMoveAssignmentOperator ())
1097
1131
return checkMoveAssignment (callOp, methodDecl);
1098
1132
if (methodDecl->isCopyAssignmentOperator ())
1099
- llvm_unreachable ( " NYI " );
1133
+ return checkCopyAssignment (callOp, methodDecl );
1100
1134
if (isOperatorStar (methodDecl))
1101
1135
return checkOperatorStar (callOp);
1102
1136
if (sinkUnsupportedOperator (methodDecl))
@@ -1105,22 +1139,8 @@ void LifetimeCheckPass::checkCall(CallOp callOp) {
1105
1139
// For any other methods...
1106
1140
1107
1141
// Non-const member call to a Owner invalidates any of its users.
1108
- if (isNonConstUseOfOwner (callOp, methodDecl)) {
1109
- auto ownerAddr = callOp.getOperand (0 );
1110
- // 2.4.2 - On every non-const use of a local Owner o:
1111
- //
1112
- // - For each entry e in pset(s): Remove e from pset(s), and if no other
1113
- // Owner’s pset contains only e, then KILL(e).
1114
- kill (State::getOwnedBy (ownerAddr), InvalidStyle::NonConstUseOfOwner,
1115
- callOp.getLoc ());
1116
-
1117
- // - Set pset(o) = {o__N'}, where N is one higher than the highest
1118
- // previously used suffix. For example, initially pset(o) is {o__1'}, on
1119
- // o’s first non-const use pset(o) becomes {o__2'}, on o’s second non-const
1120
- // use pset(o) becomes {o__3'}, and so on.
1121
- incOwner (ownerAddr);
1122
- return ;
1123
- }
1142
+ if (isNonConstUseOfOwner (callOp, methodDecl))
1143
+ return checkNonConstUseOfOwner (callOp);
1124
1144
1125
1145
// Take a pset(Ptr) = { Ownr' } where Own got invalidated, this will become
1126
1146
// invalid access to Ptr if any of its methods are used.
0 commit comments