Skip to content

Commit 912bcf9

Browse files
committed
C++: Add more classes supporting transformed types
1 parent 6686222 commit 912bcf9

File tree

3 files changed

+115
-67
lines changed

3 files changed

+115
-67
lines changed

cpp/ql/lib/cpp.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import semmle.code.cpp.Include
2626
import semmle.code.cpp.Macro
2727
import semmle.code.cpp.Type
2828
import semmle.code.cpp.TypedefType
29+
import semmle.code.cpp.TransformedType
2930
import semmle.code.cpp.Class
3031
import semmle.code.cpp.Struct
3132
import semmle.code.cpp.Union
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/**
2+
* Provides classes for modeling types obtained by applying type transforming
3+
* intrinsics or the C23 `typeof` operator to a type.
4+
*/
5+
6+
import semmle.code.cpp.Type
7+
8+
/**
9+
* A type obtained by applying a type transforming intrinsic or the C23 `typeof`
10+
* operator to a type. For example:
11+
* ```
12+
* __make_unsigned(int) x;
13+
* typeof_unqual(const int) y;
14+
* ```
15+
*/
16+
class TransformedType extends Type, @type_operator {
17+
override string getAPrimaryQlClass() { result = "TransformedType" }
18+
19+
/**
20+
* Gets the type immediately yielded by this transformation.
21+
*/
22+
Type getBaseType() { type_operators(underlyingElement(this), _, _, unresolveElement(result)) }
23+
24+
/**
25+
* Gets the type that is transformed.
26+
*/
27+
Type getTransformedType() {
28+
type_operators(underlyingElement(this), unresolveElement(result), _, _)
29+
}
30+
31+
override Type getUnderlyingType() { result = this.getBaseType().getUnderlyingType() }
32+
33+
override Type stripTopLevelSpecifiers() { result = this.getBaseType().stripTopLevelSpecifiers() }
34+
35+
override Type stripType() { result = this.getBaseType().stripType() }
36+
37+
override Type resolveTypedefs() { result = this.getBaseType().resolveTypedefs() }
38+
39+
override string getName() { none() }
40+
41+
override int getSize() { result = this.getBaseType().getSize() }
42+
43+
override int getAlignment() { result = this.getBaseType().getAlignment() }
44+
45+
override int getPointerIndirectionLevel() {
46+
result = this.getBaseType().getPointerIndirectionLevel()
47+
}
48+
49+
override string explain() {
50+
result = "type transformation resulting in {" + this.getBaseType().explain() + "}"
51+
}
52+
53+
override predicate involvesReference() { this.getBaseType().involvesReference() }
54+
55+
override predicate involvesTemplateParameter() { this.getBaseType().involvesTemplateParameter() }
56+
57+
override predicate isDeeplyConst() { this.getBaseType().isDeeplyConst() }
58+
59+
override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConstBelow() }
60+
61+
override Specifier internal_getAnAdditionalSpecifier() {
62+
result = this.getBaseType().getASpecifier()
63+
}
64+
}
65+
66+
/**
67+
* A type obtained by C23 `typeof` or `typeof_unqual` operator taking a type as its
68+
* argument. For example:
69+
* ```
70+
* typeof_unqual(const int) b;
71+
* ```
72+
*/
73+
class TypeofTypeType extends TransformedType, TypeofType {
74+
TypeofTypeType() { type_operators(underlyingElement(this), _, 0, _) }
75+
76+
override string getAPrimaryQlClass() { result = "TypeofTypeType" }
77+
78+
override string toString() { result = "typeof(...)" }
79+
80+
override Type getBaseType() { result = this.(TransformedType).getBaseType() }
81+
}
82+
83+
/**
84+
* A type obtained by applying a type transforming intrinsic. For example:
85+
* ```
86+
* __make_unsigned(int) x;
87+
* ```
88+
*/
89+
class IntrinsicTransformedType extends TransformedType {
90+
IntrinsicTransformedType() { type_operators(underlyingElement(this), _, [1 .. 19], _) }
91+
92+
override string getAPrimaryQlClass() { result = "IntrinsicTransformedType" }
93+
94+
override string toString() { result = "__...(...)" }
95+
}

cpp/ql/lib/semmle/code/cpp/Type.qll

Lines changed: 19 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class Type extends Locatable, @type {
9393
* Gets this type after typedefs have been resolved.
9494
*
9595
* The result of this predicate will be the type itself, except in the case of a TypedefType, a Decltype,
96-
* or a TypeofExprType, in which case the result will be type which results from (possibly recursively)
96+
* or a TypeofType, in which case the result will be type which results from (possibly recursively)
9797
* resolving typedefs.
9898
*/
9999
pragma[nomagic]
@@ -1111,6 +1111,20 @@ class DerivedType extends Type, @derivedtype {
11111111
override Type stripType() { result = this.getBaseType().stripType() }
11121112
}
11131113

1114+
/**
1115+
* An instance of the C23 `typeof` operator. For example:
1116+
* ```
1117+
* int a;
1118+
* typeof(a) b;
1119+
* ```
1120+
*/
1121+
abstract class TypeofType extends Type {
1122+
/**
1123+
* Gets the type immediately yielded by this typeof.
1124+
*/
1125+
abstract Type getBaseType();
1126+
}
1127+
11141128
/**
11151129
* An instance of the C++11 `decltype` operator. For example:
11161130
* ```
@@ -1187,14 +1201,14 @@ class Decltype extends Type, @decltype {
11871201
}
11881202

11891203
/**
1190-
* An instance of the C23 `typeof` operator taking an expression as its argument.
1191-
* For example:
1204+
* An instance of the C23 `typeof` or `typeof_unqual` operator taking an expression
1205+
* as its argument. For example:
11921206
* ```
11931207
* int a;
11941208
* typeof(a) b;
11951209
* ```
11961210
*/
1197-
class TypeofExprType extends Type, @decltype {
1211+
class TypeofExprType extends TypeofType, @decltype {
11981212
TypeofExprType() { decltypes(underlyingElement(this), _, 1, _, _) }
11991213

12001214
override string getAPrimaryQlClass() { result = "TypeofExprType" }
@@ -1204,10 +1218,7 @@ class TypeofExprType extends Type, @decltype {
12041218
*/
12051219
Expr getExpr() { decltypes(underlyingElement(this), unresolveElement(result), _, _, _) }
12061220

1207-
/**
1208-
* Gets the type immediately yielded by this typeof.
1209-
*/
1210-
Type getBaseType() { decltypes(underlyingElement(this), _, _, unresolveElement(result), _) }
1221+
override Type getBaseType() { decltypes(underlyingElement(this), _, _, unresolveElement(result), _) }
12111222

12121223
override Type getUnderlyingType() { result = this.getBaseType().getUnderlyingType() }
12131224

@@ -1248,65 +1259,6 @@ class TypeofExprType extends Type, @decltype {
12481259
}
12491260
}
12501261

1251-
/**
1252-
* A type obtained by applying a type transforming intrinsic or the C23 `typeof`
1253-
* operator to a type.
1254-
* For example:
1255-
* ```
1256-
* __make_unsigned(int) x;
1257-
* typeof_unqual(const int) y;
1258-
* ```
1259-
*/
1260-
class TransformedType extends Type, @type_operator {
1261-
override string getAPrimaryQlClass() { result = "TransformedType" }
1262-
1263-
/**
1264-
* Gets the type immediately yielded by this transformation.
1265-
*/
1266-
Type getBaseType() { type_operators(underlyingElement(this), _, _, unresolveElement(result)) }
1267-
1268-
/**
1269-
* Gets the type that is transformed.
1270-
*/
1271-
Type getTransformedType() {
1272-
type_operators(underlyingElement(this), unresolveElement(result), _, _)
1273-
}
1274-
1275-
override Type getUnderlyingType() { result = this.getBaseType().getUnderlyingType() }
1276-
1277-
override Type stripTopLevelSpecifiers() { result = this.getBaseType().stripTopLevelSpecifiers() }
1278-
1279-
override Type stripType() { result = this.getBaseType().stripType() }
1280-
1281-
override Type resolveTypedefs() { result = this.getBaseType().resolveTypedefs() }
1282-
1283-
override string getName() { none() }
1284-
1285-
override int getSize() { result = this.getBaseType().getSize() }
1286-
1287-
override int getAlignment() { result = this.getBaseType().getAlignment() }
1288-
1289-
override int getPointerIndirectionLevel() {
1290-
result = this.getBaseType().getPointerIndirectionLevel()
1291-
}
1292-
1293-
override string explain() {
1294-
result = "type transformation resulting in {" + this.getBaseType().explain() + "}"
1295-
}
1296-
1297-
override predicate involvesReference() { this.getBaseType().involvesReference() }
1298-
1299-
override predicate involvesTemplateParameter() { this.getBaseType().involvesTemplateParameter() }
1300-
1301-
override predicate isDeeplyConst() { this.getBaseType().isDeeplyConst() }
1302-
1303-
override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConstBelow() }
1304-
1305-
override Specifier internal_getAnAdditionalSpecifier() {
1306-
result = this.getBaseType().getASpecifier()
1307-
}
1308-
}
1309-
13101262
/**
13111263
* A C/C++ pointer type. See 4.9.1.
13121264
* ```

0 commit comments

Comments
 (0)