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