Skip to content

Commit d20a0c9

Browse files
committed
C++: Add a class that models wrapped pointer types.
1 parent 72ae902 commit d20a0c9

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

cpp/ql/src/semmle/code/cpp/exprs/Call.qll

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,53 @@ class OverloadedPointerDereferenceExpr extends FunctionCall {
350350
}
351351
}
352352

353+
/**
354+
* An instance of a call to a _user-defined_ `operator->`.
355+
* ```
356+
* struct T2 { T1 b; };
357+
* struct T3 { T2* operator->(); };
358+
* T3 a;
359+
* T1 x = a->b;
360+
* ```
361+
*/
362+
class OverloadedArrowExpr extends FunctionCall {
363+
OverloadedArrowExpr() { getTarget().hasName("operator->") }
364+
365+
override string getAPrimaryQlClass() { result = "OverloadedArrowExpr" }
366+
367+
/** Gets the expression this `operator->` applies to. */
368+
Expr getExpr() { result = this.getQualifier() }
369+
370+
/** Gets the field accessed by this call to `operator->`, if any. */
371+
FieldAccess getFieldAccess() { result.getQualifier() = this }
372+
373+
override predicate mayBeImpure() {
374+
FunctionCall.super.mayBeImpure() and
375+
(
376+
this.getExpr().mayBeImpure()
377+
or
378+
not exists(Class declaring |
379+
this.getTarget().getDeclaringType().isConstructedFrom*(declaring)
380+
|
381+
declaring.getNamespace() instanceof StdNamespace
382+
)
383+
)
384+
}
385+
386+
override predicate mayBeGloballyImpure() {
387+
FunctionCall.super.mayBeGloballyImpure() and
388+
(
389+
this.getExpr().mayBeGloballyImpure()
390+
or
391+
not exists(Class declaring |
392+
this.getTarget().getDeclaringType().isConstructedFrom*(declaring)
393+
|
394+
declaring.getNamespace() instanceof StdNamespace
395+
)
396+
)
397+
}
398+
}
399+
353400
/**
354401
* An instance of a _user-defined_ binary `operator[]` applied to its arguments.
355402
* ```

cpp/ql/src/semmle/code/cpp/models/Models.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@ private import implementations.Recv
3333
private import implementations.Accept
3434
private import implementations.Poll
3535
private import implementations.Select
36+
private import implementations.PointerWrapper
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/** Provides classes for modeling pointer wrapper types and expressions. */
2+
3+
private import cpp
4+
5+
/** A class that wraps a pointer type. For example, `std::unique_ptr` and `std::shared_ptr`. */
6+
class PointerWrapper extends Class {
7+
PointerWrapper() { this.hasQualifiedName(["std", "bsl", "boost"], ["shared_ptr", "unique_ptr"]) }
8+
}
9+
10+
/** An expression of a `PointerWrapper` type. */
11+
class PointerWrapperExpr extends Expr {
12+
PointerWrapperExpr() { this.getUnspecifiedType() instanceof PointerWrapper }
13+
14+
/** Gets a dereference of the wrapped pointer. */
15+
Expr getADereference() { result.(OverloadedPointerDereferenceExpr).getExpr() = this }
16+
17+
/** Gets an access to the wrapped pointer. */
18+
Expr getAPointerAccess() {
19+
result.(OverloadedArrowExpr).getExpr() = this
20+
or
21+
exists(FunctionCall call | call = result |
22+
call.getQualifier() = this and
23+
call.getTarget().hasName("get")
24+
)
25+
}
26+
}

0 commit comments

Comments
 (0)