Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cpp/ql/src/semmle/code/cpp/Declaration.qll
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ abstract class Declaration extends Locatable, @declaration {
* To test whether this declaration has a particular name in the global
* namespace, use `hasGlobalName`.
*/
string getName() { result = underlyingElement(this).(Q::Declaration).getName() }
abstract string getName();

/** Holds if this declaration has the given name. */
predicate hasName(string name) { name = this.getName() }
Expand Down
5 changes: 5 additions & 0 deletions cpp/ql/src/semmle/code/cpp/Enum.qll
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ class EnumConstant extends Declaration, @enumconstant {
result = this.getDeclaringEnum().getDeclaringType()
}

/**
* Gets the name of this enumerator.
*/
override string getName() { enumconstants(underlyingElement(this),_,_,_,result,_) }

/**
* Gets the value that this enumerator is initialized to, as a
* string. This can be a value explicitly given to the enumerator, or an
Expand Down
5 changes: 5 additions & 0 deletions cpp/ql/src/semmle/code/cpp/FriendDecl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ class FriendDecl extends Declaration, @frienddecl {
/** Gets the location of this friend declaration. */
override Location getLocation() { frienddecls(underlyingElement(this),_,_,result) }

/** Gets a descriptive string for this friend declaration. */
override string getName() {
result = this.getDeclaringClass().getName() + "'s friend"
}

/**
* Friend declarations do not have specifiers. It makes no difference
* whether they are declared in a public, protected or private section of
Expand Down
2 changes: 2 additions & 0 deletions cpp/ql/src/semmle/code/cpp/Function.qll
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ private import semmle.code.cpp.internal.ResolveClass
* in more detail in `Declaration.qll`.
*/
class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
override string getName() { functions(underlyingElement(this),result,_) }

/**
* DEPRECATED: Use `getIdentityString(Declaration)` from `semmle.code.cpp.Print` instead.
* Gets the full signature of this function, including return type, parameter
Expand Down
3 changes: 3 additions & 0 deletions cpp/ql/src/semmle/code/cpp/ObjectiveC.qll
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ deprecated class FinallyBlock extends Block {
deprecated class Property extends Declaration {
Property() { none() }

/** Gets the name of this property. */
override string getName() { none() }

/**
* Gets nothing (provided for compatibility with Declaration).
*
Expand Down
55 changes: 44 additions & 11 deletions cpp/ql/src/semmle/code/cpp/Parameter.qll
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import semmle.code.cpp.Location
import semmle.code.cpp.Declaration
private import semmle.code.cpp.internal.ResolveClass
private import semmle.code.cpp.internal.QualifiedName as Q

/**
* A C/C++ function parameter or catch block parameter.
Expand All @@ -14,6 +13,26 @@ private import semmle.code.cpp.internal.QualifiedName as Q
* have multiple declarations.
*/
class Parameter extends LocalScopeVariable, @parameter {

/**
* Gets the canonical name, or names, of this parameter.
*
* The canonical names are the first non-empty category from the
* following list:
* 1. The name given to the parameter at the function's definition or
* (for catch block parameters) at the catch block.
* 2. A name given to the parameter at a function declaration.
* 3. The name "p#i" where i is the index of the parameter.
*/
override string getName() {
exists (VariableDeclarationEntry vde
| vde = getANamedDeclarationEntry() and result = vde.getName()
| vde.isDefinition() or not getANamedDeclarationEntry().isDefinition())
or
(not exists(getANamedDeclarationEntry()) and
result = "p#" + this.getIndex().toString())
}

/**
* Gets the name of this parameter, including it's type.
*
Expand All @@ -34,6 +53,27 @@ class Parameter extends LocalScopeVariable, @parameter {
else result = typeString + nameString))
}

private VariableDeclarationEntry getANamedDeclarationEntry() {
result = getAnEffectiveDeclarationEntry() and result.getName() != ""
}

/**
* Gets a declaration entry corresponding to this declaration.
*
* This predicate is the same as getADeclarationEntry(), except that for
* parameters of instantiated function templates, gives the declaration
* entry of the prototype instantiation of the parameter (as
* non-prototype instantiations don't have declaration entries of their
* own).
*/
private VariableDeclarationEntry getAnEffectiveDeclarationEntry() {
if getFunction().isConstructedFrom(_)
then exists (Function prototypeInstantiation
| prototypeInstantiation.getParameter(getIndex()) = result.getVariable() and
getFunction().isConstructedFrom(prototypeInstantiation))
else result = getADeclarationEntry()
}

/**
* Gets the name of this parameter in the given block (which should be
* the body of a function with which the parameter is associated).
Expand All @@ -55,9 +95,7 @@ class Parameter extends LocalScopeVariable, @parameter {
* In other words, this predicate holds precisely when the result of
* `getName()` is not "p#i" (where `i` is the index of the parameter).
*/
predicate isNamed() {
exists(underlyingElement(this).(Q::Parameter).getANamedDeclarationEntry())
}
predicate isNamed() { exists(getANamedDeclarationEntry()) }

/**
* Gets the function to which this parameter belongs, if it is a function
Expand Down Expand Up @@ -97,13 +135,8 @@ class Parameter extends LocalScopeVariable, @parameter {
* of the declaration locations.
*/
override Location getLocation() {
exists(VariableDeclarationEntry vde |
vde = underlyingElement(this).(Q::Parameter).getAnEffectiveDeclarationEntry() and
result = vde.getLocation()
|
vde.isDefinition()
or
not underlyingElement(this).(Q::Parameter).getAnEffectiveDeclarationEntry().isDefinition()
exists(VariableDeclarationEntry vde | vde = getAnEffectiveDeclarationEntry() and result = vde.getLocation() |
vde.isDefinition() or not getAnEffectiveDeclarationEntry().isDefinition()
)
}
}
7 changes: 4 additions & 3 deletions cpp/ql/src/semmle/code/cpp/UserType.qll
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ private import semmle.code.cpp.internal.ResolveClass
* `Enum`, and `TypedefType`.
*/
class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @usertype {
override string getName() {
result = Declaration.super.getName()
}
/**
* Gets the name of this type.
*/
override string getName() { usertypes(underlyingElement(this),result,_) }

/**
* Gets the simple name of this type, without any template parameters. For example
Expand Down
9 changes: 9 additions & 0 deletions cpp/ql/src/semmle/code/cpp/Variable.qll
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ class Variable extends Declaration, @variable {
/** Holds if this variable is `volatile`. */
predicate isVolatile() { this.getType().isVolatile() }

/** Gets the name of this variable. */
override string getName() { none() }

/** Gets the type of this variable. */
Type getType() { none() }

Expand Down Expand Up @@ -294,6 +297,8 @@ deprecated class StackVariable extends Variable {
* A local variable can be declared by a `DeclStmt` or a `ConditionDeclExpr`.
*/
class LocalVariable extends LocalScopeVariable, @localvariable {
override string getName() { localvariables(underlyingElement(this),_,result) }

override Type getType() { localvariables(underlyingElement(this),unresolveElement(result),_) }

override Function getFunction() {
Expand All @@ -306,6 +311,8 @@ class LocalVariable extends LocalScopeVariable, @localvariable {
* A C/C++ variable which has global scope or namespace scope.
*/
class GlobalOrNamespaceVariable extends Variable, @globalvariable {
override string getName() { globalvariables(underlyingElement(this),_,result) }

override Type getType() { globalvariables(underlyingElement(this),unresolveElement(result),_) }

override Element getEnclosingElement() { none() }
Expand Down Expand Up @@ -353,6 +360,8 @@ class MemberVariable extends Variable, @membervariable {
/** Holds if this member is public. */
predicate isPublic() { this.hasSpecifier("public") }

override string getName() { membervariables(underlyingElement(this),_,result) }

override Type getType() {
if (strictcount(this.getAType()) = 1) then (
result = this.getAType()
Expand Down
68 changes: 2 additions & 66 deletions cpp/ql/src/semmle/code/cpp/internal/QualifiedName.qll
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
private import semmle.code.cpp.Declaration as D
/**
* INTERNAL: Do not use. Provides classes and predicates for getting names of
* declarations, especially qualified names. Import this library `private` and
Expand Down Expand Up @@ -37,8 +38,7 @@ abstract class Declaration extends @declaration {
string toString() { result = "QualifiedName Declaration" }

/** Gets the name of this declaration. */
cached
abstract string getName();
final string getName() { result = this.(D::Declaration).getName() }

string getTypeQualifierWithoutArgs() {
exists(UserType declaringType |
Expand Down Expand Up @@ -133,8 +133,6 @@ abstract class Declaration extends @declaration {
}

class Variable extends Declaration, @variable {
override string getName() { none() }

VariableDeclarationEntry getADeclarationEntry() { result.getDeclaration() = this }
}

Expand All @@ -147,7 +145,6 @@ class TemplateVariable extends Variable {
class LocalScopeVariable extends Variable, @localscopevariable { }

class LocalVariable extends LocalScopeVariable, @localvariable {
override string getName() { localvariables(this, _, result) }
}

/**
Expand All @@ -174,75 +171,20 @@ class Parameter extends LocalScopeVariable, @parameter {
int index;

Parameter() { params(this, function, index, _) }

/**
* Gets the canonical name, or names, of this parameter.
*
* The canonical names are the first non-empty category from the
* following list:
* 1. The name given to the parameter at the function's definition or
* (for catch block parameters) at the catch block.
* 2. A name given to the parameter at a function declaration.
* 3. The name "p#i" where i is the index of the parameter.
*/
override string getName() {
exists(VariableDeclarationEntry vde |
vde = getANamedDeclarationEntry() and result = vde.getName()
|
vde.isDefinition() or not getANamedDeclarationEntry().isDefinition()
)
or
not exists(getANamedDeclarationEntry()) and
result = "p#" + index.toString()
}

VariableDeclarationEntry getANamedDeclarationEntry() {
result = getAnEffectiveDeclarationEntry() and exists(result.getName())
}

/**
* Gets a declaration entry corresponding to this declaration.
*
* This predicate is the same as getADeclarationEntry(), except that for
* parameters of instantiated function templates, gives the declaration
* entry of the prototype instantiation of the parameter (as
* non-prototype instantiations don't have declaration entries of their
* own).
*/
VariableDeclarationEntry getAnEffectiveDeclarationEntry() {
if function.(Function).isConstructedFrom(_)
then
exists(Function prototypeInstantiation |
prototypeInstantiation.getParameter(index) = result.getVariable() and
function.(Function).isConstructedFrom(prototypeInstantiation)
)
else result = getADeclarationEntry()
}
}

class GlobalOrNamespaceVariable extends Variable, @globalvariable {
override string getName() { globalvariables(this, _, result) }
}

class MemberVariable extends Variable, @membervariable {
MemberVariable() { this.isMember() }

override string getName() { membervariables(this, _, result) }
}

// Unlike the usual `EnumConstant`, this one doesn't have a
// `getDeclaringType()`. This simplifies the recursive computation of type
// qualifier names since it can assume that any declaration with a
// `getDeclaringType()` should use that type in its type qualifier name.
class EnumConstant extends Declaration, @enumconstant {
override string getName() { enumconstants(this, _, _, _, result, _) }

UserType getDeclaringEnum() { enumconstants(this, result, _, _, _, _) }
}

class Function extends Declaration, @function {
override string getName() { functions(this, result, _) }

predicate isConstructedFrom(Function f) { function_instantiation(this, f) }

Parameter getParameter(int n) { params(result, this, n, _) }
Expand All @@ -258,8 +200,6 @@ class TemplateFunction extends Function {
}

class UserType extends Declaration, @usertype {
override string getName() { result = getUserTypeNameWithArgs(this) }

predicate isLocal() { enclosingfunction(this, _) }

// Gets a member of this class, if it's a class.
Expand Down Expand Up @@ -291,10 +231,6 @@ class TemplateClass extends UserType {
}

class FriendDecl extends Declaration, @frienddecl {
override string getName() {
result = getUserTypeNameWithArgs(this.getDeclaringClass()) + "'s friend"
}

UserType getDeclaringClass() { frienddecls(this, result, _, _) }
}

Expand Down