Merge pull request #21164 from jketema/jketema/builtin

C++: More builtins and information regarding this param refs
This commit is contained in:
Jeroen Ketema
2026-01-15 08:21:01 +01:00
committed by GitHub
16 changed files with 10885 additions and 797 deletions

View File

@@ -0,0 +1,17 @@
class Expr extends @expr {
string toString() { none() }
}
class Location extends @location_default {
string toString() { none() }
}
predicate isExprWithNewBuiltin(Expr expr) {
exists(int kind | exprs(expr, kind, _) | 394 <= kind and kind <= 396)
}
from Expr expr, int kind, int kind_new, Location location
where
exprs(expr, kind, location) and
if isExprWithNewBuiltin(expr) then kind_new = 1 else kind_new = kind
select expr, kind_new, location

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
description: Add new builtin operations and this parameter access table
compatibility: partial
exprs.rel: run exprs.qlo
param_ref_to_this.rel: delete

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Added subclasses of `BuiltInOperations` for the `__is_bitwise_cloneable`, `__is_invocable`, and `__is_nothrow_invocable` builtin operations.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Added a `isThisAccess` predicate to `ParamAccessForType` that holds when the access is to the implicit object parameter.

View File

@@ -394,6 +394,11 @@ class FunctionAccess extends Access, @routineexpr {
*/
class ParamAccessForType extends Expr, @param_ref {
override string toString() { result = "param access" }
/**
* Holds if the accessed parameter is implicit object parameter of the function.
*/
predicate isThisAccess() { param_ref_to_this(underlyingElement(this)) }
}
/**

View File

@@ -1941,3 +1941,61 @@ class BuiltInOperationIsTriviallyRelocatable extends BuiltInOperation, @istrivia
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyRelocatable" }
}
/**
* A C++ `__is_bitwise_cloneable` built-in operation.
*
* Returns `true` if an object of type `_Tp` is bitwise cloneable.
*
* ```
* template<typename _Tp>
* struct is_bitwise_cloneable
* : public integral_constant<bool, __is_bitwise_cloneable(_Tp)>
* {};
* ```
*/
class BuiltInOperationIsBitwiseCloneable extends BuiltInOperation, @isbitwisecloneable {
override string toString() { result = "__is_bitwise_cloneable" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsBitwiseCloneable" }
}
/**
* A C++ `__is_invocable` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns `true` if a function of type `_FTpn` can be invoked with arguments of
* type `_Tps`.
*
* ```
* template<typename _FTpn, typename... _Tps>
* struct is_invocable
* : public integral_constant<bool, __is_invocable(_FTpn, _Tps...)>
* {};
* ```
*/
class BuiltInOperationIsInvocable extends BuiltInOperation, @isinvocable {
override string toString() { result = "__is_invocable" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsInvocable" }
}
/**
* A C++ `__is_nothrow_invocable` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns `true` if a function of non-throwing type `_FTpn` can be invoked
* with arguments of type `_Tps`.
*
* ```
* template<typename _FTpn, typename... _Tps>
* struct is_nothrow_invocable
* : public integral_constant<bool, __is_nothrow_invocable(_FTpn, _Tps...)>
* {};
* ```
*/
class BuiltInOperationIsNothrowInvocable extends BuiltInOperation, @isnothrowinvocable {
override string toString() { result = "__is_nothrow_invocable" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsNothrowInvocable" }
}

View File

@@ -1902,6 +1902,9 @@ case @expr.kind of
| 391 = @nested_requirement
| 392 = @compound_requirement
| 393 = @concept_id
| 394 = @isinvocable
| 395 = @isnothrowinvocable
| 396 = @isbitwisecloneable
;
@var_args_expr = @vastartexpr
@@ -2018,6 +2021,9 @@ case @expr.kind of
| @istriviallyequalitycomparable
| @isscopedenum
| @istriviallyrelocatable
| @isinvocable
| @isnothrowinvocable
| @isbitwisecloneable
;
compound_requirement_is_noexcept(
@@ -2034,6 +2040,10 @@ new_array_allocated_type(
int type_id: @type ref
);
param_ref_to_this(
int expr: @param_ref ref
)
/**
* The field being initialized by an initializer expression within an aggregate
* initializer for a class/struct/union. Position is used to sort repeated initializers.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Add new builtin operations and this parameter access table
compatibility: backwards

View File

@@ -1,4 +1,4 @@
// semmle-extractor-options: --clang --clang_version 190000
// semmle-extractor-options: --clang --clang_version 210000
struct S {
void f() {}
@@ -121,3 +121,11 @@ bool b_is_scoped_enum2 = __is_scoped_enum(int);
bool b_is_trivially_relocatable1 = __is_trivially_relocatable(int);
bool b_is_trivially_relocatable2 = __is_trivially_relocatable(void);
struct S3{
S3(S3 &);
S3& operator=(S3&);
};
bool bok_is_bitwise_cloneable1 = __is_bitwise_cloneable(int);
bool bok_is_bitwise_cloneable2 = __is_bitwise_cloneable(S3);

View File

@@ -165,6 +165,10 @@
| clang.cpp:122:36:122:66 | int | | <none> |
| clang.cpp:123:36:123:67 | __is_trivially_relocatable | void | 0 |
| clang.cpp:123:36:123:67 | void | | <none> |
| clang.cpp:130:34:130:60 | __is_bitwise_cloneable | int | 1 |
| clang.cpp:130:34:130:60 | int | | <none> |
| clang.cpp:131:34:131:59 | S3 | | <none> |
| clang.cpp:131:34:131:59 | __is_bitwise_cloneable | S3 | 0 |
| file://:0:0:0:0 | 0 | | 0 |
| file://:0:0:0:0 | 0 | | 0 |
| file://:0:0:0:0 | 1 | | 1 |
@@ -211,6 +215,16 @@
| gcc.cpp:29:45:29:93 | __reference_converts_from_temporary | int &&,int && | 0 |
| gcc.cpp:29:45:29:93 | int && | | <none> |
| gcc.cpp:29:45:29:93 | int && | | <none> |
| gcc.cpp:33:24:33:45 | __is_invocable | f_type | 1 |
| gcc.cpp:33:24:33:45 | f_type | | <none> |
| gcc.cpp:34:24:34:51 | __is_invocable | f_type,bool | 0 |
| gcc.cpp:34:24:34:51 | bool | | <none> |
| gcc.cpp:34:24:34:51 | f_type | | <none> |
| gcc.cpp:36:32:36:61 | __is_nothrow_invocable | f_type | 1 |
| gcc.cpp:36:32:36:61 | f_type | | <none> |
| gcc.cpp:37:32:37:67 | __is_nothrow_invocable | f_type,bool | 0 |
| gcc.cpp:37:32:37:67 | bool | | <none> |
| gcc.cpp:37:32:37:67 | f_type | | <none> |
| ms.cpp:38:41:38:45 | 0 | | 0 |
| ms.cpp:88:27:88:45 | __has_assign | empty | 0 |
| ms.cpp:88:27:88:45 | empty | | <none> |

View File

@@ -1,4 +1,4 @@
// semmle-extractor-options: --gnu_version 130000
// semmle-extractor-options: --gnu_version 150000
__attribute__ ((aligned(8))) int v;
bool b_has_attribute1 = __builtin_has_attribute(v, aligned);
@@ -27,3 +27,11 @@ bool b_reference_constructs_from_temporary2 = __reference_constructs_from_tempor
bool b_reference_converts_from_temporary1 = __reference_converts_from_temporary(int&&, int);
bool b_reference_converts_from_temporary2 = __reference_converts_from_temporary(int&&, int&&);
using f_type = void(*)() noexcept;
bool b_is_invocable1 = __is_invocable(f_type);
bool b_is_invocable2 = __is_invocable(f_type, bool);
bool b_is_nothrow_invocable1 = __is_nothrow_invocable(f_type);
bool b_is_nothrow_invocable2 = __is_nothrow_invocable(f_type, bool);