C++: Introduce ElementBase class

By extending this class, a class can define its own `getLocation`
predicate without participating in the dispatch hierarchy of
`getLocation` as defined on `Element`. Classes wanting to override their
location previously had to define `getURL` or `hasLocationInfo` instead
and rely on these predicates not being defined on future versions of
`Element`.
This commit is contained in:
Jonas Jensen
2018-08-29 13:21:10 +02:00
parent ea26ac8c22
commit 8b9e4e347c
7 changed files with 38 additions and 12 deletions

View File

@@ -54,7 +54,11 @@ class SuppressionComment extends CppStyleComment {
/**
* The scope of an alert suppression comment.
*/
class SuppressionScope extends SuppressionComment {
class SuppressionScope extends ElementBase {
SuppressionScope() {
this instanceof SuppressionComment
}
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
@@ -63,7 +67,7 @@ class SuppressionScope extends SuppressionComment {
* [LGTM locations](https://lgtm.com/help/ql/locations).
*/
predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
this.covers(filepath, startline, startcolumn, endline, endcolumn)
this.(SuppressionComment).covers(filepath, startline, startcolumn, endline, endcolumn)
}
}

View File

@@ -46,8 +46,9 @@ predicate masterVde(VariableDeclarationEntry master, VariableDeclarationEntry vd
exists(VariableDeclarationEntry previous | previousVde(previous, vde) and masterVde(master, previous))
}
class VariableDeclarationGroup extends VariableDeclarationEntry {
class VariableDeclarationGroup extends ElementBase {
VariableDeclarationGroup() {
this instanceof VariableDeclarationEntry and
not previousVde(_, this)
}
Class getClass() {
@@ -62,7 +63,7 @@ class VariableDeclarationGroup extends VariableDeclarationEntry {
masterVde(this, last) and
this instanceof VariableDeclarationGroup and
not previousVde(last, _) and
this.getLocation() = lstart and
exists(VariableDeclarationEntry vde | vde=this and vde instanceof VariableDeclarationEntry and vde.getLocation() = lstart) and
last.getLocation() = lend and
lstart.hasLocationInfo(path, startline, startcol, _, _) and
lend.hasLocationInfo(path, _, _, endline, endcol)
@@ -78,7 +79,7 @@ class VariableDeclarationGroup extends VariableDeclarationEntry {
name = vde.getName()))
+ " fields here"
else
result = "declaration of " + this.getVariable().getName()
result = "declaration of " + this.(VariableDeclarationEntry).getVariable().getName()
}
}

View File

@@ -46,16 +46,29 @@ Element mkElement(@element e) {
}
/**
* A C/C++ element. This class is the base class for all C/C++
* elements, such as functions, classes, expressions, and so on.
* A C/C++ element with no member predicates other than `toString`. Not for
* general use. This class does not define a location, so classes wanting to
* change their location without affecting other classes can extend
* `ElementBase` instead of `Element` to create a new rootdef for `getURL`,
* `getLocation`, or `hasLocationInfo`.
*/
class Element extends @element {
Element() {
class ElementBase extends @element {
ElementBase() {
this = resolveElement(_)
}
/** Gets a textual representation of this element. */
string toString() { none() }
}
/**
* A C/C++ element. This class is the base class for all C/C++
* elements, such as functions, classes, expressions, and so on.
*/
class Element extends ElementBase {
Element() {
this = resolveElement(_)
}
/** Gets the primary file where this element occurs. */
File getFile() { result = this.getLocation().getFile() }

View File

@@ -146,12 +146,12 @@ private predicate loopConditionAlwaysUponEntry(ControlFlowNode loop, Expr condit
/**
* An element that is convertible to `ControlFlowNode`. This class is similar
* to `ControlFlowNode` except that is has no member predicates apart from
* those inherited from `Locatable`.
* `toString`.
*
* This class can be used as base class for classes that want to inherit the
* extent of `ControlFlowNode` without inheriting its public member predicates.
*/
class ControlFlowNodeBase extends Locatable, @cfgnode {
class ControlFlowNodeBase extends ElementBase, @cfgnode {
}
predicate truecond_base(ControlFlowNodeBase n1, ControlFlowNodeBase n2) {

View File

@@ -88,7 +88,7 @@ class DefOrUse extends ControlFlowNodeBase {
// Uninstantiated templates are purely syntax, and only on instantiation
// will they be complete with information about types, conversions, call
// targets, etc.
not this.isFromUninstantiatedTemplate(_)
not this.(ControlFlowNode).isFromUninstantiatedTemplate(_)
}
/**

View File

@@ -70,6 +70,10 @@ class SsaDefinition extends ControlFlowNodeBase {
exists(StandardSSA x | x.phi_node(v, (BasicBlock)this))
}
Location getLocation() {
result = this.(ControlFlowNode).getLocation()
}
/** Holds if the SSA variable `(this, p)` is defined by parameter `p`. */
predicate definedByParameter(Parameter p) {
this = p.getFunction().getEntryPoint()

View File

@@ -113,6 +113,10 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
guard_defn(v, guard, this, branch)
}
Location getLocation() {
result = this.(ControlFlowNode).getLocation()
}
/** Whether this definition is from a parameter */
predicate definedByParameter(Parameter p) {
this = p.getFunction().getEntryPoint()