Skip to content

Commit a7f45bb

Browse files
authored
Merge pull request #608 from jbj/assignment-this-templates
C++: Fix "Overloaded assignment does not return 'this'" for templates
2 parents a23f7a6 + 6239455 commit a7f45bb

File tree

3 files changed

+26
-3
lines changed

3 files changed

+26
-3
lines changed

cpp/ql/src/jsf/4.10 Classes/AV Rule 82.ql

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ predicate dereferenceThis(Expr e) {
5151
* This includes functions whose body is not in the database.
5252
*/
5353
predicate returnsPointerThis(Function f) {
54-
f.getType().getUnspecifiedType() instanceof PointerType and
5554
forall(ReturnStmt s | s.getEnclosingFunction() = f and reachable(s) |
5655
// `return this`
5756
pointerThis(s.getExpr())
@@ -64,7 +63,6 @@ predicate returnsPointerThis(Function f) {
6463
* database.
6564
*/
6665
predicate returnsDereferenceThis(Function f) {
67-
f.getType().getUnspecifiedType() instanceof ReferenceType and
6866
forall(ReturnStmt s | s.getEnclosingFunction() = f and reachable(s) |
6967
// `return *this`
7068
dereferenceThis(s.getExpr())
@@ -76,7 +74,7 @@ predicate assignOperatorWithWrongType(Operator op, string msg) {
7674
and exists(op.getBlock())
7775
and exists(Class c |
7876
c = op.getDeclaringType()
79-
and op.getType() = c
77+
and op.getType().getUnspecifiedType() = c
8078
and msg = "Assignment operator in class " + c.getName() + " should have return type " + c.getName() + "&. Otherwise a copy is created at each call."
8179
)
8280
}

cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 82/AV Rule 82.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,35 @@ class Forgivable {
181181
Forgivable operator=(int *_val);
182182
};
183183

184+
// This template has structure similar to `std::enable_if`.
185+
template<typename S, typename T>
186+
struct second {
187+
typedef T type;
188+
};
189+
190+
struct TemplatedAssignmentGood {
191+
template<typename T>
192+
typename second<T, TemplatedAssignmentGood &>::type operator=(T val) { // GOOD
193+
return *this;
194+
}
195+
};
196+
197+
struct TemplatedAssignmentBad {
198+
template<typename T>
199+
typename second<T, TemplatedAssignmentBad>::type operator=(T val) { // BAD (missing &)
200+
return *this;
201+
}
202+
};
203+
184204
int main() {
185205
Container c;
186206
c = c;
187207
TemplateReturnAssignment<int> tra(1);
188208
tra = 2;
189209
tra = true;
210+
TemplatedAssignmentGood taGood;
211+
taGood = 3;
212+
TemplatedAssignmentBad taBad;
213+
taBad = 4;
190214
return 0;
191215
}

cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 82/AV Rule 82.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
| AV Rule 82.cpp:24:8:24:16 | operator= | Assignment operator in class Bad2 should have return type Bad2&. Otherwise a copy is created at each call. |
33
| AV Rule 82.cpp:63:29:63:29 | operator= | Assignment operator in class TemplateReturnAssignment<int> does not return a reference to *this. |
44
| AV Rule 82.cpp:63:29:63:37 | operator= | Assignment operator in class TemplateReturnAssignment<T> does not return a reference to *this. |
5+
| AV Rule 82.cpp:199:52:199:52 | operator= | Assignment operator in class TemplatedAssignmentBad should have return type TemplatedAssignmentBad&. Otherwise a copy is created at each call. |

0 commit comments

Comments
 (0)