diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll b/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll index 7beaabb1d97..f2d519e8bc9 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll @@ -87,31 +87,28 @@ class Expr extends StmtParent, @expr { /** Gets the value of this expression, if it is a constant. */ string getValue() { exists(@value v | values(v,result) and valuebind(v,underlyingElement(this))) } + /** Gets the value text of this expression that's in the database. */ + private string getDbValueText() { + exists(@value v | valuebind(v,underlyingElement(this)) and valuetext(v, result)) + } + /** - * Walk along the sequence of `getConversion()s` until we reach - * one with a valuetext, and then return that valuetext, if any. - * For example, in an invocation of `#define THREE (1+2)`, there - * will not be a valuetext for `1+2`, but the conversion `(1+2)` - * will have valuetext `THREE`. + * Gets the value text of `this`. If it doesn't have one, then instead + * gets the value text is `this`'s nearest compatible conversion, if any. */ - private string getValueTextFollowingConversions(Expr e) { - e = this.getConversion*() - and - e.getValue() = this.getValue() - and - (if exists(@value v | - valuebind(v,underlyingElement(e)) and - valuetext(v, _)) - then exists(@value v | - valuebind(v,underlyingElement(e)) and - valuetext(v, result)) - else result = this.getValueTextFollowingConversions(e.getConversion())) + private string getValueTextFollowingConversions() { + if exists(this.getDbValueText()) + then result = this.getDbValueText() + else exists(Expr e | + e = this.getConversion() and + e.getValue() = this.getValue() and + result = e.getValueTextFollowingConversions()) } /** Gets the source text for the value of this expression, if it is a constant. */ string getValueText() { - if exists(this.getValueTextFollowingConversions(this)) - then result = this.getValueTextFollowingConversions(this) + if exists(this.getValueTextFollowingConversions()) + then result = this.getValueTextFollowingConversions() else result = this.getValue() }