Skip to content
Merged
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
1 change: 1 addition & 0 deletions cpp/ql/src/semmle/code/cpp/exprs/BuiltInOperations.qll
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import semmle.code.cpp.exprs.Expr
* A C/C++ builtin operation.
*/
abstract class BuiltInOperation extends Expr {
override string getCanonicalQLClass() { result = "BuiltInOperation" }
}

/**
Expand Down
73 changes: 66 additions & 7 deletions cpp/ql/src/semmle/code/cpp/exprs/Literal.qll
Original file line number Diff line number Diff line change
Expand Up @@ -234,16 +234,33 @@ class ClassAggregateLiteral extends AggregateLiteral {
}

/**
* A C/C++ aggregate literal that initializes an array
* A C/C++ aggregate literal that initializes an array or a GNU vector type.
*/
class ArrayAggregateLiteral extends AggregateLiteral {
ArrayType arrayType;
class ArrayOrVectorAggregateLiteral extends AggregateLiteral {
ArrayOrVectorAggregateLiteral() {
exists(DerivedType type |
type = this.getUnspecifiedType() and
(
type instanceof ArrayType or
type instanceof GNUVectorType
)
)
}

ArrayAggregateLiteral() {
arrayType = this.getUnspecifiedType()
/**
* Gets the number of elements initialized by this initializer list, either explicitly with an
* expression, or by implicit value initialization.
*/
int getArraySize() {
none()
}

override string getCanonicalQLClass() { result = "ArrayAggregateLiteral" }
/**
* Gets the type of the elements in the initializer list.
*/
Type getElementType() {
none()
}

/**
* Gets the expression within the aggregate literal that is used to initialize
Expand All @@ -262,7 +279,7 @@ class ArrayAggregateLiteral extends AggregateLiteral {
bindingset[elementIndex]
predicate isInitialized(int elementIndex) {
elementIndex >= 0 and
elementIndex < arrayType.getArraySize()
elementIndex < getArraySize()
}

/**
Expand All @@ -279,3 +296,45 @@ class ArrayAggregateLiteral extends AggregateLiteral {
not exists(getElementExpr(elementIndex))
}
}

/**
* A C/C++ aggregate literal that initializes an array
*/
class ArrayAggregateLiteral extends ArrayOrVectorAggregateLiteral {
ArrayType arrayType;

ArrayAggregateLiteral() {
arrayType = this.getUnspecifiedType()
}

override string getCanonicalQLClass() { result = "ArrayAggregateLiteral" }

override int getArraySize() {
result = arrayType.getArraySize()
}

override Type getElementType() {
result = arrayType.getBaseType()
}
}

/**
* A C/C++ aggregate literal that initializes a GNU vector type.
*/
class VectorAggregateLiteral extends ArrayOrVectorAggregateLiteral {
GNUVectorType vectorType;

VectorAggregateLiteral() {
vectorType = this.getUnspecifiedType()
}

override string getCanonicalQLClass() { result = "VectorAggregateLiteral" }

override int getArraySize() {
result = vectorType.getNumElements()
}

override Type getElementType() {
result = vectorType.getBaseType()
}
}
12 changes: 7 additions & 5 deletions cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ private newtype TOpcode =
TUnmodeledUse() or
TAliasedDefinition() or
TPhi() or
TBuiltIn() or
TVarArgsStart() or
TVarArgsEnd() or
TVarArg() or
Expand Down Expand Up @@ -115,7 +116,7 @@ abstract class CatchOpcode extends Opcode {}

abstract class OpcodeWithCondition extends Opcode {}

abstract class BuiltInOpcode extends Opcode {}
abstract class BuiltInOperationOpcode extends Opcode {}

abstract class SideEffectOpcode extends Opcode {}

Expand Down Expand Up @@ -204,10 +205,11 @@ module Opcode {
class UnmodeledUse extends Opcode, TUnmodeledUse { override final string toString() { result = "UnmodeledUse" } }
class AliasedDefinition extends Opcode, TAliasedDefinition { override final string toString() { result = "AliasedDefinition" } }
class Phi extends Opcode, TPhi { override final string toString() { result = "Phi" } }
class VarArgsStart extends BuiltInOpcode, TVarArgsStart { override final string toString() { result = "VarArgsStart" } }
class VarArgsEnd extends BuiltInOpcode, TVarArgsEnd { override final string toString() { result = "VarArgsEnd" } }
class VarArg extends BuiltInOpcode, TVarArg { override final string toString() { result = "VarArg" } }
class VarArgCopy extends BuiltInOpcode, TVarArgCopy { override final string toString() { result = "VarArgCopy" } }
class BuiltIn extends BuiltInOperationOpcode, TBuiltIn { override final string toString() { result = "BuiltIn" } }
class VarArgsStart extends BuiltInOperationOpcode, TVarArgsStart { override final string toString() { result = "VarArgsStart" } }
class VarArgsEnd extends BuiltInOperationOpcode, TVarArgsEnd { override final string toString() { result = "VarArgsEnd" } }
class VarArg extends BuiltInOperationOpcode, TVarArg { override final string toString() { result = "VarArg" } }
class VarArgCopy extends BuiltInOperationOpcode, TVarArgCopy { override final string toString() { result = "VarArgCopy" } }
class CallSideEffect extends MayWriteSideEffectOpcode, TCallSideEffect { override final string toString() { result = "CallSideEffect" } }
class CallReadSideEffect extends ReadSideEffectOpcode, TCallReadSideEffect { override final string toString() { result = "CallReadSideEffect" } }
class IndirectReadSideEffect extends ReadSideEffectOpcode, MemoryAccessOpcode, TIndirectReadSideEffect { override final string toString() { result = "IndirectReadSideEffect" } }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ module InstructionSanity {
operand.getOperandTag() = tag) and
not expectsOperand(instr, tag) and
not (instr instanceof CallInstruction and tag instanceof ArgumentOperandTag) and
not (instr instanceof BuiltInInstruction and tag instanceof PositionalArgumentOperandTag) and
not (instr instanceof BuiltInOperationInstruction and tag instanceof PositionalArgumentOperandTag) and
not (instr instanceof InlineAsmInstruction and tag instanceof AsmOperandTag)
}

Expand Down Expand Up @@ -1831,8 +1831,29 @@ class UnreachedInstruction extends Instruction {
* An instruction representing a built-in operation. This is used to represent
* operations such as access to variable argument lists.
*/
class BuiltInInstruction extends Instruction {
class BuiltInOperationInstruction extends Instruction {
Language::BuiltInOperation operation;

BuiltInOperationInstruction() {
getOpcode() instanceof BuiltInOperationOpcode and
operation = Construction::getInstructionBuiltInOperation(this)
}

final Language::BuiltInOperation getBuiltInOperation() {
result = operation
}
}

/**
* An instruction representing a built-in operation that does not have a specific opcode. The
* actual operation is specified by the `getBuiltInOperation()` predicate.
*/
class BuiltInInstruction extends BuiltInOperationInstruction {
BuiltInInstruction() {
getOpcode() instanceof BuiltInOpcode
getOpcode() instanceof Opcode::BuiltIn
}

override final string getImmediateString() {
result = getBuiltInOperation().toString()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,10 @@ cached private module Cached {
result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue()
}

cached BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) {
result = getOldInstruction(instruction).(OldIR::BuiltInOperationInstruction).getBuiltInOperation()
}

cached Type getInstructionExceptionType(Instruction instruction) {
result = getOldInstruction(instruction).(OldIR::CatchByTypeInstruction).getExceptionType()
}
Expand Down
27 changes: 24 additions & 3 deletions cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ module InstructionSanity {
operand.getOperandTag() = tag) and
not expectsOperand(instr, tag) and
not (instr instanceof CallInstruction and tag instanceof ArgumentOperandTag) and
not (instr instanceof BuiltInInstruction and tag instanceof PositionalArgumentOperandTag) and
not (instr instanceof BuiltInOperationInstruction and tag instanceof PositionalArgumentOperandTag) and
not (instr instanceof InlineAsmInstruction and tag instanceof AsmOperandTag)
}

Expand Down Expand Up @@ -1831,8 +1831,29 @@ class UnreachedInstruction extends Instruction {
* An instruction representing a built-in operation. This is used to represent
* operations such as access to variable argument lists.
*/
class BuiltInInstruction extends Instruction {
class BuiltInOperationInstruction extends Instruction {
Language::BuiltInOperation operation;

BuiltInOperationInstruction() {
getOpcode() instanceof BuiltInOperationOpcode and
operation = Construction::getInstructionBuiltInOperation(this)
}

final Language::BuiltInOperation getBuiltInOperation() {
result = operation
}
}

/**
* An instruction representing a built-in operation that does not have a specific opcode. The
* actual operation is specified by the `getBuiltInOperation()` predicate.
*/
class BuiltInInstruction extends BuiltInOperationInstruction {
BuiltInInstruction() {
getOpcode() instanceof BuiltInOpcode
getOpcode() instanceof Opcode::BuiltIn
}

override final string getImmediateString() {
result = getBuiltInOperation().toString()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,12 @@ cached private module Cached {
getInstructionTag(instruction))
}

cached BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) {
result =
getInstructionTranslatedElement(instruction).getInstructionBuiltInOperation(
getInstructionTag(instruction))
}

cached Type getInstructionExceptionType(Instruction instruction) {
result =
getInstructionTranslatedElement(instruction).getInstructionExceptionType(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ newtype TTranslatedElement =
exists(ClassAggregateLiteral initList |
initList.getFieldExpr(_).getFullyConverted() = expr
) or
exists(ArrayAggregateLiteral initList |
exists(ArrayOrVectorAggregateLiteral initList |
initList.getElementExpr(_).getFullyConverted() = expr
) or
exists(ReturnStmt returnStmt |
Expand Down Expand Up @@ -320,13 +320,13 @@ newtype TTranslatedElement =
} or
// The initialization of an array element via a member of an initializer list.
TTranslatedExplicitElementInitialization(
ArrayAggregateLiteral initList, int elementIndex) {
ArrayOrVectorAggregateLiteral initList, int elementIndex) {
not ignoreExpr(initList) and
exists(initList.getElementExpr(elementIndex))
} or
// The value initialization of a range of array elements that were omitted
// from an initializer list.
TTranslatedElementValueInitialization(ArrayAggregateLiteral initList,
TTranslatedElementValueInitialization(ArrayOrVectorAggregateLiteral initList,
int elementIndex, int elementCount) {
not ignoreExpr(initList) and
isFirstValueInitializedElementInRange(initList, elementIndex) and
Expand Down Expand Up @@ -412,12 +412,13 @@ newtype TTranslatedElement =
* `initList`, the result is the total number of elements in the array being
* initialized.
*/
private int getEndOfValueInitializedRange(ArrayAggregateLiteral initList, int afterElementIndex) {
private int getEndOfValueInitializedRange(ArrayOrVectorAggregateLiteral initList,
int afterElementIndex) {
result = getNextExplicitlyInitializedElementAfter(initList, afterElementIndex)
or
isFirstValueInitializedElementInRange(initList, afterElementIndex) and
not exists(getNextExplicitlyInitializedElementAfter(initList, afterElementIndex)) and
result = initList.getUnspecifiedType().(ArrayType).getArraySize()
result = initList.getArraySize()
}

/**
Expand All @@ -427,7 +428,7 @@ private int getEndOfValueInitializedRange(ArrayAggregateLiteral initList, int af
* `initList`.
*/
private int getNextExplicitlyInitializedElementAfter(
ArrayAggregateLiteral initList, int afterElementIndex) {
ArrayOrVectorAggregateLiteral initList, int afterElementIndex) {
isFirstValueInitializedElementInRange(initList, afterElementIndex) and
result = min(int i | exists(initList.getElementExpr(i)) and i > afterElementIndex)
}
Expand All @@ -437,7 +438,7 @@ private int getNextExplicitlyInitializedElementAfter(
* range of one or more consecutive value-initialized elements in `initList`.
*/
private predicate isFirstValueInitializedElementInRange(
ArrayAggregateLiteral initList, int elementIndex) {
ArrayOrVectorAggregateLiteral initList, int elementIndex) {
initList.isValueInitialized(elementIndex) and
(
elementIndex = 0 or
Expand Down Expand Up @@ -634,6 +635,13 @@ abstract class TranslatedElement extends TTranslatedElement {
none()
}

/**
* If the instruction specified by `tag` is a `BuiltInInstruction`, gets the built-in operation.
*/
BuiltInOperation getInstructionBuiltInOperation(InstructionTag tag) {
none()
}

/**
* If the instruction specified by `tag` is a `CatchByTypeInstruction`,
* gets the type of the exception to be caught.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -612,10 +612,15 @@ class TranslatedPostfixCrementOperation extends TranslatedCrementOperation {
}
}

/**
* IR translation of an array access expression (e.g. `a[i]`). The array being accessed will either
* be a prvalue of pointer type (possibly due to an implicit array-to-pointer conversion), or a
* glvalue of a GNU vector type.
*/
class TranslatedArrayExpr extends TranslatedNonConstantExpr {
override ArrayExpr expr;

override Instruction getFirstInstruction() {
override final Instruction getFirstInstruction() {
result = getBaseOperand().getFirstInstruction()
}

Expand Down Expand Up @@ -650,8 +655,8 @@ class TranslatedArrayExpr extends TranslatedNonConstantExpr {
Type resultType, boolean isGLValue) {
tag = OnlyInstructionTag() and
opcode instanceof Opcode::PointerAdd and
resultType = getBaseOperand().getResultType() and
isGLValue = false
resultType = getResultType() and
isGLValue = true
}

override Instruction getInstructionOperand(InstructionTag tag,
Expand All @@ -671,7 +676,7 @@ class TranslatedArrayExpr extends TranslatedNonConstantExpr {

override int getInstructionElementSize(InstructionTag tag) {
tag = OnlyInstructionTag() and
result = max(getBaseOperand().getResultType().(PointerType).getBaseType().getSize())
result = max(getResultType().getSize())
}

private TranslatedExpr getBaseOperand() {
Expand Down Expand Up @@ -2373,7 +2378,13 @@ class TranslatedReThrowExpr extends TranslatedThrowExpr {
* The IR translation of a built-in operation (i.e. anything that extends
* `BuiltInOperation`).
*/
abstract class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {
class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {
override BuiltInOperation expr;

TranslatedBuiltInOperation() {
not expr instanceof BuiltInOperationBuiltInAddressOf // Handled specially
}

override final Instruction getResult() {
result = getInstruction(OnlyInstructionTag())
}
Expand Down Expand Up @@ -2423,7 +2434,14 @@ abstract class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {
)
}

abstract Opcode getOpcode();
Opcode getOpcode() {
result instanceof Opcode::BuiltIn
}

override final BuiltInOperation getInstructionBuiltInOperation(InstructionTag tag) {
tag = OnlyInstructionTag() and
result = expr
}
}

/**
Expand Down
Loading