11import semmle.code.cpp.Location
22import semmle.code.cpp.Declaration
33private import semmle.code.cpp.internal.ResolveClass
4- private import semmle.code.cpp.internal.QualifiedName as Q
54
65/**
76 * A C/C++ function parameter or catch block parameter.
@@ -14,6 +13,26 @@ private import semmle.code.cpp.internal.QualifiedName as Q
1413 * have multiple declarations.
1514 */
1615class Parameter extends LocalScopeVariable , @parameter {
16+
17+ /**
18+ * Gets the canonical name, or names, of this parameter.
19+ *
20+ * The canonical names are the first non-empty category from the
21+ * following list:
22+ * 1. The name given to the parameter at the function's definition or
23+ * (for catch block parameters) at the catch block.
24+ * 2. A name given to the parameter at a function declaration.
25+ * 3. The name "p#i" where i is the index of the parameter.
26+ */
27+ override string getName ( ) {
28+ exists ( VariableDeclarationEntry vde
29+ | vde = getANamedDeclarationEntry ( ) and result = vde .getName ( )
30+ | vde .isDefinition ( ) or not getANamedDeclarationEntry ( ) .isDefinition ( ) )
31+ or
32+ ( not exists ( getANamedDeclarationEntry ( ) ) and
33+ result = "p#" + this .getIndex ( ) .toString ( ) )
34+ }
35+
1736 /**
1837 * Gets the name of this parameter, including it's type.
1938 *
@@ -34,6 +53,27 @@ class Parameter extends LocalScopeVariable, @parameter {
3453 else result = typeString + nameString ) )
3554 }
3655
56+ private VariableDeclarationEntry getANamedDeclarationEntry ( ) {
57+ result = getAnEffectiveDeclarationEntry ( ) and result .getName ( ) != ""
58+ }
59+
60+ /**
61+ * Gets a declaration entry corresponding to this declaration.
62+ *
63+ * This predicate is the same as getADeclarationEntry(), except that for
64+ * parameters of instantiated function templates, gives the declaration
65+ * entry of the prototype instantiation of the parameter (as
66+ * non-prototype instantiations don't have declaration entries of their
67+ * own).
68+ */
69+ private VariableDeclarationEntry getAnEffectiveDeclarationEntry ( ) {
70+ if getFunction ( ) .isConstructedFrom ( _)
71+ then exists ( Function prototypeInstantiation
72+ | prototypeInstantiation .getParameter ( getIndex ( ) ) = result .getVariable ( ) and
73+ getFunction ( ) .isConstructedFrom ( prototypeInstantiation ) )
74+ else result = getADeclarationEntry ( )
75+ }
76+
3777 /**
3878 * Gets the name of this parameter in the given block (which should be
3979 * the body of a function with which the parameter is associated).
@@ -55,9 +95,7 @@ class Parameter extends LocalScopeVariable, @parameter {
5595 * In other words, this predicate holds precisely when the result of
5696 * `getName()` is not "p#i" (where `i` is the index of the parameter).
5797 */
58- predicate isNamed ( ) {
59- exists ( underlyingElement ( this ) .( Q:: Parameter ) .getANamedDeclarationEntry ( ) )
60- }
98+ predicate isNamed ( ) { exists ( getANamedDeclarationEntry ( ) ) }
6199
62100 /**
63101 * Gets the function to which this parameter belongs, if it is a function
@@ -97,13 +135,8 @@ class Parameter extends LocalScopeVariable, @parameter {
97135 * of the declaration locations.
98136 */
99137 override Location getLocation ( ) {
100- exists ( VariableDeclarationEntry vde |
101- vde = underlyingElement ( this ) .( Q:: Parameter ) .getAnEffectiveDeclarationEntry ( ) and
102- result = vde .getLocation ( )
103- |
104- vde .isDefinition ( )
105- or
106- not underlyingElement ( this ) .( Q:: Parameter ) .getAnEffectiveDeclarationEntry ( ) .isDefinition ( )
138+ exists ( VariableDeclarationEntry vde | vde = getAnEffectiveDeclarationEntry ( ) and result = vde .getLocation ( ) |
139+ vde .isDefinition ( ) or not getAnEffectiveDeclarationEntry ( ) .isDefinition ( )
107140 )
108141 }
109142}
0 commit comments