Skip to content

Commit

Permalink
Merge pull request #18360 from github/jketema/template-parameters-3
Browse files Browse the repository at this point in the history
C++: Support arguments and instantiations of template template parameters
  • Loading branch information
jketema authored Jan 6, 2025
2 parents 2e1e46c + 0942945 commit 01a7a53
Show file tree
Hide file tree
Showing 12 changed files with 10,259 additions and 481 deletions.
2,358 changes: 2,358 additions & 0 deletions cpp/downgrades/4813509d85b45ae17421c036905199f7324cf228/old.dbscheme

Large diffs are not rendered by default.

2,343 changes: 2,343 additions & 0 deletions cpp/downgrades/4813509d85b45ae17421c036905199f7324cf228/semmlecode.cpp.dbscheme

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 instantiations of template template parameters.
* 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
41 changes: 41 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,18 @@ 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 result is
* `Container<Elem>`:
* ```
* template <template <typename T> class Container, class Elem>
* void foo(const Container<Elem> &value) { }
* ```
*/
Class getAnInstantiation() { result.isConstructedFrom(this) }
}

/**
Expand All @@ -90,3 +102,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(
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

0 comments on commit 01a7a53

Please sign in to comment.