mirror of
https://github.com/github/codeql.git
synced 2026-04-22 15:25:18 +02:00
C++: Also resolve typedefs when parsing MaD model parameter names.
This commit is contained in:
@@ -479,15 +479,87 @@ private Function getFullyTemplatedFunction(Function f) {
|
||||
)
|
||||
}
|
||||
|
||||
/** Prefixes `const` to `s` if `t` is const, or returns `s` otherwise. */
|
||||
bindingset[s, t]
|
||||
private string withConst(string s, Type t) {
|
||||
if t.isConst() then result = "const " + s else result = s
|
||||
}
|
||||
|
||||
/** Prefixes `volatile` to `s` if `t` is const, or returns `s` otherwise. */
|
||||
bindingset[s, t]
|
||||
private string withVolatile(string s, Type t) {
|
||||
if t.isVolatile() then result = "volatile " + s else result = s
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type name of the `n`'th parameter of `f` without any template
|
||||
* arguments.
|
||||
* Returns `s` prefixed with appropriate speciiers from `t`, or `s` if `t` has
|
||||
* no relevant specifiers.
|
||||
*/
|
||||
bindingset[s, t]
|
||||
private string withSpecifiers(string s, Type t) {
|
||||
// An `int` that is both const and volatile will be printed as
|
||||
// `const volatile int` to match the behavior of `Type.getName` which
|
||||
// is generated by the extractor.
|
||||
result = withConst(withVolatile(s, t), t)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string version of `t`. The boolean `needsSpace` is `true`
|
||||
* if a space should be appended before concatenating any additional symbols
|
||||
* (such as `*` or `&`) when recursively constructing the type name.
|
||||
*/
|
||||
private string getTypeName(Type t, boolean needsSpace) {
|
||||
// We don't care about template instantiations since we always base models
|
||||
// on the uninstantiated templates
|
||||
not t.isFromTemplateInstantiation(_) and
|
||||
(
|
||||
exists(DerivedType dt, string s, boolean needsSpace0 |
|
||||
dt = t and s = withSpecifiers(getTypeName(dt.getBaseType(), needsSpace0), dt)
|
||||
|
|
||||
dt instanceof ReferenceType and
|
||||
not dt instanceof RValueReferenceType and
|
||||
needsSpace = false and
|
||||
(if needsSpace0 = true then result = s + " &" else result = s + "&")
|
||||
or
|
||||
dt instanceof RValueReferenceType and
|
||||
needsSpace = false and
|
||||
(if needsSpace0 = true then result = s + " &&" else result = s + "&&")
|
||||
or
|
||||
dt instanceof PointerType and
|
||||
needsSpace = false and
|
||||
(if needsSpace0 = true then result = s + " *" else result = s + "*")
|
||||
or
|
||||
not dt instanceof ReferenceType and
|
||||
not dt instanceof PointerType and
|
||||
result = s and
|
||||
needsSpace = needsSpace0
|
||||
)
|
||||
or
|
||||
not t instanceof DerivedType and
|
||||
not t instanceof TypedefType and
|
||||
result = t.getName() and
|
||||
(if result.matches(["%*", "%&", "%]"]) then needsSpace = false else needsSpace = true)
|
||||
)
|
||||
or
|
||||
result = getTypeName(t.(TypedefType).getBaseType(), needsSpace)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a type name for the `n`'th parameter of `f` without any template
|
||||
* arguments. The result may be a string representing a type for which the
|
||||
* typedefs have been resolved.
|
||||
*/
|
||||
bindingset[f]
|
||||
pragma[inline_late]
|
||||
string getParameterTypeWithoutTemplateArguments(Function f, int n) {
|
||||
exists(string s, string base, string specifiers |
|
||||
s = f.getParameter(n).getType().getName() and
|
||||
exists(string s, string base, string specifiers, Type t |
|
||||
t = f.getParameter(n).getType() and
|
||||
// The name of the string can either be the possibly typedefed name
|
||||
// or an alternartive name where typedefs has been resolved.
|
||||
// `getTypeName(t, _)` is almost equal to `t.resolveTypedefs().getName()`,
|
||||
// except that `t.resolveTypedefs()` doesn't have a result when the
|
||||
// resulting type doesn't appear in the database.
|
||||
s = [t.getName(), getTypeName(t, _)] and
|
||||
parseAngles(s, base, _, specifiers) and
|
||||
result = base + specifiers
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user