Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll
Original file line number Diff line number Diff line change
Expand Up @@ -1322,3 +1322,31 @@ class CoYieldExpr extends UnaryOperation, @co_yield {

override int getPrecedence() { result = 2 }
}

class ReuseExpr extends Expr, @reuseexpr {
override string getAPrimaryQlClass() { result = "ReuseExpr" }

override string toString() {
result = "reuse of " + this.getReusedExpr().toString()
}

override Type getType() {
result = this.getReusedExpr().getType()
}

override predicate isLValueCategory() {
none()
}

override predicate isXValueCategory() {
any()
}

override predicate isPRValueCategory() {
none()
}

Expr getReusedExpr() {
expr_reuse(underlyingElement(this), unresolveElement(result))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,10 @@ private predicate ignoreExprAndDescendants(Expr expr) {
vaStartExpr.getLastNamedParameter().getFullyConverted() = expr
)
or
// suppress destructors of temporary variables until proper support is added for them.
exists(Expr parent | parent.getAnImplicitDestructorCall() = expr)
// Do not translate implicit destructor calls for unnamed temporary variables that are
// conditionally constructed (until we have a mechanism for calling these only when the
// temporary's constructor was run)
isConditionalTemporaryDestructorCall(expr)
}

/**
Expand Down Expand Up @@ -229,6 +231,20 @@ private predicate usedAsCondition(Expr expr) {
)
}

private predicate isInConditionalEvaluation(Expr e) {
exists(ConditionalExpr cond |
e = cond.getThen() and not cond.isTwoOperand()
or
e = cond.getElse()
)
or
isInConditionalEvaluation(getRealParent(e))
}

private predicate isConditionalTemporaryDestructorCall(DestructorCall dc) {
isInConditionalEvaluation(dc.getQualifier().(ReuseExpr).getReusedExpr())
}

/**
* Holds if `conv` is an `InheritanceConversion` that requires a `TranslatedLoad`, despite not being
* marked as having an lvalue-to-rvalue conversion.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,19 @@ abstract class TranslatedExpr extends TranslatedElement {
)
}

final override predicate hasAnImplicitDestructorCall() {
exists(expr.getAnImplicitDestructorCall())
}

final override int getFirstDestructorCallIndex() {
not this.handlesDestructorsExplicitly() and
(
result = max(int childId | exists(this.getChildInternal(childId))) + 1
or
not exists(this.getChildInternal(_)) and result = 0
)
}

final override Locatable getAst() { result = expr }

final override Declaration getFunction() { result = getEnclosingDeclaration(expr) }
Expand Down Expand Up @@ -2769,6 +2782,43 @@ class TranslatedTemporaryObjectExpr extends TranslatedNonConstantExpr,
final override Instruction getResult() { result = this.getTargetAddress() }
}

class TranslatedReuseExpr extends TranslatedNonConstantExpr {
override ReuseExpr expr;

override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(OnlyInstructionTag()) and
kind instanceof GotoEdge
}

override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
opcode instanceof Opcode::CopyValue and
tag instanceof OnlyInstructionTag and
resultType = this.getResultType()
}

override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) }

override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
kind instanceof GotoEdge and
result = this.getParent().getChildSuccessor(this, kind)
}

override TranslatedElement getChildInternal(int id) { none() }

override Instruction getALastInstructionInternal() {
result = this.getInstruction(OnlyInstructionTag())
}

override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
tag = OnlyInstructionTag() and
operandTag instanceof UnaryOperandTag and
if getTranslatedExpr(expr.getReusedExpr()) instanceof TranslatedLoad
then result = getTranslatedExpr(expr.getReusedExpr()).(TranslatedLoad).getOperand().getResult()
else result = getTranslatedExpr(expr.getReusedExpr()).getResult()
}
}

/**
* IR translation of a `throw` expression.
*/
Expand Down
6 changes: 6 additions & 0 deletions cpp/ql/lib/semmlecode.cpp.dbscheme
Original file line number Diff line number Diff line change
Expand Up @@ -1513,6 +1513,11 @@ exprs(
int location: @location_expr ref
);

expr_reuse(
int reuse: @expr ref,
int original: @expr ref
)

/*
case @value.category of
1 = prval
Expand Down Expand Up @@ -1741,6 +1746,7 @@ case @expr.kind of
| 360 = @isunsigned
| 361 = @isvoid
| 362 = @isvolatile
| 363 = @reuseexpr
;

@var_args_expr = @vastartexpr
Expand Down
Loading