Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C++: Support arguments and instantiations of template template parameters #18360

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,358 changes: 2,358 additions & 0 deletions cpp/downgrades/ffa82fdef56ce4b818a5f046242775ee074cf6ae/old.dbscheme

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
description: Support template template parameter arguments and instantiations
compatibility: full
template_template_instantiation.rel: delete
template_template_argument.rel: delete
template_template_argument_value.rel: delete
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
category: feature
---
* A new class `TemplateTemplateParameterInstantiation` was introduced, which represents the instantiation of a template template parameter.
* A new predicate `getAnInstantiation` was added to the `TemplateTemplateParameter` class, which yields instantiations of template template parameters.
* The `getTemplateArgumentType` and `getTemplateArgumentValue` predicates of the `Declaration` class now also yield template arguments of template template parameters.
9 changes: 6 additions & 3 deletions cpp/ql/lib/semmle/code/cpp/Class.qll
Original file line number Diff line number Diff line change
Expand Up @@ -570,10 +570,13 @@ class Class extends UserType {
/**
* Holds if this class, struct or union is constructed from another class as
* a result of template instantiation. It originates either from a class
* template or from a class nested in a class template.
* template, a class nested in a class template, or a template template
* parameter.
*/
predicate isConstructedFrom(Class c) {
class_instantiation(underlyingElement(this), unresolveElement(c))
predicate isConstructedFrom(UserType t) {
class_instantiation(underlyingElement(this), unresolveElement(t))
or
template_template_instantiation(underlyingElement(this), unresolveElement(t))
}

/**
Expand Down
4 changes: 4 additions & 0 deletions cpp/ql/lib/semmle/code/cpp/Declaration.qll
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,8 @@ class Declaration extends Locatable, @declaration {
function_template_argument(underlyingElement(this), index, unresolveElement(result))
or
variable_template_argument(underlyingElement(this), index, unresolveElement(result))
or
template_template_argument(underlyingElement(this), index, unresolveElement(result))
}

private Expr getTemplateArgumentValue(int index) {
Expand All @@ -285,6 +287,8 @@ class Declaration extends Locatable, @declaration {
function_template_argument_value(underlyingElement(this), index, unresolveElement(result))
or
variable_template_argument_value(underlyingElement(this), index, unresolveElement(result))
or
template_template_argument_value(underlyingElement(this), index, unresolveElement(result))
}
}

Expand Down
44 changes: 44 additions & 0 deletions cpp/ql/lib/semmle/code/cpp/TemplateParameter.qll
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,21 @@ class TemplateTemplateParameter extends TypeTemplateParameter {
TemplateTemplateParameter() { usertypes(underlyingElement(this), _, 8) }

override string getAPrimaryQlClass() { result = "TemplateTemplateParameter" }

/**
* Gets a class instantiated from this template template parameter.
*
* For example for `Container<T>` in the following code, the results is
* `Container<Elem>`:
* ```
* template <template <typename T> class Container, class Elem>
* void foo(const Container<Elem> &value) { }
* ```
*/
Class getAnInstantiation() {
result.isConstructedFrom(this) and
exists(result.getATemplateArgument())
}
}

/**
Expand All @@ -90,3 +105,32 @@ class AutoType extends TypeTemplateParameter {

override Location getLocation() { result instanceof UnknownDefaultLocation }
}

/**
* A class that is an instantiation of a template template parameter. For example,
* in the following code there is a `Container<Elem>` instantiation:
* ```
* template <template <typename T> class Container, class Elem>
* void foo(const Container<Elem> &value) { }
* ```
* For the `Container` template itself, see `TemplateTemplateParameter`.
*/
class TemplateTemplateParameterInstantiation extends Class {
TemplateTemplateParameter ttp;

TemplateTemplateParameterInstantiation() { ttp.getAnInstantiation() = this }

override string getAPrimaryQlClass() { result = "TemplateTemplateParameterInstantiation" }

/**
* Gets the template template parameter from which this instantiation was instantiated.
*
* For example for `Container<Elem>` in the following code, the result is
* `Container<T>`:
* ```
* template <template <typename T> class Container, class Elem>
* void foo(const Container<Elem> &value) { }
* ```
*/
TemplateTemplateParameter getTemplate() { result = ttp }
}
15 changes: 15 additions & 0 deletions cpp/ql/lib/semmlecode.cpp.dbscheme
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,21 @@ variable_template_argument_value(
int arg_value: @expr ref
);

template_template_instantiation(
unique int to: @usertype ref,
int from: @usertype ref
);
template_template_argument(
int type_id: @usertype ref,
int index: int ref,
int arg_type: @type ref
);
template_template_argument_value(
int type_id: @usertype ref,
int index: int ref,
int arg_value: @expr ref
);

routinetypes(
unique int id: @routinetype,
int return_type: @type ref
Expand Down
Loading
Loading