/** * Provides classes for modeling literals in the source code such as `0`, `'c'` * or `"string"`. */ import semmle.code.cpp.exprs.Expr /** * A C/C++ literal. * * The is the QL root class for all literals. */ class Literal extends Expr, @literal { /** Gets a textual representation of this literal. */ override string toString() { result = this.getValue() or not exists(this.getValue()) and result = "Unknown literal" } override string getAPrimaryQlClass() { result = "Literal" } override predicate mayBeImpure() { none() } override predicate mayBeGloballyImpure() { none() } } /** * A label literal, that is, a use of the '&&' operator to take the address of a * label for use in a computed goto statement. This is a non-standard C/C++ extension. * * For example: * ``` * void *label_ptr = &&myLabel; // &&myLabel is a LabelLiteral * goto *label_ptr; // this is a ComputedGotoStmt * myLabel: // this is a LabelStmt * ``` */ class LabelLiteral extends Literal { LabelLiteral() { jumpinfo(underlyingElement(this), _, _) } override string getAPrimaryQlClass() { result = "LabelLiteral" } /** Gets the corresponding label statement. */ LabelStmt getLabel() { jumpinfo(underlyingElement(this), _, unresolveElement(result)) } } /** A character literal or a string literal. */ class TextLiteral extends Literal { TextLiteral() { // String Literal // Note that `AggregateLiteral`s can also have an array type, but they derive from // @aggregateliteral rather than @literal. this.getType() instanceof ArrayType or // Char literal this.getValueText().regexpMatch("(?s)\\s*L?'.*") } /** Gets a hex escape sequence that appears in the character or string literal (see [lex.ccon] in the C++ Standard). */ string getAHexEscapeSequence(int occurrence, int offset) { result = this.getValueText().regexpFind("(?= 0 and elementIndex < this.getArraySize() } /** * Holds if the element `elementIndex` is value initialized because it is not * explicitly initialized by this initializer list. * * Value initialization (see [dcl.init]/8) recursively initializes all fields * of an object to `false`, `0`, `nullptr`, or by calling the default * constructor, as appropriate to the type. */ bindingset[elementIndex] predicate isValueInitialized(int elementIndex) { this.isInitialized(elementIndex) and not exists(this.getAnElementExpr(elementIndex)) } } /** * A C/C++ aggregate literal that initializes an array * ``` * S s[4] = { s_1, s_2, s_3, s_n }; * ``` */ class ArrayAggregateLiteral extends ArrayOrVectorAggregateLiteral { ArrayType arrayType; ArrayAggregateLiteral() { arrayType = this.getUnspecifiedType() } override string getAPrimaryQlClass() { 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. * * Braced initializer lists are used, similarly to what is done * for arrays. * ``` * typedef int v4si __attribute__ (( vector_size(4*sizeof(int)) )); * v4si v = (v4si){ 1, 2, 3, 4 }; * typedef float float4 __attribute__((ext_vector_type(4))); * float4 vf = {1.0f, 2.0f, 3.0f, 4.0f}; * ``` */ class VectorAggregateLiteral extends ArrayOrVectorAggregateLiteral { GNUVectorType vectorType; VectorAggregateLiteral() { vectorType = this.getUnspecifiedType() } override string getAPrimaryQlClass() { result = "VectorAggregateLiteral" } override int getArraySize() { result = vectorType.getNumElements() } override Type getElementType() { result = vectorType.getBaseType() } }