@@ -479,15 +479,87 @@ private Function getFullyTemplatedFunction(Function f) {
479
479
)
480
480
}
481
481
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
+
482
547
/**
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.
485
551
*/
486
552
bindingset [ f]
487
553
pragma [ inline_late]
488
554
string 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
491
563
parseAngles ( s , base , _, specifiers ) and
492
564
result = base + specifiers
493
565
)
@@ -902,18 +974,19 @@ private Element interpretElement0(
902
974
)
903
975
}
904
976
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
-
915
977
cached
916
978
private 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
+
917
990
/**
918
991
* Holds if `node` is specified as a source with the given kind in a CSV flow
919
992
* model.
0 commit comments