Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 09d74a3

Browse files
committed
C++: Move 'CanonicalField' stuff.
1 parent 271a759 commit 09d74a3

2 files changed

Lines changed: 138 additions & 151 deletions

File tree

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,142 @@
11
private import cpp
2+
private import semmle.code.cpp.ir.ValueNumbering
3+
private import semmle.code.cpp.ir.IR
4+
private import semmle.code.cpp.models.interfaces.DataFlow
5+
private import semmle.code.cpp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
6+
private import DataFlowPrivate
7+
private import DataFlowUtil
8+
private import ModelUtil
9+
private import SsaImpl as SsaImpl
10+
private import DataFlowImplCommon as DataFlowImplCommon
11+
private import codeql.util.Unit
12+
private import Node0ToString
13+
import ExprNodes
14+
15+
/**
16+
* A canonical representation of a field.
17+
*
18+
* For performance reasons we want a unique `Content` that represents
19+
* a given field across any template instantiation of a class.
20+
*
21+
* This is possible in _almost_ all cases, but there are cases where it is
22+
* not possible to map between a field in the uninstantiated template to a
23+
* field in the instantiated template. This happens in the case of local class
24+
* definitions (because the local class is not the template that constructs
25+
* the instantiation - it is the enclosing function). So this abstract class
26+
* has two implementations: a non-local case (where we can represent a
27+
* canonical field as the field declaration from an uninstantiated class
28+
* template or a non-templated class), and a local case (where we simply use
29+
* the field from the instantiated class).
30+
*/
31+
abstract class CanonicalField extends Field {
32+
/** Gets a field represented by this canonical field. */
33+
abstract Field getAField();
34+
35+
/**
36+
* Gets a class that declares a field represented by this canonical field.
37+
*/
38+
abstract Class getADeclaringType();
39+
40+
/**
41+
* Gets a type that this canonical field may have. Note that this may
42+
* not be a unique type. For example, consider this case:
43+
* ```
44+
* template<typename T>
45+
* struct S { T x; };
46+
*
47+
* S<int> s1;
48+
* S<char> s2;
49+
* ```
50+
* In this case the canonical field corresponding to `S::x` has two types:
51+
* `int` and `char`.
52+
*/
53+
Type getAType() { result = this.getAField().getType() }
54+
55+
Type getAnUnspecifiedType() { result = this.getAType().getUnspecifiedType() }
56+
}
57+
58+
private class NonLocalCanonicalField extends CanonicalField {
59+
Class declaringType;
60+
61+
NonLocalCanonicalField() {
62+
declaringType = this.getDeclaringType() and
63+
not declaringType.isFromTemplateInstantiation(_) and
64+
not declaringType.isLocal() // handled in LocalCanonicalField
65+
}
66+
67+
override Field getAField() {
68+
exists(Class c | result.getDeclaringType() = c |
69+
// Either the declaring class of the field is a template instantiation
70+
// that has been constructed from this canonical declaration
71+
c.isConstructedFrom(declaringType) and
72+
pragma[only_bind_out](result.getName()) = pragma[only_bind_out](this.getName())
73+
or
74+
// or this canonical declaration is not a template.
75+
not c.isConstructedFrom(_) and
76+
result = this
77+
)
78+
}
79+
80+
override Class getADeclaringType() {
81+
result = this.getDeclaringType()
82+
or
83+
result.isConstructedFrom(this.getDeclaringType())
84+
}
85+
}
86+
87+
private class LocalCanonicalField extends CanonicalField {
88+
Class declaringType;
89+
90+
LocalCanonicalField() {
91+
declaringType = this.getDeclaringType() and
92+
declaringType.isLocal()
93+
}
94+
95+
override Field getAField() { result = this }
96+
97+
override Class getADeclaringType() { result = declaringType }
98+
}
99+
100+
/**
101+
* A canonical representation of a `Union`. See `CanonicalField` for the explanation for
102+
* why we need a canonical representation.
103+
*/
104+
abstract class CanonicalUnion extends Union {
105+
/** Gets a union represented by this canonical union. */
106+
abstract Union getAUnion();
107+
108+
/** Gets a canonical field of this canonical union. */
109+
CanonicalField getACanonicalField() { result.getDeclaringType() = this }
110+
}
111+
112+
private class NonLocalCanonicalUnion extends CanonicalUnion {
113+
NonLocalCanonicalUnion() { not this.isFromTemplateInstantiation(_) and not this.isLocal() }
114+
115+
override Union getAUnion() {
116+
result = this
117+
or
118+
result.isConstructedFrom(this)
119+
}
120+
}
121+
122+
private class LocalCanonicalUnion extends CanonicalUnion {
123+
LocalCanonicalUnion() { this.isLocal() }
124+
125+
override Union getAUnion() { result = this }
126+
}
127+
128+
bindingset[f]
129+
pragma[inline_late]
130+
int getFieldSize(CanonicalField f) { result = max(f.getAType().getSize()) }
131+
132+
/**
133+
* Gets a field in the union `u` whose size
134+
* is `bytes` number of bytes.
135+
*/
136+
private CanonicalField getAFieldWithSize(CanonicalUnion u, int bytes) {
137+
result = u.getACanonicalField() and
138+
bytes = getFieldSize(result)
139+
}
2140

3141
cached
4142
private module Cached {

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 0 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -2029,157 +2029,6 @@ predicate localExprFlow(Expr e1, Expr e2) {
20292029
localExprFlowPlus(e1, e2)
20302030
}
20312031

2032-
/**
2033-
* A canonical representation of a field.
2034-
*
2035-
* For performance reasons we want a unique `Content` that represents
2036-
* a given field across any template instantiation of a class.
2037-
*
2038-
* This is possible in _almost_ all cases, but there are cases where it is
2039-
* not possible to map between a field in the uninstantiated template to a
2040-
* field in the instantiated template. This happens in the case of local class
2041-
* definitions (because the local class is not the template that constructs
2042-
* the instantiation - it is the enclosing function). So this abstract class
2043-
* has two implementations: a non-local case (where we can represent a
2044-
* canonical field as the field declaration from an uninstantiated class
2045-
* template or a non-templated class), and a local case (where we simply use
2046-
* the field from the instantiated class).
2047-
*/
2048-
abstract private class CanonicalField extends Field {
2049-
/** Gets a field represented by this canonical field. */
2050-
abstract Field getAField();
2051-
2052-
/**
2053-
* Gets a class that declares a field represented by this canonical field.
2054-
*/
2055-
abstract Class getADeclaringType();
2056-
2057-
/**
2058-
* Gets a type that this canonical field may have. Note that this may
2059-
* not be a unique type. For example, consider this case:
2060-
* ```
2061-
* template<typename T>
2062-
* struct S { T x; };
2063-
*
2064-
* S<int> s1;
2065-
* S<char> s2;
2066-
* ```
2067-
* In this case the canonical field corresponding to `S::x` has two types:
2068-
* `int` and `char`.
2069-
*/
2070-
Type getAType() { result = this.getAField().getType() }
2071-
2072-
Type getAnUnspecifiedType() { result = this.getAType().getUnspecifiedType() }
2073-
}
2074-
2075-
private class NonLocalCanonicalField extends CanonicalField {
2076-
Class declaringType;
2077-
2078-
NonLocalCanonicalField() {
2079-
declaringType = this.getDeclaringType() and
2080-
not declaringType.isFromTemplateInstantiation(_) and
2081-
not declaringType.isLocal() // handled in LocalCanonicalField
2082-
}
2083-
2084-
override Field getAField() {
2085-
exists(Class c | result.getDeclaringType() = c |
2086-
// Either the declaring class of the field is a template instantiation
2087-
// that has been constructed from this canonical declaration
2088-
c.isConstructedFrom(declaringType) and
2089-
pragma[only_bind_out](result.getName()) = pragma[only_bind_out](this.getName())
2090-
or
2091-
// or this canonical declaration is not a template.
2092-
not c.isConstructedFrom(_) and
2093-
result = this
2094-
)
2095-
}
2096-
2097-
override Class getADeclaringType() {
2098-
result = this.getDeclaringType()
2099-
or
2100-
result.isConstructedFrom(this.getDeclaringType())
2101-
}
2102-
}
2103-
2104-
private class LocalCanonicalField extends CanonicalField {
2105-
Class declaringType;
2106-
2107-
LocalCanonicalField() {
2108-
declaringType = this.getDeclaringType() and
2109-
declaringType.isLocal()
2110-
}
2111-
2112-
override Field getAField() { result = this }
2113-
2114-
override Class getADeclaringType() { result = declaringType }
2115-
}
2116-
2117-
/**
2118-
* A canonical representation of a `Union`. See `CanonicalField` for the explanation for
2119-
* why we need a canonical representation.
2120-
*/
2121-
abstract private class CanonicalUnion extends Union {
2122-
/** Gets a union represented by this canonical union. */
2123-
abstract Union getAUnion();
2124-
2125-
/** Gets a canonical field of this canonical union. */
2126-
CanonicalField getACanonicalField() { result.getDeclaringType() = this }
2127-
}
2128-
2129-
private class NonLocalCanonicalUnion extends CanonicalUnion {
2130-
NonLocalCanonicalUnion() { not this.isFromTemplateInstantiation(_) and not this.isLocal() }
2131-
2132-
override Union getAUnion() {
2133-
result = this
2134-
or
2135-
result.isConstructedFrom(this)
2136-
}
2137-
}
2138-
2139-
private class LocalCanonicalUnion extends CanonicalUnion {
2140-
LocalCanonicalUnion() { this.isLocal() }
2141-
2142-
override Union getAUnion() { result = this }
2143-
}
2144-
2145-
bindingset[f]
2146-
pragma[inline_late]
2147-
private int getFieldSize(CanonicalField f) { result = max(f.getAType().getSize()) }
2148-
2149-
/**
2150-
* Gets a field in the union `u` whose size
2151-
* is `bytes` number of bytes.
2152-
*/
2153-
private CanonicalField getAFieldWithSize(CanonicalUnion u, int bytes) {
2154-
result = u.getACanonicalField() and
2155-
bytes = getFieldSize(result)
2156-
}
2157-
2158-
cached
2159-
private newtype TContent =
2160-
TNonUnionContent(CanonicalField f, int indirectionIndex) {
2161-
// the indirection index for field content starts at 1 (because `TNonUnionContent` is thought of as
2162-
// the address of the field, `FieldAddress` in the IR).
2163-
indirectionIndex = [1 .. max(SsaImpl::getMaxIndirectionsForType(f.getAnUnspecifiedType()))] and
2164-
// Reads and writes of union fields are tracked using `UnionContent`.
2165-
not f.getDeclaringType() instanceof Union
2166-
} or
2167-
TUnionContent(CanonicalUnion u, int bytes, int indirectionIndex) {
2168-
exists(CanonicalField f |
2169-
f = u.getACanonicalField() and
2170-
bytes = getFieldSize(f) and
2171-
// We key `UnionContent` by the union instead of its fields since a write to one
2172-
// field can be read by any read of the union's fields. Again, the indirection index
2173-
// is 1-based (because 0 is considered the address).
2174-
indirectionIndex =
2175-
[1 .. max(SsaImpl::getMaxIndirectionsForType(getAFieldWithSize(u, bytes)
2176-
.getAnUnspecifiedType())
2177-
)]
2178-
)
2179-
} or
2180-
TElementContent(int indirectionIndex) {
2181-
indirectionIndex = [1 .. getMaxElementContentIndirectionIndex()]
2182-
}
21832032

21842033
/**
21852034
* A description of the way data may be stored inside an object. Examples

0 commit comments

Comments
 (0)