-
Notifications
You must be signed in to change notification settings - Fork 69
Add new library, backported to a small handful of queries, for resolving types. #991
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
MichaelRFairhurst
wants to merge
3
commits into
main
Choose a base branch
from
michaelrfairhurst/resolves-to-type-lib
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| - `INT36-C` - `ConvertingAPointerToIntegerOrIntegerToPointer.ql`: | ||
| - Integrated new type resolution modules to fully handle typedefs and ignore cv-qualifiers during type comparisons, such as in detecting int types, pointer types, (u)intptr_t types, and void pointer types. | ||
| - `RULE-22-12`, `RULE-22-13`, `RULE-22-14` - `NonstandardUseOfThreadingObject.ql`, `ThreadingObjectWithInvalidStorageDuration.ql`, `MutexNotInitializedBeforeUse.ql`: | ||
| - Integrated new type resolution modules to handle typedefs when identifying threading object types. | ||
| - `RULE-9-5-1` - `LegacyForStatementsShouldBeSimple.ql`: | ||
| - Refactor to integrate new type resolution, no change in functionality expected. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,273 @@ | ||||||
| private import cpp | ||||||
| private import qtil.Qtil | ||||||
| private import codingstandards.cpp.types.Specifiers | ||||||
| private import codeql.util.Boolean | ||||||
|
|
||||||
| Type typeResolvesToTypeStep(Type type) { | ||||||
| result = type.(Decltype).getBaseType() | ||||||
| or | ||||||
| result = type.(TypedefType).getBaseType() | ||||||
| } | ||||||
|
|
||||||
| module PointerTo<Qtil::Signature<Type>::Type PointeeType> { | ||||||
| /** | ||||||
| * A pointer type that points to a type that resolves to the module's `PointeeType` type parameter. | ||||||
| */ | ||||||
| class Type extends Qtil::Final<PointerType>::Type { | ||||||
| Type() { getBaseType() instanceof PointeeType } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| module ReferenceOf<Qtil::Signature<Type>::Type ReferencedType> { | ||||||
| /** | ||||||
| * A reference type that refers to a type that resolves to the module's `ReferencedType` type | ||||||
| * parameter. | ||||||
| */ | ||||||
| class Type extends Qtil::Final<ReferenceType>::Type { | ||||||
| Type() { getBaseType() instanceof ReferencedType } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * A module for handling complex type resolution in c++, such as a decltype of a const typedef | ||||||
| * of a struct type, which resolves to a const struct type. | ||||||
| * | ||||||
| * Basic usage: | ||||||
| * - `ResolvesTo<ClassType>::Exactly` is the set of class types, and typedefs/decltypes that resolve | ||||||
| * to class types exactly (without specifiers). | ||||||
| * - `resolvedType.resolve()` gets the fully resolved class type for the above. | ||||||
| * - `ResolvesTo<ClassType>::Specified` is the set of types that resolve to a specified class type. | ||||||
| * - `ResolvesTo<ClassType>::Ref` is the set of types that resolve to a reference to a class type. | ||||||
| * - `ResolvesTo<ClassType>::Const` is the set of types that resolve to a const class type. | ||||||
| * - `ResolvesTo<ClassType>::IgnoringSpecifiers` is the set of types that resolve to a class type | ||||||
| * ignoring specifiers. | ||||||
| * - `ResolvesTo<ClassType>::ExactlyOrRef` is the set of types that resolve to a class type and | ||||||
| * unwraps references. | ||||||
| * | ||||||
| * These module classes are preferred to the member predicates on `Type` such as `resolveTypedefs`, | ||||||
| * `stripSpecifiers`, `getUnderlyingType()`, etc, for the following reasons: | ||||||
| * - Hopefully the API is clearer and easier to use correctly. | ||||||
| * - Unlike `resolveTypedefs`, these classes can find types that resolve to other typedefs (via | ||||||
| * `ResolvesType<SomeTypedefType>::Exactly` etc.), instead of always resolving all typedefs. | ||||||
| * - The member predicates on `Type` have cases with no result. For instance, if there's a const | ||||||
| * typedef `const T = F`, but `const F` is never explicitly written in the code, then there is no | ||||||
| * matching extracted `Type` for `resolveTypedefs` to return, and it will have no result. | ||||||
| */ | ||||||
| module ResolvesTo<Qtil::Signature<Type>::Type ResolvedType> { | ||||||
| private import cpp as cpp | ||||||
|
|
||||||
| final class CppType = cpp::Type; | ||||||
|
|
||||||
| /** | ||||||
| * A type that resolve exactly to the module's `ResolvedType` type parameter. | ||||||
MichaelRFairhurst marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| * | ||||||
| * For example, `ResolvesTo<FooType>::Type` is the set of all `FooType`s and types that resolve | ||||||
| * (through typedefs * and/or decltypes) to `FooType`s. This does _not_ include types that resolve | ||||||
| * to a const `FooType` (though `FooType` itself may be const). To perform type resolution and | ||||||
| * check or strip specifiers, see module classes `IgnoringSpecifiers`, `Specified`, `Const`, etc. | ||||||
| * | ||||||
| * ``` | ||||||
| * // Example `ResolvesTo<FooType>::Exactly` types: | ||||||
| * FooType f; // matches (a FooType) | ||||||
| * decltype(f); // matches (a decltype of FooType) | ||||||
| * typedef FooType FT; // matches (a typedef of FooType) | ||||||
| * FT f2; // matches (a typedef of FooType) | ||||||
| * decltype(f2); // matches (a decltype of typedef of FooType) | ||||||
| * typedef FT FT2; // matches (a typedef of typedef of FooType) | ||||||
| * | ||||||
| * // Examples types that are not `ResolvesTo<FooType>::Exactly` types: | ||||||
| * const FooType cf; // does not match (specified FooTypes) | ||||||
| * FooType& rf = f; // does not match (references to FooTypes) | ||||||
| * NotFooType nf; // does not match (non FooTypes) | ||||||
| * ``` | ||||||
| */ | ||||||
| class Exactly extends CppType { | ||||||
| ResolvedType resolvedType; | ||||||
|
|
||||||
| Exactly() { resolvedType = typeResolvesToTypeStep*(this) } | ||||||
|
|
||||||
| ResolvedType resolve() { result = resolvedType } | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * A type that resolves to a const type that in turn resolves to the module's `ResolvedType` type. | ||||||
| * | ||||||
| * For example, `ResolvesTo<FooType>::CvConst` is the set of all const `FooType`s and types that | ||||||
| * resolve (through typedefs and/or decltypes) to const `FooType`s, including cases involving | ||||||
| * `const` typedefs, etc. | ||||||
| * | ||||||
| * Volatile specifiers are ignored, since const volatile types are still const. | ||||||
| * | ||||||
| * For matching both const and non-const types that resolve to `FooType`, see | ||||||
| * `IgnoringSpecifiers`. | ||||||
| * | ||||||
| * ``` | ||||||
| * // Note that this does NOT match `FooType`s that are not const. | ||||||
| * FooType f; // does not match (non-const) | ||||||
| * decltype(f) df; // does not match (non-const) | ||||||
| * typedef TF = FooType; // does not match (non-const) | ||||||
| * | ||||||
| * // Example `ResolvesTo<FooType>::Const` types: | ||||||
| * const FooType cf; // matches (a const FooType) | ||||||
| * const volatile FooType cf; // matches (a const FooType, volatile is allowed and ignored) | ||||||
| * decltype(cf); // matches (a decltype of a const FooType) | ||||||
| * const decltype(f); // matches (a const decltype of FooType) | ||||||
| * const decltype(cf); // matches (a const decltype of a const FooType) | ||||||
| * typedef const FooType CFT; // matches (a typedef of const FooType) | ||||||
| * const TF ctf; // matches (a const typedef of FooType) | ||||||
| * | ||||||
| * // Additional examples types that are not `ResolvesTo<FooType>::Const` types: | ||||||
| * const FooType &f; // does not match (reference to const FooType) | ||||||
| * ``` | ||||||
| */ | ||||||
| class CvConst extends Specified { | ||||||
| CvConst() { getASpecifier() instanceof ConstSpecifier } | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * A type that resolves to a cv-qualified (or otherwise specified) type that in turn resolves to | ||||||
| * the module's `ResolvedType` type parameter. | ||||||
| * | ||||||
| * For example, `ResolvesTo<FooType>::Specified` is the set of all specified `FooType`s and types | ||||||
| * that resolve (through typedefs and/or decltypes) to specified `FooType`s, including cases | ||||||
| * involving `const` and `volatile` typedefs, etc. | ||||||
| * | ||||||
| * ``` | ||||||
| * // Note that this does NOT match `FooType`s that are not specified. | ||||||
| * FooType f; // does not match (not specified) | ||||||
| * decltype(f) df; // does not match (not specified) | ||||||
| * typedef TF = FooType; // does not match (not specified) | ||||||
| * | ||||||
| * // Example `ResolvesTo<FooType>::Specified` types: | ||||||
| * const FooType cf; // matches (a const FooType) | ||||||
| * volatile FooType vf; // matches (a volatile FooType) | ||||||
| * const volatile FooType cvf; // matches (a const volatile FooType) | ||||||
| * decltype(cf); // matches (a decltype of a const FooType) | ||||||
| * volatile decltype(f); // matches (a volatile decltype of FooType) | ||||||
| * const decltype(vf); // matches (a const decltype of volatile FooType) | ||||||
| * const decltype(cf); // matches (a const decltype of const FooType) | ||||||
| * typedef const FooType CFT; // matches (a typedef of const FooType) | ||||||
| * const TF ctf; // matches (a const typedef of FooType) | ||||||
| * volatile TF ctf; // matches (a volatile typedef of FooType) | ||||||
| * | ||||||
| * // Additional examples types that are not `ResolvesTo<FooType>::Specified` types: | ||||||
| * const FooType &f; // does not match (reference to const FooType) | ||||||
| * ``` | ||||||
| */ | ||||||
| class Specified extends CppType { | ||||||
| ResolvedType resolved; | ||||||
|
|
||||||
| Specified() { | ||||||
| resolved = typeResolvesToTypeStep*(this).(SpecifiedType).getBaseType().(Exactly).resolve() | ||||||
| } | ||||||
|
|
||||||
| ResolvedType resolve() { result = resolved } | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * A class that resolves to the module's `ResolvedType` type parameter, ignoring specifiers. | ||||||
| */ | ||||||
| class IgnoringSpecifiers extends CppType { | ||||||
| ResolvedType resolved; | ||||||
|
|
||||||
| IgnoringSpecifiers() { | ||||||
| resolved = this.(Specified).resolve() | ||||||
| or | ||||||
| resolved = this.(Exactly).resolve() | ||||||
| } | ||||||
|
|
||||||
| ResolvedType resolve() { result = resolved } | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * A type that resolves to a reference to that resolves to the module's `ResolvedType` type | ||||||
MichaelRFairhurst marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| * parameter. | ||||||
| * | ||||||
| * For example, `ResolvesTo<FooType>::Ref` is the set of all references to `FooType`s and types | ||||||
| * that resolve (through typedefs and/or decltypes) to references to `FooType`s. | ||||||
| * | ||||||
| * ``` | ||||||
| * // Example `ResolvesTo<FooType>::Ref` types: | ||||||
| * FooType &f; // matches (a reference to FooType) | ||||||
| * decltype(f); // matches (a decltype of reference to FooType) | ||||||
| * typedef FooType &FT; // matches (a typedef of ref to FooType) | ||||||
| * FT f2; // matches (a typedef of ref to FooType) | ||||||
| * decltype(f2); // matches (a decltype of typedef of ref to FooType) | ||||||
| * typedef FT FT2; // matches (a typedef of typedef of ref to FooType) | ||||||
| * | ||||||
| * // Examples types that are not `ResolvesTo<FooType>::Ref` types: | ||||||
| * const FooType &cf; // does not match (specified references to FooTypes) | ||||||
| * FooType rf = f; // does not match (non-rerefence FooTypes) | ||||||
|
||||||
| * FooType rf = f; // does not match (non-rerefence FooTypes) | |
| * FooType rf = f; // does not match (non-reference FooTypes) |
MichaelRFairhurst marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
MichaelRFairhurst marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
MichaelRFairhurst marked this conversation as resolved.
Show resolved
Hide resolved
MichaelRFairhurst marked this conversation as resolved.
Show resolved
Hide resolved
MichaelRFairhurst marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
MichaelRFairhurst marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.