Files
codeql/cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll
2025-11-18 19:52:05 +00:00

1003 lines
32 KiB
Plaintext

/**
* Provides classes for modeling C/C++ casts and conversions, as well as some
* type-related operators such as `sizeof` and `alignof`.
*/
import semmle.code.cpp.exprs.Expr
private import semmle.code.cpp.internal.ResolveClass
/**
* A C/C++ cast expression or similar unary expression that doesn't affect the logical value of its operand.
*
* Instances of this class are not present in the main AST which is navigated by parent/child links. Instead,
* instances of this class are attached to nodes in the main AST via special conversion links.
*/
class Conversion extends Expr, @conversion {
/** Gets the expression being converted. */
Expr getExpr() { result.getConversion() = this }
/** Holds if this conversion is an implicit conversion. */
predicate isImplicit() { this.isCompilerGenerated() }
override predicate mayBeImpure() { this.getExpr().mayBeImpure() }
override predicate mayBeGloballyImpure() { this.getExpr().mayBeGloballyImpure() }
}
/**
* A C/C++ cast expression.
*
* To get the type which the expression is being cast to, use `Cast::getType()`.
*
* There are two groups of subtypes of `Cast`. The first group differentiates
* between the different cast syntax forms, e.g. `CStyleCast`, `StaticCast`,
* etc. The second group differentiates between the semantic operation being
* performed by the cast, e.g. `IntegralConversion`, `PointerBaseClassConversion`,
* etc.
* The two groups are largely orthogonal to one another. For example, a
* cast that is syntactically as `CStyleCast` may also be an `IntegralConversion`,
* a `PointerBaseClassConversion`, or some other semantic conversion. Similarly,
* a `PointerDerivedClassConversion` may also be a `CStyleCast` or a `StaticCast`.
*
* This is a root QL class representing the different casts. For
* specific examples, consult the documentation for any of QL classes mentioned above.
*/
class Cast extends Conversion, @cast {
/**
* Gets a string describing the semantic conversion operation being performed by
* this cast.
*/
string getSemanticConversionString() { result = "unknown conversion" }
}
/**
* INTERNAL: Do not use.
* Query predicates used to check invariants that should hold for all `Cast`
* nodes. To run all consistency queries for the ASTs, including the ones below,
* run "semmle/code/cpp/ASTConsistency.ql".
*/
module CastConsistency {
/**
* Holds if the cast has more than one result for `Cast.getSemanticConversionString()`.
*/
query predicate multipleSemanticConversionStrings(Cast cast, Type fromType, string kind) {
// Every cast should have exactly one semantic conversion kind
count(cast.getSemanticConversionString()) > 1 and
kind = cast.getSemanticConversionString() and
fromType = cast.getExpr().getUnspecifiedType()
}
/**
* Holds if the cast has no result for `Cast.getSemanticConversionString()`.
*/
query predicate missingSemanticConversionString(Cast cast, Type fromType) {
// Every cast should have exactly one semantic conversion kind
not exists(cast.getSemanticConversionString()) and
fromType = cast.getExpr().getUnspecifiedType()
}
/**
* Holds if the cast has a result for `Cast.getSemanticConversionString()` that indicates that the
* kind of its semantic conversion is not known.
*/
query predicate unknownSemanticConversionString(Cast cast, Type fromType) {
// Every cast should have a known semantic conversion kind
cast.getSemanticConversionString() = "unknown conversion" and
fromType = cast.getExpr().getUnspecifiedType()
}
}
/**
* A cast expression in C, or a C-style cast expression in C++.
* ```
* float f = 3.0f;
* int i = (int)f;
* ```
*/
class CStyleCast extends Cast, @c_style_cast {
override string toString() { result = "(" + this.getType().getName() + ")..." }
override string getAPrimaryQlClass() { result = "CStyleCast" }
override int getPrecedence() { result = 16 }
}
/**
* A C++ `static_cast` expression.
*
* Please see https://en.cppreference.com/w/cpp/language/static_cast for
* more information.
* ```
* struct T: S {};
* struct S *s = get_S();
* struct T *t = static_cast<struct T *>(s); // downcast
* ```
*/
class StaticCast extends Cast, @static_cast {
override string toString() { result = "static_cast<" + this.getType().getName() + ">..." }
override string getAPrimaryQlClass() { result = "StaticCast" }
override int getPrecedence() { result = 17 }
}
/**
* A C++ `const_cast` expression.
*
* Please see https://en.cppreference.com/w/cpp/language/const_cast for
* more information.
* ```
* const struct S *s = get_S();
* struct S *t = const_cast<struct S *>(s);
* ```
*/
class ConstCast extends Cast, @const_cast {
override string toString() { result = "const_cast<" + this.getType().getName() + ">..." }
override string getAPrimaryQlClass() { result = "ConstCast" }
override int getPrecedence() { result = 17 }
}
/**
* A C++ `reinterpret_cast` expression.
*
* Please see https://en.cppreference.com/w/cpp/language/reinterpret_cast for
* more information.
* ```
* struct S *s = get_S();
* std::uintptr_t p = reinterpret_cast<std::uintptr_t>(s);
* ```
*/
class ReinterpretCast extends Cast, @reinterpret_cast {
override string toString() { result = "reinterpret_cast<" + this.getType().getName() + ">..." }
override string getAPrimaryQlClass() { result = "ReinterpretCast" }
override int getPrecedence() { result = 17 }
}
private predicate isArithmeticOrEnum(Type type) {
type instanceof ArithmeticType or
type instanceof Enum
}
private predicate isIntegralOrEnum(Type type) {
type instanceof IntegralType or
type instanceof Enum
}
private predicate isPointerOrNullPointer(Type type) {
type instanceof PointerType or
type instanceof FunctionPointerType or
type instanceof NullPointerType
}
private predicate isPointerToMemberOrNullPointer(Type type) {
type instanceof PointerToMemberType or
type instanceof NullPointerType
}
/**
* A conversion from one arithmetic or `enum` type to another.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class ArithmeticConversion extends Cast {
ArithmeticConversion() {
conversionkinds(underlyingElement(this), 0) and
isArithmeticOrEnum(this.getUnspecifiedType()) and
isArithmeticOrEnum(this.getExpr().getUnspecifiedType())
}
override string getSemanticConversionString() { result = "arithmetic conversion" }
}
/**
* A conversion from one integral or enum type to another.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class IntegralConversion extends ArithmeticConversion {
IntegralConversion() {
isIntegralOrEnum(this.getUnspecifiedType()) and
isIntegralOrEnum(this.getExpr().getUnspecifiedType())
}
override string getAPrimaryQlClass() {
not exists(qlCast(this)) and result = "IntegralConversion"
}
override string getSemanticConversionString() { result = "integral conversion" }
}
/**
* A conversion from one floating point type.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class FloatingPointConversion extends ArithmeticConversion {
FloatingPointConversion() {
this.getUnspecifiedType() instanceof FloatingPointType and
this.getExpr().getUnspecifiedType() instanceof FloatingPointType
}
override string getAPrimaryQlClass() {
not exists(qlCast(this)) and result = "FloatingPointConversion"
}
override string getSemanticConversionString() { result = "floating point conversion" }
}
/**
* A conversion from a floating point type to an integral or enum type.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class FloatingPointToIntegralConversion extends ArithmeticConversion {
FloatingPointToIntegralConversion() {
isIntegralOrEnum(this.getUnspecifiedType()) and
this.getExpr().getUnspecifiedType() instanceof FloatingPointType
}
override string getAPrimaryQlClass() {
not exists(qlCast(this)) and result = "FloatingPointToIntegralConversion"
}
override string getSemanticConversionString() { result = "floating point to integral conversion" }
}
/**
* A conversion from an integral or enum type to a floating point type.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class IntegralToFloatingPointConversion extends ArithmeticConversion {
IntegralToFloatingPointConversion() {
this.getUnspecifiedType() instanceof FloatingPointType and
isIntegralOrEnum(this.getExpr().getUnspecifiedType())
}
override string getAPrimaryQlClass() {
not exists(qlCast(this)) and result = "IntegralToFloatingPointConversion"
}
override string getSemanticConversionString() { result = "integral to floating point conversion" }
}
/**
* A conversion from one pointer type to another.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*
* The conversion does
* not modify the value of the pointer. For pointer conversions involving
* casts between base and derived classes, please see see `BaseClassConversion` or
* `DerivedClassConversion`.
*/
class PointerConversion extends Cast {
PointerConversion() {
conversionkinds(underlyingElement(this), 0) and
isPointerOrNullPointer(this.getUnspecifiedType()) and
isPointerOrNullPointer(this.getExpr().getUnspecifiedType())
}
override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "PointerConversion" }
override string getSemanticConversionString() { result = "pointer conversion" }
}
/**
* A conversion from one pointer-to-member type to another.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*
* The conversion does not modify the value of the pointer-to-member.
* For pointer-to-member conversions involving casts between base and
* derived classes, please see `PointerToMemberBaseClassConversion`
* or `PointerToMemberDerivedClassConversion`.
*/
class PointerToMemberConversion extends Cast {
PointerToMemberConversion() {
conversionkinds(underlyingElement(this), 0) and
exists(Type fromType, Type toType |
fromType = this.getExpr().getUnspecifiedType() and
toType = this.getUnspecifiedType() and
isPointerToMemberOrNullPointer(fromType) and
isPointerToMemberOrNullPointer(toType) and
// A conversion from nullptr to nullptr is a `PointerConversion`, not a
// `PointerToMemberConversion`.
not (
fromType instanceof NullPointerType and
toType instanceof NullPointerType
)
)
}
override string getAPrimaryQlClass() {
not exists(qlCast(this)) and result = "PointerToMemberConversion"
}
override string getSemanticConversionString() { result = "pointer-to-member conversion" }
}
/**
* A conversion from a pointer type to an integral or enum type.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class PointerToIntegralConversion extends Cast {
PointerToIntegralConversion() {
conversionkinds(underlyingElement(this), 0) and
isIntegralOrEnum(this.getUnspecifiedType()) and
isPointerOrNullPointer(this.getExpr().getUnspecifiedType())
}
override string getAPrimaryQlClass() {
not exists(qlCast(this)) and result = "PointerToIntegralConversion"
}
override string getSemanticConversionString() { result = "pointer to integral conversion" }
}
/**
* A conversion from an integral or enum type to a pointer type.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class IntegralToPointerConversion extends Cast {
IntegralToPointerConversion() {
conversionkinds(underlyingElement(this), 0) and
isPointerOrNullPointer(this.getUnspecifiedType()) and
isIntegralOrEnum(this.getExpr().getUnspecifiedType())
}
override string getAPrimaryQlClass() {
not exists(qlCast(this)) and result = "IntegralToPointerConversion"
}
override string getSemanticConversionString() { result = "integral to pointer conversion" }
}
/**
* A conversion to `bool`. Returns `false` if the source value is zero,
* `false`, or `nullptr`. Returns `true` otherwise.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class BoolConversion extends Cast {
BoolConversion() { conversionkinds(underlyingElement(this), 1) }
override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "BoolConversion" }
override string getSemanticConversionString() { result = "conversion to bool" }
}
/**
* A conversion to `void`.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class VoidConversion extends Cast {
VoidConversion() {
conversionkinds(underlyingElement(this), 0) and
this.getUnspecifiedType() instanceof VoidType
}
override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "VoidConversion" }
override string getSemanticConversionString() { result = "conversion to void" }
}
/**
* A conversion between two pointers or _glvalue_s related by inheritance.
*
* The base class will always be either a direct base class of the derived class,
* or a virtual base class of the derived class. A conversion to an indirect
* non-virtual base class will be represented as a sequence of conversions to
* direct base classes.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class InheritanceConversion extends Cast {
InheritanceConversion() {
conversionkinds(underlyingElement(this), 2) or conversionkinds(underlyingElement(this), 3)
}
/**
* Gets the `ClassDerivation` for the inheritance relationship between
* the base and derived classes. This predicate does not hold if the
* conversion is to an indirect virtual base class.
*/
final ClassDerivation getDerivation() {
result.getBaseClass() = this.getBaseClass() and
result.getDerivedClass() = this.getDerivedClass()
}
/**
* Gets the base class of the conversion. This will be either a direct
* base class of the derived class, or a virtual base class of the
* derived class.
*/
Class getBaseClass() {
none() // Overridden by subclasses
}
/**
* Gets the derived class of the conversion.
*/
Class getDerivedClass() {
none() // Overridden by subclasses
}
}
/**
* Given the source operand or result of an `InheritanceConversion`, returns the
* class being converted from or to. If the type of the expression is a pointer,
* this returns the pointed-to class. Otherwise, the type of the expression must
* be a class, in which case the result is that class.
*/
private Class getConversionClass(Expr expr) {
exists(Type operandType |
operandType = expr.getUnspecifiedType() and
(
result = operandType or
result = operandType.(PointerType).getBaseType()
)
)
}
/**
* A conversion from a pointer or _glvalue_ of a derived class to a pointer or
* _glvalue_ of a direct or virtual base class.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class BaseClassConversion extends InheritanceConversion {
BaseClassConversion() { conversionkinds(underlyingElement(this), 2) }
override string getAPrimaryQlClass() {
not exists(qlCast(this)) and result = "BaseClassConversion"
}
override string getSemanticConversionString() { result = "base class conversion" }
override Class getBaseClass() { result = getConversionClass(this) }
override Class getDerivedClass() { result = getConversionClass(this.getExpr()) }
/**
* Holds if this conversion is to a virtual base class.
*/
predicate isVirtual() { this.getDerivation().isVirtual() or not exists(this.getDerivation()) }
}
/**
* A conversion from a pointer or _glvalue_ to a base class to a pointer or _glvalue_
* to a direct derived class.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class DerivedClassConversion extends InheritanceConversion {
DerivedClassConversion() { conversionkinds(underlyingElement(this), 3) }
override string getAPrimaryQlClass() {
not exists(qlCast(this)) and result = "DerivedClassConversion"
}
override string getSemanticConversionString() { result = "derived class conversion" }
override Class getBaseClass() { result = getConversionClass(this.getExpr()) }
override Class getDerivedClass() { result = getConversionClass(this) }
}
/**
* A conversion from a pointer-to-member of a derived class to a pointer-to-member
* of an immediate base class.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class PointerToMemberBaseClassConversion extends Cast {
PointerToMemberBaseClassConversion() { conversionkinds(underlyingElement(this), 4) }
override string getAPrimaryQlClass() {
not exists(qlCast(this)) and result = "PointerToMemberBaseClassConversion"
}
override string getSemanticConversionString() {
result = "pointer-to-member base class conversion"
}
}
/**
* A conversion from a pointer-to-member of a base class to a pointer-to-member
* of an immediate derived class.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class PointerToMemberDerivedClassConversion extends Cast {
PointerToMemberDerivedClassConversion() { conversionkinds(underlyingElement(this), 5) }
override string getAPrimaryQlClass() {
not exists(qlCast(this)) and result = "PointerToMemberDerivedClassConversion"
}
override string getSemanticConversionString() {
result = "pointer-to-member derived class conversion"
}
}
/**
* A conversion of a _glvalue_ from one type to another. The conversion does not
* modify the address of the _glvalue_. For _glvalue_ conversions involving base and
* derived classes, see `BaseClassConversion` and `DerivedClassConversion`.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class GlvalueConversion extends Cast {
GlvalueConversion() { conversionkinds(underlyingElement(this), 6) }
override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "GlvalueConversion" }
override string getSemanticConversionString() { result = "glvalue conversion" }
}
/**
* The adjustment of the type of a class _prvalue_. Most commonly seen in code
* similar to:
* ```
* class String { ... };
* String func();
* void caller() {
* const String& r = func();
* }
* ```
* In the above example, the result of the call to `func` is a _prvalue_ of type
* `String`, which will be adjusted to type `const String` before being bound
* to the reference.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class PrvalueAdjustmentConversion extends Cast {
PrvalueAdjustmentConversion() { conversionkinds(underlyingElement(this), 7) }
override string getAPrimaryQlClass() {
not exists(qlCast(this)) and result = "PrvalueAdjustmentConversion"
}
override string getSemanticConversionString() { result = "prvalue adjustment conversion" }
}
/**
* A C++ `dynamic_cast` expression.
*
* Please see https://en.cppreference.com/w/cpp/language/dynamic_cast for
* more information.
* ```
* struct T: S {};
* struct S *s = get_S();
* struct T *t = dynamic_cast<struct T *>(s); // downcast
* ```
*/
class DynamicCast extends Cast, @dynamic_cast {
override string toString() { result = "dynamic_cast<" + this.getType().getName() + ">..." }
override int getPrecedence() { result = 17 }
override string getAPrimaryQlClass() { result = "DynamicCast" }
override string getSemanticConversionString() { result = "dynamic_cast" }
}
/**
* A Microsoft C/C++ `__uuidof` expression that returns the UUID of a type, as
* specified by the `__declspec(uuid)` attribute.
* ```
* struct UUID { char a[16]; };
* struct __declspec(uuid("{01234567-89ab-cdef-0123-456789ABCDEF}")) S {};
* UUID uuid = __uuidof(S);
* ```
*/
class UuidofOperator extends Expr, @uuidof {
override string toString() {
if exists(this.getTypeOperand())
then result = "__uuidof(" + this.getTypeOperand().getName() + ")"
else result = "__uuidof(0)"
}
override int getPrecedence() { result = 16 }
/** Gets the contained type. */
Type getTypeOperand() { uuidof_bind(underlyingElement(this), unresolveElement(result)) }
}
/**
* A C++ `typeid` expression which provides run-time type information (RTTI)
* about its argument.
*
* Please see https://en.cppreference.com/w/cpp/language/typeid for more
* information.
* ```
* Base *ptr = new Derived;
* const std::type_info &info1 = typeid(ptr);
* printf("the type of ptr is: %s\n", typeid(ptr).name());
* ```
*/
class TypeidOperator extends Expr, @type_id {
/**
* Gets the type that is returned by this typeid expression.
*/
Type getResultType() { typeid_bind(underlyingElement(this), unresolveElement(result)) }
override string getAPrimaryQlClass() { result = "TypeidOperator" }
/**
* Gets the contained expression, if any (if this typeid contains
* a type rather than an expression, there is no result).
*/
Expr getExpr() { result = this.getChild(0) }
override string toString() { result = "typeid ..." }
override int getPrecedence() { result = 17 }
override predicate mayBeImpure() { this.getExpr().mayBeImpure() }
override predicate mayBeGloballyImpure() { this.getExpr().mayBeGloballyImpure() }
}
/**
* A C++11 `sizeof...` expression which determines the size of a template
* parameter pack.
*
* This expression only appears in templates themselves - in any actual
* instantiations, "sizeof...(x)" will be replaced by its integer value.
* ```
* template < typename... T >
* int count ( T &&... t ) { return sizeof... ( t ); }
* ```
*/
class SizeofPackOperator extends Expr, @sizeof_pack {
override predicate mayBeImpure() { none() }
override predicate mayBeGloballyImpure() { none() }
}
/**
* A C++11 `sizeof...` expression which determines the size of a template
* parameter pack and whose operand is an expression.
*
* This expression only appears in templates themselves - in any actual
* instantiations, "sizeof...(x)" will be replaced by its integer value.
* ```
* template < typename... T >
* int count ( T &&... t ) { return sizeof... ( t ); }
* ```
*/
class SizeofPackExprOperator extends SizeofPackOperator {
SizeofPackExprOperator() { exists(this.getChild(0)) }
override string getAPrimaryQlClass() { result = "SizeofPackExprOperator" }
/** Gets the contained expression. */
Expr getExprOperand() { result = this.getChild(0) }
override string toString() { result = "sizeof...(<expr>)" }
}
/**
* A C++11 `sizeof...` expression which determines the size of a template
* parameter pack and whose operand is an type name or a template template
* parameter.
*
* This expression only appears in templates themselves - in any actual
* instantiations, "sizeof...(x)" will be replaced by its integer value.
* ```
* template < typename... T >
* int count ( T &&... t ) { return sizeof... ( T ); }
* ```
*/
class SizeofPackTypeOperator extends SizeofPackOperator {
SizeofPackTypeOperator() { sizeof_bind(underlyingElement(this), _) }
override string getAPrimaryQlClass() { result = "SizeofPackTypeOperator" }
/** Gets the contained type. */
Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) }
override string toString() { result = "sizeof...(" + this.getTypeOperand().getName() + ")" }
}
/**
* A C/C++ sizeof expression.
*/
class SizeofOperator extends Expr, @runtime_sizeof {
override int getPrecedence() { result = 16 }
/**
* Gets the contained type of this `sizeof`. For example,
* the result is `int` in both cases below:
* ```
* sizeof(int);
* sizeof(42);
* ```
*/
Type getTypeOperand() { none() } // overridden in subclasses
}
/**
* A C/C++ sizeof expression whose operand is an expression.
* ```
* if (sizeof(a) == sizeof(b)) { c = (b)a; }
* ```
*/
class SizeofExprOperator extends SizeofOperator {
SizeofExprOperator() { exists(this.getChild(0)) }
override string getAPrimaryQlClass() { result = "SizeofExprOperator" }
/** Gets the contained expression. */
Expr getExprOperand() { result = this.getChild(0) }
override Type getTypeOperand() { result = this.getExprOperand().getType() }
override string toString() { result = "sizeof(<expr>)" }
override predicate mayBeImpure() { this.getExprOperand().mayBeImpure() }
override predicate mayBeGloballyImpure() { this.getExprOperand().mayBeGloballyImpure() }
}
/**
* A C/C++ sizeof expression whose operand is a type name.
* ```
* int szlong = sizeof(int) == sizeof(long)? 4 : 8;
* ```
*/
class SizeofTypeOperator extends SizeofOperator {
SizeofTypeOperator() { sizeof_bind(underlyingElement(this), _) }
override string getAPrimaryQlClass() { result = "SizeofTypeOperator" }
override Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) }
override string toString() { result = "sizeof(" + this.getTypeOperand().getName() + ")" }
override predicate mayBeImpure() { none() }
override predicate mayBeGloballyImpure() { none() }
}
/**
* A C++11 `alignof` expression.
*/
class AlignofOperator extends Expr, @runtime_alignof {
override int getPrecedence() { result = 16 }
}
/**
* A C++11 `alignof` expression whose operand is an expression.
* ```
* int addrMask = ~(alignof(expr) - 1);
* ```
*/
class AlignofExprOperator extends AlignofOperator {
AlignofExprOperator() { exists(this.getChild(0)) }
/**
* Gets the contained expression.
*/
Expr getExprOperand() { result = this.getChild(0) }
override string toString() { result = "alignof(<expr>)" }
}
/**
* A C++11 `alignof` expression whose operand is a type name.
* ```
* bool proper_alignment = (alignof(T) == alignof(T[0]);
* ```
*/
class AlignofTypeOperator extends AlignofOperator {
AlignofTypeOperator() { sizeof_bind(underlyingElement(this), _) }
/** Gets the contained type. */
Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) }
override string toString() { result = "alignof(" + this.getTypeOperand().getName() + ")" }
}
/**
* A C++ `__datasizeof` expression (used by some implementations
* of the `<type_traits>` header).
*
* The `__datasizeof` expression behaves identically to `sizeof` except
* that the result ignores tail padding.
*/
class DatasizeofOperator extends Expr, @datasizeof {
override int getPrecedence() { result = 16 }
/**
* Gets the contained type of this `__datasizeof`. For example,
* the result is `int` in both cases below:
* ```
* __datasizeof(int);
* __datasizeof(42);
* ```
*/
Type getTypeOperand() { none() }
}
/**
* A C++ `__datasizeof` expression whose operand is an expression.
*/
class DatasizeofExprOperator extends DatasizeofOperator {
DatasizeofExprOperator() { exists(this.getChild(0)) }
override string getAPrimaryQlClass() { result = "DatasizeofExprOperator" }
/** Gets the contained expression. */
Expr getExprOperand() { result = this.getChild(0) }
override Type getTypeOperand() { result = this.getExprOperand().getType() }
override string toString() { result = "__datasizeof(<expr>)" }
override predicate mayBeImpure() { this.getExprOperand().mayBeImpure() }
override predicate mayBeGloballyImpure() { this.getExprOperand().mayBeGloballyImpure() }
}
/**
* A C++ `__datasizeof` expression whose operand is a type name.
*/
class DatasizeofTypeOperator extends DatasizeofOperator {
DatasizeofTypeOperator() { sizeof_bind(underlyingElement(this), _) }
override string getAPrimaryQlClass() { result = "DatasizeofTypeOperator" }
override Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) }
override string toString() { result = "__datasizeof(" + this.getTypeOperand().getName() + ")" }
override predicate mayBeImpure() { none() }
override predicate mayBeGloballyImpure() { none() }
}
/**
* A C/C++ array to pointer conversion.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class ArrayToPointerConversion extends Conversion, @array_to_pointer {
/** Gets a textual representation of this conversion. */
override string toString() { result = "array to pointer conversion" }
override string getAPrimaryQlClass() { result = "ArrayToPointerConversion" }
override predicate mayBeImpure() { none() }
override predicate mayBeGloballyImpure() { none() }
}
/**
* A node representing a temporary object created as part of an expression.
*
* This is most commonly seen in the following cases:
* ```c++
* // when binding a reference to a prvalue
* const std::string& r = std::string("text");
*
* // when performing member access on a class prvalue
* strlen(std::string("text").c_str());
*
* // when a prvalue of a type with a destructor is discarded
* s.substr(0, 5); // Return value is discarded but requires destruction
* ```
*/
class TemporaryObjectExpr extends Conversion, @temp_init {
/** Gets a textual representation of this conversion. */
override string toString() { result = "temporary object" }
override string getAPrimaryQlClass() { result = "TemporaryObjectExpr" }
}
/**
* A node representing the Cast sub-class of entity `cast`.
*/
string qlCast(Cast cast) {
// NB: Take care and include only leaf QL classes
cast instanceof CStyleCast and result = "CStyleCast"
or
cast instanceof StaticCast and result = "StaticCast"
or
cast instanceof DynamicCast and result = "DynamicCast"
or
cast instanceof ConstCast and result = "ConstCast"
or
cast instanceof ReinterpretCast and result = "ReinterpretCast"
}
/**
* A node representing the Conversion sub-class of entity `cast`.
*/
string qlConversion(Cast cast) {
// NB: Take care and include only leaf QL classes
cast instanceof IntegralConversion and result = "IntegralConversion"
or
cast instanceof FloatingPointConversion and result = "FloatingPointConversion"
or
cast instanceof FloatingPointToIntegralConversion and result = "FloatingPointToIntegralConversion"
or
cast instanceof IntegralToFloatingPointConversion and result = "IntegralToFloatingPointConversion"
or
cast instanceof PointerConversion and result = "PointerConversion"
or
cast instanceof PointerToMemberConversion and result = "PointerToMemberConversion"
or
cast instanceof PointerToIntegralConversion and result = "PointerToIntegralConversion"
or
cast instanceof IntegralToPointerConversion and result = "IntegralToPointerConversion"
or
cast instanceof BoolConversion and result = "BoolConversion"
or
cast instanceof VoidConversion and result = "VoidConversion"
or
cast instanceof BaseClassConversion and result = "BaseClassConversion"
or
cast instanceof DerivedClassConversion and result = "DerivedClassConversion"
or
cast instanceof PointerToMemberBaseClassConversion and
result = "PointerToMemberBaseClassConversion"
or
cast instanceof PointerToMemberDerivedClassConversion and
result = "PointerToMemberDerivedClassConversion"
or
cast instanceof GlvalueConversion and result = "GlvalueConversion"
or
cast instanceof PrvalueAdjustmentConversion and result = "PrvalueAdjustmentConversion"
or
// treat dynamic_cast<...>(...) as a conversion
cast instanceof DynamicCast and result = "DynamicCast"
}