Skip to content

Commit

Permalink
C++: Define an extractor version table and use in IR generation
Browse files Browse the repository at this point in the history
  • Loading branch information
jketema committed Oct 24, 2023
1 parent ba67217 commit 7baeaed
Show file tree
Hide file tree
Showing 10 changed files with 8,984 additions and 18 deletions.
2,225 changes: 2,225 additions & 0 deletions cpp/downgrades/576ce5b08f2a6314cc604654149f46d15a1044ab/old.dbscheme

Large diffs are not rendered by default.

2,221 changes: 2,221 additions & 0 deletions cpp/downgrades/576ce5b08f2a6314cc604654149f46d15a1044ab/semmlecode.cpp.dbscheme

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
description: Introduce extractor version number
compatibility: breaking
extractor_version.rel: delete
7 changes: 7 additions & 0 deletions cpp/ql/lib/semmle/code/cpp/internal/ExtractorVersion.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* INTERNAL: Do not use. Provides a predicate for getting the extractor version.
*/

int getExtractorVersion() {
extractor_version(result)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
private import cpp
import semmle.code.cpp.ir.implementation.raw.IR
private import semmle.code.cpp.internal.ExtractorVersion
private import semmle.code.cpp.ir.IRConfiguration
private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.ir.implementation.internal.OperandTag
Expand Down Expand Up @@ -362,10 +363,10 @@ predicate ignoreLoad(Expr expr) {
expr instanceof FunctionAccess
or
// The load is duplicated from the operand.
expr instanceof ParenthesisExpr
exists(getExtractorVersion()) and expr instanceof ParenthesisExpr
or
// The load is duplicated from the right operand.
expr instanceof CommaExpr
exists(getExtractorVersion()) and expr instanceof CommaExpr
or
expr.(PointerDereferenceExpr).getOperand().getFullyConverted().getType().getUnspecifiedType()
instanceof FunctionPointerType
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
private import cpp
private import semmle.code.cpp.internal.ExtractorVersion
private import semmle.code.cpp.ir.implementation.IRType
private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.ir.implementation.internal.OperandTag
Expand Down Expand Up @@ -648,7 +649,21 @@ abstract class TranslatedCrementOperation extends TranslatedNonConstantExpr {
class TranslatedPrefixCrementOperation extends TranslatedCrementOperation {
override PrefixCrementOperation expr;

override Instruction getResult() { result = this.getUnloadedOperand().getResult() }
override Instruction getResult() {
// The following distinction is needed to work around extractor limitations
// in old versions of the extractor.
if expr.isPRValueCategory() and not exists(getExtractorVersion())
then
// If this is C, then the result of a prefix crement is a prvalue for the
// new value assigned to the operand. If this is C++, then the result is
// an lvalue, but that lvalue is being loaded as part of this expression.
// EDG doesn't mark this as a load.
result = this.getInstruction(CrementOpTag())
else
// This is C++, where the result is an lvalue for the operand, and that
// lvalue is not being loaded as part of this expression.
result = this.getUnloadedOperand().getResult()
}
}

class TranslatedPostfixCrementOperation extends TranslatedCrementOperation {
Expand Down Expand Up @@ -1491,7 +1506,21 @@ class TranslatedAssignExpr extends TranslatedNonConstantExpr {
result = this.getRightOperand().getFirstInstruction()
}

final override Instruction getResult() { result = this.getLeftOperand().getResult() }
final override Instruction getResult() {
// The following distinction is needed to work around extractor limitations
// in old versions of the extractor.
if expr.isPRValueCategory() and not exists(getExtractorVersion())
then
// If this is C, then the result of an assignment is a prvalue for the new
// value assigned to the left operand. If this is C++, then the result is
// an lvalue, but that lvalue is being loaded as part of this expression.
// EDG doesn't mark this as a load.
result = this.getRightOperand().getResult()
else
// This is C++, where the result is an lvalue for the left operand,
// and that lvalue is not being loaded as part of this expression.
result = this.getLeftOperand().getResult()
}

final TranslatedExpr getLeftOperand() {
result = getTranslatedExpr(expr.getLValue().getFullyConverted())
Expand Down Expand Up @@ -1617,7 +1646,21 @@ class TranslatedAssignOperation extends TranslatedNonConstantExpr {
result = this.getRightOperand().getFirstInstruction()
}

final override Instruction getResult() { result = this.getUnloadedLeftOperand().getResult() }
final override Instruction getResult() {
// The following distinction is needed to work around extractor limitations
// in old versions of the extractor.
if expr.isPRValueCategory() and not exists(getExtractorVersion())
then
// If this is C, then the result of an assignment is a prvalue for the new
// value assigned to the left operand. If this is C++, then the result is
// an lvalue, but that lvalue is being loaded as part of this expression.
// EDG doesn't mark this as a load.
result = this.getStoredValue()
else
// This is C++, where the result is an lvalue for the left operand,
// and that lvalue is not being loaded as part of this expression.
result = this.getUnloadedLeftOperand().getResult()
}

final TranslatedExpr getUnloadedLeftOperand() {
result = this.getLoadedLeftOperand().getOperand()
Expand Down Expand Up @@ -2155,15 +2198,16 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr {
not this.elseIsVoid() and tag = ConditionValueFalseStoreTag()
) and
opcode instanceof Opcode::Store and
(
if exists(getExtractorVersion())
then
not expr.hasLValueToRValueConversion() and
resultType = this.getResultType()
or
expr.hasLValueToRValueConversion() and
resultType = getTypeForPRValue(expr.getType())
)
else resultType = this.getResultType()
or
not expr.hasLValueToRValueConversion() and
(not expr.hasLValueToRValueConversion() or not exists(getExtractorVersion())) and
tag = ConditionValueResultLoadTag() and
opcode instanceof Opcode::Load and
resultType = this.getResultType()
Expand Down Expand Up @@ -2193,15 +2237,16 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr {
)
or
tag = ConditionValueResultTempAddressTag() and
(
if exists(getExtractorVersion())
then
not expr.hasLValueToRValueConversion() and
result = this.getInstruction(ConditionValueResultLoadTag())
or
expr.hasLValueToRValueConversion() and
result = this.getParent().getChildSuccessor(this)
)
else result = this.getInstruction(ConditionValueResultLoadTag())
or
not expr.hasLValueToRValueConversion() and
(not expr.hasLValueToRValueConversion() or not exists(getExtractorVersion())) and
tag = ConditionValueResultLoadTag() and
result = this.getParent().getChildSuccessor(this)
)
Expand Down Expand Up @@ -2230,7 +2275,7 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr {
result = this.getElse().getResult()
)
or
not expr.hasLValueToRValueConversion() and
(not expr.hasLValueToRValueConversion() or not exists(getExtractorVersion())) and
tag = ConditionValueResultLoadTag() and
operandTag instanceof AddressOperandTag and
result = this.getInstruction(ConditionValueResultTempAddressTag())
Expand All @@ -2240,13 +2285,14 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr {
final override predicate hasTempVariable(TempVariableTag tag, CppType type) {
not this.resultIsVoid() and
tag = ConditionValueTempVar() and
(
if exists(getExtractorVersion())
then
not expr.hasLValueToRValueConversion() and
type = this.getResultType()
or
expr.hasLValueToRValueConversion() and
type = getTypeForPRValue(expr.getType())
)
else type = this.getResultType()
}

final override IRVariable getInstructionVariable(InstructionTag tag) {
Expand All @@ -2261,13 +2307,14 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr {

final override Instruction getResult() {
not this.resultIsVoid() and
(
if exists(getExtractorVersion())
then
expr.hasLValueToRValueConversion() and
result = this.getInstruction(ConditionValueResultTempAddressTag())
or
not expr.hasLValueToRValueConversion() and
result = this.getInstruction(ConditionValueResultLoadTag())
)
else result = this.getInstruction(ConditionValueResultLoadTag())
}

override Instruction getChildSuccessor(TranslatedElement child) {
Expand Down Expand Up @@ -3226,9 +3273,19 @@ predicate exprNeedsCopyIfNotLoaded(Expr expr) {
(
expr instanceof AssignExpr
or
expr instanceof AssignOperation
expr instanceof AssignOperation and
(
not expr.isPRValueCategory() // is C++
or
exists(getExtractorVersion())
)
or
expr instanceof PrefixCrementOperation
expr instanceof PrefixCrementOperation and
(
not expr.isPRValueCategory() // is C++
or
exists(getExtractorVersion())
)
or
// Because the load is on the `e` in `e++`.
expr instanceof PostfixCrementOperation
Expand Down
4 changes: 4 additions & 0 deletions cpp/ql/lib/semmlecode.cpp.dbscheme
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,10 @@ svnchurn(
* C++ dbscheme
*/

extractor_version(
int version: int ref
)

@location = @location_stmt | @location_expr | @location_default ;

/**
Expand Down
Loading

0 comments on commit 7baeaed

Please sign in to comment.