Skip to content

Commit

Permalink
C++: Introduce a new base class for template parameters
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jketema committed Dec 17, 2024
1 parent 7ab06fc commit f8535ee
Show file tree
Hide file tree
Showing 14 changed files with 51 additions and 23 deletions.
4 changes: 4 additions & 0 deletions cpp/ql/lib/change-notes/2024-12-17-template-parameter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
--
category: deprecated
---
* The `TemplateParameter` class, representing C++ type template parameters has been deprecated. Use `TypeTemplateParameter` instead.
6 changes: 3 additions & 3 deletions cpp/ql/lib/semmle/code/cpp/Class.qll
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
}

Expand Down Expand Up @@ -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)))
}

Expand Down Expand Up @@ -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))
}
}
Expand Down
2 changes: 1 addition & 1 deletion cpp/ql/lib/semmle/code/cpp/Declaration.qll
Original file line number Diff line number Diff line change
Expand Up @@ -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()
)
}
Expand Down
2 changes: 1 addition & 1 deletion cpp/ql/lib/semmle/code/cpp/Print.qll
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ""
}

/**
Expand Down
34 changes: 29 additions & 5 deletions cpp/ql/lib/semmle/code/cpp/Type.qll
Original file line number Diff line number Diff line change
Expand Up @@ -1666,6 +1666,30 @@ class RoutineType extends Type, @routinetype {
}
}

/**
* A C++ template parameter.
*
* In the example below, `T` and `I` are template parameters:
* ```
* template <class T, int I>
* class C { };
* ```
*/
abstract class TemplateParameterBase extends Locatable {
TemplateParameterBase() {
usertypes(underlyingElement(this), _, 7) or usertypes(underlyingElement(this), _, 8)
}

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

/**
* A C++ `typename` (or `class`) template parameter.
*
* DEPRECATED: Use `TypeTemplateParameter` instead.
*/
deprecated class TemplateParameter = TypeTemplateParameter;

/**
* A C++ `typename` (or `class`) template parameter.
*
Expand All @@ -1675,12 +1699,12 @@ class RoutineType extends Type, @routinetype {
* class C { };
* ```
*/
class TemplateParameter extends UserType {
TemplateParameter() {
class TypeTemplateParameter extends UserType, TemplateParameterBase {
TypeTemplateParameter() {
usertypes(underlyingElement(this), _, 7) or usertypes(underlyingElement(this), _, 8)
}

override string getAPrimaryQlClass() { result = "TemplateParameter" }
override string getAPrimaryQlClass() { result = "TypeTemplateParameter" }

override predicate involvesTemplateParameter() { any() }
}
Expand All @@ -1695,7 +1719,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" }
Expand All @@ -1707,7 +1731,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" }
Expand Down
2 changes: 1 addition & 1 deletion cpp/ql/lib/semmle/code/cpp/commons/Dependency.qll
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand Down
4 changes: 2 additions & 2 deletions cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
6 changes: 3 additions & 3 deletions cpp/ql/lib/semmle/code/cpp/internal/QualifiedName.qll
Original file line number Diff line number Diff line change
Expand Up @@ -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()
)
}
Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion cpp/ql/src/Best Practices/Unused Entities/UnusedLocals.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
}

Expand Down
2 changes: 1 addition & 1 deletion cpp/ql/src/Likely Bugs/ReturnConstTypeCommon.qll
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions cpp/ql/test/library-tests/declaration/declaration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ union MyUnion0 {
// Typedef
typedef MyClass0 *MyClassPtr;

// TemplateClass, TemplateParameter (UserType)
// TemplateClass, TypeTemplateParameter (UserType)

template <typename T>
class myTemplateClass
Expand Down Expand Up @@ -113,7 +113,7 @@ class MyClass1 {
// Typedef
typedef MyClass1 *MyClassPtr;

// TemplateClass, TemplateParameter (UserType)
// TemplateClass, TypeTemplateParameter (UserType)

template <typename T>
class myTemplateClass
Expand Down
2 changes: 1 addition & 1 deletion cpp/ql/test/library-tests/proxy_class/locations.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
Expand Down

0 comments on commit f8535ee

Please sign in to comment.