@@ -479,15 +479,87 @@ private Function getFullyTemplatedFunction(Function f) {
479479 )
480480}
481481
482+ /** Prefixes `const` to `s` if `t` is const, or returns `s` otherwise. */
483+ bindingset [ s, t]
484+ private string withConst ( string s , Type t ) {
485+ if t .isConst ( ) then result = "const " + s else result = s
486+ }
487+
488+ /** Prefixes `volatile` to `s` if `t` is const, or returns `s` otherwise. */
489+ bindingset [ s, t]
490+ private string withVolatile ( string s , Type t ) {
491+ if t .isVolatile ( ) then result = "volatile " + s else result = s
492+ }
493+
494+ /**
495+ * Returns `s` prefixed with appropriate specifiers from `t`, or `s` if `t` has
496+ * no relevant specifiers.
497+ */
498+ bindingset [ s, t]
499+ private string withSpecifiers ( string s , Type t ) {
500+ // An `int` that is both const and volatile will be printed as
501+ // `const volatile int` to match the behavior of `Type.getName` which
502+ // is generated by the extractor.
503+ result = withConst ( withVolatile ( s , t ) , t )
504+ }
505+
506+ /**
507+ * Gets the string version of `t`, after resolving typedefs. The boolean `needsSpace` is `true`
508+ * if a space should be appended before concatenating any additional symbols
509+ * (such as `*` or `&`) when recursively constructing the type name.
510+ */
511+ private string getTypeName ( Type t , boolean needsSpace ) {
512+ // We don't care about template instantiations since we always base models
513+ // on the uninstantiated templates
514+ not t .isFromTemplateInstantiation ( _) and
515+ (
516+ exists ( DerivedType dt , string s , boolean needsSpace0 |
517+ dt = t and s = withSpecifiers ( getTypeName ( dt .getBaseType ( ) , needsSpace0 ) , dt )
518+ |
519+ dt instanceof ReferenceType and
520+ not dt instanceof RValueReferenceType and
521+ needsSpace = false and
522+ ( if needsSpace0 = true then result = s + " &" else result = s + "&" )
523+ or
524+ dt instanceof RValueReferenceType and
525+ needsSpace = false and
526+ ( if needsSpace0 = true then result = s + " &&" else result = s + "&&" )
527+ or
528+ dt instanceof PointerType and
529+ needsSpace = false and
530+ ( if needsSpace0 = true then result = s + " *" else result = s + "*" )
531+ or
532+ not dt instanceof ReferenceType and
533+ not dt instanceof PointerType and
534+ result = s and
535+ needsSpace = needsSpace0
536+ )
537+ or
538+ not t instanceof DerivedType and
539+ not t instanceof TypedefType and
540+ result = t .getName ( ) and
541+ ( if result .matches ( [ "%*" , "%&" , "%]" ] ) then needsSpace = false else needsSpace = true )
542+ )
543+ or
544+ result = getTypeName ( t .( TypedefType ) .getBaseType ( ) , needsSpace )
545+ }
546+
482547/**
483- * Gets the type name of the `n`'th parameter of `f` without any template
484- * arguments.
548+ * Gets a type name for the `n`'th parameter of `f` without any template
549+ * arguments. The result may be a string representing a type for which the
550+ * typedefs have been resolved.
485551 */
486552bindingset [ f]
487553pragma [ inline_late]
488554string getParameterTypeWithoutTemplateArguments ( Function f , int n ) {
489- exists ( string s , string base , string specifiers |
490- s = f .getParameter ( n ) .getType ( ) .getName ( ) and
555+ exists ( string s , string base , string specifiers , Type t |
556+ t = f .getParameter ( n ) .getType ( ) and
557+ // The name of the string can either be the possibly typedefed name
558+ // or an alternative name where typedefs has been resolved.
559+ // `getTypeName(t, _)` is almost equal to `t.resolveTypedefs().getName()`,
560+ // except that `t.resolveTypedefs()` doesn't have a result when the
561+ // resulting type doesn't appear in the database.
562+ s = [ t .getName ( ) , getTypeName ( t , _) ] and
491563 parseAngles ( s , base , _, specifiers ) and
492564 result = base + specifiers
493565 )
@@ -902,18 +974,19 @@ private Element interpretElement0(
902974 )
903975}
904976
905- /** Gets the source/sink/summary element corresponding to the supplied parameters. */
906- Element interpretElement (
907- string namespace , string type , boolean subtypes , string name , string signature , string ext
908- ) {
909- elementSpec ( namespace , type , subtypes , name , signature , ext ) and
910- exists ( Element e | e = interpretElement0 ( namespace , type , subtypes , name , signature ) |
911- ext = "" and result = e
912- )
913- }
914-
915977cached
916978private module Cached {
979+ /** Gets the source/sink/summary element corresponding to the supplied parameters. */
980+ cached
981+ Element interpretElement (
982+ string namespace , string type , boolean subtypes , string name , string signature , string ext
983+ ) {
984+ elementSpec ( namespace , type , subtypes , name , signature , ext ) and
985+ exists ( Element e | e = interpretElement0 ( namespace , type , subtypes , name , signature ) |
986+ ext = "" and result = e
987+ )
988+ }
989+
917990 /**
918991 * Holds if `node` is specified as a source with the given kind in a CSV flow
919992 * model.
0 commit comments