Skip to content

Commit 18b28b1

Browse files
authored
Merge pull request github#1959 from jbj/const-pmf
C++: Classify more expressions as constant
2 parents e1594a4 + 0aafa0b commit 18b28b1

File tree

9 files changed

+67
-10
lines changed

9 files changed

+67
-10
lines changed

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ class Expr extends StmtParent, @expr {
131131
valuebind(_, underlyingElement(this))
132132
or
133133
addressConstantExpression(this)
134+
or
135+
constantTemplateLiteral(this)
134136
}
135137

136138
/**
@@ -1119,3 +1121,17 @@ private predicate isStandardPlacementNewAllocator(Function operatorNew) {
11191121

11201122
// Pulled out for performance. See QL-796.
11211123
private predicate hasNoConversions(Expr e) { not e.hasConversion() }
1124+
1125+
/**
1126+
* Holds if `e` is a literal of unknown value in a template, or a cast thereof.
1127+
* We assume that such literals are constant.
1128+
*/
1129+
private predicate constantTemplateLiteral(Expr e) {
1130+
// Unknown literals in uninstantiated templates could be enum constant
1131+
// accesses or pointer-to-member literals.
1132+
e instanceof Literal and
1133+
e.isFromUninstantiatedTemplate(_) and
1134+
not exists(e.getValue())
1135+
or
1136+
constantTemplateLiteral(e.(Cast).getExpr())
1137+
}

cpp/ql/src/semmle/code/cpp/internal/AddressConstantExpression.qll

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ private predicate constantAddressLValue(Expr lvalue) {
3232
// tells us how it's going to be used.
3333
lvalue.(FunctionAccess).getType() instanceof RoutineType
3434
or
35+
// Pointer-to-member literals in uninstantiated templates
36+
lvalue instanceof Literal and
37+
not exists(lvalue.getValue()) and
38+
lvalue.isFromUninstantiatedTemplate(_)
39+
or
3540
// String literals have array types and undergo array-to-pointer conversion.
3641
lvalue instanceof StringLiteral
3742
or
@@ -61,6 +66,10 @@ private predicate constantAddressPointer(Expr pointer) {
6166
// tells us how it's going to be used.
6267
pointer.(FunctionAccess).getType() instanceof FunctionPointerType
6368
or
69+
// Pointer to member function. These accesses are always pointers even though
70+
// their type is `RoutineType`.
71+
pointer.(FunctionAccess).getTarget() instanceof MemberFunction
72+
or
6473
addressConstantVariable(pointer.(VariableAccess).getTarget()) and
6574
pointer.getType().getUnderlyingType() instanceof PointerType
6675
or

cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ instructionWithoutSuccessor
2020
| ms_try_mix.cpp:11:12:11:15 | Chi: call to C |
2121
| ms_try_mix.cpp:28:12:28:15 | Chi: call to C |
2222
| ms_try_mix.cpp:48:10:48:13 | Chi: call to C |
23-
| pointer_to_member.cpp:35:11:35:21 | FieldAddress: {...} |
23+
| pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} |
2424
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... |
2525
| vla.c:5:9:5:14 | Uninitialized: definition of matrix |
2626
| vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef |

cpp/ql/test/library-tests/syntax-zoo/pointer_to_member.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,16 @@ int usePM(int PM::* pm) {
3232
void pmIsConst() {
3333
static const struct {
3434
int PM::* pm1;
35-
} pms = { &PM::x1 };
35+
void (PM::* pm2)();
36+
} pms = { &PM::x1, &PM::f1 };
3637
}
38+
39+
template<typename T>
40+
void pmIsConstT() {
41+
static const struct {
42+
int T::* pm1;
43+
void (T::* pm2)();
44+
} pms = { &T::x1, &T::f1 };
45+
}
46+
47+
template void pmIsConstT<PM>();

cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ missingOperand
77
| misc.c:220:3:223:3 | Store: ... = ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) |
88
| misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) |
99
| misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) |
10-
| pointer_to_member.cpp:35:13:35:19 | FieldAddress: x1 | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
10+
| pointer_to_member.cpp:36:13:36:19 | FieldAddress: x1 | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
1111
| range_analysis.c:368:10:368:21 | Store: ... ? ... : ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | range_analysis.c:355:14:355:27 | IR: test_ternary01 | unsigned int test_ternary01(unsigned int) |
1212
| range_analysis.c:369:10:369:36 | Store: ... ? ... : ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | range_analysis.c:355:14:355:27 | IR: test_ternary01 | unsigned int test_ternary01(unsigned int) |
1313
| range_analysis.c:370:10:370:38 | Store: ... ? ... : ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | range_analysis.c:355:14:355:27 | IR: test_ternary01 | unsigned int test_ternary01(unsigned int) |
@@ -66,7 +66,7 @@ instructionWithoutSuccessor
6666
| ms_try_mix.cpp:48:10:48:13 | CallSideEffect: call to C |
6767
| ms_try_mix.cpp:51:5:51:11 | ThrowValue: throw ... |
6868
| ms_try_mix.cpp:53:13:54:3 | NoOp: { ... } |
69-
| pointer_to_member.cpp:35:11:35:21 | FieldAddress: {...} |
69+
| pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} |
7070
| static_init_templates.cpp:80:27:80:36 | Convert: (void *)... |
7171
| static_init_templates.cpp:80:27:80:36 | Convert: (void *)... |
7272
| static_init_templates.cpp:89:27:89:36 | Convert: (void *)... |
@@ -673,7 +673,8 @@ useNotDominatedByDefinition
673673
| ms_try_mix.cpp:38:16:38:19 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | ms_try_mix.cpp:27:6:27:19 | IR: ms_finally_mix | void ms_finally_mix(int) |
674674
| ms_try_mix.cpp:41:12:41:15 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | ms_try_mix.cpp:27:6:27:19 | IR: ms_finally_mix | void ms_finally_mix(int) |
675675
| ms_try_mix.cpp:51:5:51:11 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | ms_try_mix.cpp:47:6:47:28 | IR: ms_empty_finally_at_end | void ms_empty_finally_at_end() |
676-
| pointer_to_member.cpp:35:13:35:19 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
676+
| pointer_to_member.cpp:36:11:36:30 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
677+
| pointer_to_member.cpp:36:13:36:19 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
677678
| stmt_expr.cpp:30:20:30:21 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | stmt_expr.cpp:21:6:21:6 | IR: g | void stmtexpr::g(int) |
678679
| stmt_expr.cpp:31:16:31:18 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | stmt_expr.cpp:21:6:21:6 | IR: g | void stmtexpr::g(int) |
679680
| try_catch.cpp:21:13:21:24 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | try_catch.cpp:19:6:19:23 | IR: throw_from_nonstmt | void throw_from_nonstmt(int) |

cpp/ql/test/library-tests/syntax-zoo/staticlocals.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,16 @@ void f2() {
2929
static C c{};
3030
}
3131

32+
template<typename T>
33+
struct Sizeof {
34+
enum sizeof_enum { value = sizeof(T) };
35+
};
36+
37+
template<typename T>
38+
void f3() {
39+
static int i = Sizeof<T>::value;
40+
}
41+
42+
template void f3<int>();
43+
3244
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
| staticlocals__staticlocals_f2 | file://:0:0:0:0 | call to C | staticlocals.cpp:30:1:30:1 | return ... | Standard edge, only from QL |
2-
| staticlocals__staticlocals_f2 | file://:0:0:0:0 | initializer for c | file://:0:0:0:0 | call to C | Standard edge, only from QL |
3-
| staticlocals__staticlocals_f2 | staticlocals.cpp:29:5:29:17 | declaration | file://:0:0:0:0 | initializer for c | Standard edge, only from QL |
1+
| staticlocals__staticlocals_f2 | file://:0:0:0:0 | call to C | staticlocals.cpp:30:1:30:1 | return ... | Standard edge, only from QL | |
2+
| staticlocals__staticlocals_f2 | file://:0:0:0:0 | initializer for c | file://:0:0:0:0 | call to C | Standard edge, only from QL | |
3+
| staticlocals__staticlocals_f2 | staticlocals.cpp:29:5:29:17 | declaration | file://:0:0:0:0 | initializer for c | Standard edge, only from QL | |
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
import Compare
22

3+
string describeTemplate(ControlFlowNode node) {
4+
node.isFromTemplateInstantiation(_) and
5+
result = "instantiation"
6+
or
7+
node.isFromUninstantiatedTemplate(_) and
8+
result = "uninstantiated"
9+
}
10+
311
from ControlFlowNode n1, ControlFlowNode n2, string msg
412
where differentEdge(n1, n2, msg)
5-
select getScopeName(n1), n1, n2, msg
13+
select getScopeName(n1), n1, n2, msg, concat(describeTemplate(n1), ", ")

cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ instructionWithoutSuccessor
2929
| ms_try_mix.cpp:11:12:11:15 | CallSideEffect: call to C |
3030
| ms_try_mix.cpp:28:12:28:15 | CallSideEffect: call to C |
3131
| ms_try_mix.cpp:48:10:48:13 | CallSideEffect: call to C |
32-
| pointer_to_member.cpp:35:11:35:21 | FieldAddress: {...} |
32+
| pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} |
3333
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... |
3434
| vla.c:5:9:5:14 | Uninitialized: definition of matrix |
3535
| vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef |

0 commit comments

Comments
 (0)