Merge pull request #18353 from jketema/template-parameters-2

C++: Handle `sizeof...` for types and template template parameters
This commit is contained in:
Jeroen Ketema
2024-12-20 19:15:50 +01:00
committed by GitHub
11 changed files with 9435 additions and 11 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Allow sizeof pack in sizeof_bind
compatibility: full

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* New classes `SizeofPackExprOperator` and `SizeofPackTypeOperator` were introduced, which represent the C++ `sizeof...` operator taking an expression and a type argument, respectively.

View File

@@ -1056,6 +1056,8 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
or
expr.(SizeofExprOperator).getExprOperand() = ele and pred = "getExprOperand()"
or
expr.(SizeofPackExprOperator).getExprOperand() = ele and pred = "getExprOperand()"
or
expr.(StmtExpr).getStmt() = ele and pred = "getStmt()"
or
expr.(ThrowExpr).getExpr() = ele and pred = "getExpr()"

View File

@@ -684,7 +684,8 @@ class TypeidOperator extends Expr, @type_id {
}
/**
* A C++11 `sizeof...` expression which determines the size of a template parameter pack.
* A C++11 `sizeof...` expression which determines the size of a template
* parameter pack.
*
* This expression only appears in templates themselves - in any actual
* instantiations, "sizeof...(x)" will be replaced by its integer value.
@@ -694,15 +695,56 @@ class TypeidOperator extends Expr, @type_id {
* ```
*/
class SizeofPackOperator extends Expr, @sizeof_pack {
override string toString() { result = "sizeof...(...)" }
override string getAPrimaryQlClass() { result = "SizeofPackOperator" }
override predicate mayBeImpure() { none() }
override predicate mayBeGloballyImpure() { none() }
}
/**
* A C++11 `sizeof...` expression which determines the size of a template
* parameter pack and whose operand is an expression.
*
* This expression only appears in templates themselves - in any actual
* instantiations, "sizeof...(x)" will be replaced by its integer value.
* ```
* template < typename... T >
* int count ( T &&... t ) { return sizeof... ( t ); }
* ```
*/
class SizeofPackExprOperator extends SizeofPackOperator {
SizeofPackExprOperator() { exists(this.getChild(0)) }
override string getAPrimaryQlClass() { result = "SizeofPackExprOperator" }
/** Gets the contained expression. */
Expr getExprOperand() { result = this.getChild(0) }
override string toString() { result = "sizeof...(<expr>)" }
}
/**
* A C++11 `sizeof...` expression which determines the size of a template
* parameter pack and whose operand is an type name or a template template
* parameter.
*
* This expression only appears in templates themselves - in any actual
* instantiations, "sizeof...(x)" will be replaced by its integer value.
* ```
* template < typename... T >
* int count ( T &&... t ) { return sizeof... ( T ); }
* ```
*/
class SizeofPackTypeOperator extends SizeofPackOperator {
SizeofPackTypeOperator() { sizeof_bind(underlyingElement(this), _) }
override string getAPrimaryQlClass() { result = "SizeofPackTypeOperator" }
/** Gets the contained type. */
Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) }
override string toString() { result = "sizeof...(" + this.getTypeOperand().getName() + ")" }
}
/**
* A C/C++ sizeof expression.
*/

View File

@@ -1994,10 +1994,10 @@ uuidof_bind(
int type_id: @type ref
);
@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof | @datasizeof;
@sizeof_or_alignof = @runtime_sizeof | @runtime_alignof | @datasizeof | @sizeof_pack;
sizeof_bind(
unique int expr: @runtime_sizeof_or_alignof ref,
unique int expr: @sizeof_or_alignof ref,
int type_id: @type ref
);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Allow sizeof pack in sizeof_bind
compatibility: backwards

View File

@@ -3,15 +3,15 @@
| choose_second | 27 | 1 | { ... } | 28 | return ... |
| choose_second | 28 | 2 | return ... | 25 | choose_second |
| count_args_1 prototype instantiation | 11 | 1 | { ... } | 12 | return ... |
| count_args_1 prototype instantiation | 12 | 2 | return ... | 12 | sizeof...(...) |
| count_args_1 prototype instantiation | 12 | 3 | sizeof...(...) | 11 | count_args_1 |
| count_args_1 prototype instantiation | 12 | 2 | return ... | 12 | sizeof...(Args) |
| count_args_1 prototype instantiation | 12 | 3 | sizeof...(Args) | 11 | count_args_1 |
| count_args_1<> | 11 | 1 | { ... } | 12 | return ... |
| count_args_1<> | 12 | 2 | return ... | 12 | 0 |
| count_args_1<> | 12 | 3 | 0 | 11 | count_args_1 |
| count_args_2 prototype instantiation | 15 | 1 | { ... } | 16 | return ... |
| count_args_2 prototype instantiation | 16 | 2 | return ... | 16 | a |
| count_args_2 prototype instantiation | 16 | 3 | a | 16 | sizeof...(...) |
| count_args_2 prototype instantiation | 16 | 4 | sizeof...(...) | 15 | count_args_2 |
| count_args_2 prototype instantiation | 16 | 3 | a | 16 | sizeof...(<expr>) |
| count_args_2 prototype instantiation | 16 | 4 | sizeof...(<expr>) | 15 | count_args_2 |
| count_args_2<int,double> | 15 | 1 | { ... } | 16 | return ... |
| count_args_2<int,double> | 16 | 2 | return ... | 16 | 2 |
| count_args_2<int,double> | 16 | 3 | 2 | 15 | count_args_2 |