Skip to content

Commit b73e154

Browse files
committed
C++: Use the new extensionals to map template functions and classes to their fully templated versions.
1 parent 5f54a86 commit b73e154

1 file changed

Lines changed: 66 additions & 2 deletions

File tree

cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,11 +277,43 @@ private predicate isClassConstructedFrom(Class c, Class templateClass) {
277277
}
278278

279279
/** Gets the fully templated version of `f`. */
280-
private Class getFullyTemplatedClass(Class c) {
280+
private Class getFullyTemplatedClassOld(Class c) {
281281
not c.isFromUninstantiatedTemplate(_) and
282282
isClassConstructedFrom(c, result)
283283
}
284284

285+
private TemplateClass getOriginalClassTemplate(TemplateClass tc) {
286+
result = tc.getOriginalTemplate()
287+
or
288+
not exists(tc.getOriginalTemplate()) and
289+
result = tc
290+
}
291+
292+
/** Gets the fully templated version of `f`. */
293+
private Class getFullyTemplatedClassNew(Class c) {
294+
not c.isFromUninstantiatedTemplate(_) and
295+
exists(Class mid |
296+
c.isConstructedFrom(mid)
297+
or
298+
not c.isConstructedFrom(_) and c = mid
299+
|
300+
result = getOriginalClassTemplate(mid)
301+
or
302+
not mid instanceof TemplateClass and mid = result
303+
)
304+
}
305+
306+
private Class getFullyTemplatedClass(Class c) {
307+
// The `Class::getOriginalTemplate` predicate was introduced in CodeQL
308+
// version 2.25.6 and the upgrade script leaves the
309+
// `class_template_generated_from` extensionals empty if the database
310+
// was generated with an older extractor. So we use the old implementation
311+
// if the `class_template_generated_from` extensional is empty.
312+
if class_template_generated_from(_, _)
313+
then result = getFullyTemplatedClassNew(c)
314+
else result = getFullyTemplatedClassOld(c)
315+
}
316+
285317
/**
286318
* Holds if `f` is an instantiation of a function template `templateFunc`, or
287319
* holds with `f = templateFunc` if `f` is not an instantiation of any function
@@ -298,7 +330,7 @@ private predicate isFunctionConstructedFrom(Function f, Function templateFunc) {
298330
}
299331

300332
/** Gets the fully templated version of `f`. */
301-
Function getFullyTemplatedFunction(Function f) {
333+
private Function getFullyTemplatedFunctionOld(Function f) {
302334
not f.isFromUninstantiatedTemplate(_) and
303335
(
304336
exists(Class c, Class templateClass, int i |
@@ -312,6 +344,38 @@ Function getFullyTemplatedFunction(Function f) {
312344
)
313345
}
314346

347+
private TemplateFunction getOriginalFunctionTemplate(TemplateFunction tf) {
348+
result = tf.getOriginalTemplate()
349+
or
350+
not exists(tf.getOriginalTemplate()) and
351+
result = tf
352+
}
353+
354+
/** Gets the fully templated version of `f`. */
355+
private Function getFullyTemplatedFunctionNew(Function f) {
356+
not f.isFromUninstantiatedTemplate(_) and
357+
exists(Function mid |
358+
f.isConstructedFrom(mid)
359+
or
360+
not f.isConstructedFrom(_) and f = mid
361+
|
362+
result = getOriginalFunctionTemplate(mid)
363+
or
364+
not mid instanceof TemplateFunction and mid = result
365+
)
366+
}
367+
368+
private Function getFullyTemplatedFunction(Function f) {
369+
// The `Function::getOriginalTemplate` predicate was introduced in CodeQL
370+
// version 2.25.6 and the upgrade script leaves the
371+
// `function_template_generated_from` extensionals empty if the database
372+
// was generated with an older extractor. So we use the old implementation
373+
// if the `function_template_generated_from` extensional is empty.
374+
if function_template_generated_from(_, _)
375+
then result = getFullyTemplatedFunctionNew(f)
376+
else result = getFullyTemplatedFunctionOld(f)
377+
}
378+
315379
/** Prefixes `const` to `s` if `t` is const, or returns `s` otherwise. */
316380
bindingset[s, t]
317381
private string withConst(string s, Type t) {

0 commit comments

Comments
 (0)