Skip to content

Commit ae0c4e4

Browse files
Merge pull request github#1925 from geoffw0/qldoceg10
CPP: Add syntax examples to QLDoc in Access.qll, Declaration.qll
2 parents 26fd0df + 0398681 commit ae0c4e4

File tree

8 files changed

+242
-30
lines changed

8 files changed

+242
-30
lines changed

cpp/ql/src/semmle/code/cpp/Declaration.qll

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@ private import semmle.code.cpp.internal.QualifiedName as Q
1414
* ```
1515
* extern int myglobal;
1616
* ```
17-
* Each of these declarations is given its own distinct `DeclarationEntry`,
18-
* but they all share the same `Declaration`.
17+
* and defined in one:
18+
* ```
19+
* int myglobal;
20+
* ```
21+
* Each of these declarations (including the definition) is given its own
22+
* distinct `DeclarationEntry`, but they all share the same `Declaration`.
1923
*
2024
* Some derived class of `Declaration` do not have a corresponding
2125
* `DeclarationEntry`, because they always have a unique source ___location.
@@ -206,9 +210,19 @@ abstract class Declaration extends Locatable, @declaration {
206210
}
207211

208212
/**
209-
* A C/C++ declaration entry. See the comment above `Declaration` for an
210-
* explanation of the relationship between `Declaration` and
211-
* `DeclarationEntry`.
213+
* A C/C++ declaration entry. For example the following code contains five
214+
* declaration entries:
215+
* ```
216+
* extern int myGlobal;
217+
* int myVariable;
218+
* typedef char MyChar;
219+
* void myFunction();
220+
* void myFunction() {
221+
* // ...
222+
* }
223+
* ```
224+
* See the comment above `Declaration` for an explanation of the relationship
225+
* between `Declaration` and `DeclarationEntry`.
212226
*/
213227
abstract class DeclarationEntry extends Locatable {
214228
/** Gets a specifier associated with this declaration entry. */
@@ -281,8 +295,19 @@ abstract class DeclarationEntry extends Locatable {
281295
* A declaration that can potentially have more C++ access rights than its
282296
* enclosing element. This comprises `Class` (they have access to their own
283297
* private members) along with other `UserType`s and `Function` (they can be
284-
* the target of `friend` declarations).
298+
* the target of `friend` declarations). For example `MyClass` and
299+
* `myFunction` in the following code:
300+
* ```
301+
* class MyClass
302+
* {
303+
* public:
304+
* ...
305+
* };
285306
*
307+
* void myFunction() {
308+
* // ...
309+
* }
310+
* ```
286311
* In the C++ standard (N4140 11.2), rules for access control revolve around
287312
* the informal phrase "_R_ occurs in a member or friend of class C", where
288313
* `AccessHolder` corresponds to this _R_.
@@ -416,8 +441,19 @@ abstract class AccessHolder extends Declaration {
416441
/**
417442
* A declaration that very likely has more C++ access rights than its
418443
* enclosing element. This comprises `Class` (they have access to their own
419-
* private members) along with any target of a `friend` declaration.
444+
* private members) along with any target of a `friend` declaration. For
445+
* example `MyClass` and `friendFunction` in the following code:
446+
* ```
447+
* class MyClass
448+
* {
449+
* public:
450+
* friend void friendFunction();
451+
* };
420452
*
453+
* void friendFunction() {
454+
* // ...
455+
* }
456+
* ```
421457
* Most access rights are computed for `DirectAccessHolder` instead of
422458
* `AccessHolder` -- that's more efficient because there are fewer
423459
* `DirectAccessHolder`s. If a `DirectAccessHolder` contains an `AccessHolder`,

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

Lines changed: 136 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,18 @@ abstract class Access extends Expr, NameQualifiableElement {
1818
}
1919

2020
/**
21-
* A C/C++ enum constant access expression.
21+
* A C/C++ `enum` constant access expression. For example the access to
22+
* `MYENUMCONST1` in `myFunction` in the following code:
23+
* ```
24+
* enum MyEnum {
25+
* MYENUMCONST1,
26+
* MYENUMCONST2
27+
* };
28+
*
29+
* void myFunction() {
30+
* MyEnum v = MYENUMCONST1;
31+
* };
32+
* ```
2233
*/
2334
class EnumConstantAccess extends Access, @varaccess {
2435
override string getCanonicalQLClass() { result = "EnumConstantAccess" }
@@ -27,15 +38,23 @@ class EnumConstantAccess extends Access, @varaccess {
2738
exists(EnumConstant c | varbind(underlyingElement(this), unresolveElement(c)))
2839
}
2940

30-
/** Gets the accessed enum constant. */
41+
/** Gets the accessed `enum` constant. */
3142
override EnumConstant getTarget() { varbind(underlyingElement(this), unresolveElement(result)) }
3243

33-
/** Gets a textual representation of this enum constant access. */
44+
/** Gets a textual representation of this `enum` constant access. */
3445
override string toString() { result = this.getTarget().getName() }
3546
}
3647

3748
/**
38-
* A C/C++ variable access expression.
49+
* A C/C++ variable access expression. For example the accesses to
50+
* `x` and `y` in `myFunction` in the following code:
51+
* ```
52+
* int x;
53+
*
54+
* void myFunction(int y) {
55+
* x = y;
56+
* };
57+
* ```
3958
*/
4059
class VariableAccess extends Access, @varaccess {
4160
override string getCanonicalQLClass() { result = "VariableAccess" }
@@ -129,7 +148,18 @@ class VariableAccess extends Access, @varaccess {
129148
}
130149

131150
/**
132-
* A C/C++ field access expression.
151+
* A C/C++ field access expression. For example the accesses to
152+
* `x` and `y` in `myMethod` in the following code:
153+
* ```
154+
* class MyClass {
155+
* public:
156+
* void myMethod(MyClass &other) {
157+
* x = other.y;
158+
* }
159+
*
160+
* int x, y;
161+
* };
162+
* ```
133163
*/
134164
class FieldAccess extends VariableAccess {
135165
override string getCanonicalQLClass() { result = "FieldAccess" }
@@ -141,8 +171,23 @@ class FieldAccess extends VariableAccess {
141171
}
142172

143173
/**
144-
* A field access of the form `obj->field`. The type of `obj` is a pointer,
145-
* so this is equivalent to `(*obj).field`.
174+
* A field access whose qualifier is a pointer to a class, struct or union.
175+
* These typically take the form `obj->field`. Another case is a field access
176+
* with an implicit `this->` qualifier, which is often a `PointerFieldAccess`
177+
* (but see also `ImplicitThisFieldAccess`).
178+
*
179+
* For example the accesses to `x` and `y` in `myMethod` in the following code
180+
* are each a `PointerFieldAccess`:
181+
* ```
182+
* class MyClass {
183+
* public:
184+
* void myMethod(MyClass *other) {
185+
* other->x = y;
186+
* }
187+
*
188+
* int x, y;
189+
* };
190+
* ```
146191
*/
147192
class PointerFieldAccess extends FieldAccess {
148193
override string getCanonicalQLClass() { result = "PointerFieldAccess" }
@@ -169,7 +214,18 @@ class DotFieldAccess extends FieldAccess {
169214

170215
/**
171216
* A field access of the form `obj.field`, where the type of `obj` is a
172-
* reference to a class/struct/union.
217+
* reference to a class/struct/union. For example the accesses to `y` in
218+
* `myMethod` in the following code:
219+
* ```
220+
* class MyClass {
221+
* public:
222+
* void myMethod(MyClass a, MyClass &b) {
223+
* a.x = b.y;
224+
* }
225+
*
226+
* int x, y;
227+
* };
228+
* ```
173229
*/
174230
class ReferenceFieldAccess extends DotFieldAccess {
175231
override string getCanonicalQLClass() { result = "ReferenceFieldAccess" }
@@ -179,7 +235,18 @@ class ReferenceFieldAccess extends DotFieldAccess {
179235

180236
/**
181237
* A field access of the form `obj.field`, where the type of `obj` is a
182-
* class/struct/union (and not a reference).
238+
* class/struct/union (and not a reference). For example the accesses to `x`
239+
* in `myMethod` in the following code:
240+
* ```
241+
* class MyClass {
242+
* public:
243+
* void myMethod(MyClass a, MyClass &b) {
244+
* a.x = b.y;
245+
* }
246+
*
247+
* int x, y;
248+
* };
249+
* ```
183250
*/
184251
class ValueFieldAccess extends DotFieldAccess {
185252
override string getCanonicalQLClass() { result = "ValueFieldAccess" }
@@ -198,25 +265,40 @@ private predicate referenceConversion(Conversion c) {
198265
/**
199266
* Holds if `e` is a reference expression (that is, it has a type of the
200267
* form `T&`), which is converted to a value. For example:
201-
*
202268
* ```
203269
* int myfcn(MyStruct &x) {
204270
* return x.field;
205271
* }
206272
* ```
207-
*
208273
* In this example, the type of `x` is `MyStruct&`, but it gets implicitly
209274
* converted to `MyStruct` in the expression `x.field`.
210275
*/
211276
private predicate exprHasReferenceConversion(Expr e) { referenceConversion(e.getConversion+()) }
212277

213278
/**
214-
* A field access of a field of `this`. The access has no qualifier because
215-
* the use of `this` is implicit. For example, `field` is equivalent to
216-
* `this->field` if `field` is a member of `this`.
279+
* A field access of a field of `this` which has no qualifier because
280+
* the use of `this` is implicit. For example, in the following code the
281+
* implicit call to the destructor of `A` has no qualifier because the
282+
* use of `this` is implicit:
283+
* ```
284+
* class A {
285+
* public:
286+
* ~A() {
287+
* // ...
288+
* }
289+
* };
217290
*
291+
* class B {
292+
* public:
293+
* A a;
294+
*
295+
* ~B() {
296+
* // Implicit call to the destructor of `A`.
297+
* }
298+
* };
299+
* ```
218300
* Note: the C++ front-end often automatically desugars `field` to
219-
* `this->field`, so most implicit accesses of `this->field` are instances
301+
* `this->field`, so most accesses of `this->field` are instances
220302
* of `PointerFieldAccess` (with `ThisExpr` as the qualifier), not
221303
* `ImplicitThisFieldAccess`.
222304
*/
@@ -250,7 +332,15 @@ class PointerToFieldLiteral extends ImplicitThisFieldAccess {
250332
}
251333

252334
/**
253-
* A C/C++ function access expression.
335+
* A C/C++ function access expression. For example the access to
336+
* `myFunctionTarget` in `myFunction` in the following code:
337+
* ```
338+
* int myFunctionTarget(int);
339+
*
340+
* void myFunction() {
341+
* int (*myFunctionPointer)(int) = &myTarget;
342+
* }
343+
* ```
254344
*/
255345
class FunctionAccess extends Access, @routineexpr {
256346
FunctionAccess() { not iscall(underlyingElement(this), _) }
@@ -269,7 +359,7 @@ class FunctionAccess extends Access, @routineexpr {
269359
}
270360

271361
/**
272-
* An access to a parameter of a function signature for the purposes of a decltype.
362+
* An access to a parameter of a function signature for the purposes of a `decltype`.
273363
*
274364
* For example, given the following code:
275365
* ```
@@ -279,15 +369,30 @@ class FunctionAccess extends Access, @routineexpr {
279369
* }
280370
* ```
281371
* The return type of the function is a decltype, the expression of which contains
282-
* an add expression, which in turn has two ParamAccessForType children.
372+
* an add expression, which in turn has two `ParamAccessForType` children.
283373
*/
284374
class ParamAccessForType extends Expr, @param_ref {
285375
override string toString() { result = "param access" }
286376
}
287377

288378
/**
289379
* An access to a type. This occurs in certain contexts where a built-in
290-
* works on types directly rather than variables, expressions etc.
380+
* works on types directly rather than variables, expressions etc. For
381+
* example the reference to `MyClass` in `__is_pod` in the following code:
382+
* ```
383+
* class MyClass {
384+
* ...
385+
* };
386+
*
387+
* void myFunction() {
388+
* if (__is_pod(MyClass))
389+
* {
390+
* ...
391+
* } else {
392+
* ...
393+
* }
394+
* }
395+
* ```
291396
*/
292397
class TypeName extends Expr, @type_operand {
293398
override string getCanonicalQLClass() { result = "TypeName" }
@@ -296,24 +401,32 @@ class TypeName extends Expr, @type_operand {
296401
}
297402

298403
/**
299-
* A C/C++ array access expression.
404+
* A C/C++ array access expression. For example, the access to `as` in
405+
* `myFunction` in the following code:
406+
* ```
407+
* int as[10];
300408
*
301-
* For calls to operator[], which look syntactically identical, see OverloadedArrayExpr.
409+
* void myFunction() {
410+
* as[0]++;
411+
* }
412+
* ```
413+
* For calls to `operator[]`, which look syntactically identical, see
414+
* `OverloadedArrayExpr`.
302415
*/
303416
class ArrayExpr extends Expr, @subscriptexpr {
304417
override string getCanonicalQLClass() { result = "ArrayExpr" }
305418

306419
/**
307420
* Gets the array or pointer expression being subscripted.
308421
*
309-
* This is arr in both arr[0] and 0[arr].
422+
* This is `arr` in both `arr[0]` and `0[arr]`.
310423
*/
311424
Expr getArrayBase() { result = this.getChild(0) }
312425

313426
/**
314427
* Gets the expression giving the index into the array.
315428
*
316-
* This is 0 in both arr[0] and 0[arr].
429+
* This is `0` in both `arr[0]` and `0[arr]`.
317430
*/
318431
Expr getArrayOffset() { result = this.getChild(1) }
319432

cpp/ql/src/semmle/code/cpp/stmts/Stmt.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1645,6 +1645,7 @@ class EnumSwitch extends SwitchStmt {
16451645
* } catch (std::exception &e) {
16461646
* g();
16471647
* }
1648+
* ```
16481649
* there is a handler that's associated with the `catch` block and controls
16491650
* entry to it.
16501651
*/

cpp/ql/test/library-tests/access/FieldAccess/FieldAccess.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,34 @@ int test_val00(S s) {
8484
int test_val01(U u) {
8585
return u.x;
8686
}
87+
88+
class MyClass {
89+
public:
90+
void myMethod(MyClass a, MyClass &b, MyClass *c) {
91+
a.x = b.y; // val, ref
92+
c->x = y; // ptr, ptr
93+
c->x = this->y; // ptr, ptr
94+
(&b)->y = (*c).y; // ptr, val
95+
}
96+
97+
int x, y;
98+
};
99+
100+
class MyHasDestructor1 {
101+
public:
102+
~MyHasDestructor1() {
103+
// ...
104+
}
105+
};
106+
107+
class MyHasDestructor2 {
108+
public:
109+
int x;
110+
MyHasDestructor1 v;
111+
112+
~MyHasDestructor2() {
113+
x++; // PointerFieldAccess, the `this->` is generated rather than implicit.
114+
115+
// ImplicitThisFieldAccess on call `v`s destructor.
116+
}
117+
};

0 commit comments

Comments
 (0)