@@ -435,12 +435,17 @@ private predicate elementSpec(
435435}
436436
437437/** Gets the fully templated version of `f`. */
438- private Function getFullyTemplatedMemberFunction ( Function f ) {
438+ private Function getFullyTemplatedFunction ( Function f ) {
439439 not f .isFromUninstantiatedTemplate ( _) and
440- exists ( Class c , Class templateClass , int i |
441- c .isConstructedFrom ( templateClass ) and
442- f = c .getAMember ( i ) and
443- result = templateClass .getCanonicalMember ( i )
440+ (
441+ exists ( Class c , Class templateClass , int i |
442+ c .isConstructedFrom ( templateClass ) and
443+ f = c .getAMember ( i ) and
444+ result = templateClass .getCanonicalMember ( i )
445+ )
446+ or
447+ not exists ( f .getDeclaringType ( ) ) and
448+ f .isConstructedFrom ( result )
444449 )
445450}
446451
@@ -464,14 +469,14 @@ string getParameterTypeWithoutTemplateArguments(Function f, int n) {
464469 */
465470private string getTypeNameWithoutFunctionTemplates ( Function f , int n , int remaining ) {
466471 exists ( Function templateFunction |
467- templateFunction = getFullyTemplatedMemberFunction ( f ) and
472+ templateFunction = getFullyTemplatedFunction ( f ) and
468473 remaining = templateFunction .getNumberOfTemplateArguments ( ) and
469474 result = getParameterTypeWithoutTemplateArguments ( templateFunction , n )
470475 )
471476 or
472477 exists ( string mid , TemplateParameter tp , Function templateFunction |
473478 mid = getTypeNameWithoutFunctionTemplates ( f , n , remaining + 1 ) and
474- templateFunction = getFullyTemplatedMemberFunction ( f ) and
479+ templateFunction = getFullyTemplatedFunction ( f ) and
475480 tp = templateFunction .getTemplateArgument ( remaining ) and
476481 result = mid .replaceAll ( tp .getName ( ) , "func:" + remaining .toString ( ) )
477482 )
@@ -482,12 +487,18 @@ private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remain
482487 * with `class:N` (where `N` is the index of the template).
483488 */
484489private string getTypeNameWithoutClassTemplates ( Function f , int n , int remaining ) {
490+ // If there is a declaring type then we start by expanding the function templates
485491 exists ( Class template |
486492 f .getDeclaringType ( ) .isConstructedFrom ( template ) and
487493 remaining = template .getNumberOfTemplateArguments ( ) and
488494 result = getTypeNameWithoutFunctionTemplates ( f , n , 0 )
489495 )
490496 or
497+ // If there is no declaring type we're done after expanding the function templates
498+ not exists ( f .getDeclaringType ( ) ) and
499+ remaining = 0 and
500+ result = getTypeNameWithoutFunctionTemplates ( f , n , 0 )
501+ or
491502 exists ( string mid , TemplateParameter tp , Class template |
492503 mid = getTypeNameWithoutClassTemplates ( f , n , remaining + 1 ) and
493504 f .getDeclaringType ( ) .isConstructedFrom ( template ) and
@@ -570,38 +581,6 @@ private string getSignatureWithoutFunctionTemplateNames(
570581 )
571582}
572583
573- private string paramsStringPart ( Function c , int i ) {
574- not c .isFromUninstantiatedTemplate ( _) and
575- (
576- i = - 1 and result = "(" and exists ( c )
577- or
578- exists ( int n , string p | getParameterTypeName ( c , n ) = p |
579- i = 2 * n and result = p
580- or
581- i = 2 * n - 1 and result = "," and n != 0
582- )
583- or
584- i = 2 * c .getNumberOfParameters ( ) and result = ")"
585- )
586- }
587-
588- /**
589- * Gets a parenthesized string containing all parameter types of this callable, separated by a comma.
590- *
591- * Returns the empty string if the callable has no parameters.
592- * Parameter types are represented by their type erasure.
593- */
594- cached
595- private string paramsString ( Function c ) {
596- result = concat ( int i | | paramsStringPart ( c , i ) order by i )
597- }
598-
599- bindingset [ func]
600- private predicate matchesSignature ( Function func , string signature ) {
601- signature = "" or
602- paramsString ( func ) = signature
603- }
604-
605584/**
606585 * Holds if `elementSpec(_, type, _, name, signature, _)` holds and
607586 * - `typeArgs` represents the named template parameters supplied to `type`, and
@@ -750,17 +729,17 @@ private predicate elementSpecWithArguments0(
750729
751730/**
752731 * Holds if `elementSpec(namespace, type, subtypes, name, signature, _)` and
753- * `method `'s signature matches `signature`.
732+ * `func `'s signature matches `signature`.
754733 *
755734 * `signature` may contain template parameter names that are bound by `type` and `name`.
756735 */
757736pragma [ nomagic]
758737private predicate elementSpecMatchesSignature (
759- Function method , string namespace , string type , boolean subtypes , string name , string signature
738+ Function func , string namespace , string type , boolean subtypes , string name , string signature
760739) {
761740 elementSpec ( namespace , pragma [ only_bind_into ] ( type ) , subtypes , pragma [ only_bind_into ] ( name ) ,
762741 pragma [ only_bind_into ] ( signature ) , _) and
763- signatureMatches ( method , signature , type , name , 0 )
742+ signatureMatches ( func , signature , type , name , 0 )
764743}
765744
766745/**
@@ -776,13 +755,22 @@ private predicate hasClassAndName(Class classWithMethod, Function method, string
776755 )
777756}
778757
758+ bindingset [ name]
759+ pragma [ inline_late]
760+ private predicate funcHasQualifiedName ( Function func , string namespace , string name ) {
761+ exists ( string nameWithoutArgs |
762+ parseAngles ( name , nameWithoutArgs , _, "" ) and
763+ func .hasQualifiedName ( namespace , nameWithoutArgs )
764+ )
765+ }
766+
779767/**
780768 * Holds if `namedClass` is in namespace `namespace` and has
781769 * name `type` (excluding any template parameters).
782770 */
783771bindingset [ type, namespace]
784772pragma [ inline_late]
785- private predicate hasQualifiedName ( Class namedClass , string namespace , string type ) {
773+ private predicate classHasQualifiedName ( Class namedClass , string namespace , string type ) {
786774 exists ( string typeWithoutArgs |
787775 parseAngles ( type , typeWithoutArgs , _, "" ) and
788776 namedClass .hasQualifiedName ( namespace , typeWithoutArgs )
@@ -804,15 +792,16 @@ private Element interpretElement0(
804792 string namespace , string type , boolean subtypes , string name , string signature
805793) {
806794 (
807- elementSpec ( namespace , type , subtypes , name , signature , _) and
808795 // Non-member functions
809- exists ( Function func |
810- func .hasQualifiedName ( namespace , name ) and
811- type = "" and
812- matchesSignature ( func , signature ) and
813- subtypes = false and
814- not exists ( func .getDeclaringType ( ) ) and
815- result = func
796+ elementSpec ( namespace , type , subtypes , name , signature , _) and
797+ subtypes = false and
798+ type = "" and
799+ (
800+ elementSpecMatchesSignature ( result , namespace , type , subtypes , name , signature )
801+ or
802+ signature = "" and
803+ elementSpec ( namespace , type , subtypes , name , "" , _) and
804+ funcHasQualifiedName ( result , namespace , name )
816805 )
817806 or
818807 // Member functions
@@ -825,7 +814,7 @@ private Element interpretElement0(
825814 elementSpec ( namespace , type , subtypes , name , "" , _) and
826815 hasClassAndName ( classWithMethod , result , name )
827816 ) and
828- hasQualifiedName ( namedClass , namespace , type ) and
817+ classHasQualifiedName ( namedClass , namespace , type ) and
829818 (
830819 // member declared in the named type or a subtype of it
831820 subtypes = true and
0 commit comments