mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge pull request #18483 from jketema/extractor-fixes
C++: Fix types of struct/union templates and fix assumptions on proxy classes
This commit is contained in:
2415
cpp/downgrades/a01d8f91b8d49259e509b574962dec90719f69a6/old.dbscheme
Normal file
2415
cpp/downgrades/a01d8f91b8d49259e509b574962dec90719f69a6/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
description: Improve user types and proxy classes
|
||||
compatibility: full
|
||||
usertypes.rel: run usertypes.qlo
|
||||
@@ -0,0 +1,10 @@
|
||||
class UserType extends @usertype {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
bindingset[kind]
|
||||
int getKind(int kind) { if kind in [15, 16, 17] then result = 6 else result = kind }
|
||||
|
||||
from UserType usertype, string name, int kind
|
||||
where usertypes(usertype, name, kind)
|
||||
select usertype, name, getKind(kind)
|
||||
6
cpp/ql/lib/change-notes/2025-01-13-struct-proxy.md
Normal file
6
cpp/ql/lib/change-notes/2025-01-13-struct-proxy.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* A new predicate `getDecltype`was added to the `ProxyClass` class, which yields the decltype for the proxy class.
|
||||
* Template classes that are of `struct` type are now also instances of the `Struct` class.
|
||||
* Template classes that are of `union` type are now also instances of the `Union` class.
|
||||
@@ -869,7 +869,7 @@ class AbstractClass extends Class {
|
||||
* `FullClassTemplateSpecialization`.
|
||||
*/
|
||||
class TemplateClass extends Class {
|
||||
TemplateClass() { usertypes(underlyingElement(this), _, 6) }
|
||||
TemplateClass() { usertypes(underlyingElement(this), _, [15, 16, 17]) }
|
||||
|
||||
/**
|
||||
* Gets a class instantiated from this template.
|
||||
@@ -1076,13 +1076,19 @@ class VirtualBaseClass extends Class {
|
||||
}
|
||||
|
||||
/**
|
||||
* The proxy class (where needed) associated with a template parameter, as
|
||||
* in the following code:
|
||||
* ```
|
||||
* The proxy class (where needed) associated with a template parameter or a
|
||||
* decltype, as in the following code:
|
||||
* ```cpp
|
||||
* template <typename T>
|
||||
* struct S : T { // the type of this T is a proxy class
|
||||
* ...
|
||||
* };
|
||||
*
|
||||
* template <typename T>
|
||||
* concept C =
|
||||
* decltype(std::span{std::declval<T&>()})::extent
|
||||
* != std::dynamic_extent;
|
||||
* // the type of decltype(std::span{std::declval<T&>()}) is a proxy class
|
||||
* ```
|
||||
*/
|
||||
class ProxyClass extends UserType {
|
||||
@@ -1093,10 +1099,13 @@ class ProxyClass extends UserType {
|
||||
/** Gets the location of the proxy class. */
|
||||
override Location getLocation() { result = this.getTemplateParameter().getDefinitionLocation() }
|
||||
|
||||
/** Gets the template parameter for which this is the proxy class. */
|
||||
/** Gets the template parameter for which this is the proxy class, if any. */
|
||||
TypeTemplateParameter getTemplateParameter() {
|
||||
is_proxy_class_for(underlyingElement(this), unresolveElement(result))
|
||||
}
|
||||
|
||||
/** Gets the decltype for which this is the proxy class, if any. */
|
||||
Decltype getDecltype() { is_proxy_class_for(underlyingElement(this), unresolveElement(result)) }
|
||||
}
|
||||
|
||||
// Unpacks "array of ... of array of t" into t.
|
||||
|
||||
@@ -20,7 +20,7 @@ import semmle.code.cpp.Class
|
||||
* ```
|
||||
*/
|
||||
class Struct extends Class {
|
||||
Struct() { usertypes(underlyingElement(this), _, 1) or usertypes(underlyingElement(this), _, 3) }
|
||||
Struct() { usertypes(underlyingElement(this), _, [1, 3, 15, 17]) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Struct" }
|
||||
|
||||
|
||||
@@ -52,9 +52,7 @@ deprecated class TemplateParameter = TypeTemplateParameter;
|
||||
* ```
|
||||
*/
|
||||
class TypeTemplateParameter extends UserType, TemplateParameterImpl {
|
||||
TypeTemplateParameter() {
|
||||
usertypes(underlyingElement(this), _, 7) or usertypes(underlyingElement(this), _, 8)
|
||||
}
|
||||
TypeTemplateParameter() { usertypes(underlyingElement(this), _, [7, 8]) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "TypeTemplateParameter" }
|
||||
|
||||
|
||||
@@ -406,10 +406,7 @@ class IntegralOrEnumType extends Type {
|
||||
isIntegralType(underlyingElement(this), _)
|
||||
or
|
||||
// Enum type
|
||||
(
|
||||
usertypes(underlyingElement(this), _, 4) or
|
||||
usertypes(underlyingElement(this), _, 13)
|
||||
)
|
||||
usertypes(underlyingElement(this), _, [4, 13])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,10 +13,7 @@ private import semmle.code.cpp.internal.ResolveClass
|
||||
* ```
|
||||
*/
|
||||
class TypedefType extends UserType {
|
||||
TypedefType() {
|
||||
usertypes(underlyingElement(this), _, 5) or
|
||||
usertypes(underlyingElement(this), _, 14)
|
||||
}
|
||||
TypedefType() { usertypes(underlyingElement(this), _, [5, 14]) }
|
||||
|
||||
/**
|
||||
* Gets the base type of this typedef type.
|
||||
|
||||
@@ -15,7 +15,7 @@ import semmle.code.cpp.Struct
|
||||
* ```
|
||||
*/
|
||||
class Union extends Struct {
|
||||
Union() { usertypes(underlyingElement(this), _, 3) }
|
||||
Union() { usertypes(underlyingElement(this), _, [3, 17]) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Union" }
|
||||
|
||||
|
||||
@@ -227,11 +227,11 @@ class ProxyClass extends UserType {
|
||||
}
|
||||
|
||||
class TypeTemplateParameter extends UserType {
|
||||
TypeTemplateParameter() { usertypes(this, _, 7) or usertypes(this, _, 8) }
|
||||
TypeTemplateParameter() { usertypes(this, _, [7, 8]) }
|
||||
}
|
||||
|
||||
class TemplateClass extends UserType {
|
||||
TemplateClass() { usertypes(this, _, 6) }
|
||||
TemplateClass() { usertypes(this, _, [15, 16, 17]) }
|
||||
|
||||
UserType getAnInstantiation() {
|
||||
class_instantiation(result, this) and
|
||||
|
||||
@@ -114,15 +114,7 @@ private module Cached {
|
||||
* Holds if `t` is a struct, class, union, or template.
|
||||
*/
|
||||
cached
|
||||
predicate isClass(@usertype t) {
|
||||
usertypes(t, _, 1) or
|
||||
usertypes(t, _, 2) or
|
||||
usertypes(t, _, 3) or
|
||||
usertypes(t, _, 6) or
|
||||
usertypes(t, _, 10) or
|
||||
usertypes(t, _, 11) or
|
||||
usertypes(t, _, 12)
|
||||
}
|
||||
predicate isClass(@usertype t) { usertypes(t, _, [1, 2, 3, 15, 16, 17]) }
|
||||
|
||||
cached
|
||||
predicate isType(@type t) {
|
||||
|
||||
@@ -771,12 +771,13 @@ decltypes(
|
||||
|
||||
/*
|
||||
case @usertype.kind of
|
||||
1 = @struct
|
||||
| 0 = @unknown_usertype
|
||||
| 1 = @struct
|
||||
| 2 = @class
|
||||
| 3 = @union
|
||||
| 4 = @enum
|
||||
| 5 = @typedef // classic C: typedef typedef type name
|
||||
| 6 = @template
|
||||
// ... 6 = @template deprecated
|
||||
| 7 = @template_parameter
|
||||
| 8 = @template_template_parameter
|
||||
| 9 = @proxy_class // a proxy class associated with a template parameter
|
||||
@@ -785,6 +786,9 @@ case @usertype.kind of
|
||||
// ... 12 objc_category deprecated
|
||||
| 13 = @scoped_enum
|
||||
| 14 = @using_alias // a using name = type style typedef
|
||||
| 15 = @template_struct
|
||||
| 16 = @template_class
|
||||
| 17 = @template_union
|
||||
;
|
||||
*/
|
||||
|
||||
@@ -843,9 +847,11 @@ class_template_argument_value(
|
||||
int arg_value: @expr ref
|
||||
);
|
||||
|
||||
@user_or_decltype = @usertype | @decltype;
|
||||
|
||||
is_proxy_class_for(
|
||||
unique int id: @usertype ref,
|
||||
unique int templ_param_id: @usertype ref
|
||||
int templ_param_id: @user_or_decltype ref
|
||||
);
|
||||
|
||||
type_mentions(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
description: Improve user types and proxy classes
|
||||
compatibility: partial
|
||||
usertypes.rel: run usertypes.qlo
|
||||
@@ -0,0 +1,17 @@
|
||||
class UserType extends @usertype {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
bindingset[kind]
|
||||
int getKind(int kind) {
|
||||
if kind in [10, 11, 12]
|
||||
then result = 0
|
||||
else
|
||||
if kind = 6
|
||||
then result = 16
|
||||
else result = kind
|
||||
}
|
||||
|
||||
from UserType usertype, string name, int kind
|
||||
where usertypes(usertype, name, kind)
|
||||
select usertype, name, getKind(kind)
|
||||
@@ -21,7 +21,7 @@ string kindstr(Class c) {
|
||||
or
|
||||
kind = 2 and result = "Class"
|
||||
or
|
||||
kind = 6 and result = "Template class"
|
||||
kind = [15, 16] and result = "Template class"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
| ODASA-5186.cpp:4:8:4:14 | MyClass<T> | Class | ODASA-5186.cpp:5:8:5:17 | operator== | |
|
||||
| ODASA-5186.cpp:4:8:4:14 | MyClass<T> | Struct | ODASA-5186.cpp:5:8:5:17 | operator== | |
|
||||
| ODASA-5186.cpp:4:8:4:14 | MyClass<int> | Struct | ODASA-5186.cpp:5:8:5:8 | operator== | |
|
||||
| file://:0:0:0:0 | __va_list_tag | Struct | file://:0:0:0:0 | operator= | |
|
||||
| file://:0:0:0:0 | __va_list_tag | Struct | file://:0:0:0:0 | operator= | |
|
||||
|
||||
@@ -12445,11 +12445,11 @@ ir.cpp:
|
||||
# 1088| [ConstMemberFunction] bool std::iterator<Category, value_type, difference_type, pointer_type, reference_type>::operator==(std::iterator<Category, value_type, difference_type, pointer_type, reference_type>) const
|
||||
# 1088| <params>:
|
||||
# 1088| getParameter(0): [Parameter] other
|
||||
# 1088| Type = [TemplateClass] iterator<Category, value_type, difference_type, pointer_type, reference_type>
|
||||
# 1088| Type = [Struct,TemplateClass] iterator<Category, value_type, difference_type, pointer_type, reference_type>
|
||||
# 1089| [ConstMemberFunction] bool std::iterator<Category, value_type, difference_type, pointer_type, reference_type>::operator!=(std::iterator<Category, value_type, difference_type, pointer_type, reference_type>) const
|
||||
# 1089| <params>:
|
||||
# 1089| getParameter(0): [Parameter] other
|
||||
# 1089| Type = [TemplateClass] iterator<Category, value_type, difference_type, pointer_type, reference_type>
|
||||
# 1089| Type = [Struct,TemplateClass] iterator<Category, value_type, difference_type, pointer_type, reference_type>
|
||||
# 1089| [ConstMemberFunction] bool std::iterator<std::random_access_iterator_tag, ClassWithDestructor, std::ptrdiff_t, ClassWithDestructor*, ClassWithDestructor&>::operator!=(std::iterator<std::random_access_iterator_tag, ClassWithDestructor, std::ptrdiff_t, ClassWithDestructor*, ClassWithDestructor&>) const
|
||||
# 1089| <params>:
|
||||
# 1089| getParameter(0): [Parameter] other
|
||||
@@ -12497,7 +12497,7 @@ ir.cpp:
|
||||
# 1096| [MemberFunction] int std::iterator<Category, value_type, difference_type, pointer_type, reference_type>::operator-(std::iterator<Category, value_type, difference_type, pointer_type, reference_type>)
|
||||
# 1096| <params>:
|
||||
# 1096| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
# 1096| Type = [TemplateClass] iterator<Category, value_type, difference_type, pointer_type, reference_type>
|
||||
# 1096| Type = [Struct,TemplateClass] iterator<Category, value_type, difference_type, pointer_type, reference_type>
|
||||
# 1097| [MemberFunction] reference_type std::iterator<Category, value_type, difference_type, pointer_type, reference_type>::operator[](int)
|
||||
# 1097| <params>:
|
||||
# 1097| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
| proxy_class.cpp:3:20:3:20 | T | ProxyClass |
|
||||
| proxy_class.cpp:3:20:3:20 | T | TypeTemplateParameter |
|
||||
| proxy_class.cpp:4:8:4:14 | Derived<Base> | Struct |
|
||||
| proxy_class.cpp:4:8:4:14 | Derived<T> | Struct |
|
||||
|
||||
Reference in New Issue
Block a user