Skip to content

Commit f30bfb6

Browse files
committed
C++: Insert int-to-bool conversions at 'NotExpr's.
1 parent 1e33593 commit f30bfb6

File tree

2 files changed

+63
-10
lines changed

2 files changed

+63
-10
lines changed

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ newtype TInstructionTag =
5151
ConditionValueResultLoadTag() or
5252
BoolConversionConstantTag() or
5353
BoolConversionCompareTag() or
54+
NotExprOperationTag() or
55+
NotExprConstantTag() or
5456
ResultCopyTag() or
5557
LoadTag() or // Implicit load due to lvalue-to-rvalue conversion
5658
CatchTag() or
@@ -193,6 +195,10 @@ string getInstructionTagId(TInstructionTag tag) {
193195
or
194196
tag = BoolConversionCompareTag() and result = "BoolConvComp"
195197
or
198+
tag = NotExprOperationTag() and result = "NotExprOperation"
199+
or
200+
tag = NotExprConstantTag() and result = "NotExprWithBoolConversionConstant"
201+
or
196202
tag = ResultCopyTag() and result = "ResultCopy"
197203
or
198204
tag = LoadTag() and result = "Load" // Implicit load due to lvalue-to-rvalue conversion

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,51 +1320,98 @@ class TranslatedUnaryExpr extends TranslatedSingleInstructionExpr {
13201320
}
13211321
}
13221322

1323+
/**
1324+
* The IR translation of a `NotExpr`.
1325+
*
1326+
* In C++ an operation such as `!x` where `x` is an `int` will generate
1327+
* ```
1328+
* r1(glval<int>) = VariableAddress[x] :
1329+
* r2(int) = Load : &r1
1330+
* r3(int) = Constant[0] :
1331+
* r4(bool) = CompareNE : r2, r3
1332+
* r5(bool) = LogicalNot : r4
1333+
* ```
1334+
* since C does not do implicit int-to-bool casts we need to generate the
1335+
* `Constant[0]`, `CompareNE`, and `LogicalNot` instructions manually, but
1336+
* we simplify this and generate `Constant[0]`, `CompareEQ` instead.
1337+
*/
13231338
class TranslatedNotExpr extends TranslatedNonConstantExpr {
13241339
override NotExpr expr;
13251340

13261341
override Type getExprType() { result instanceof BoolType }
13271342

1343+
private Type getOperandType() { result = this.getOperand().getExprType().getUnspecifiedType() }
1344+
1345+
predicate shouldGenerateEq() { not this.getOperandType() instanceof BoolType }
1346+
13281347
final override Instruction getFirstInstruction(EdgeKind kind) {
13291348
result = this.getOperand().getFirstInstruction(kind)
13301349
}
13311350

13321351
override Instruction getALastInstructionInternal() {
1333-
result = this.getInstruction(OnlyInstructionTag())
1352+
result = this.getInstruction(NotExprOperationTag())
13341353
}
13351354

13361355
final override TranslatedElement getChildInternal(int id) {
13371356
id = 0 and result = this.getOperand()
13381357
}
13391358

13401359
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
1341-
tag = OnlyInstructionTag() and
1342-
opcode instanceof Opcode::LogicalNot and
1343-
resultType = getBoolType()
1360+
this.shouldGenerateEq() and
1361+
tag = NotExprConstantTag() and
1362+
opcode instanceof Opcode::Constant and
1363+
resultType = getTypeForPRValue(this.getOperandType())
1364+
or
1365+
resultType = getBoolType() and
1366+
tag = NotExprOperationTag() and
1367+
if this.shouldGenerateEq()
1368+
then opcode instanceof Opcode::CompareEQ
1369+
else opcode instanceof Opcode::LogicalNot
13441370
}
13451371

13461372
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
1347-
tag = OnlyInstructionTag() and
1373+
tag = NotExprOperationTag() and
13481374
result = this.getParent().getChildSuccessor(this, kind)
1375+
or
1376+
tag = NotExprConstantTag() and
1377+
kind instanceof GotoEdge and
1378+
result = this.getInstruction(NotExprOperationTag())
13491379
}
13501380

13511381
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
13521382
child = this.getOperand() and
13531383
kind instanceof GotoEdge and
1354-
result = this.getInstruction(OnlyInstructionTag())
1384+
if this.shouldGenerateEq()
1385+
then result = this.getInstruction(NotExprConstantTag())
1386+
else result = this.getInstruction(NotExprOperationTag())
13551387
}
13561388

13571389
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
1358-
tag = OnlyInstructionTag() and
1359-
operandTag instanceof UnaryOperandTag and
1360-
result = this.getOperand().getResult()
1390+
tag = NotExprOperationTag() and
1391+
if this.shouldGenerateEq()
1392+
then (
1393+
result = this.getOperand().getResult() and
1394+
operandTag instanceof LeftOperandTag
1395+
or
1396+
result = this.getInstruction(NotExprConstantTag()) and
1397+
operandTag instanceof RightOperandTag
1398+
) else (
1399+
operandTag instanceof UnaryOperandTag and
1400+
result = this.getOperand().getResult()
1401+
)
13611402
}
13621403

13631404
private TranslatedExpr getOperand() {
13641405
result = getTranslatedExpr(expr.getOperand().getFullyConverted())
13651406
}
13661407

1367-
final override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) }
1408+
final override Instruction getResult() { result = this.getInstruction(NotExprOperationTag()) }
1409+
1410+
override string getInstructionConstantValue(InstructionTag tag) {
1411+
this.shouldGenerateEq() and
1412+
tag = NotExprConstantTag() and
1413+
result = "0"
1414+
}
13681415
}
13691416

13701417
/**

0 commit comments

Comments
 (0)