Files
codeql/cpp/ql/lib/semmle/code/cpp/Enum.qll
Erik Krogh Kristensen fe891746bf C++: fix implicit this
2021-10-15 14:59:48 +01:00

205 lines
5.7 KiB
Plaintext

/**
* Provides classes representing C/C++ enums and enum constants.
*/
import semmle.code.cpp.Type
private import semmle.code.cpp.internal.ResolveClass
/**
* A C/C++ enum [N4140 7.2]. For example, the types `MyEnum` and
* `MyScopedEnum` in:
* ```
* enum MyEnum {
* MyEnumConstant
* };
*
* enum class MyScopedEnum {
* MyScopedEnumConstant
* };
* ```
* This includes C++ scoped enums, see the `ScopedEnum` QL class.
*/
class Enum extends UserType, IntegralOrEnumType {
/** Gets an enumerator of this enumeration. */
EnumConstant getAnEnumConstant() { result.getDeclaringEnum() = this }
/**
* Gets the enumerator of this enumeration that was declared at the zero-based position `index`.
* For example, `zero` is at index 2 in the following declaration:
* ```
* enum ReversedOrder {
* two = 2,
* one = 1,
* zero = 0
* };
* ```
*/
EnumConstant getEnumConstant(int index) {
enumconstants(unresolveElement(result), underlyingElement(this), index, _, _, _)
}
override string getAPrimaryQlClass() { result = "Enum" }
/**
* Gets a descriptive string for the enum. This method is only intended to
* be used for debugging purposes. For more information, see the comment
* for `Type.explain`.
*/
override string explain() { result = "enum " + this.getName() }
override int getSize() {
// Workaround for extractor bug CPP-348: No size information for enums.
// If the extractor didn't provide a size, assume four bytes.
result = UserType.super.getSize()
or
not exists(UserType.super.getSize()) and result = 4
}
/** See `Type.isDeeplyConst` and `Type.isDeeplyConstBelow`. Internal. */
override predicate isDeeplyConstBelow() { any() } // No subparts
/**
* Holds if this enum has an enum-base [N4140 7.2].
* For example: `enum E : int`.
*/
predicate hasExplicitUnderlyingType() { derivations(_, underlyingElement(this), _, _, _) }
/**
* The type of the enum-base [N4140 7.2], if it is specified.
* For example: `int` in `enum E : int`.
*/
Type getExplicitUnderlyingType() {
derivations(_, underlyingElement(this), _, unresolveElement(result), _)
}
}
/**
* A C/C++ enum that is directly enclosed by a function. For example, the type
* `MyLocalEnum` in:
* ```
* void myFunction() {
* enum MyLocalEnum {
* MyLocalEnumConstant
* };
* }
* ```
*/
class LocalEnum extends Enum {
LocalEnum() { this.isLocal() }
override string getAPrimaryQlClass() { result = "LocalEnum" }
}
/**
* A C/C++ enum that is declared within a class/struct. For example, the type
* `MyNestedEnum` in:
* ```
* class MyClass {
* public:
* enum MyNestedEnum {
* MyNestedEnumConstant
* };
* };
* ```
*/
class NestedEnum extends Enum {
NestedEnum() { this.isMember() }
override string getAPrimaryQlClass() { result = "NestedEnum" }
/** Holds if this member is private. */
predicate isPrivate() { this.hasSpecifier("private") }
/** Holds if this member is protected. */
predicate isProtected() { this.hasSpecifier("protected") }
/** Holds if this member is public. */
predicate isPublic() { this.hasSpecifier("public") }
}
/**
* A C++ scoped enum, that is, an enum whose constants must be qualified with
* the name of the enum. For example, the type `Color` in:
* ```
* enum class Color {
* red,
* blue
* }
* ```
*/
class ScopedEnum extends Enum {
ScopedEnum() { usertypes(underlyingElement(this), _, 13) }
override string getAPrimaryQlClass() { result = "ScopedEnum" }
}
/**
* A C/C++ enumerator [N4140 7.2], also known as an enumeration constant.
*
* For example the enumeration constant `green` in:
* ```
* enum {
* red,
* green,
* blue
* }
* ```
*/
class EnumConstant extends Declaration, @enumconstant {
/**
* Gets the enumeration of which this enumerator is a member.
*/
Enum getDeclaringEnum() {
enumconstants(underlyingElement(this), unresolveElement(result), _, _, _, _)
}
override string getAPrimaryQlClass() { result = "EnumConstant" }
override Class getDeclaringType() { result = this.getDeclaringEnum().getDeclaringType() }
/**
* Gets the name of this enumerator.
*/
override string getName() { enumconstants(underlyingElement(this), _, _, _, result, _) }
/**
* Gets the value that this enumerator is initialized to, as a
* string. This can be a value explicitly given to the enumerator, or an
* automatically assigned value.
*/
string getValue() { result = this.getInitializer().getExpr().getValue() }
/** Gets the type of this enumerator. */
Type getType() { enumconstants(underlyingElement(this), _, _, unresolveElement(result), _, _) }
/** Gets the location of a declaration of this enumerator. */
override Location getADeclarationLocation() { result = this.getDefinitionLocation() }
/** Gets the location of the definition of this enumerator. */
override Location getDefinitionLocation() {
enumconstants(underlyingElement(this), _, _, _, _, result)
}
/** Gets the location of the definition of this enumerator. */
override Location getLocation() { result = this.getDefinitionLocation() }
/** Gets the initializer of this enumerator, if any. */
Initializer getInitializer() { result.getDeclaration() = this }
/** Gets an access of this enumerator. */
EnumConstantAccess getAnAccess() { result.getTarget() = this }
/** Gets a specifier of this enumerator. */
override Specifier getASpecifier() {
varspecifiers(underlyingElement(this), unresolveElement(result))
}
/**
* An attribute of this enumerator.
*
* Note that allowing attributes on enumerators is a language extension
* which is only supported by Clang.
*/
Attribute getAnAttribute() { varattributes(underlyingElement(this), unresolveElement(result)) }
}