mirror of
https://github.com/github/codeql.git
synced 2026-04-25 00:35:20 +02:00
C++: Introduce a new base class for template parameters
This will enable us to support non-type template parameters, which we currently do not support, and error template parameters, which might become relevant in the `build-mode: none` context.
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* A new class `TemplateParameterBase` was introduced, which represents C++ non-type template parameters, type template parameters, and template template parameters.
|
||||
4
cpp/ql/lib/change-notes/2024-12-17-template-parameter.md
Normal file
4
cpp/ql/lib/change-notes/2024-12-17-template-parameter.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* The `TemplateParameter` class, representing C++ type template parameters has been deprecated. Use `TypeTemplateParameter` instead.
|
||||
@@ -952,7 +952,7 @@ class ClassTemplateSpecialization extends Class {
|
||||
result.getNamespace() = this.getNamespace() and
|
||||
// It is distinguished by the fact that each of its template arguments
|
||||
// is a distinct template parameter.
|
||||
count(TemplateParameter tp | tp = result.getATemplateArgument()) =
|
||||
count(TemplateParameterBase tp | tp = result.getATemplateArgument()) =
|
||||
count(int i | exists(result.getTemplateArgument(i)))
|
||||
}
|
||||
|
||||
@@ -1006,7 +1006,7 @@ private predicate isPartialClassTemplateSpecialization(Class c) {
|
||||
*/
|
||||
|
||||
exists(Type ta | ta = c.getATemplateArgument() and ta.involvesTemplateParameter()) and
|
||||
count(TemplateParameter tp | tp = c.getATemplateArgument()) !=
|
||||
count(TemplateParameterBase tp | tp = c.getATemplateArgument()) !=
|
||||
count(int i | exists(c.getTemplateArgument(i)))
|
||||
}
|
||||
|
||||
@@ -1091,7 +1091,7 @@ class ProxyClass extends UserType {
|
||||
override Location getLocation() { result = this.getTemplateParameter().getDefinitionLocation() }
|
||||
|
||||
/** Gets the template parameter for which this is the proxy class. */
|
||||
TemplateParameter getTemplateParameter() {
|
||||
TypeTemplateParameter getTemplateParameter() {
|
||||
is_proxy_class_for(underlyingElement(this), unresolveElement(result))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ class Declaration extends Locatable, @declaration {
|
||||
this instanceof Parameter or
|
||||
this instanceof ProxyClass or
|
||||
this instanceof LocalVariable or
|
||||
this instanceof TemplateParameter or
|
||||
this instanceof TypeTemplateParameter or
|
||||
this.(UserType).isLocal()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ private string getScopePrefix(Declaration decl) {
|
||||
result = "(" + type.getEnclosingFunction().(DumpFunction).getIdentityString() + ")::"
|
||||
)
|
||||
or
|
||||
decl instanceof TemplateParameter and result = ""
|
||||
decl instanceof TypeTemplateParameter and result = ""
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1666,6 +1666,28 @@ class RoutineType extends Type, @routinetype {
|
||||
}
|
||||
}
|
||||
|
||||
abstract private class TemplateParameterImpl extends Locatable {
|
||||
override string getAPrimaryQlClass() { result = "TemplateParameterImpl" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ template parameter.
|
||||
*
|
||||
* In the example below, `T` and `I` are template parameters:
|
||||
* ```
|
||||
* template <class T, int I>
|
||||
* class C { };
|
||||
* ```
|
||||
*/
|
||||
final class TemplateParameterBase = TemplateParameterImpl;
|
||||
|
||||
/**
|
||||
* A C++ `typename` (or `class`) template parameter.
|
||||
*
|
||||
* DEPRECATED: Use `TypeTemplateParameter` instead.
|
||||
*/
|
||||
deprecated class TemplateParameter = TypeTemplateParameter;
|
||||
|
||||
/**
|
||||
* A C++ `typename` (or `class`) template parameter.
|
||||
*
|
||||
@@ -1675,12 +1697,12 @@ class RoutineType extends Type, @routinetype {
|
||||
* class C { };
|
||||
* ```
|
||||
*/
|
||||
class TemplateParameter extends UserType {
|
||||
TemplateParameter() {
|
||||
class TypeTemplateParameter extends UserType, TemplateParameterImpl {
|
||||
TypeTemplateParameter() {
|
||||
usertypes(underlyingElement(this), _, 7) or usertypes(underlyingElement(this), _, 8)
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "TemplateParameter" }
|
||||
override string getAPrimaryQlClass() { result = "TypeTemplateParameter" }
|
||||
|
||||
override predicate involvesTemplateParameter() { any() }
|
||||
}
|
||||
@@ -1695,7 +1717,7 @@ class TemplateParameter extends UserType {
|
||||
* void foo(const Container<Elem> &value) { }
|
||||
* ```
|
||||
*/
|
||||
class TemplateTemplateParameter extends TemplateParameter {
|
||||
class TemplateTemplateParameter extends TypeTemplateParameter {
|
||||
TemplateTemplateParameter() { usertypes(underlyingElement(this), _, 8) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "TemplateTemplateParameter" }
|
||||
@@ -1707,7 +1729,7 @@ class TemplateTemplateParameter extends TemplateParameter {
|
||||
* auto val = some_typed_expr();
|
||||
* ```
|
||||
*/
|
||||
class AutoType extends TemplateParameter {
|
||||
class AutoType extends TypeTemplateParameter {
|
||||
AutoType() { usertypes(underlyingElement(this), "auto", 7) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AutoType" }
|
||||
|
||||
@@ -66,7 +66,7 @@ class Symbol extends DependsSource {
|
||||
not this.(TypeDeclarationEntry).getType() instanceof LocalEnum and
|
||||
not this.(TypeDeclarationEntry).getType() instanceof LocalClass and
|
||||
not this.(TypeDeclarationEntry).getType() instanceof LocalTypedefType and
|
||||
not this.(TypeDeclarationEntry).getType() instanceof TemplateParameter
|
||||
not this.(TypeDeclarationEntry).getType() instanceof TypeTemplateParameter
|
||||
or
|
||||
this instanceof NamespaceDeclarationEntry
|
||||
)
|
||||
|
||||
@@ -504,7 +504,7 @@ private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remain
|
||||
result = getParameterTypeWithoutTemplateArguments(templateFunction, n)
|
||||
)
|
||||
or
|
||||
exists(string mid, TemplateParameter tp, Function templateFunction |
|
||||
exists(string mid, TypeTemplateParameter tp, Function templateFunction |
|
||||
mid = getTypeNameWithoutFunctionTemplates(f, n, remaining + 1) and
|
||||
templateFunction = getFullyTemplatedFunction(f) and
|
||||
tp = templateFunction.getTemplateArgument(remaining) and
|
||||
@@ -529,7 +529,7 @@ private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining
|
||||
remaining = 0 and
|
||||
result = getTypeNameWithoutFunctionTemplates(f, n, 0)
|
||||
or
|
||||
exists(string mid, TemplateParameter tp, Class template |
|
||||
exists(string mid, TypeTemplateParameter tp, Class template |
|
||||
mid = getTypeNameWithoutClassTemplates(f, n, remaining + 1) and
|
||||
isClassConstructedFrom(f.getDeclaringType(), template) and
|
||||
tp = template.getTemplateArgument(remaining) and
|
||||
|
||||
@@ -130,7 +130,7 @@ class Declaration extends @declaration {
|
||||
this instanceof Parameter or
|
||||
this instanceof ProxyClass or
|
||||
this instanceof LocalVariable or
|
||||
this instanceof TemplateParameter or
|
||||
this instanceof TypeTemplateParameter or
|
||||
this.(UserType).isLocal()
|
||||
)
|
||||
}
|
||||
@@ -226,8 +226,8 @@ class ProxyClass extends UserType {
|
||||
ProxyClass() { usertypes(this, _, 9) }
|
||||
}
|
||||
|
||||
class TemplateParameter extends UserType {
|
||||
TemplateParameter() { usertypes(this, _, 7) or usertypes(this, _, 8) }
|
||||
class TypeTemplateParameter extends UserType {
|
||||
TypeTemplateParameter() { usertypes(this, _, 7) or usertypes(this, _, 8) }
|
||||
}
|
||||
|
||||
class TemplateClass extends UserType {
|
||||
|
||||
@@ -26,7 +26,7 @@ import cpp
|
||||
*/
|
||||
class TemplateDependentType extends Type {
|
||||
TemplateDependentType() {
|
||||
this instanceof TemplateParameter
|
||||
this instanceof TypeTemplateParameter
|
||||
or
|
||||
exists(TemplateDependentType t |
|
||||
this.refersToDirectly(t) and
|
||||
|
||||
@@ -49,7 +49,7 @@ predicate nanTest(EqualityOperation cmp) {
|
||||
pointlessSelfComparison(cmp) and
|
||||
exists(Type t | t = cmp.getLeftOperand().getUnspecifiedType() |
|
||||
t instanceof FloatingPointType or
|
||||
t instanceof TemplateParameter
|
||||
t instanceof TypeTemplateParameter
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import cpp
|
||||
|
||||
private predicate mightHaveConstMethods(Type t) {
|
||||
t instanceof Class or
|
||||
t instanceof TemplateParameter
|
||||
t instanceof TypeTemplateParameter
|
||||
}
|
||||
|
||||
predicate hasSuperfluousConstReturn(Function f) {
|
||||
|
||||
@@ -26,7 +26,7 @@ predicate functionsMissingReturnStmt(Function f, ControlFlowNode blame) {
|
||||
exists(Type returnType |
|
||||
returnType = f.getUnspecifiedType() and
|
||||
not returnType instanceof VoidType and
|
||||
not returnType instanceof TemplateParameter
|
||||
not returnType instanceof TypeTemplateParameter
|
||||
) and
|
||||
exists(ReturnStmt s |
|
||||
f.getAPredecessor() = s and
|
||||
|
||||
@@ -915,7 +915,7 @@ VacuousDestructorCall.cpp:
|
||||
# 2| [TemplateFunction,TopLevelFunction] void CallDestructor<T>(T, T*)
|
||||
# 2| <params>:
|
||||
# 2| getParameter(0): [Parameter] x
|
||||
# 2| Type = [TemplateParameter] T
|
||||
# 2| Type = [TypeTemplateParameter] T
|
||||
# 2| getParameter(1): [Parameter] y
|
||||
# 2| Type = [PointerType] T *
|
||||
# 2| getEntryPoint(): [BlockStmt] { ... }
|
||||
@@ -927,7 +927,7 @@ VacuousDestructorCall.cpp:
|
||||
# 3| Type = [UnknownType] unknown
|
||||
# 3| ValueCategory = prvalue
|
||||
# 3| getChild(-1): [VariableAccess] x
|
||||
# 3| Type = [TemplateParameter] T
|
||||
# 3| Type = [TypeTemplateParameter] T
|
||||
# 3| ValueCategory = lvalue
|
||||
# 4| getStmt(1): [ExprStmt] ExprStmt
|
||||
# 4| getExpr(): [ExprCall] call to expression
|
||||
|
||||
@@ -56,7 +56,7 @@ union MyUnion0 {
|
||||
// Typedef
|
||||
typedef MyClass0 *MyClassPtr;
|
||||
|
||||
// TemplateClass, TemplateParameter (UserType)
|
||||
// TemplateClass, TypeTemplateParameter (UserType)
|
||||
|
||||
template <typename T>
|
||||
class myTemplateClass
|
||||
@@ -113,7 +113,7 @@ public:
|
||||
// Typedef
|
||||
typedef MyClass1 *MyClassPtr;
|
||||
|
||||
// TemplateClass, TemplateParameter (UserType)
|
||||
// TemplateClass, TypeTemplateParameter (UserType)
|
||||
|
||||
template <typename T>
|
||||
class myTemplateClass
|
||||
|
||||
@@ -9016,9 +9016,9 @@ ir.cpp:
|
||||
# 704| [TemplateFunction,TopLevelFunction] T min<T>(T, T)
|
||||
# 704| <params>:
|
||||
# 704| getParameter(0): [Parameter] x
|
||||
# 704| Type = [TemplateParameter] T
|
||||
# 704| Type = [TypeTemplateParameter] T
|
||||
# 704| getParameter(1): [Parameter] y
|
||||
# 704| Type = [TemplateParameter] T
|
||||
# 704| Type = [TypeTemplateParameter] T
|
||||
# 704| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 705| getStmt(0): [ReturnStmt] return ...
|
||||
# 705| getExpr(): [ConditionalExpr] ... ? ... : ...
|
||||
@@ -9028,16 +9028,16 @@ ir.cpp:
|
||||
# 705| Type = [UnknownType] unknown
|
||||
# 705| ValueCategory = prvalue
|
||||
# 705| getLesserOperand(): [VariableAccess] x
|
||||
# 705| Type = [TemplateParameter] T
|
||||
# 705| Type = [TypeTemplateParameter] T
|
||||
# 705| ValueCategory = lvalue
|
||||
# 705| getGreaterOperand(): [VariableAccess] y
|
||||
# 705| Type = [TemplateParameter] T
|
||||
# 705| Type = [TypeTemplateParameter] T
|
||||
# 705| ValueCategory = lvalue
|
||||
# 705| getThen(): [VariableAccess] x
|
||||
# 705| Type = [TemplateParameter] T
|
||||
# 705| Type = [TypeTemplateParameter] T
|
||||
# 705| ValueCategory = lvalue
|
||||
# 705| getElse(): [VariableAccess] y
|
||||
# 705| Type = [TemplateParameter] T
|
||||
# 705| Type = [TypeTemplateParameter] T
|
||||
# 705| ValueCategory = lvalue
|
||||
# 705| getCondition().getFullyConverted(): [CStyleCast] (bool)...
|
||||
# 705| Conversion = [BoolConversion] conversion to bool
|
||||
@@ -9095,24 +9095,24 @@ ir.cpp:
|
||||
# 715| [MemberFunction,TemplateFunction] T Outer<T>::Func<U, V>(U, V)
|
||||
# 715| <params>:
|
||||
# 715| getParameter(0): [Parameter] x
|
||||
# 715| Type = [TemplateParameter] U
|
||||
# 715| Type = [TypeTemplateParameter] U
|
||||
# 715| getParameter(1): [Parameter] y
|
||||
# 715| Type = [TemplateParameter] V
|
||||
# 715| Type = [TypeTemplateParameter] V
|
||||
# 715| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 716| getStmt(0): [ReturnStmt] return ...
|
||||
# 716| getExpr(): [Literal] 0
|
||||
# 716| Type = [TemplateParameter] T
|
||||
# 716| Type = [TypeTemplateParameter] T
|
||||
# 716| Value = [Literal] 0
|
||||
# 716| ValueCategory = prvalue
|
||||
# 716| getExpr().getFullyConverted(): [TemporaryObjectExpr] temporary object
|
||||
# 716| Type = [TemplateParameter] T
|
||||
# 716| Type = [TypeTemplateParameter] T
|
||||
# 716| ValueCategory = prvalue(load)
|
||||
# 715| [MemberFunction,TemplateFunction] long Outer<long>::Func<U, V>(U, V)
|
||||
# 715| <params>:
|
||||
# 715| getParameter(0): [Parameter] x
|
||||
# 715| Type = [TemplateParameter] U
|
||||
# 715| Type = [TypeTemplateParameter] U
|
||||
# 715| getParameter(1): [Parameter] y
|
||||
# 715| Type = [TemplateParameter] V
|
||||
# 715| Type = [TypeTemplateParameter] V
|
||||
# 715| [FunctionTemplateInstantiation,MemberFunction] long Outer<long>::Func<void*, char>(void*, char)
|
||||
# 715| <params>:
|
||||
# 715| getParameter(0): [Parameter] x
|
||||
@@ -12559,7 +12559,7 @@ ir.cpp:
|
||||
# 1109| [Constructor] void std::vector<T>::vector(T)
|
||||
# 1109| <params>:
|
||||
# 1109| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
# 1109| Type = [TemplateParameter] T
|
||||
# 1109| Type = [TypeTemplateParameter] T
|
||||
# 1109| [Constructor] void std::vector<char>::vector(char)
|
||||
# 1109| <params>:
|
||||
# 1109| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
@@ -12601,15 +12601,15 @@ ir.cpp:
|
||||
# 1120| [Operator,TemplateFunction,TopLevelFunction] bool std::operator==<T>(iterator, iterator)
|
||||
# 1120| <params>:
|
||||
# 1120| getParameter(0): [Parameter] left
|
||||
# 1120| Type = [TemplateParameter] iterator
|
||||
# 1120| Type = [TypeTemplateParameter] iterator
|
||||
# 1120| getParameter(1): [Parameter] right
|
||||
# 1120| Type = [TemplateParameter] iterator
|
||||
# 1120| Type = [TypeTemplateParameter] iterator
|
||||
# 1122| [Operator,TemplateFunction,TopLevelFunction] bool std::operator!=<T>(iterator, iterator)
|
||||
# 1122| <params>:
|
||||
# 1122| getParameter(0): [Parameter] left
|
||||
# 1122| Type = [TemplateParameter] iterator
|
||||
# 1122| Type = [TypeTemplateParameter] iterator
|
||||
# 1122| getParameter(1): [Parameter] right
|
||||
# 1122| Type = [TemplateParameter] iterator
|
||||
# 1122| Type = [TypeTemplateParameter] iterator
|
||||
# 1126| [TopLevelFunction] void RangeBasedFor(std::vector<int> const&)
|
||||
# 1126| <params>:
|
||||
# 1126| getParameter(0): [Parameter] v
|
||||
@@ -14129,11 +14129,11 @@ ir.cpp:
|
||||
# 1375| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 1376| getStmt(0): [ReturnStmt] return ...
|
||||
# 1376| getExpr(): [Literal] 0
|
||||
# 1376| Type = [TemplateParameter] T
|
||||
# 1376| Type = [TypeTemplateParameter] T
|
||||
# 1376| Value = [Literal] 0
|
||||
# 1376| ValueCategory = prvalue
|
||||
# 1376| getExpr().getFullyConverted(): [TemporaryObjectExpr] temporary object
|
||||
# 1376| Type = [TemplateParameter] T
|
||||
# 1376| Type = [TypeTemplateParameter] T
|
||||
# 1376| ValueCategory = prvalue(load)
|
||||
# 1375| [FunctionTemplateInstantiation,TopLevelFunction] copy_constructor defaultConstruct<copy_constructor>()
|
||||
# 1375| <params>:
|
||||
@@ -14223,7 +14223,7 @@ ir.cpp:
|
||||
# 1409| [TemplateFunction,TopLevelFunction] void acceptValue<T>(T)
|
||||
# 1409| <params>:
|
||||
# 1409| getParameter(0): [Parameter] v
|
||||
# 1409| Type = [TemplateParameter] T
|
||||
# 1409| Type = [TypeTemplateParameter] T
|
||||
# 1409| [FunctionTemplateInstantiation,TopLevelFunction] void acceptValue<copy_constructor>(copy_constructor)
|
||||
# 1409| <params>:
|
||||
# 1409| getParameter(0): [Parameter] v
|
||||
@@ -20584,7 +20584,7 @@ ir.cpp:
|
||||
# 2256| Type = [LValueReferenceType] T &
|
||||
# 2256| ValueCategory = prvalue(load)
|
||||
# 2256| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 2256| Type = [TemplateParameter] T
|
||||
# 2256| Type = [TypeTemplateParameter] T
|
||||
# 2256| ValueCategory = lvalue
|
||||
# 2256| [FunctionTemplateInstantiation,TopLevelFunction] int& vacuous_destructor_call::get<int>(int&)
|
||||
# 2256| <params>:
|
||||
@@ -20648,7 +20648,7 @@ ir.cpp:
|
||||
# 2260| Type = [LValueReferenceType] T &
|
||||
# 2260| ValueCategory = prvalue(load)
|
||||
# 2260| getArgument(0).getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 2260| Type = [TemplateParameter] T
|
||||
# 2260| Type = [TypeTemplateParameter] T
|
||||
# 2260| ValueCategory = lvalue
|
||||
# 2261| getStmt(1): [ReturnStmt] return ...
|
||||
# 2259| [FunctionTemplateInstantiation,TopLevelFunction] void vacuous_destructor_call::call_destructor<int>(int&)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
| proxy_class.cpp:1:8:1:11 | Base | Struct |
|
||||
| proxy_class.cpp:3:20:3:20 | T | ProxyClass |
|
||||
| proxy_class.cpp:3:20:3:20 | T | TemplateParameter |
|
||||
| proxy_class.cpp:3:20:3:20 | T | TypeTemplateParameter |
|
||||
| proxy_class.cpp:4:8:4:14 | Derived<Base> | Struct |
|
||||
|
||||
@@ -3,7 +3,7 @@ import cpp
|
||||
string clazz(Declaration d) {
|
||||
d instanceof ProxyClass and result = "ProxyClass"
|
||||
or
|
||||
d instanceof TemplateParameter and result = "TemplateParameter"
|
||||
d instanceof TypeTemplateParameter and result = "TypeTemplateParameter"
|
||||
or
|
||||
d instanceof Struct and result = "Struct"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user