mirror of
https://github.com/github/codeql.git
synced 2026-07-07 12:35:33 +02:00
Compare commits
54 Commits
codeql-cli
...
aibaars-pa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a2f66a221 | ||
|
|
1737d08145 | ||
|
|
b5d4a2d462 | ||
|
|
ed67fb0933 | ||
|
|
b50f4bc1a8 | ||
|
|
4ce100f9a3 | ||
|
|
45e14c96f2 | ||
|
|
13f2cf9003 | ||
|
|
daf1fa3c31 | ||
|
|
405d0fcd54 | ||
|
|
593ce01362 | ||
|
|
48e93b3654 | ||
|
|
22c5b7af4f | ||
|
|
34edb2537f | ||
|
|
5b1fe56d5f | ||
|
|
ec03ebbbfc | ||
|
|
6091f0dbce | ||
|
|
099ab0e0c2 | ||
|
|
604328ea5f | ||
|
|
652230d021 | ||
|
|
69633948ce | ||
|
|
065fecc57e | ||
|
|
50e1ffda64 | ||
|
|
a27b1ee33a | ||
|
|
5a59354d73 | ||
|
|
bce253920c | ||
|
|
afdd21eab7 | ||
|
|
295ecbb401 | ||
|
|
1806b8933f | ||
|
|
20b66eaf34 | ||
|
|
81e687ea98 | ||
|
|
a85d3f9b7f | ||
|
|
0c03935437 | ||
|
|
c4283dd23f | ||
|
|
9876c391fa | ||
|
|
e140d2ab4f | ||
|
|
985237ab2d | ||
|
|
1737ed50ba | ||
|
|
8cd2aeb65d | ||
|
|
7475f84ea5 | ||
|
|
e7f275382e | ||
|
|
8a36a2b563 | ||
|
|
ddf715e6a9 | ||
|
|
d547a417c9 | ||
|
|
cb006900cd | ||
|
|
7d7966e711 | ||
|
|
b491884996 | ||
|
|
76ea63ffbe | ||
|
|
ab1370cc8f | ||
|
|
7ca955a0e6 | ||
|
|
6087bc6888 | ||
|
|
1788507571 | ||
|
|
a1fe8a5b2b | ||
|
|
882000afb3 |
5
.github/actions/fetch-codeql/action.yml
vendored
5
.github/actions/fetch-codeql/action.yml
vendored
@@ -13,6 +13,11 @@ runs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: echo "GA_CODEQL_CLI_PLATFORM=osx64" >> $GITHUB_ENV
|
run: echo "GA_CODEQL_CLI_PLATFORM=osx64" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Select platform - Windows
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
shell: bash
|
||||||
|
run: echo "GA_CODEQL_CLI_PLATFORM=win64" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Fetch CodeQL
|
- name: Fetch CodeQL
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
class Expr extends @expr {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Location extends @location_expr {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate isExprWithNewBuiltin(Expr expr) {
|
||||||
|
exists(int kind | exprs(expr, kind, _) | 330 <= kind and kind <= 334)
|
||||||
|
}
|
||||||
|
|
||||||
|
from Expr expr, int kind, int kind_new, Location location
|
||||||
|
where
|
||||||
|
exprs(expr, kind, location) and
|
||||||
|
if isExprWithNewBuiltin(expr) then kind_new = 0 else kind_new = kind
|
||||||
|
select expr, kind_new, location
|
||||||
2125
cpp/downgrades/23f7cbb88a4eb29f30c3490363dc201bc054c5ff/old.dbscheme
Normal file
2125
cpp/downgrades/23f7cbb88a4eb29f30c3490363dc201bc054c5ff/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: Add new builtin operations
|
||||||
|
compatibility: partial
|
||||||
|
exprs.rel: run exprs.qlo
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: feature
|
||||||
|
---
|
||||||
|
* Added subclasses of `BuiltInOperations` for `__builtin_bit_cast`, `__builtin_shuffle`, `__has_unique_object_representations`, `__is_aggregate`, and `__is_assignable`.
|
||||||
@@ -121,7 +121,7 @@ class BuiltInNoOp extends BuiltInOperation, @noopexpr {
|
|||||||
/**
|
/**
|
||||||
* A C/C++ `__builtin_offsetof` built-in operation (used by some implementations
|
* A C/C++ `__builtin_offsetof` built-in operation (used by some implementations
|
||||||
* of `offsetof`). The operation retains its semantics even in the presence
|
* of `offsetof`). The operation retains its semantics even in the presence
|
||||||
* of an overloaded `operator &`). This is a GNU/Clang extension.
|
* of an overloaded `operator &`). This is a gcc/clang extension.
|
||||||
* ```
|
* ```
|
||||||
* struct S {
|
* struct S {
|
||||||
* int a, b;
|
* int a, b;
|
||||||
@@ -479,8 +479,7 @@ class BuiltInOperationBuiltInTypesCompatibleP extends BuiltInOperation, @typesco
|
|||||||
/**
|
/**
|
||||||
* A clang `__builtin_shufflevector` expression.
|
* A clang `__builtin_shufflevector` expression.
|
||||||
*
|
*
|
||||||
* It outputs a permutation of elements from one or two input vectors.
|
* It outputs a permutation of elements from one or two input vectors. See
|
||||||
* Please see
|
|
||||||
* https://releases.llvm.org/3.7.0/tools/clang/docs/LanguageExtensions.html#langext-builtin-shufflevector
|
* https://releases.llvm.org/3.7.0/tools/clang/docs/LanguageExtensions.html#langext-builtin-shufflevector
|
||||||
* for more information.
|
* for more information.
|
||||||
* ```
|
* ```
|
||||||
@@ -494,11 +493,29 @@ class BuiltInOperationBuiltInShuffleVector extends BuiltInOperation, @builtinshu
|
|||||||
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInShuffleVector" }
|
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInShuffleVector" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A gcc `__builtin_shuffle` expression.
|
||||||
|
*
|
||||||
|
* It outputs a permutation of elements from one or two input vectors.
|
||||||
|
* See https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
|
||||||
|
* for more information.
|
||||||
|
* ```
|
||||||
|
* // Concatenate every other element of 4-element vectors V1 and V2.
|
||||||
|
* M = {0, 2, 4, 6};
|
||||||
|
* V3 = __builtin_shuffle(V1, V2, M);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
class BuiltInOperationBuiltInShuffle extends BuiltInOperation, @builtinshuffle {
|
||||||
|
override string toString() { result = "__builtin_shuffle" }
|
||||||
|
|
||||||
|
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInShuffle" }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A clang `__builtin_convertvector` expression.
|
* A clang `__builtin_convertvector` expression.
|
||||||
*
|
*
|
||||||
* Allows for conversion of vectors of equal element count and compatible
|
* Allows for conversion of vectors of equal element count and compatible
|
||||||
* element types. Please see
|
* element types. See
|
||||||
* https://releases.llvm.org/3.7.0/tools/clang/docs/LanguageExtensions.html#builtin-convertvector
|
* https://releases.llvm.org/3.7.0/tools/clang/docs/LanguageExtensions.html#builtin-convertvector
|
||||||
* for more information.
|
* for more information.
|
||||||
* ```
|
* ```
|
||||||
@@ -612,13 +629,10 @@ class BuiltInOperationIsTriviallyDestructible extends BuiltInOperation, @istrivi
|
|||||||
* The `__is_trivially_assignable` built-in operation (used by some
|
* The `__is_trivially_assignable` built-in operation (used by some
|
||||||
* implementations of the `<type_traits>` header).
|
* implementations of the `<type_traits>` header).
|
||||||
*
|
*
|
||||||
* Returns `true` if the assignment operator `C::operator =(const C& c)` is
|
* Returns `true` if the assignment operator `C::operator =(const D& d)` is
|
||||||
* trivial.
|
* trivial (i.e., it will not call any operation that is non-trivial).
|
||||||
* ```
|
* ```
|
||||||
* template<typename T>
|
* bool v = __is_trivially_assignable(MyType1, MyType2);
|
||||||
* struct is_trivially_assignable
|
|
||||||
* : public integral_constant<bool, __is_trivially_assignable(T) >
|
|
||||||
* { };
|
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istriviallyassignableexpr {
|
class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istriviallyassignableexpr {
|
||||||
@@ -631,10 +645,10 @@ class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istrivial
|
|||||||
* The `__is_nothrow_assignable` built-in operation (used by some
|
* The `__is_nothrow_assignable` built-in operation (used by some
|
||||||
* implementations of the `<type_traits>` header).
|
* implementations of the `<type_traits>` header).
|
||||||
*
|
*
|
||||||
* Returns true if there exists a `C::operator =(const C& c) nothrow`
|
* Returns true if there exists a `C::operator =(const D& d) nothrow`
|
||||||
* assignment operator (i.e, with an empty exception specification).
|
* assignment operator (i.e, with an empty exception specification).
|
||||||
* ```
|
* ```
|
||||||
* bool v = __is_nothrow_assignable(MyType);
|
* bool v = __is_nothrow_assignable(MyType1, MyType2);
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowassignableexpr {
|
class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowassignableexpr {
|
||||||
@@ -643,15 +657,30 @@ class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowas
|
|||||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsNothrowAssignable" }
|
override string getAPrimaryQlClass() { result = "BuiltInOperationIsNothrowAssignable" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `__is_assignable` built-in operation (used by some implementations
|
||||||
|
* of the `<type_traits>` header).
|
||||||
|
*
|
||||||
|
* Returns true if there exists a `C::operator =(const D& d)` assignment
|
||||||
|
* operator.
|
||||||
|
* ```
|
||||||
|
* bool v = __is_assignable(MyType1, MyType2);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
class BuiltInOperationIsAssignable extends BuiltInOperation, @isassignable {
|
||||||
|
override string toString() { result = "__is_assignable" }
|
||||||
|
|
||||||
|
override string getAPrimaryQlClass() { result = "BuiltInOperationIsAssignable" }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `__is_standard_layout` built-in operation (used by some implementations
|
* The `__is_standard_layout` built-in operation (used by some implementations
|
||||||
* of the `<type_traits>` header).
|
* of the `<type_traits>` header).
|
||||||
*
|
*
|
||||||
* Returns `true` if the type is a primitive type, or a `class`, `struct` or
|
* Returns `true` if the type is a primitive type, or a `class`, `struct` or
|
||||||
* `union` WITHOUT (1) virtual functions or base classes, (2) reference member
|
* `union` without (1) virtual functions or base classes, (2) reference member
|
||||||
* variable or (3) multiple occurrences of base `class` objects, among other
|
* variable, or (3) multiple occurrences of base `class` objects, among other
|
||||||
* restrictions. Please see
|
* restrictions. See https://en.cppreference.com/w/cpp/named_req/StandardLayoutType
|
||||||
* https://en.cppreference.com/w/cpp/named_req/StandardLayoutType
|
|
||||||
* for more information.
|
* for more information.
|
||||||
* ```
|
* ```
|
||||||
* bool v = __is_standard_layout(MyType);
|
* bool v = __is_standard_layout(MyType);
|
||||||
@@ -682,7 +711,7 @@ class BuiltInOperationIsTriviallyCopyable extends BuiltInOperation, @istrivially
|
|||||||
* the `<type_traits>` header).
|
* the `<type_traits>` header).
|
||||||
*
|
*
|
||||||
* Returns `true` if the type is a scalar type, a reference type or an array of
|
* Returns `true` if the type is a scalar type, a reference type or an array of
|
||||||
* literal types, among others. Please see
|
* literal types, among others. See
|
||||||
* https://en.cppreference.com/w/cpp/named_req/LiteralType
|
* https://en.cppreference.com/w/cpp/named_req/LiteralType
|
||||||
* for more information.
|
* for more information.
|
||||||
*
|
*
|
||||||
@@ -803,7 +832,7 @@ class BuiltInOperationHasFinalizer extends BuiltInOperation, @hasfinalizerexpr {
|
|||||||
* The `__is_delegate` built-in operation. This is a Microsoft extension.
|
* The `__is_delegate` built-in operation. This is a Microsoft extension.
|
||||||
*
|
*
|
||||||
* Returns `true` if the function has been declared as a `delegate`, used in
|
* Returns `true` if the function has been declared as a `delegate`, used in
|
||||||
* message forwarding. Please see
|
* message forwarding. See
|
||||||
* https://docs.microsoft.com/en-us/cpp/extensions/delegate-cpp-component-extensions
|
* https://docs.microsoft.com/en-us/cpp/extensions/delegate-cpp-component-extensions
|
||||||
* for more information.
|
* for more information.
|
||||||
*/
|
*/
|
||||||
@@ -816,7 +845,7 @@ class BuiltInOperationIsDelegate extends BuiltInOperation, @isdelegateexpr {
|
|||||||
/**
|
/**
|
||||||
* The `__is_interface_class` built-in operation. This is a Microsoft extension.
|
* The `__is_interface_class` built-in operation. This is a Microsoft extension.
|
||||||
*
|
*
|
||||||
* Returns `true` if the type has been declared as an `interface`. Please see
|
* Returns `true` if the type has been declared as an `interface`. See
|
||||||
* https://docs.microsoft.com/en-us/cpp/extensions/interface-class-cpp-component-extensions
|
* https://docs.microsoft.com/en-us/cpp/extensions/interface-class-cpp-component-extensions
|
||||||
* for more information.
|
* for more information.
|
||||||
*/
|
*/
|
||||||
@@ -829,7 +858,7 @@ class BuiltInOperationIsInterfaceClass extends BuiltInOperation, @isinterfacecla
|
|||||||
/**
|
/**
|
||||||
* The `__is_ref_array` built-in operation. This is a Microsoft extension.
|
* The `__is_ref_array` built-in operation. This is a Microsoft extension.
|
||||||
*
|
*
|
||||||
* Returns `true` if the object passed in is a _platform array_. Please see
|
* Returns `true` if the object passed in is a _platform array_. See
|
||||||
* https://docs.microsoft.com/en-us/cpp/extensions/arrays-cpp-component-extensions
|
* https://docs.microsoft.com/en-us/cpp/extensions/arrays-cpp-component-extensions
|
||||||
* for more information.
|
* for more information.
|
||||||
* ```
|
* ```
|
||||||
@@ -846,7 +875,7 @@ class BuiltInOperationIsRefArray extends BuiltInOperation, @isrefarrayexpr {
|
|||||||
/**
|
/**
|
||||||
* The `__is_ref_class` built-in operation. This is a Microsoft extension.
|
* The `__is_ref_class` built-in operation. This is a Microsoft extension.
|
||||||
*
|
*
|
||||||
* Returns `true` if the type is a _reference class_. Please see
|
* Returns `true` if the type is a _reference class_. See
|
||||||
* https://docs.microsoft.com/en-us/cpp/extensions/classes-and-structs-cpp-component-extensions
|
* https://docs.microsoft.com/en-us/cpp/extensions/classes-and-structs-cpp-component-extensions
|
||||||
* for more information.
|
* for more information.
|
||||||
* ```
|
* ```
|
||||||
@@ -900,7 +929,7 @@ class BuiltInOperationIsSimpleValueClass extends BuiltInOperation, @issimplevalu
|
|||||||
/**
|
/**
|
||||||
* The `__is_value_class` built-in operation. This is a Microsoft extension.
|
* The `__is_value_class` built-in operation. This is a Microsoft extension.
|
||||||
*
|
*
|
||||||
* Returns `true` if passed a value type. Please see
|
* Returns `true` if passed a value type. See
|
||||||
* https://docs.microsoft.com/en-us/cpp/extensions/classes-and-structs-cpp-component-extensions
|
* https://docs.microsoft.com/en-us/cpp/extensions/classes-and-structs-cpp-component-extensions
|
||||||
* For more information.
|
* For more information.
|
||||||
* ```
|
* ```
|
||||||
@@ -933,7 +962,7 @@ class BuiltInOperationIsFinal extends BuiltInOperation, @isfinalexpr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `__builtin_choose_expr` expression. This is a GNU/Clang extension.
|
* The `__builtin_choose_expr` expression. This is a gcc/clang extension.
|
||||||
*
|
*
|
||||||
* The expression functions similarly to the ternary `?:` operator, except
|
* The expression functions similarly to the ternary `?:` operator, except
|
||||||
* that it is evaluated at compile-time.
|
* that it is evaluated at compile-time.
|
||||||
@@ -978,3 +1007,50 @@ class BuiltInComplexOperation extends BuiltInOperation, @builtincomplex {
|
|||||||
/** Gets the operand corresponding to the imaginary part of the complex number. */
|
/** Gets the operand corresponding to the imaginary part of the complex number. */
|
||||||
Expr getImaginaryOperand() { this.hasChild(result, 1) }
|
Expr getImaginaryOperand() { this.hasChild(result, 1) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A C++ `__is_aggregate` built-in operation (used by some implementations of the
|
||||||
|
* `<type_traits>` header).
|
||||||
|
*
|
||||||
|
* Returns `true` if the type has is an aggregate type.
|
||||||
|
* ```
|
||||||
|
* std::integral_constant<bool, __is_aggregate(_Tp)> ia;
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
class BuiltInOperationIsAggregate extends BuiltInOperation, @isaggregate {
|
||||||
|
override string toString() { result = "__is_aggregate" }
|
||||||
|
|
||||||
|
override string getAPrimaryQlClass() { result = "BuiltInOperationIsAggregate" }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A C++ `__has_unique_object_representations` built-in operation (used by some
|
||||||
|
* implementations of the `<type_traits>` header).
|
||||||
|
*
|
||||||
|
* Returns `true` if the type is trivially copyable and if the object representation
|
||||||
|
* is unique for two objects with the same value.
|
||||||
|
* ```
|
||||||
|
* bool v = __has_unique_object_representations(MyType);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
class BuiltInOperationHasUniqueObjectRepresentations extends BuiltInOperation,
|
||||||
|
@hasuniqueobjectrepresentations {
|
||||||
|
override string toString() { result = "__has_unique_object_representations" }
|
||||||
|
|
||||||
|
override string getAPrimaryQlClass() { result = "BuiltInOperationHasUniqueObjectRepresentations" }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A C/C++ `__builtin_bit_cast` built-in operation (used by some implementations
|
||||||
|
* of `std::bit_cast`).
|
||||||
|
*
|
||||||
|
* Performs a bit cast from a value to a type.
|
||||||
|
* ```
|
||||||
|
* __builtin_bit_cast(Type, value);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
class BuiltInBitCast extends BuiltInOperation, @builtinbitcast {
|
||||||
|
override string toString() { result = "__builtin_bit_cast" }
|
||||||
|
|
||||||
|
override string getAPrimaryQlClass() { result = "BuiltInBitCast" }
|
||||||
|
}
|
||||||
|
|||||||
@@ -596,9 +596,12 @@ class ParenthesisExpr extends Conversion, @parexpr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A C/C++ expression that has not been resolved.
|
* A C/C++ expression that could not be resolved, or that can no longer be
|
||||||
|
* represented due to a database upgrade or downgrade.
|
||||||
*
|
*
|
||||||
* It is assigned `ErroneousType` as its type.
|
* If the expression could not be resolved, it has type `ErroneousType`. In the
|
||||||
|
* case of a database upgrade or downgrade, the original type from before the
|
||||||
|
* upgrade or downgrade is kept if that type can be represented.
|
||||||
*/
|
*/
|
||||||
class ErrorExpr extends Expr, @errorexpr {
|
class ErrorExpr extends Expr, @errorexpr {
|
||||||
override string toString() { result = "<error expr>" }
|
override string toString() { result = "<error expr>" }
|
||||||
|
|||||||
@@ -1650,6 +1650,11 @@ case @expr.kind of
|
|||||||
| 327 = @co_await
|
| 327 = @co_await
|
||||||
| 328 = @co_yield
|
| 328 = @co_yield
|
||||||
| 329 = @temp_init
|
| 329 = @temp_init
|
||||||
|
| 330 = @isassignable
|
||||||
|
| 331 = @isaggregate
|
||||||
|
| 332 = @hasuniqueobjectrepresentations
|
||||||
|
| 333 = @builtinbitcast
|
||||||
|
| 334 = @builtinshuffle
|
||||||
;
|
;
|
||||||
|
|
||||||
@var_args_expr = @vastartexpr
|
@var_args_expr = @vastartexpr
|
||||||
@@ -1711,6 +1716,11 @@ case @expr.kind of
|
|||||||
| @isfinalexpr
|
| @isfinalexpr
|
||||||
| @builtinchooseexpr
|
| @builtinchooseexpr
|
||||||
| @builtincomplex
|
| @builtincomplex
|
||||||
|
| @isassignable
|
||||||
|
| @isaggregate
|
||||||
|
| @hasuniqueobjectrepresentations
|
||||||
|
| @builtinbitcast
|
||||||
|
| @builtinshuffle
|
||||||
;
|
;
|
||||||
|
|
||||||
new_allocated_type(
|
new_allocated_type(
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
|||||||
|
description: Add new builtin operations
|
||||||
|
compatibility: backwards
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
|
// semmle-extractor-options: --clang
|
||||||
struct mystruct {
|
struct mystruct {
|
||||||
int f1;
|
int f1;
|
||||||
int f2;
|
int f2;
|
||||||
@@ -13,3 +13,6 @@ void f(void) {
|
|||||||
int i2 = edg_offsetof(struct mystruct,f2);
|
int i2 = edg_offsetof(struct mystruct,f2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void g(void) {
|
||||||
|
double f = __builtin_bit_cast(double,42l);
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,3 +13,6 @@
|
|||||||
| edg.c:13:14:13:45 | (size_t)... | 0 | 0 |
|
| edg.c:13:14:13:45 | (size_t)... | 0 | 0 |
|
||||||
| edg.c:13:14:13:45 | __INTADDR__ | 1 | 1 |
|
| edg.c:13:14:13:45 | __INTADDR__ | 1 | 1 |
|
||||||
| edg.c:13:43:13:44 | f2 | 0 | 0 |
|
| edg.c:13:43:13:44 | f2 | 0 | 0 |
|
||||||
|
| edg.c:17:16:17:45 | __builtin_bit_cast | 1 | 1 |
|
||||||
|
| edg.c:17:16:17:45 | double | 0 | 0 |
|
||||||
|
| edg.c:17:42:17:44 | 42 | 1 | 1 |
|
||||||
|
|||||||
@@ -296,3 +296,20 @@
|
|||||||
| ms.cpp:255:24:255:43 | a_struct | | <none> |
|
| ms.cpp:255:24:255:43 | a_struct | | <none> |
|
||||||
| ms.cpp:256:24:256:49 | __is_final | a_final_struct | 1 |
|
| ms.cpp:256:24:256:49 | __is_final | a_final_struct | 1 |
|
||||||
| ms.cpp:256:24:256:49 | a_final_struct | | <none> |
|
| ms.cpp:256:24:256:49 | a_final_struct | | <none> |
|
||||||
|
| ms.cpp:258:29:258:62 | __is_assignable | a_struct,a_struct | 1 |
|
||||||
|
| ms.cpp:258:29:258:62 | a_struct | | <none> |
|
||||||
|
| ms.cpp:258:29:258:62 | a_struct | | <none> |
|
||||||
|
| ms.cpp:259:29:259:59 | __is_assignable | a_struct,empty | 0 |
|
||||||
|
| ms.cpp:259:29:259:59 | a_struct | | <none> |
|
||||||
|
| ms.cpp:259:29:259:59 | empty | | <none> |
|
||||||
|
| ms.cpp:260:29:260:57 | __is_assignable | a_struct,int | 0 |
|
||||||
|
| ms.cpp:260:29:260:57 | a_struct | | <none> |
|
||||||
|
| ms.cpp:260:29:260:57 | int | | <none> |
|
||||||
|
| ms.cpp:262:28:262:51 | __is_aggregate | a_struct | 1 |
|
||||||
|
| ms.cpp:262:28:262:51 | a_struct | | <none> |
|
||||||
|
| ms.cpp:263:28:263:46 | __is_aggregate | int | 0 |
|
||||||
|
| ms.cpp:263:28:263:46 | int | | <none> |
|
||||||
|
| ms.cpp:265:49:265:88 | __has_unique_object_representations | int | 1 |
|
||||||
|
| ms.cpp:265:49:265:88 | int | | <none> |
|
||||||
|
| ms.cpp:266:49:266:90 | __has_unique_object_representations | float | 0 |
|
||||||
|
| ms.cpp:266:49:266:90 | float | | <none> |
|
||||||
|
|||||||
@@ -254,5 +254,14 @@ void f(void) {
|
|||||||
|
|
||||||
bool b_is_final1 = __is_final(a_struct);
|
bool b_is_final1 = __is_final(a_struct);
|
||||||
bool b_is_final2 = __is_final(a_final_struct);
|
bool b_is_final2 = __is_final(a_final_struct);
|
||||||
}
|
|
||||||
|
|
||||||
|
bool b_is_assignable1 = __is_assignable(a_struct,a_struct);
|
||||||
|
bool b_is_assignable2 = __is_assignable(a_struct,empty);
|
||||||
|
bool b_is_assignable3 = __is_assignable(a_struct,int);
|
||||||
|
|
||||||
|
bool b_is_aggregate1 = __is_aggregate(a_struct);
|
||||||
|
bool b_is_aggregate2 = __is_aggregate(int);
|
||||||
|
|
||||||
|
bool b_has_unique_object_representations1 = __has_unique_object_representations(int);
|
||||||
|
bool b_has_unique_object_representations2 = __has_unique_object_representations(float);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,2 +1,4 @@
|
|||||||
|
| vector_types2.cpp:10:15:10:42 | __builtin_shuffle |
|
||||||
|
| vector_types2.cpp:11:15:11:45 | __builtin_shuffle |
|
||||||
| vector_types.cpp:31:13:31:49 | __builtin_shufflevector |
|
| vector_types.cpp:31:13:31:49 | __builtin_shufflevector |
|
||||||
| vector_types.cpp:58:10:58:52 | __builtin_convertvector |
|
| vector_types.cpp:58:10:58:52 | __builtin_convertvector |
|
||||||
|
|||||||
@@ -13,6 +13,12 @@
|
|||||||
| file://:0:0:0:0 | gp_offset | gp_offset | file://:0:0:0:0 | unsigned int | 4 |
|
| file://:0:0:0:0 | gp_offset | gp_offset | file://:0:0:0:0 | unsigned int | 4 |
|
||||||
| file://:0:0:0:0 | overflow_arg_area | overflow_arg_area | file://:0:0:0:0 | void * | 8 |
|
| file://:0:0:0:0 | overflow_arg_area | overflow_arg_area | file://:0:0:0:0 | void * | 8 |
|
||||||
| file://:0:0:0:0 | reg_save_area | reg_save_area | file://:0:0:0:0 | void * | 8 |
|
| file://:0:0:0:0 | reg_save_area | reg_save_area | file://:0:0:0:0 | void * | 8 |
|
||||||
|
| vector_types2.cpp:5:7:5:7 | a | a | vector_types2.cpp:2:13:2:15 | v4i | 16 |
|
||||||
|
| vector_types2.cpp:6:7:6:7 | b | b | vector_types2.cpp:2:13:2:15 | v4i | 16 |
|
||||||
|
| vector_types2.cpp:7:7:7:12 | mask_1 | mask_1 | vector_types2.cpp:2:13:2:15 | v4i | 16 |
|
||||||
|
| vector_types2.cpp:8:7:8:12 | mask_2 | mask_2 | vector_types2.cpp:2:13:2:15 | v4i | 16 |
|
||||||
|
| vector_types2.cpp:10:7:10:11 | res_1 | res_1 | vector_types2.cpp:2:13:2:15 | v4i | 16 |
|
||||||
|
| vector_types2.cpp:11:7:11:11 | res_2 | res_2 | vector_types2.cpp:2:13:2:15 | v4i | 16 |
|
||||||
| vector_types.cpp:9:21:9:21 | x | x | vector_types.cpp:6:15:6:17 | v4f | 16 |
|
| vector_types.cpp:9:21:9:21 | x | x | vector_types.cpp:6:15:6:17 | v4f | 16 |
|
||||||
| vector_types.cpp:14:18:14:20 | lhs | lhs | vector_types.cpp:6:15:6:17 | v4f | 16 |
|
| vector_types.cpp:14:18:14:20 | lhs | lhs | vector_types.cpp:6:15:6:17 | v4f | 16 |
|
||||||
| vector_types.cpp:14:27:14:29 | rhs | rhs | vector_types.cpp:6:15:6:17 | v4f | 16 |
|
| vector_types.cpp:14:27:14:29 | rhs | rhs | vector_types.cpp:6:15:6:17 | v4f | 16 |
|
||||||
|
|||||||
12
cpp/ql/test/library-tests/vector_types/vector_types2.cpp
Normal file
12
cpp/ql/test/library-tests/vector_types/vector_types2.cpp
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// semmle-extractor-options: --gnu --gnu_version 80000
|
||||||
|
typedef int v4i __attribute__((vector_size (16)));
|
||||||
|
|
||||||
|
void f() {
|
||||||
|
v4i a = {1,2,3,4};
|
||||||
|
v4i b = {5,6,7,8};
|
||||||
|
v4i mask_1 = {3,0,1,2};
|
||||||
|
v4i mask_2 = {3,5,4,2};
|
||||||
|
|
||||||
|
v4i res_1 = __builtin_shuffle(a, mask_1);
|
||||||
|
v4i res_2 = __builtin_shuffle(a, b, mask_2);
|
||||||
|
}
|
||||||
@@ -12,6 +12,8 @@ Type getAMentionedType(RefType type) {
|
|||||||
result = getAMentionedType(type).(InstantiatedType).getATypeArgument()
|
result = getAMentionedType(type).(InstantiatedType).getATypeArgument()
|
||||||
or
|
or
|
||||||
result = getAMentionedType(type).(NestedType).getEnclosingType()
|
result = getAMentionedType(type).(NestedType).getEnclosingType()
|
||||||
|
or
|
||||||
|
result = getAMentionedType(type).(Wildcard).getATypeBound().getType()
|
||||||
}
|
}
|
||||||
|
|
||||||
Type getATypeUsedInClass(RefType type) {
|
Type getATypeUsedInClass(RefType type) {
|
||||||
|
|||||||
@@ -20,3 +20,15 @@ private class KtExpectationComment extends KtComment, ExpectationComment {
|
|||||||
|
|
||||||
override string getContents() { result = this.getText().suffix(2).trim() }
|
override string getContents() { result = this.getText().suffix(2).trim() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class XmlExpectationComment extends ExpectationComment instanceof XMLComment {
|
||||||
|
override string getContents() { result = this.(XMLComment).getText().trim() }
|
||||||
|
|
||||||
|
override Location getLocation() { result = this.(XMLComment).getLocation() }
|
||||||
|
|
||||||
|
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
||||||
|
this.(XMLComment).hasLocationInfo(path, sl, sc, el, ec)
|
||||||
|
}
|
||||||
|
|
||||||
|
override string toString() { result = this.(XMLComment).toString() }
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ calls
|
|||||||
| test.kt:22:15:22:33 | setter(...) | test.kt:12:1:25:1 | user | test.kt:0:0:0:0 | TestKt | file:///!unknown-binary-location/Generic.class:0:0:0:0 | setter | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic<? super String> |
|
| test.kt:22:15:22:33 | setter(...) | test.kt:12:1:25:1 | user | test.kt:0:0:0:0 | TestKt | file:///!unknown-binary-location/Generic.class:0:0:0:0 | setter | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic<? super String> |
|
||||||
| test.kt:23:15:23:22 | getter(...) | test.kt:12:1:25:1 | user | test.kt:0:0:0:0 | TestKt | file:///!unknown-binary-location/Generic.class:0:0:0:0 | getter | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic<? super String> |
|
| test.kt:23:15:23:22 | getter(...) | test.kt:12:1:25:1 | user | test.kt:0:0:0:0 | TestKt | file:///!unknown-binary-location/Generic.class:0:0:0:0 | getter | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic<? super String> |
|
||||||
constructors
|
constructors
|
||||||
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2<? extends String>(java.lang.String) | ? extends String | void | Test.java:1:7:1:14 | Generic2 | Test.java:3:10:3:17 | Generic2 |
|
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2<? extends String>(<nulltype>) | <nulltype> | void | Test.java:1:7:1:14 | Generic2 | Test.java:3:10:3:17 | Generic2 |
|
||||||
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2<? super String>(java.lang.Object) | ? super String | void | Test.java:1:7:1:14 | Generic2 | Test.java:3:10:3:17 | Generic2 |
|
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2<? super String>(java.lang.String) | String | void | Test.java:1:7:1:14 | Generic2 | Test.java:3:10:3:17 | Generic2 |
|
||||||
| Generic2.class:0:0:0:0 | Generic2<String> | Generic2.class:0:0:0:0 | Generic2<String> | Generic2<String>(java.lang.String) | String | void | Test.java:1:7:1:14 | Generic2 | Test.java:3:10:3:17 | Generic2 |
|
| Generic2.class:0:0:0:0 | Generic2<String> | Generic2.class:0:0:0:0 | Generic2<String> | Generic2<String>(java.lang.String) | String | void | Test.java:1:7:1:14 | Generic2 | Test.java:3:10:3:17 | Generic2 |
|
||||||
| Test.java:1:7:1:14 | Generic2 | Test.java:3:10:3:17 | Generic2 | Generic2(java.lang.Object) | T | void | Test.java:1:7:1:14 | Generic2 | Test.java:3:10:3:17 | Generic2 |
|
| Test.java:1:7:1:14 | Generic2 | Test.java:3:10:3:17 | Generic2 | Generic2(java.lang.Object) | T | void | Test.java:1:7:1:14 | Generic2 | Test.java:3:10:3:17 | Generic2 |
|
||||||
| Test.java:14:14:14:17 | Test | Test.java:14:14:14:17 | Test | Test() | No parameters | void | Test.java:14:14:14:17 | Test | Test.java:14:14:14:17 | Test |
|
| Test.java:14:14:14:17 | Test | Test.java:14:14:14:17 | Test | Test() | No parameters | void | Test.java:14:14:14:17 | Test | Test.java:14:14:14:17 | Test |
|
||||||
@@ -34,14 +34,14 @@ refTypes
|
|||||||
| test.kt:1:1:10:1 | Generic |
|
| test.kt:1:1:10:1 | Generic |
|
||||||
| test.kt:1:15:1:15 | T |
|
| test.kt:1:15:1:15 | T |
|
||||||
#select
|
#select
|
||||||
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | getter | getter() | No parameters | ? extends String | Test.java:1:7:1:14 | Generic2 | Test.java:9:5:9:10 | getter |
|
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | getter | getter() | No parameters | String | Test.java:1:7:1:14 | Generic2 | Test.java:9:5:9:10 | getter |
|
||||||
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | identity | identity(java.lang.String) | ? extends String | ? extends String | Test.java:1:7:1:14 | Generic2 | Test.java:8:5:8:12 | identity |
|
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | identity | identity(<nulltype>) | <nulltype> | String | Test.java:1:7:1:14 | Generic2 | Test.java:8:5:8:12 | identity |
|
||||||
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | identity2 | identity2(java.lang.String) | ? extends String | ? extends String | Test.java:1:7:1:14 | Generic2 | Test.java:7:5:7:13 | identity2 |
|
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | identity2 | identity2(<nulltype>) | <nulltype> | String | Test.java:1:7:1:14 | Generic2 | Test.java:7:5:7:13 | identity2 |
|
||||||
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | setter | setter(java.lang.String) | ? extends String | void | Test.java:1:7:1:14 | Generic2 | Test.java:10:8:10:13 | setter |
|
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | setter | setter(<nulltype>) | <nulltype> | void | Test.java:1:7:1:14 | Generic2 | Test.java:10:8:10:13 | setter |
|
||||||
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | getter | getter() | No parameters | ? super String | Test.java:1:7:1:14 | Generic2 | Test.java:9:5:9:10 | getter |
|
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | getter | getter() | No parameters | Object | Test.java:1:7:1:14 | Generic2 | Test.java:9:5:9:10 | getter |
|
||||||
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | identity | identity(java.lang.Object) | ? super String | ? super String | Test.java:1:7:1:14 | Generic2 | Test.java:8:5:8:12 | identity |
|
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | identity | identity(java.lang.String) | String | Object | Test.java:1:7:1:14 | Generic2 | Test.java:8:5:8:12 | identity |
|
||||||
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | identity2 | identity2(java.lang.Object) | ? super String | ? super String | Test.java:1:7:1:14 | Generic2 | Test.java:7:5:7:13 | identity2 |
|
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | identity2 | identity2(java.lang.String) | String | Object | Test.java:1:7:1:14 | Generic2 | Test.java:7:5:7:13 | identity2 |
|
||||||
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | setter | setter(java.lang.Object) | ? super String | void | Test.java:1:7:1:14 | Generic2 | Test.java:10:8:10:13 | setter |
|
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | setter | setter(java.lang.String) | String | void | Test.java:1:7:1:14 | Generic2 | Test.java:10:8:10:13 | setter |
|
||||||
| Generic2.class:0:0:0:0 | Generic2<String> | Generic2.class:0:0:0:0 | getter | getter() | No parameters | String | Test.java:1:7:1:14 | Generic2 | Test.java:9:5:9:10 | getter |
|
| Generic2.class:0:0:0:0 | Generic2<String> | Generic2.class:0:0:0:0 | getter | getter() | No parameters | String | Test.java:1:7:1:14 | Generic2 | Test.java:9:5:9:10 | getter |
|
||||||
| Generic2.class:0:0:0:0 | Generic2<String> | Generic2.class:0:0:0:0 | identity | identity(java.lang.String) | String | String | Test.java:1:7:1:14 | Generic2 | Test.java:8:5:8:12 | identity |
|
| Generic2.class:0:0:0:0 | Generic2<String> | Generic2.class:0:0:0:0 | identity | identity(java.lang.String) | String | String | Test.java:1:7:1:14 | Generic2 | Test.java:8:5:8:12 | identity |
|
||||||
| Generic2.class:0:0:0:0 | Generic2<String> | Generic2.class:0:0:0:0 | identity2 | identity2(java.lang.String) | String | String | Test.java:1:7:1:14 | Generic2 | Test.java:7:5:7:13 | identity2 |
|
| Generic2.class:0:0:0:0 | Generic2<String> | Generic2.class:0:0:0:0 | identity2 | identity2(java.lang.String) | String | String | Test.java:1:7:1:14 | Generic2 | Test.java:7:5:7:13 | identity2 |
|
||||||
|
|||||||
20
java/ql/test/library-tests/wildcard-substitution/Lib.java
Normal file
20
java/ql/test/library-tests/wildcard-substitution/Lib.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Lib<T> {
|
||||||
|
|
||||||
|
public void takesVar(T t) { }
|
||||||
|
public void takesInvar(List<T> lt) { }
|
||||||
|
public void takesUnbound(List<?> lt) { }
|
||||||
|
public void takesExtends(List<? extends T> lt) { }
|
||||||
|
public void takesSuper(List<? super T> lt) { }
|
||||||
|
|
||||||
|
public T returnsVar() { return null; }
|
||||||
|
public List<T> returnsInvar() { return null; }
|
||||||
|
public List<?> returnsUnbound() { return null; }
|
||||||
|
public List<? extends T> returnsExtends() { return null; }
|
||||||
|
public List<? super T> returnsSuper() { return null; }
|
||||||
|
|
||||||
|
public void takesArray(T[] ts) { }
|
||||||
|
public T[] returnsArray() { return null; }
|
||||||
|
|
||||||
|
}
|
||||||
12
java/ql/test/library-tests/wildcard-substitution/User.java
Normal file
12
java/ql/test/library-tests/wildcard-substitution/User.java
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
public class User {
|
||||||
|
|
||||||
|
public static void test(Lib<CharSequence> invarLib, Lib<? extends CharSequence> extendsLib, Lib<? super CharSequence> superLib, Lib<?> unboundLib) {
|
||||||
|
|
||||||
|
invarLib.takesVar(null);
|
||||||
|
extendsLib.takesVar(null);
|
||||||
|
superLib.takesVar(null);
|
||||||
|
unboundLib.takesVar(null);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | returnsArray | CharSequence[] |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | returnsExtends | List<? extends CharSequence> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | returnsInvar | List<? extends CharSequence> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | returnsSuper | List<?> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | returnsUnbound | List<?> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | returnsVar | CharSequence |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | takesArray | <nulltype>[] |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | takesExtends | List<? extends CharSequence> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | takesInvar | List<? extends CharSequence> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | takesSuper | List<?> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | takesUnbound | List<?> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | takesVar | <nulltype> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | returnsArray | Object[] |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | returnsExtends | List<?> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | returnsInvar | List<? super CharSequence> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | returnsSuper | List<? super CharSequence> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | returnsUnbound | List<?> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | returnsVar | Object |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | takesArray | CharSequence[] |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | takesExtends | List<?> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | takesInvar | List<? super CharSequence> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | takesSuper | List<? super CharSequence> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | takesUnbound | List<?> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | takesVar | CharSequence |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | returnsArray | Object[] |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | returnsExtends | List<? extends Object> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | returnsInvar | List<?> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | returnsSuper | List<?> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | returnsUnbound | List<?> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | returnsVar | Object |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | takesArray | <nulltype>[] |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | takesExtends | List<? extends Object> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | takesInvar | List<?> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | takesSuper | List<?> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | takesUnbound | List<?> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | takesVar | <nulltype> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | returnsArray | CharSequence[] |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | returnsExtends | List<? extends CharSequence> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | returnsInvar | List<CharSequence> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | returnsSuper | List<? super CharSequence> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | returnsUnbound | List<?> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | returnsVar | CharSequence |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | takesArray | CharSequence[] |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | takesExtends | List<? extends CharSequence> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | takesInvar | List<CharSequence> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | takesSuper | List<? super CharSequence> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | takesUnbound | List<?> |
|
||||||
|
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | takesVar | CharSequence |
|
||||||
|
| Lib.java:3:14:3:16 | Lib | Lib.java:5:15:5:22 | takesVar | T |
|
||||||
|
| Lib.java:3:14:3:16 | Lib | Lib.java:6:15:6:24 | takesInvar | List<T> |
|
||||||
|
| Lib.java:3:14:3:16 | Lib | Lib.java:7:15:7:26 | takesUnbound | List<?> |
|
||||||
|
| Lib.java:3:14:3:16 | Lib | Lib.java:8:15:8:26 | takesExtends | List<? extends T> |
|
||||||
|
| Lib.java:3:14:3:16 | Lib | Lib.java:9:15:9:24 | takesSuper | List<? super T> |
|
||||||
|
| Lib.java:3:14:3:16 | Lib | Lib.java:11:12:11:21 | returnsVar | T |
|
||||||
|
| Lib.java:3:14:3:16 | Lib | Lib.java:12:18:12:29 | returnsInvar | List<T> |
|
||||||
|
| Lib.java:3:14:3:16 | Lib | Lib.java:13:18:13:31 | returnsUnbound | List<?> |
|
||||||
|
| Lib.java:3:14:3:16 | Lib | Lib.java:14:28:14:41 | returnsExtends | List<? extends T> |
|
||||||
|
| Lib.java:3:14:3:16 | Lib | Lib.java:15:26:15:37 | returnsSuper | List<? super T> |
|
||||||
|
| Lib.java:3:14:3:16 | Lib | Lib.java:17:15:17:24 | takesArray | T[] |
|
||||||
|
| Lib.java:3:14:3:16 | Lib | Lib.java:18:14:18:25 | returnsArray | T[] |
|
||||||
|
| User.java:1:14:1:17 | User | User.java:3:22:3:25 | test | Lib<? extends CharSequence> |
|
||||||
|
| User.java:1:14:1:17 | User | User.java:3:22:3:25 | test | Lib<? super CharSequence> |
|
||||||
|
| User.java:1:14:1:17 | User | User.java:3:22:3:25 | test | Lib<?> |
|
||||||
|
| User.java:1:14:1:17 | User | User.java:3:22:3:25 | test | Lib<CharSequence> |
|
||||||
7
java/ql/test/library-tests/wildcard-substitution/test.ql
Normal file
7
java/ql/test/library-tests/wildcard-substitution/test.ql
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import java
|
||||||
|
|
||||||
|
Type notVoid(Type t) { result = t and not result instanceof VoidType }
|
||||||
|
|
||||||
|
from Callable c
|
||||||
|
where c.getSourceDeclaration().fromSource()
|
||||||
|
select c.getDeclaringType(), c, notVoid([c.getAParamType(), c.getReturnType()]).toString()
|
||||||
3
java/ql/test/library-tests/xml/Test.java
Normal file
3
java/ql/test/library-tests/xml/Test.java
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
public class Test {
|
||||||
|
|
||||||
|
}
|
||||||
2
java/ql/test/library-tests/xml/XMLTest.expected
Normal file
2
java/ql/test/library-tests/xml/XMLTest.expected
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
| test.xml:4:5:4:32 | attribute=value | Unexpected result: hasXmlResult= |
|
||||||
|
| test.xml:5:29:5:52 | $ hasXmlResult | Missing result:hasXmlResult= |
|
||||||
17
java/ql/test/library-tests/xml/XMLTest.ql
Normal file
17
java/ql/test/library-tests/xml/XMLTest.ql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import semmle.code.xml.XML
|
||||||
|
import TestUtilities.InlineExpectationsTest
|
||||||
|
|
||||||
|
class XmlTest extends InlineExpectationsTest {
|
||||||
|
XmlTest() { this = "XmlTest" }
|
||||||
|
|
||||||
|
override string getARelevantTag() { result = "hasXmlResult" }
|
||||||
|
|
||||||
|
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||||
|
tag = "hasXmlResult" and
|
||||||
|
exists(XMLAttribute a |
|
||||||
|
a.getLocation() = location and
|
||||||
|
element = a.toString() and
|
||||||
|
value = ""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
6
java/ql/test/library-tests/xml/test.xml
Normal file
6
java/ql/test/library-tests/xml/test.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document>
|
||||||
|
<element attribute="value">Text</element> <!-- $ hasXmlResult -->
|
||||||
|
<element attribute="value">Text</element> <!-- Missing -->
|
||||||
|
<element>Text</element> <!-- $ hasXmlResult --> <!-- Spurious -->
|
||||||
|
</document>
|
||||||
@@ -527,16 +527,55 @@ class StarPatternElementNode extends Node, TStarPatternElementNode {
|
|||||||
override Location getLocation() { result = consumer.getLocation() }
|
override Location getLocation() { result = consumer.getLocation() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a node that controls whether other nodes are evaluated.
|
||||||
|
*
|
||||||
|
* In the base case, this is the last node of `conditionBlock`, and `flipped` is `false`.
|
||||||
|
* This definition accounts for (short circuting) `and`- and `or`-expressions, as the structure
|
||||||
|
* of basic blocks will reflect their semantics.
|
||||||
|
*
|
||||||
|
* However, in the program
|
||||||
|
* ```python
|
||||||
|
* if not is_safe(path):
|
||||||
|
* return
|
||||||
|
* ```
|
||||||
|
* the last node in the `ConditionBlock` is `not is_safe(path)`.
|
||||||
|
*
|
||||||
|
* We would like to consider also `is_safe(path)` a guard node, albeit with `flipped` being `true`.
|
||||||
|
* Thus we recurse through `not`-expressions.
|
||||||
|
*/
|
||||||
|
ControlFlowNode guardNode(ConditionBlock conditionBlock, boolean flipped) {
|
||||||
|
// Base case: the last node truly does determine which successor is chosen
|
||||||
|
result = conditionBlock.getLastNode() and
|
||||||
|
flipped = false
|
||||||
|
or
|
||||||
|
// Recursive case: if a guard node is a `not`-expression,
|
||||||
|
// the operand is also a guard node, but with inverted polarity.
|
||||||
|
exists(UnaryExprNode notNode |
|
||||||
|
result = notNode.getOperand() and
|
||||||
|
notNode.getNode().getOp() instanceof Not
|
||||||
|
|
|
||||||
|
notNode = guardNode(conditionBlock, flipped.booleanNot())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A node that controls whether other nodes are evaluated.
|
* A node that controls whether other nodes are evaluated.
|
||||||
|
*
|
||||||
|
* The field `flipped` allows us to match `GuardNode`s underneath
|
||||||
|
* `not`-expressions and still choose the appropriate branch.
|
||||||
*/
|
*/
|
||||||
class GuardNode extends ControlFlowNode {
|
class GuardNode extends ControlFlowNode {
|
||||||
ConditionBlock conditionBlock;
|
ConditionBlock conditionBlock;
|
||||||
|
boolean flipped;
|
||||||
|
|
||||||
GuardNode() { this = conditionBlock.getLastNode() }
|
GuardNode() { this = guardNode(conditionBlock, flipped) }
|
||||||
|
|
||||||
/** Holds if this guard controls block `b` upon evaluating to `branch`. */
|
/** Holds if this guard controls block `b` upon evaluating to `branch`. */
|
||||||
predicate controlsBlock(BasicBlock b, boolean branch) { conditionBlock.controls(b, branch) }
|
predicate controlsBlock(BasicBlock b, boolean branch) {
|
||||||
|
branch in [true, false] and
|
||||||
|
conditionBlock.controls(b, branch.booleanXor(flipped))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ def test_non_eq2():
|
|||||||
if not ts == "safe":
|
if not ts == "safe":
|
||||||
ensure_tainted(ts) # $ tainted
|
ensure_tainted(ts) # $ tainted
|
||||||
else:
|
else:
|
||||||
ensure_not_tainted(ts) # $ SPURIOUS: tainted
|
ensure_not_tainted(ts)
|
||||||
|
|
||||||
|
|
||||||
def test_in_list():
|
def test_in_list():
|
||||||
@@ -157,7 +157,7 @@ def test_not_in2():
|
|||||||
if not ts in ["safe", "also_safe"]:
|
if not ts in ["safe", "also_safe"]:
|
||||||
ensure_tainted(ts) # $ tainted
|
ensure_tainted(ts) # $ tainted
|
||||||
else:
|
else:
|
||||||
ensure_not_tainted(ts) # $ SPURIOUS: tainted
|
ensure_not_tainted(ts)
|
||||||
|
|
||||||
|
|
||||||
def is_safe(x):
|
def is_safe(x):
|
||||||
|
|||||||
@@ -6,12 +6,20 @@ isSanitizer
|
|||||||
| TestTaintTrackingConfiguration | test.py:34:39:34:39 | ControlFlowNode for s |
|
| TestTaintTrackingConfiguration | test.py:34:39:34:39 | ControlFlowNode for s |
|
||||||
| TestTaintTrackingConfiguration | test.py:52:28:52:28 | ControlFlowNode for s |
|
| TestTaintTrackingConfiguration | test.py:52:28:52:28 | ControlFlowNode for s |
|
||||||
| TestTaintTrackingConfiguration | test.py:66:10:66:29 | ControlFlowNode for emulated_escaping() |
|
| TestTaintTrackingConfiguration | test.py:66:10:66:29 | ControlFlowNode for emulated_escaping() |
|
||||||
| TestTaintTrackingConfiguration | test_logical.py:30:28:30:28 | ControlFlowNode for s |
|
| TestTaintTrackingConfiguration | test_logical.py:33:28:33:28 | ControlFlowNode for s |
|
||||||
| TestTaintTrackingConfiguration | test_logical.py:45:28:45:28 | ControlFlowNode for s |
|
| TestTaintTrackingConfiguration | test_logical.py:40:28:40:28 | ControlFlowNode for s |
|
||||||
| TestTaintTrackingConfiguration | test_logical.py:50:28:50:28 | ControlFlowNode for s |
|
| TestTaintTrackingConfiguration | test_logical.py:48:28:48:28 | ControlFlowNode for s |
|
||||||
| TestTaintTrackingConfiguration | test_logical.py:89:28:89:28 | ControlFlowNode for s |
|
| TestTaintTrackingConfiguration | test_logical.py:53:28:53:28 | ControlFlowNode for s |
|
||||||
| TestTaintTrackingConfiguration | test_logical.py:100:28:100:28 | ControlFlowNode for s |
|
| TestTaintTrackingConfiguration | test_logical.py:92:28:92:28 | ControlFlowNode for s |
|
||||||
| TestTaintTrackingConfiguration | test_logical.py:145:28:145:28 | ControlFlowNode for s |
|
| TestTaintTrackingConfiguration | test_logical.py:103:28:103:28 | ControlFlowNode for s |
|
||||||
|
| TestTaintTrackingConfiguration | test_logical.py:111:28:111:28 | ControlFlowNode for s |
|
||||||
|
| TestTaintTrackingConfiguration | test_logical.py:130:28:130:28 | ControlFlowNode for s |
|
||||||
|
| TestTaintTrackingConfiguration | test_logical.py:137:28:137:28 | ControlFlowNode for s |
|
||||||
| TestTaintTrackingConfiguration | test_logical.py:148:28:148:28 | ControlFlowNode for s |
|
| TestTaintTrackingConfiguration | test_logical.py:148:28:148:28 | ControlFlowNode for s |
|
||||||
| TestTaintTrackingConfiguration | test_logical.py:155:28:155:28 | ControlFlowNode for s |
|
| TestTaintTrackingConfiguration | test_logical.py:151:28:151:28 | ControlFlowNode for s |
|
||||||
|
| TestTaintTrackingConfiguration | test_logical.py:158:28:158:28 | ControlFlowNode for s |
|
||||||
|
| TestTaintTrackingConfiguration | test_logical.py:167:24:167:24 | ControlFlowNode for s |
|
||||||
|
| TestTaintTrackingConfiguration | test_logical.py:176:24:176:24 | ControlFlowNode for s |
|
||||||
|
| TestTaintTrackingConfiguration | test_logical.py:185:24:185:24 | ControlFlowNode for s |
|
||||||
|
| TestTaintTrackingConfiguration | test_logical.py:193:24:193:24 | ControlFlowNode for s |
|
||||||
| TestTaintTrackingConfiguration | test_reference.py:31:28:31:28 | ControlFlowNode for s |
|
| TestTaintTrackingConfiguration | test_reference.py:31:28:31:28 | ControlFlowNode for s |
|
||||||
|
|||||||
@@ -6,6 +6,12 @@ predicate isSafeCheck(DataFlow::GuardNode g, ControlFlowNode node, boolean branc
|
|||||||
branch = true
|
branch = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
predicate isUnsafeCheck(DataFlow::GuardNode g, ControlFlowNode node, boolean branch) {
|
||||||
|
g.(CallNode).getNode().getFunc().(Name).getId() in ["is_unsafe", "emulated_is_unsafe"] and
|
||||||
|
node = g.(CallNode).getAnArg() and
|
||||||
|
branch = false
|
||||||
|
}
|
||||||
|
|
||||||
class CustomSanitizerOverrides extends TestTaintTrackingConfiguration {
|
class CustomSanitizerOverrides extends TestTaintTrackingConfiguration {
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
override predicate isSanitizer(DataFlow::Node node) {
|
||||||
exists(Call call |
|
exists(Call call |
|
||||||
@@ -16,6 +22,8 @@ class CustomSanitizerOverrides extends TestTaintTrackingConfiguration {
|
|||||||
node.asExpr().(Call).getFunc().(Name).getId() = "emulated_escaping"
|
node.asExpr().(Call).getFunc().(Name).getId() = "emulated_escaping"
|
||||||
or
|
or
|
||||||
node = DataFlow::BarrierGuard<isSafeCheck/3>::getABarrierNode()
|
node = DataFlow::BarrierGuard<isSafeCheck/3>::getABarrierNode()
|
||||||
|
or
|
||||||
|
node = DataFlow::BarrierGuard<isUnsafeCheck/3>::getABarrierNode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ def random_choice():
|
|||||||
def is_safe(arg):
|
def is_safe(arg):
|
||||||
return arg == "safe"
|
return arg == "safe"
|
||||||
|
|
||||||
|
def is_unsafe(arg):
|
||||||
|
return arg == TAINTED_STRING
|
||||||
|
|
||||||
|
|
||||||
def test_basic():
|
def test_basic():
|
||||||
s = TAINTED_STRING
|
s = TAINTED_STRING
|
||||||
@@ -34,7 +37,7 @@ def test_basic():
|
|||||||
if not is_safe(s):
|
if not is_safe(s):
|
||||||
ensure_tainted(s) # $ tainted
|
ensure_tainted(s) # $ tainted
|
||||||
else:
|
else:
|
||||||
ensure_not_tainted(s) # $ SPURIOUS: tainted
|
ensure_not_tainted(s)
|
||||||
|
|
||||||
|
|
||||||
def test_if_in_depth():
|
def test_if_in_depth():
|
||||||
@@ -105,7 +108,7 @@ def test_and():
|
|||||||
ensure_tainted(s) # $ tainted
|
ensure_tainted(s) # $ tainted
|
||||||
else:
|
else:
|
||||||
# cannot be tainted
|
# cannot be tainted
|
||||||
ensure_not_tainted(s) # $ SPURIOUS: tainted
|
ensure_not_tainted(s)
|
||||||
|
|
||||||
|
|
||||||
def test_tricky():
|
def test_tricky():
|
||||||
@@ -124,14 +127,14 @@ def test_nesting_not():
|
|||||||
s = TAINTED_STRING
|
s = TAINTED_STRING
|
||||||
|
|
||||||
if not(not(is_safe(s))):
|
if not(not(is_safe(s))):
|
||||||
ensure_not_tainted(s) # $ SPURIOUS: tainted
|
ensure_not_tainted(s)
|
||||||
else:
|
else:
|
||||||
ensure_tainted(s) # $ tainted
|
ensure_tainted(s) # $ tainted
|
||||||
|
|
||||||
if not(not(not(is_safe(s)))):
|
if not(not(not(is_safe(s)))):
|
||||||
ensure_tainted(s) # $ tainted
|
ensure_tainted(s) # $ tainted
|
||||||
else:
|
else:
|
||||||
ensure_not_tainted(s) # $ SPURIOUS: tainted
|
ensure_not_tainted(s)
|
||||||
|
|
||||||
|
|
||||||
# Adding `and True` makes the sanitizer trigger when it would otherwise not. See output in
|
# Adding `and True` makes the sanitizer trigger when it would otherwise not. See output in
|
||||||
@@ -161,7 +164,16 @@ def test_with_return():
|
|||||||
if not is_safe(s):
|
if not is_safe(s):
|
||||||
return
|
return
|
||||||
|
|
||||||
ensure_not_tainted(s) # $ SPURIOUS: tainted
|
ensure_not_tainted(s)
|
||||||
|
|
||||||
|
|
||||||
|
def test_with_return_neg():
|
||||||
|
s = TAINTED_STRING
|
||||||
|
|
||||||
|
if is_unsafe(s):
|
||||||
|
return
|
||||||
|
|
||||||
|
ensure_not_tainted(s)
|
||||||
|
|
||||||
|
|
||||||
def test_with_exception():
|
def test_with_exception():
|
||||||
@@ -170,7 +182,15 @@ def test_with_exception():
|
|||||||
if not is_safe(s):
|
if not is_safe(s):
|
||||||
raise Exception("unsafe")
|
raise Exception("unsafe")
|
||||||
|
|
||||||
ensure_not_tainted(s) # $ SPURIOUS: tainted
|
ensure_not_tainted(s)
|
||||||
|
|
||||||
|
def test_with_exception_neg():
|
||||||
|
s = TAINTED_STRING
|
||||||
|
|
||||||
|
if is_unsafe(s):
|
||||||
|
raise Exception("unsafe")
|
||||||
|
|
||||||
|
ensure_not_tainted(s)
|
||||||
|
|
||||||
# Make tests runable
|
# Make tests runable
|
||||||
|
|
||||||
@@ -182,7 +202,12 @@ test_tricky()
|
|||||||
test_nesting_not()
|
test_nesting_not()
|
||||||
test_nesting_not_with_and_true()
|
test_nesting_not_with_and_true()
|
||||||
test_with_return()
|
test_with_return()
|
||||||
|
test_with_return_neg()
|
||||||
try:
|
try:
|
||||||
test_with_exception()
|
test_with_exception()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
try:
|
||||||
|
test_with_exception_neg()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|||||||
@@ -86,11 +86,10 @@ def generate(opts, renderer):
|
|||||||
renderer.render(cpp.TrapList(entries, opts.dbscheme), out / dir / "TrapEntries")
|
renderer.render(cpp.TrapList(entries, opts.dbscheme), out / dir / "TrapEntries")
|
||||||
|
|
||||||
tags = []
|
tags = []
|
||||||
for index, tag in enumerate(toposort_flatten(tag_graph)):
|
for tag in toposort_flatten(tag_graph):
|
||||||
tags.append(cpp.Tag(
|
tags.append(cpp.Tag(
|
||||||
name=get_tag_name(tag),
|
name=get_tag_name(tag),
|
||||||
bases=[get_tag_name(b) for b in sorted(tag_graph[tag])],
|
bases=[get_tag_name(b) for b in sorted(tag_graph[tag])],
|
||||||
index=index,
|
|
||||||
id=tag,
|
id=tag,
|
||||||
))
|
))
|
||||||
renderer.render(cpp.TagList(tags, opts.dbscheme), out / "TrapTags")
|
renderer.render(cpp.TagList(tags, opts.dbscheme), out / "TrapTags")
|
||||||
|
|||||||
@@ -83,7 +83,6 @@ class TagBase:
|
|||||||
class Tag:
|
class Tag:
|
||||||
name: str
|
name: str
|
||||||
bases: List[TagBase]
|
bases: List[TagBase]
|
||||||
index: int
|
|
||||||
id: str
|
id: str
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ LValueType:
|
|||||||
|
|
||||||
ModuleType:
|
ModuleType:
|
||||||
_extends: Type
|
_extends: Type
|
||||||
|
module: ModuleDecl
|
||||||
|
|
||||||
PlaceholderType:
|
PlaceholderType:
|
||||||
_extends: Type
|
_extends: Type
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace codeql {
|
|||||||
|
|
||||||
// {{id}}
|
// {{id}}
|
||||||
struct {{name}}Tag {{#has_bases}}: {{#bases}}{{^first}}, {{/first}}{{base}}Tag{{/bases}} {{/has_bases}}{
|
struct {{name}}Tag {{#has_bases}}: {{#bases}}{{^first}}, {{/first}}{{base}}Tag{{/bases}} {{/has_bases}}{
|
||||||
static constexpr const char* prefix = "{{index}}";
|
static constexpr const char* prefix = "{{name}}";
|
||||||
};
|
};
|
||||||
{{/tags}}
|
{{/tags}}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ def test_trap_has_first_field_marked():
|
|||||||
def test_tag_has_first_base_marked():
|
def test_tag_has_first_base_marked():
|
||||||
bases = ["a", "b", "c"]
|
bases = ["a", "b", "c"]
|
||||||
expected = [cpp.TagBase("a", first=True), cpp.TagBase("b"), cpp.TagBase("c")]
|
expected = [cpp.TagBase("a", first=True), cpp.TagBase("b"), cpp.TagBase("c")]
|
||||||
t = cpp.Tag("name", bases, 0, "id")
|
t = cpp.Tag("name", bases, "id")
|
||||||
assert t.bases == expected
|
assert t.bases == expected
|
||||||
|
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ def test_tag_has_first_base_marked():
|
|||||||
(["a", "b"], True)
|
(["a", "b"], True)
|
||||||
])
|
])
|
||||||
def test_tag_has_bases(bases, expected):
|
def test_tag_has_bases(bases, expected):
|
||||||
t = cpp.Tag("name", bases, 0, "id")
|
t = cpp.Tag("name", bases, "id")
|
||||||
assert t.has_bases is expected
|
assert t.has_bases is expected
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -162,10 +162,10 @@ def test_one_union_tags(generate_tags):
|
|||||||
assert generate_tags([
|
assert generate_tags([
|
||||||
dbscheme.Union(lhs="@left_hand_side", rhs=["@b", "@a", "@c"]),
|
dbscheme.Union(lhs="@left_hand_side", rhs=["@b", "@a", "@c"]),
|
||||||
]) == [
|
]) == [
|
||||||
cpp.Tag(name="LeftHandSide", bases=[], index=0, id="@left_hand_side"),
|
cpp.Tag(name="LeftHandSide", bases=[], id="@left_hand_side"),
|
||||||
cpp.Tag(name="A", bases=["LeftHandSide"], index=1, id="@a"),
|
cpp.Tag(name="A", bases=["LeftHandSide"], id="@a"),
|
||||||
cpp.Tag(name="B", bases=["LeftHandSide"], index=2, id="@b"),
|
cpp.Tag(name="B", bases=["LeftHandSide"], id="@b"),
|
||||||
cpp.Tag(name="C", bases=["LeftHandSide"], index=3, id="@c"),
|
cpp.Tag(name="C", bases=["LeftHandSide"], id="@c"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -175,12 +175,12 @@ def test_multiple_union_tags(generate_tags):
|
|||||||
dbscheme.Union(lhs="@a", rhs=["@b", "@c"]),
|
dbscheme.Union(lhs="@a", rhs=["@b", "@c"]),
|
||||||
dbscheme.Union(lhs="@e", rhs=["@c", "@f"]),
|
dbscheme.Union(lhs="@e", rhs=["@c", "@f"]),
|
||||||
]) == [
|
]) == [
|
||||||
cpp.Tag(name="D", bases=[], index=0, id="@d"),
|
cpp.Tag(name="D", bases=[], id="@d"),
|
||||||
cpp.Tag(name="E", bases=[], index=1, id="@e"),
|
cpp.Tag(name="E", bases=[], id="@e"),
|
||||||
cpp.Tag(name="A", bases=["D"], index=2, id="@a"),
|
cpp.Tag(name="A", bases=["D"], id="@a"),
|
||||||
cpp.Tag(name="F", bases=["E"], index=3, id="@f"),
|
cpp.Tag(name="F", bases=["E"], id="@f"),
|
||||||
cpp.Tag(name="B", bases=["A"], index=4, id="@b"),
|
cpp.Tag(name="B", bases=["A"], id="@b"),
|
||||||
cpp.Tag(name="C", bases=["A", "E"], index=5, id="@c"),
|
cpp.Tag(name="C", bases=["A", "E"], id="@c"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,10 @@ load("//swift:rules.bzl", "swift_cc_binary")
|
|||||||
|
|
||||||
swift_cc_binary(
|
swift_cc_binary(
|
||||||
name = "extractor",
|
name = "extractor",
|
||||||
srcs = [
|
srcs = glob([
|
||||||
"SwiftOutputRewrite.cpp",
|
"*.h",
|
||||||
"SwiftOutputRewrite.h",
|
"*.cpp",
|
||||||
"SwiftExtractor.cpp",
|
]),
|
||||||
"SwiftExtractor.h",
|
|
||||||
"SwiftExtractorConfiguration.h",
|
|
||||||
"main.cpp",
|
|
||||||
],
|
|
||||||
visibility = ["//swift:__pkg__"],
|
visibility = ["//swift:__pkg__"],
|
||||||
deps = [
|
deps = [
|
||||||
"//swift/extractor/infra",
|
"//swift/extractor/infra",
|
||||||
|
|||||||
@@ -14,9 +14,10 @@
|
|||||||
#include "swift/extractor/trap/generated/TrapClasses.h"
|
#include "swift/extractor/trap/generated/TrapClasses.h"
|
||||||
#include "swift/extractor/trap/TrapDomain.h"
|
#include "swift/extractor/trap/TrapDomain.h"
|
||||||
#include "swift/extractor/visitors/SwiftVisitor.h"
|
#include "swift/extractor/visitors/SwiftVisitor.h"
|
||||||
#include "swift/extractor/infra/TargetFile.h"
|
#include "swift/extractor/TargetTrapFile.h"
|
||||||
|
|
||||||
using namespace codeql;
|
using namespace codeql;
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
static void archiveFile(const SwiftExtractorConfiguration& config, swift::SourceFile& file) {
|
static void archiveFile(const SwiftExtractorConfiguration& config, swift::SourceFile& file) {
|
||||||
if (std::error_code ec = llvm::sys::fs::create_directories(config.trapDir)) {
|
if (std::error_code ec = llvm::sys::fs::create_directories(config.trapDir)) {
|
||||||
@@ -53,13 +54,19 @@ static std::string getFilename(swift::ModuleDecl& module, swift::SourceFile* pri
|
|||||||
if (primaryFile) {
|
if (primaryFile) {
|
||||||
return primaryFile->getFilename().str();
|
return primaryFile->getFilename().str();
|
||||||
}
|
}
|
||||||
// Several modules with different name might come from .pcm (clang module) files
|
// PCM clang module
|
||||||
|
if (module.isNonSwiftModule()) {
|
||||||
|
// Several modules with different names might come from .pcm (clang module) files
|
||||||
// In this case we want to differentiate them
|
// In this case we want to differentiate them
|
||||||
std::string filename = module.getModuleFilename().str();
|
// Moreover, pcm files may come from caches located in different directories, but are
|
||||||
|
// unambiguously identified by the base file name, so we can discard the absolute directory
|
||||||
|
std::string filename = "/pcms/"s + llvm::sys::path::filename(module.getModuleFilename()).str();
|
||||||
filename += "-";
|
filename += "-";
|
||||||
filename += module.getName().str();
|
filename += module.getName().str();
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
return module.getModuleFilename().str();
|
||||||
|
}
|
||||||
|
|
||||||
static llvm::SmallVector<swift::Decl*> getTopLevelDecls(swift::ModuleDecl& module,
|
static llvm::SmallVector<swift::Decl*> getTopLevelDecls(swift::ModuleDecl& module,
|
||||||
swift::SourceFile* primaryFile = nullptr) {
|
swift::SourceFile* primaryFile = nullptr) {
|
||||||
@@ -73,20 +80,6 @@ static llvm::SmallVector<swift::Decl*> getTopLevelDecls(swift::ModuleDecl& modul
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dumpArgs(TargetFile& out, const SwiftExtractorConfiguration& config) {
|
|
||||||
out << "/* extractor-args:\n";
|
|
||||||
for (const auto& opt : config.frontendOptions) {
|
|
||||||
out << " " << std::quoted(opt) << " \\\n";
|
|
||||||
}
|
|
||||||
out << "\n*/\n";
|
|
||||||
|
|
||||||
out << "/* swift-frontend-args:\n";
|
|
||||||
for (const auto& opt : config.patchedFrontendOptions) {
|
|
||||||
out << " " << std::quoted(opt) << " \\\n";
|
|
||||||
}
|
|
||||||
out << "\n*/\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
static void extractDeclarations(const SwiftExtractorConfiguration& config,
|
static void extractDeclarations(const SwiftExtractorConfiguration& config,
|
||||||
swift::CompilerInstance& compiler,
|
swift::CompilerInstance& compiler,
|
||||||
swift::ModuleDecl& module,
|
swift::ModuleDecl& module,
|
||||||
@@ -96,12 +89,11 @@ static void extractDeclarations(const SwiftExtractorConfiguration& config,
|
|||||||
// The extractor can be called several times from different processes with
|
// The extractor can be called several times from different processes with
|
||||||
// the same input file(s). Using `TargetFile` the first process will win, and the following
|
// the same input file(s). Using `TargetFile` the first process will win, and the following
|
||||||
// will just skip the work
|
// will just skip the work
|
||||||
auto trapTarget = TargetFile::create(filename + ".trap", config.trapDir, config.getTempTrapDir());
|
auto trapTarget = createTargetTrapFile(config, filename);
|
||||||
if (!trapTarget) {
|
if (!trapTarget) {
|
||||||
// another process arrived first, nothing to do for us
|
// another process arrived first, nothing to do for us
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dumpArgs(*trapTarget, config);
|
|
||||||
TrapDomain trap{*trapTarget};
|
TrapDomain trap{*trapTarget};
|
||||||
|
|
||||||
// TODO: remove this and recreate it with IPA when we have that
|
// TODO: remove this and recreate it with IPA when we have that
|
||||||
@@ -166,21 +158,21 @@ void codeql::extractSwiftFiles(const SwiftExtractorConfiguration& config,
|
|||||||
auto modules = collectModules(compiler);
|
auto modules = collectModules(compiler);
|
||||||
|
|
||||||
for (auto& module : modules) {
|
for (auto& module : modules) {
|
||||||
// We only extract system and builtin modules here as the other "user" modules can be built
|
bool isFromSourceFile = false;
|
||||||
// during the build process and then re-used at a later stage. In this case, we extract the
|
|
||||||
// user code twice: once during the module build in a form of a source file, and then as
|
|
||||||
// a pre-built module during building of the dependent source files.
|
|
||||||
if (module->isSystemModule() || module->isBuiltinModule()) {
|
|
||||||
extractDeclarations(config, compiler, *module);
|
|
||||||
} else {
|
|
||||||
for (auto file : module->getFiles()) {
|
for (auto file : module->getFiles()) {
|
||||||
auto sourceFile = llvm::dyn_cast<swift::SourceFile>(file);
|
auto sourceFile = llvm::dyn_cast<swift::SourceFile>(file);
|
||||||
if (!sourceFile || inputFiles.count(sourceFile->getFilename().str()) == 0) {
|
if (!sourceFile) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
isFromSourceFile = true;
|
||||||
|
if (inputFiles.count(sourceFile->getFilename().str()) == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
archiveFile(config, *sourceFile);
|
archiveFile(config, *sourceFile);
|
||||||
extractDeclarations(config, compiler, *module, sourceFile);
|
extractDeclarations(config, compiler, *module, sourceFile);
|
||||||
}
|
}
|
||||||
|
if (!isFromSourceFile) {
|
||||||
|
extractDeclarations(config, compiler, *module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "swift/extractor/infra/TargetFile.h"
|
||||||
|
|
||||||
namespace codeql {
|
namespace codeql {
|
||||||
struct SwiftExtractorConfiguration {
|
struct SwiftExtractorConfiguration {
|
||||||
// The location for storing TRAP files to be imported by CodeQL engine.
|
// The location for storing TRAP files to be imported by CodeQL engine.
|
||||||
@@ -33,4 +35,5 @@ struct SwiftExtractorConfiguration {
|
|||||||
// overall extraction process.
|
// overall extraction process.
|
||||||
std::string getTempArtifactDir() const { return scratchDir + "/swift-extraction-artifacts"; }
|
std::string getTempArtifactDir() const { return scratchDir + "/swift-extraction-artifacts"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace codeql
|
} // namespace codeql
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "SwiftOutputRewrite.h"
|
#include "SwiftOutputRewrite.h"
|
||||||
#include "swift/extractor/SwiftExtractorConfiguration.h"
|
#include "swift/extractor/SwiftExtractorConfiguration.h"
|
||||||
|
#include "swift/extractor/TargetTrapFile.h"
|
||||||
|
|
||||||
#include <llvm/ADT/SmallString.h>
|
#include <llvm/ADT/SmallString.h>
|
||||||
#include <llvm/Support/FileSystem.h>
|
#include <llvm/Support/FileSystem.h>
|
||||||
@@ -163,7 +164,7 @@ static std::vector<std::string> computeModuleAliases(llvm::StringRef modulePath,
|
|||||||
namespace codeql {
|
namespace codeql {
|
||||||
|
|
||||||
std::unordered_map<std::string, std::string> rewriteOutputsInPlace(
|
std::unordered_map<std::string, std::string> rewriteOutputsInPlace(
|
||||||
SwiftExtractorConfiguration& config,
|
const SwiftExtractorConfiguration& config,
|
||||||
std::vector<std::string>& CLIArgs) {
|
std::vector<std::string>& CLIArgs) {
|
||||||
std::unordered_map<std::string, std::string> remapping;
|
std::unordered_map<std::string, std::string> remapping;
|
||||||
|
|
||||||
@@ -324,4 +325,17 @@ std::vector<std::string> collectVFSFiles(const SwiftExtractorConfiguration& conf
|
|||||||
return overlays;
|
return overlays;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lockOutputSwiftModuleTraps(const SwiftExtractorConfiguration& config,
|
||||||
|
const std::unordered_map<std::string, std::string>& remapping) {
|
||||||
|
for (const auto& [oldPath, newPath] : remapping) {
|
||||||
|
if (llvm::StringRef(oldPath).endswith(".swiftmodule")) {
|
||||||
|
if (auto target = createTargetTrapFile(config, oldPath)) {
|
||||||
|
*target << "// trap file deliberately empty\n"
|
||||||
|
"// this swiftmodule was created during the build, so its entities must have"
|
||||||
|
" been extracted directly from source files";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace codeql
|
} // namespace codeql
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ struct SwiftExtractorConfiguration;
|
|||||||
// artifacts produced by the actual Swift compiler.
|
// artifacts produced by the actual Swift compiler.
|
||||||
// Returns the map containing remapping oldpath -> newPath.
|
// Returns the map containing remapping oldpath -> newPath.
|
||||||
std::unordered_map<std::string, std::string> rewriteOutputsInPlace(
|
std::unordered_map<std::string, std::string> rewriteOutputsInPlace(
|
||||||
SwiftExtractorConfiguration& config,
|
const SwiftExtractorConfiguration& config,
|
||||||
std::vector<std::string>& CLIArgs);
|
std::vector<std::string>& CLIArgs);
|
||||||
|
|
||||||
// Create directories for all the redirected new paths as the Swift compiler expects them to exist.
|
// Create directories for all the redirected new paths as the Swift compiler expects them to exist.
|
||||||
@@ -29,4 +29,7 @@ void storeRemappingForVFS(const SwiftExtractorConfiguration& config,
|
|||||||
// This is separate from storeRemappingForVFS as we also collect files produced by other processes.
|
// This is separate from storeRemappingForVFS as we also collect files produced by other processes.
|
||||||
std::vector<std::string> collectVFSFiles(const SwiftExtractorConfiguration& config);
|
std::vector<std::string> collectVFSFiles(const SwiftExtractorConfiguration& config);
|
||||||
|
|
||||||
|
// Creates empty trap files for output swiftmodule files
|
||||||
|
void lockOutputSwiftModuleTraps(const SwiftExtractorConfiguration& config,
|
||||||
|
const std::unordered_map<std::string, std::string>& remapping);
|
||||||
} // namespace codeql
|
} // namespace codeql
|
||||||
|
|||||||
23
swift/extractor/TargetTrapFile.cpp
Normal file
23
swift/extractor/TargetTrapFile.cpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#include "swift/extractor/TargetTrapFile.h"
|
||||||
|
#include <iomanip>
|
||||||
|
namespace codeql {
|
||||||
|
std::optional<TargetFile> createTargetTrapFile(const SwiftExtractorConfiguration& configuration,
|
||||||
|
std::string_view target) {
|
||||||
|
std::string trap{target};
|
||||||
|
trap += ".trap";
|
||||||
|
auto ret = TargetFile::create(trap, configuration.trapDir, configuration.getTempTrapDir());
|
||||||
|
if (ret) {
|
||||||
|
*ret << "/* extractor-args:\n";
|
||||||
|
for (const auto& opt : configuration.frontendOptions) {
|
||||||
|
*ret << " " << std::quoted(opt) << " \\\n";
|
||||||
|
}
|
||||||
|
*ret << "\n*/\n"
|
||||||
|
"/* swift-frontend-args:\n";
|
||||||
|
for (const auto& opt : configuration.patchedFrontendOptions) {
|
||||||
|
*ret << " " << std::quoted(opt) << " \\\n";
|
||||||
|
}
|
||||||
|
*ret << "\n*/\n";
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
} // namespace codeql
|
||||||
11
swift/extractor/TargetTrapFile.h
Normal file
11
swift/extractor/TargetTrapFile.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "swift/extractor/infra/TargetFile.h"
|
||||||
|
#include "swift/extractor/SwiftExtractorConfiguration.h"
|
||||||
|
|
||||||
|
namespace codeql {
|
||||||
|
|
||||||
|
std::optional<TargetFile> createTargetTrapFile(const SwiftExtractorConfiguration& configuration,
|
||||||
|
std::string_view target);
|
||||||
|
|
||||||
|
} // namespace codeql
|
||||||
@@ -215,7 +215,7 @@ class SwiftDispatcher {
|
|||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void emitDebugInfo(const Args&... args) {
|
void emitDebugInfo(const Args&... args) {
|
||||||
trap.debug(std::forward<Args>(args)...);
|
trap.debug(args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// In order to not emit duplicated entries for declarations, we restrict emission to only
|
// In order to not emit duplicated entries for declarations, we restrict emission to only
|
||||||
@@ -315,7 +315,7 @@ class SwiftDispatcher {
|
|||||||
virtual void visit(swift::TypeBase* type) = 0;
|
virtual void visit(swift::TypeBase* type) = 0;
|
||||||
|
|
||||||
void visit(const FilePath& file) {
|
void visit(const FilePath& file) {
|
||||||
auto entry = createEntry(file);
|
auto entry = createEntry(file, file.path);
|
||||||
entry.name = file.path;
|
entry.name = file.path;
|
||||||
emit(entry);
|
emit(entry);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ int main(int argc, char** argv) {
|
|||||||
codeql::rewriteOutputsInPlace(configuration, configuration.patchedFrontendOptions);
|
codeql::rewriteOutputsInPlace(configuration, configuration.patchedFrontendOptions);
|
||||||
codeql::ensureDirectoriesForNewPathsExist(remapping);
|
codeql::ensureDirectoriesForNewPathsExist(remapping);
|
||||||
codeql::storeRemappingForVFS(configuration, remapping);
|
codeql::storeRemappingForVFS(configuration, remapping);
|
||||||
|
codeql::lockOutputSwiftModuleTraps(configuration, remapping);
|
||||||
|
|
||||||
std::vector<const char*> args;
|
std::vector<const char*> args;
|
||||||
for (auto& arg : configuration.patchedFrontendOptions) {
|
for (auto& arg : configuration.patchedFrontendOptions) {
|
||||||
|
|||||||
@@ -83,11 +83,13 @@ codeql::PrecedenceGroupDecl DeclVisitor::translatePrecedenceGroupDecl(
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
codeql::ParamDecl DeclVisitor::translateParamDecl(const swift::ParamDecl& decl) {
|
std::optional<codeql::ParamDecl> DeclVisitor::translateParamDecl(const swift::ParamDecl& decl) {
|
||||||
// TODO: deduplicate
|
auto entry = createNamedEntry(decl);
|
||||||
ParamDecl entry{dispatcher_.assignNewLabel(decl)};
|
if (!entry) {
|
||||||
fillVarDecl(decl, entry);
|
return std::nullopt;
|
||||||
entry.is_inout = decl.isInOut();
|
}
|
||||||
|
fillVarDecl(decl, *entry);
|
||||||
|
entry->is_inout = decl.isInOut();
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,11 +113,20 @@ codeql::PatternBindingDecl DeclVisitor::translatePatternBindingDecl(
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
codeql::ConcreteVarDecl DeclVisitor::translateVarDecl(const swift::VarDecl& decl) {
|
std::optional<codeql::ConcreteVarDecl> DeclVisitor::translateVarDecl(const swift::VarDecl& decl) {
|
||||||
// TODO: deduplicate all non-local variables
|
std::optional<codeql::ConcreteVarDecl> entry;
|
||||||
ConcreteVarDecl entry{dispatcher_.assignNewLabel(decl)};
|
// We do not deduplicate variables from non-swift (PCM, clang modules) modules as the mangler
|
||||||
entry.introducer_int = static_cast<uint8_t>(decl.getIntroducer());
|
// crashes sometimes
|
||||||
fillVarDecl(decl, entry);
|
if (decl.getDeclContext()->isLocalContext() || decl.getModuleContext()->isNonSwiftModule()) {
|
||||||
|
entry.emplace(dispatcher_.assignNewLabel(decl));
|
||||||
|
} else {
|
||||||
|
entry = createNamedEntry(decl);
|
||||||
|
if (!entry) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entry->introducer_int = static_cast<uint8_t>(decl.getIntroducer());
|
||||||
|
fillVarDecl(decl, *entry);
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,11 +295,30 @@ std::string DeclVisitor::mangledName(const swift::ValueDecl& decl) {
|
|||||||
// ASTMangler::mangleAnyDecl crashes when called on `ModuleDecl`
|
// ASTMangler::mangleAnyDecl crashes when called on `ModuleDecl`
|
||||||
// TODO find a more unique string working also when different modules are compiled with the same
|
// TODO find a more unique string working also when different modules are compiled with the same
|
||||||
// name
|
// name
|
||||||
|
std::ostringstream ret;
|
||||||
if (decl.getKind() == swift::DeclKind::Module) {
|
if (decl.getKind() == swift::DeclKind::Module) {
|
||||||
return static_cast<const swift::ModuleDecl&>(decl).getRealName().str().str();
|
ret << static_cast<const swift::ModuleDecl&>(decl).getRealName().str().str();
|
||||||
}
|
} else if (decl.getKind() == swift::DeclKind::TypeAlias) {
|
||||||
|
// In cases like this (when coming from PCM)
|
||||||
|
// typealias CFXMLTree = CFTree
|
||||||
|
// typealias CFXMLTreeRef = CFXMLTree
|
||||||
|
// mangleAnyDecl mangles both CFXMLTree and CFXMLTreeRef into 'So12CFXMLTreeRefa'
|
||||||
|
// which is not correct and causes inconsistencies. mangleEntity makes these two distinct
|
||||||
// prefix adds a couple of special symbols, we don't necessary need them
|
// prefix adds a couple of special symbols, we don't necessary need them
|
||||||
return mangler.mangleAnyDecl(&decl, /* prefix = */ false);
|
ret << mangler.mangleEntity(&decl);
|
||||||
|
} else {
|
||||||
|
// prefix adds a couple of special symbols, we don't necessary need them
|
||||||
|
ret << mangler.mangleAnyDecl(&decl, /* prefix = */ false);
|
||||||
|
}
|
||||||
|
// there can be separate declarations (`VarDecl` or `AccessorDecl`) which are effectively the same
|
||||||
|
// (with equal mangled name) but come from different clang modules. This is the case for example
|
||||||
|
// for glibc constants like `L_SET` that appear in both `SwiftGlibc` and `CDispatch`.
|
||||||
|
// For the moment, we sidestep the problem by making them separate entities in the DB
|
||||||
|
// TODO find a more solid solution
|
||||||
|
if (decl.getModuleContext()->isNonSwiftModule()) {
|
||||||
|
ret << '_' << decl.getModuleContext()->getRealName().str().str();
|
||||||
|
}
|
||||||
|
return ret.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeclVisitor::fillAbstractFunctionDecl(const swift::AbstractFunctionDecl& decl,
|
void DeclVisitor::fillAbstractFunctionDecl(const swift::AbstractFunctionDecl& decl,
|
||||||
|
|||||||
@@ -30,10 +30,10 @@ class DeclVisitor : public AstVisitorBase<DeclVisitor> {
|
|||||||
codeql::PostfixOperatorDecl translatePostfixOperatorDecl(const swift::PostfixOperatorDecl& decl);
|
codeql::PostfixOperatorDecl translatePostfixOperatorDecl(const swift::PostfixOperatorDecl& decl);
|
||||||
codeql::InfixOperatorDecl translateInfixOperatorDecl(const swift::InfixOperatorDecl& decl);
|
codeql::InfixOperatorDecl translateInfixOperatorDecl(const swift::InfixOperatorDecl& decl);
|
||||||
codeql::PrecedenceGroupDecl translatePrecedenceGroupDecl(const swift::PrecedenceGroupDecl& decl);
|
codeql::PrecedenceGroupDecl translatePrecedenceGroupDecl(const swift::PrecedenceGroupDecl& decl);
|
||||||
codeql::ParamDecl translateParamDecl(const swift::ParamDecl& decl);
|
std::optional<codeql::ParamDecl> translateParamDecl(const swift::ParamDecl& decl);
|
||||||
codeql::TopLevelCodeDecl translateTopLevelCodeDecl(const swift::TopLevelCodeDecl& decl);
|
codeql::TopLevelCodeDecl translateTopLevelCodeDecl(const swift::TopLevelCodeDecl& decl);
|
||||||
codeql::PatternBindingDecl translatePatternBindingDecl(const swift::PatternBindingDecl& decl);
|
codeql::PatternBindingDecl translatePatternBindingDecl(const swift::PatternBindingDecl& decl);
|
||||||
codeql::ConcreteVarDecl translateVarDecl(const swift::VarDecl& decl);
|
std::optional<codeql::ConcreteVarDecl> translateVarDecl(const swift::VarDecl& decl);
|
||||||
std::variant<codeql::StructDecl, codeql::StructDeclsTrap> translateStructDecl(
|
std::variant<codeql::StructDecl, codeql::StructDeclsTrap> translateStructDecl(
|
||||||
const swift::StructDecl& decl);
|
const swift::StructDecl& decl);
|
||||||
std::variant<codeql::ClassDecl, codeql::ClassDeclsTrap> translateClassDecl(
|
std::variant<codeql::ClassDecl, codeql::ClassDeclsTrap> translateClassDecl(
|
||||||
|
|||||||
@@ -381,4 +381,14 @@ codeql::OpenedArchetypeType TypeVisitor::translateOpenedArchetypeType(
|
|||||||
fillArchetypeType(type, entry);
|
fillArchetypeType(type, entry);
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
codeql::ModuleType TypeVisitor::translateModuleType(const swift::ModuleType& type) {
|
||||||
|
auto key = type.getModule()->getRealName().str().str();
|
||||||
|
if (type.getModule()->isNonSwiftModule()) {
|
||||||
|
key += "|clang";
|
||||||
|
}
|
||||||
|
auto entry = createTypeEntry(type, key);
|
||||||
|
entry.module = dispatcher_.fetchLabel(type.getModule());
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
} // namespace codeql
|
} // namespace codeql
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ class TypeVisitor : public TypeVisitorBase<TypeVisitor> {
|
|||||||
const swift::BuiltinUnsafeValueBufferType& type);
|
const swift::BuiltinUnsafeValueBufferType& type);
|
||||||
codeql::BuiltinVectorType translateBuiltinVectorType(const swift::BuiltinVectorType& type);
|
codeql::BuiltinVectorType translateBuiltinVectorType(const swift::BuiltinVectorType& type);
|
||||||
codeql::OpenedArchetypeType translateOpenedArchetypeType(const swift::OpenedArchetypeType& type);
|
codeql::OpenedArchetypeType translateOpenedArchetypeType(const swift::OpenedArchetypeType& type);
|
||||||
|
codeql::ModuleType translateModuleType(const swift::ModuleType& type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void fillType(const swift::TypeBase& type, codeql::Type& entry);
|
void fillType(const swift::TypeBase& type, codeql::Type& entry);
|
||||||
@@ -83,9 +84,9 @@ class TypeVisitor : public TypeVisitorBase<TypeVisitor> {
|
|||||||
void emitBoundGenericType(swift::BoundGenericType* type, TrapLabel<BoundGenericTypeTag> label);
|
void emitBoundGenericType(swift::BoundGenericType* type, TrapLabel<BoundGenericTypeTag> label);
|
||||||
void emitAnyGenericType(swift::AnyGenericType* type, TrapLabel<AnyGenericTypeTag> label);
|
void emitAnyGenericType(swift::AnyGenericType* type, TrapLabel<AnyGenericTypeTag> label);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename... Args>
|
||||||
auto createTypeEntry(const T& type) {
|
auto createTypeEntry(const T& type, const Args&... args) {
|
||||||
auto entry = dispatcher_.createEntry(type);
|
auto entry = dispatcher_.createEntry(type, args...);
|
||||||
fillType(type, entry);
|
fillType(type, entry);
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ def run_codeql_database_create(cmds, lang, keep_trap=True):
|
|||||||
codeql_root = pathlib.Path(__file__).parents[2]
|
codeql_root = pathlib.Path(__file__).parents[2]
|
||||||
cmd = [
|
cmd = [
|
||||||
"codeql", "database", "create",
|
"codeql", "database", "create",
|
||||||
"-s", ".", "-l", "swift", "--internal-use-lua-tracing", f"--search-path={codeql_root}",
|
"-s", ".", "-l", "swift", "--internal-use-lua-tracing", f"--search-path={codeql_root}", "--no-cleanup",
|
||||||
]
|
]
|
||||||
if keep_trap:
|
if keep_trap:
|
||||||
cmd.append("--keep-trap")
|
cmd.append("--keep-trap")
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
| Sources/cross-references/lib.swift:10:5:10:5 | X |
|
| Sources/cross-references/lib.swift:10:5:10:5 | X |
|
||||||
| Sources/cross-references/lib.swift:10:5:10:5 | X |
|
|
||||||
| Sources/cross-references/lib.swift:17:16:17:19 | v |
|
| Sources/cross-references/lib.swift:17:16:17:19 | v |
|
||||||
| Sources/cross-references/lib.swift:22:16:22:19 | v |
|
| Sources/cross-references/lib.swift:22:16:22:19 | v |
|
||||||
| Sources/cross-references/lib.swift:27:8:27:13 | lhs |
|
| Sources/cross-references/lib.swift:27:8:27:13 | lhs |
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
| file://:0:0:0:0 | A |
|
| file://:0:0:0:0 | A |
|
||||||
| file://:0:0:0:0 | B |
|
| file://:0:0:0:0 | B |
|
||||||
|
| file://:0:0:0:0 | PackageDescription |
|
||||||
| file://:0:0:0:0 | main |
|
| file://:0:0:0:0 | main |
|
||||||
| file://:0:0:0:0 | partial_modules |
|
| file://:0:0:0:0 | partial_modules |
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ def main(opts):
|
|||||||
]
|
]
|
||||||
if opts.check_databases:
|
if opts.check_databases:
|
||||||
cmd.append("--check-databases")
|
cmd.append("--check-databases")
|
||||||
|
else:
|
||||||
|
cmd.append("--no-check-databases")
|
||||||
if opts.learn:
|
if opts.learn:
|
||||||
cmd.append("--learn")
|
cmd.append("--learn")
|
||||||
cmd.extend(str(t.parent) for t in succesful_db_creation)
|
cmd.extend(str(t.parent) for t in succesful_db_creation)
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
// generated by codegen/codegen.py
|
// generated by codegen/codegen.py
|
||||||
|
import codeql.swift.elements.decl.ModuleDecl
|
||||||
import codeql.swift.elements.type.Type
|
import codeql.swift.elements.type.Type
|
||||||
|
|
||||||
class ModuleTypeBase extends @module_type, Type {
|
class ModuleTypeBase extends @module_type, Type {
|
||||||
override string getAPrimaryQlClass() { result = "ModuleType" }
|
override string getAPrimaryQlClass() { result = "ModuleType" }
|
||||||
|
|
||||||
|
ModuleDecl getModule() {
|
||||||
|
exists(ModuleDecl x |
|
||||||
|
module_types(this, x) and
|
||||||
|
result = x.resolve()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -264,7 +264,8 @@ l_value_types( //dir=type
|
|||||||
);
|
);
|
||||||
|
|
||||||
module_types( //dir=type
|
module_types( //dir=type
|
||||||
unique int id: @module_type
|
unique int id: @module_type,
|
||||||
|
int module: @module_decl ref
|
||||||
);
|
);
|
||||||
|
|
||||||
placeholder_types( //dir=type
|
placeholder_types( //dir=type
|
||||||
|
|||||||
@@ -4,7 +4,11 @@ cached
|
|||||||
predicate toBeTested(Element e) {
|
predicate toBeTested(Element e) {
|
||||||
e instanceof File
|
e instanceof File
|
||||||
or
|
or
|
||||||
exists(ModuleDecl m | m = e and not m.isBuiltinModule() and not m.isSystemModule())
|
exists(ModuleDecl m |
|
||||||
|
not m.isBuiltinModule() and
|
||||||
|
not m.isSystemModule() and
|
||||||
|
(m = e or m.getInterfaceType() = e)
|
||||||
|
)
|
||||||
or
|
or
|
||||||
exists(Locatable loc |
|
exists(Locatable loc |
|
||||||
loc.getLocation().getFile().getName().matches("%swift/ql/test%") and
|
loc.getLocation().getFile().getName().matches("%swift/ql/test%") and
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
| var_decls.swift:4:7:4:7 | i | getInterfaceType: | Int | getName: | i | getType: | Int | getIntroducerInt: | 1 |
|
||||||
|
| var_decls.swift:7:5:7:5 | numbers | getInterfaceType: | [Int] | getName: | numbers | getType: | [Int] | getIntroducerInt: | 1 |
|
||||||
|
| var_decls.swift:10:12:10:12 | numbers | getInterfaceType: | [Int] | getName: | numbers | getType: | [Int] | getIntroducerInt: | 0 |
|
||||||
|
| var_decls.swift:15:7:15:7 | wrappedValue | getInterfaceType: | T | getName: | wrappedValue | getType: | T | getIntroducerInt: | 1 |
|
||||||
|
| var_decls.swift:20:7:20:7 | wrappedValue | getInterfaceType: | Int | getName: | wrappedValue | getType: | Int | getIntroducerInt: | 1 |
|
||||||
|
| var_decls.swift:24:15:24:15 | _wrapped | getInterfaceType: | X<Y> | getName: | _wrapped | getType: | X<Y> | getIntroducerInt: | 1 |
|
||||||
|
| var_decls.swift:24:15:24:15 | wrapped | getInterfaceType: | Int | getName: | wrapped | getType: | Int | getIntroducerInt: | 1 |
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// generated by codegen/codegen.py
|
||||||
|
import codeql.swift.elements
|
||||||
|
import TestUtils
|
||||||
|
|
||||||
|
from ConcreteVarDecl x, Type getInterfaceType, string getName, Type getType, int getIntroducerInt
|
||||||
|
where
|
||||||
|
toBeTested(x) and
|
||||||
|
not x.isUnknown() and
|
||||||
|
getInterfaceType = x.getInterfaceType() and
|
||||||
|
getName = x.getName() and
|
||||||
|
getType = x.getType() and
|
||||||
|
getIntroducerInt = x.getIntroducerInt()
|
||||||
|
select x, "getInterfaceType:", getInterfaceType, "getName:", getName, "getType:", getType,
|
||||||
|
"getIntroducerInt:", getIntroducerInt
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
| var_decls.swift:10:12:10:12 | numbers | 0 | var_decls.swift:10:12:10:12 | get |
|
||||||
|
| var_decls.swift:15:7:15:7 | wrappedValue | 0 | var_decls.swift:15:7:15:7 | get |
|
||||||
|
| var_decls.swift:15:7:15:7 | wrappedValue | 1 | var_decls.swift:15:7:15:7 | set |
|
||||||
|
| var_decls.swift:15:7:15:7 | wrappedValue | 2 | var_decls.swift:15:7:15:7 | (unnamed function decl) |
|
||||||
|
| var_decls.swift:20:7:20:7 | wrappedValue | 0 | var_decls.swift:20:7:20:7 | get |
|
||||||
|
| var_decls.swift:20:7:20:7 | wrappedValue | 1 | var_decls.swift:20:7:20:7 | set |
|
||||||
|
| var_decls.swift:20:7:20:7 | wrappedValue | 2 | var_decls.swift:20:7:20:7 | (unnamed function decl) |
|
||||||
|
| var_decls.swift:24:15:24:15 | _wrapped | 0 | var_decls.swift:24:15:24:15 | get |
|
||||||
|
| var_decls.swift:24:15:24:15 | _wrapped | 1 | var_decls.swift:24:15:24:15 | set |
|
||||||
|
| var_decls.swift:24:15:24:15 | _wrapped | 2 | var_decls.swift:24:15:24:15 | (unnamed function decl) |
|
||||||
|
| var_decls.swift:24:15:24:15 | wrapped | 0 | var_decls.swift:24:15:24:15 | get |
|
||||||
|
| var_decls.swift:24:15:24:15 | wrapped | 1 | var_decls.swift:24:15:24:15 | set |
|
||||||
|
| var_decls.swift:24:15:24:15 | wrapped | 2 | var_decls.swift:24:15:24:15 | (unnamed function decl) |
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// generated by codegen/codegen.py
|
||||||
|
import codeql.swift.elements
|
||||||
|
import TestUtils
|
||||||
|
|
||||||
|
from ConcreteVarDecl x, int index
|
||||||
|
where toBeTested(x) and not x.isUnknown()
|
||||||
|
select x, index, x.getAccessorDecl(index)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
| var_decls.swift:24:15:24:15 | wrapped | X<Y> |
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// generated by codegen/codegen.py
|
||||||
|
import codeql.swift.elements
|
||||||
|
import TestUtils
|
||||||
|
|
||||||
|
from ConcreteVarDecl x
|
||||||
|
where toBeTested(x) and not x.isUnknown()
|
||||||
|
select x, x.getAttachedPropertyWrapperType()
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
| var_decls.swift:4:7:4:7 | i | var_decls.swift:4:11:4:11 | 0 |
|
||||||
|
| var_decls.swift:7:5:7:5 | numbers | var_decls.swift:7:15:7:18 | [...] |
|
||||||
|
| var_decls.swift:10:12:10:12 | numbers | var_decls.swift:10:22:10:35 | [...] |
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// generated by codegen/codegen.py
|
||||||
|
import codeql.swift.elements
|
||||||
|
import TestUtils
|
||||||
|
|
||||||
|
from ConcreteVarDecl x
|
||||||
|
where toBeTested(x) and not x.isUnknown()
|
||||||
|
select x, x.getParentInitializer()
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
| var_decls.swift:4:7:4:7 | i | var_decls.swift:4:7:4:7 | i |
|
||||||
|
| var_decls.swift:7:5:7:5 | numbers | var_decls.swift:7:5:7:5 | numbers |
|
||||||
|
| var_decls.swift:10:12:10:12 | numbers | var_decls.swift:10:12:10:12 | numbers |
|
||||||
|
| var_decls.swift:15:7:15:7 | wrappedValue | var_decls.swift:15:7:15:21 | ... as ... |
|
||||||
|
| var_decls.swift:20:7:20:7 | wrappedValue | var_decls.swift:20:7:20:21 | ... as ... |
|
||||||
|
| var_decls.swift:24:15:24:15 | _wrapped | var_decls.swift:24:15:24:15 | ... as ... |
|
||||||
|
| var_decls.swift:24:15:24:15 | wrapped | var_decls.swift:24:15:24:25 | ... as ... |
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// generated by codegen/codegen.py
|
||||||
|
import codeql.swift.elements
|
||||||
|
import TestUtils
|
||||||
|
|
||||||
|
from ConcreteVarDecl x
|
||||||
|
where toBeTested(x) and not x.isUnknown()
|
||||||
|
select x, x.getParentPattern()
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
// generated by codegen/codegen.py
|
|
||||||
|
|
||||||
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
|
|
||||||
will appear and this file will be deleted
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
func loop() {
|
||||||
|
for i in 1...5 {
|
||||||
|
}
|
||||||
|
var i = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var numbers = [42]
|
||||||
|
|
||||||
|
struct S {
|
||||||
|
static let numbers = [42, 404, 101]
|
||||||
|
}
|
||||||
|
|
||||||
|
@propertyWrapper
|
||||||
|
struct X<T> {
|
||||||
|
var wrappedValue: T
|
||||||
|
}
|
||||||
|
|
||||||
|
@propertyWrapper
|
||||||
|
struct Y {
|
||||||
|
var wrappedValue: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Wrapped {
|
||||||
|
@X @Y var wrapped : Int
|
||||||
|
}
|
||||||
@@ -1 +1,2 @@
|
|||||||
| file://:0:0:0:0 | Foo | getInterfaceType: | module<Foo> | getName: | Foo | isBuiltinModule: | no | isSystemModule: | no |
|
| file://:0:0:0:0 | Foo | getInterfaceType: | module<Foo> | getName: | Foo | isBuiltinModule: | no | isSystemModule: | no |
|
||||||
|
| file://:0:0:0:0 | default_module_name | getInterfaceType: | module<default_module_name> | getName: | default_module_name | isBuiltinModule: | no | isSystemModule: | no |
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
// generated by codegen/codegen.py
|
|
||||||
|
|
||||||
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
|
|
||||||
will appear and this file will be deleted
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
| param_decls.swift:1:10:1:13 | _ | getInterfaceType: | Int | getName: | _ | getType: | Int | isInout: | no |
|
||||||
|
| param_decls.swift:1:18:1:29 | y | getInterfaceType: | Double | getName: | y | getType: | Double | isInout: | yes |
|
||||||
|
| param_decls.swift:2:10:2:13 | _ | getInterfaceType: | Int | getName: | _ | getType: | Int | isInout: | no |
|
||||||
|
| param_decls.swift:2:18:2:29 | y | getInterfaceType: | Double | getName: | y | getType: | Double | isInout: | yes |
|
||||||
|
| param_decls.swift:5:5:5:5 | self | getInterfaceType: | S | getName: | self | getType: | S | isInout: | yes |
|
||||||
|
| param_decls.swift:5:15:5:15 | x | getInterfaceType: | Int | getName: | x | getType: | Int | isInout: | no |
|
||||||
|
| param_decls.swift:5:15:5:15 | x | getInterfaceType: | Int | getName: | x | getType: | Int | isInout: | no |
|
||||||
|
| param_decls.swift:5:15:5:18 | x | getInterfaceType: | Int | getName: | x | getType: | Int | isInout: | no |
|
||||||
|
| param_decls.swift:5:23:5:23 | y | getInterfaceType: | Int | getName: | y | getType: | Int | isInout: | no |
|
||||||
|
| param_decls.swift:5:23:5:23 | y | getInterfaceType: | Int | getName: | y | getType: | Int | isInout: | no |
|
||||||
|
| param_decls.swift:5:23:5:26 | y | getInterfaceType: | Int | getName: | y | getType: | Int | isInout: | no |
|
||||||
|
| param_decls.swift:7:9:7:9 | newValue | getInterfaceType: | Int? | getName: | newValue | getType: | Int? | isInout: | no |
|
||||||
|
| param_decls.swift:12:13:12:22 | s | getInterfaceType: | String | getName: | s | getType: | String | isInout: | yes |
|
||||||
|
| param_decls.swift:13:13:13:22 | s | getInterfaceType: | String | getName: | s | getType: | String | isInout: | yes |
|
||||||
|
| param_decls.swift:14:26:14:26 | $0 | getInterfaceType: | Int | getName: | $0 | getType: | Int | isInout: | no |
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// generated by codegen/codegen.py
|
||||||
|
import codeql.swift.elements
|
||||||
|
import TestUtils
|
||||||
|
|
||||||
|
from ParamDecl x, Type getInterfaceType, string getName, Type getType, string isInout
|
||||||
|
where
|
||||||
|
toBeTested(x) and
|
||||||
|
not x.isUnknown() and
|
||||||
|
getInterfaceType = x.getInterfaceType() and
|
||||||
|
getName = x.getName() and
|
||||||
|
getType = x.getType() and
|
||||||
|
if x.isInout() then isInout = "yes" else isInout = "no"
|
||||||
|
select x, "getInterfaceType:", getInterfaceType, "getName:", getName, "getType:", getType,
|
||||||
|
"isInout:", isInout
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// generated by codegen/codegen.py
|
||||||
|
import codeql.swift.elements
|
||||||
|
import TestUtils
|
||||||
|
|
||||||
|
from ParamDecl x, int index
|
||||||
|
where toBeTested(x) and not x.isUnknown()
|
||||||
|
select x, index, x.getAccessorDecl(index)
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// generated by codegen/codegen.py
|
||||||
|
import codeql.swift.elements
|
||||||
|
import TestUtils
|
||||||
|
|
||||||
|
from ParamDecl x
|
||||||
|
where toBeTested(x) and not x.isUnknown()
|
||||||
|
select x, x.getAttachedPropertyWrapperType()
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// generated by codegen/codegen.py
|
||||||
|
import codeql.swift.elements
|
||||||
|
import TestUtils
|
||||||
|
|
||||||
|
from ParamDecl x
|
||||||
|
where toBeTested(x) and not x.isUnknown()
|
||||||
|
select x, x.getParentInitializer()
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// generated by codegen/codegen.py
|
||||||
|
import codeql.swift.elements
|
||||||
|
import TestUtils
|
||||||
|
|
||||||
|
from ParamDecl x
|
||||||
|
where toBeTested(x) and not x.isUnknown()
|
||||||
|
select x, x.getParentPattern()
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
func foo(_: Int, x y: inout Double) {}
|
||||||
|
func bar(_: Int, x y: inout Double) {}
|
||||||
|
|
||||||
|
struct S {
|
||||||
|
subscript(x: Int, y: Int) -> Int? {
|
||||||
|
get { nil }
|
||||||
|
set {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func closures() {
|
||||||
|
let x = {(s: inout String) -> String in s}
|
||||||
|
let y = {(s: inout String) -> String in ""}
|
||||||
|
let z : (Int) -> Int = { $0 + 1 }
|
||||||
|
}
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
// generated by codegen/codegen.py
|
|
||||||
|
|
||||||
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
|
|
||||||
will appear and this file will be deleted
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
| module<Foo> | getName: | module<Foo> | getCanonicalType: | module<Foo> | getModule: | file://:0:0:0:0 | Foo |
|
||||||
|
| module<default_module_name> | getName: | module<default_module_name> | getCanonicalType: | module<default_module_name> | getModule: | file://:0:0:0:0 | default_module_name |
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// generated by codegen/codegen.py
|
||||||
|
import codeql.swift.elements
|
||||||
|
import TestUtils
|
||||||
|
|
||||||
|
from ModuleType x, string getName, Type getCanonicalType, ModuleDecl getModule
|
||||||
|
where
|
||||||
|
toBeTested(x) and
|
||||||
|
not x.isUnknown() and
|
||||||
|
getName = x.getName() and
|
||||||
|
getCanonicalType = x.getCanonicalType() and
|
||||||
|
getModule = x.getModule()
|
||||||
|
select x, "getName:", getName, "getCanonicalType:", getCanonicalType, "getModule:", getModule
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
//codeql-extractor-options: -module-name Foo
|
||||||
Reference in New Issue
Block a user