Skip to content

Commit 55a10d9

Browse files
authored
Merge pull request #10305 from MathiasVP/ql-workaround-for-missing-decl-entries
C++: Synthesize `DeclarationEntry`s for IR construction
2 parents b129c40 + 02c18e7 commit 55a10d9

File tree

9 files changed

+608
-104
lines changed

9 files changed

+608
-104
lines changed

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll

Lines changed: 9 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ private import TranslatedInitialization
1313
* Gets the `TranslatedDeclarationEntry` that represents the declaration
1414
* `entry`.
1515
*/
16-
TranslatedDeclarationEntry getTranslatedDeclarationEntry(DeclarationEntry entry) {
17-
result.getAst() = entry
16+
TranslatedDeclarationEntry getTranslatedDeclarationEntry(IRDeclarationEntry entry) {
17+
result.getIRDeclarationEntry() = entry
1818
}
1919

2020
/**
@@ -24,20 +24,22 @@ TranslatedDeclarationEntry getTranslatedDeclarationEntry(DeclarationEntry entry)
2424
* functions do not have a `TranslatedDeclarationEntry`.
2525
*/
2626
abstract class TranslatedDeclarationEntry extends TranslatedElement, TTranslatedDeclarationEntry {
27-
DeclarationEntry entry;
27+
IRDeclarationEntry entry;
2828

2929
TranslatedDeclarationEntry() { this = TTranslatedDeclarationEntry(entry) }
3030

3131
final override Function getFunction() {
3232
exists(DeclStmt stmt |
33-
stmt.getADeclarationEntry() = entry and
33+
stmt = entry.getStmt() and
3434
result = stmt.getEnclosingFunction()
3535
)
3636
}
3737

38+
IRDeclarationEntry getIRDeclarationEntry() { result = entry }
39+
3840
final override string toString() { result = entry.toString() }
3941

40-
final override Locatable getAst() { result = entry }
42+
final override Locatable getAst() { result = entry.getAst() }
4143

4244
/** DEPRECATED: Alias for getAst */
4345
deprecated override Locatable getAST() { result = getAst() }
@@ -216,7 +218,7 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
216218
*/
217219
class TranslatedStaticLocalVariableInitialization extends TranslatedElement,
218220
TranslatedLocalVariableDeclaration, TTranslatedStaticLocalVariableInitialization {
219-
VariableDeclarationEntry entry;
221+
IRVariableDeclarationEntry entry;
220222
StaticLocalVariable var;
221223

222224
TranslatedStaticLocalVariableInitialization() {
@@ -226,7 +228,7 @@ class TranslatedStaticLocalVariableInitialization extends TranslatedElement,
226228

227229
final override string toString() { result = "init: " + entry.toString() }
228230

229-
final override Locatable getAst() { result = entry }
231+
final override Locatable getAst() { result = entry.getAst() }
230232

231233
/** DEPRECATED: Alias for getAst */
232234
deprecated override Locatable getAST() { result = getAst() }
@@ -236,40 +238,6 @@ class TranslatedStaticLocalVariableInitialization extends TranslatedElement,
236238
final override Function getFunction() { result = var.getFunction() }
237239
}
238240

239-
/**
240-
* Gets the `TranslatedRangeBasedForVariableDeclaration` that represents the declaration of
241-
* `var`.
242-
*/
243-
TranslatedRangeBasedForVariableDeclaration getTranslatedRangeBasedForVariableDeclaration(
244-
LocalVariable var
245-
) {
246-
result.getVariable() = var
247-
}
248-
249-
/**
250-
* Represents the IR translation of a compiler-generated variable in a range-based `for` loop.
251-
*/
252-
class TranslatedRangeBasedForVariableDeclaration extends TranslatedLocalVariableDeclaration,
253-
TTranslatedRangeBasedForVariableDeclaration {
254-
RangeBasedForStmt forStmt;
255-
LocalVariable var;
256-
257-
TranslatedRangeBasedForVariableDeclaration() {
258-
this = TTranslatedRangeBasedForVariableDeclaration(forStmt, var)
259-
}
260-
261-
override string toString() { result = var.toString() }
262-
263-
override Locatable getAst() { result = var }
264-
265-
/** DEPRECATED: Alias for getAst */
266-
deprecated override Locatable getAST() { result = getAst() }
267-
268-
override Function getFunction() { result = forStmt.getEnclosingFunction() }
269-
270-
override LocalVariable getVariable() { result = var }
271-
}
272-
273241
TranslatedConditionDecl getTranslatedConditionDecl(ConditionDeclExpr expr) {
274242
result.getAst() = expr
275243
}

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll

Lines changed: 100 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -443,10 +443,10 @@ predicate hasTranslatedSyntheticTemporaryObject(Expr expr) {
443443
* necessary for automatic local variables, or for static local variables with dynamic
444444
* initialization.
445445
*/
446-
private predicate translateDeclarationEntry(DeclarationEntry entry) {
446+
private predicate translateDeclarationEntry(IRDeclarationEntry entry) {
447447
exists(DeclStmt declStmt, LocalVariable var |
448448
translateStmt(declStmt) and
449-
declStmt.getADeclarationEntry() = entry and
449+
declStmt = entry.getStmt() and
450450
// Only declarations of local variables need to be translated to IR.
451451
var = entry.getDeclaration() and
452452
(
@@ -458,6 +458,102 @@ private predicate translateDeclarationEntry(DeclarationEntry entry) {
458458
)
459459
}
460460

461+
private module IRDeclarationEntries {
462+
private newtype TIRDeclarationEntry =
463+
TPresentDeclarationEntry(DeclarationEntry entry) or
464+
TMissingDeclarationEntry(DeclStmt stmt, Declaration d, int index) {
465+
not exists(stmt.getDeclarationEntry(index)) and
466+
stmt.getDeclaration(index) = d
467+
}
468+
469+
/**
470+
* An entity that represents a declaration entry in the database.
471+
*
472+
* This class exists to work around the fact that `DeclStmt`s in some cases
473+
* do not have `DeclarationEntry`s. Currently, this is the case for:
474+
* - `DeclStmt`s in template instantiations.
475+
* - `DeclStmt`s that are generated by the desugaring of range-based for-loops.
476+
*
477+
* So instead, the IR works with `IRDeclarationEntry`s that synthesize missing
478+
* `DeclarationEntry`s when there is no result for `DeclStmt::getDeclarationEntry`.
479+
*/
480+
abstract class IRDeclarationEntry extends TIRDeclarationEntry {
481+
/** Gets a string representation of this `IRDeclarationEntry`. */
482+
abstract string toString();
483+
484+
/** Gets the `DeclStmt` that this `IRDeclarationEntry` belongs to. */
485+
abstract DeclStmt getStmt();
486+
487+
/** Gets the `Declaration` declared by this `IRDeclarationEntry`. */
488+
abstract Declaration getDeclaration();
489+
490+
/** Gets the AST represented by this `IRDeclarationEntry`. */
491+
abstract Locatable getAst();
492+
493+
/**
494+
* Holds if this `IRDeclarationEntry` is the `index`'th entry
495+
* declared by the enclosing `DeclStmt`.
496+
*/
497+
abstract predicate hasIndex(int index);
498+
}
499+
500+
/** A `IRDeclarationEntry` for an existing `DeclarationEntry`. */
501+
private class PresentDeclarationEntry extends IRDeclarationEntry, TPresentDeclarationEntry {
502+
DeclarationEntry entry;
503+
504+
PresentDeclarationEntry() { this = TPresentDeclarationEntry(entry) }
505+
506+
override string toString() { result = entry.toString() }
507+
508+
override DeclStmt getStmt() { result.getADeclarationEntry() = entry }
509+
510+
override Declaration getDeclaration() { result = entry.getDeclaration() }
511+
512+
override Locatable getAst() { result = entry }
513+
514+
override predicate hasIndex(int index) { this.getStmt().getDeclarationEntry(index) = entry }
515+
}
516+
517+
/**
518+
* A synthesized `DeclarationEntry` that is created when a `DeclStmt` is missing a
519+
* result for `DeclStmt::getDeclarationEntry`
520+
*/
521+
private class MissingDeclarationEntry extends IRDeclarationEntry, TMissingDeclarationEntry {
522+
DeclStmt stmt;
523+
Declaration d;
524+
int index;
525+
526+
MissingDeclarationEntry() { this = TMissingDeclarationEntry(stmt, d, index) }
527+
528+
override string toString() { result = "missing declaration of " + d.getName() }
529+
530+
override DeclStmt getStmt() { result = stmt }
531+
532+
override Declaration getDeclaration() { result = d }
533+
534+
override Locatable getAst() { result = stmt }
535+
536+
override predicate hasIndex(int idx) { idx = index }
537+
}
538+
539+
/** A `IRDeclarationEntry` that represents an entry for a `Variable`. */
540+
class IRVariableDeclarationEntry instanceof IRDeclarationEntry {
541+
Variable v;
542+
543+
IRVariableDeclarationEntry() { super.getDeclaration() = v }
544+
545+
Variable getDeclaration() { result = v }
546+
547+
string toString() { result = super.toString() }
548+
549+
Locatable getAst() { result = super.getAst() }
550+
551+
DeclStmt getStmt() { result = super.getStmt() }
552+
}
553+
}
554+
555+
import IRDeclarationEntries
556+
461557
newtype TTranslatedElement =
462558
// An expression that is not being consumed as a condition
463559
TTranslatedValueExpr(Expr expr) {
@@ -613,23 +709,13 @@ newtype TTranslatedElement =
613709
)
614710
} or
615711
// A local declaration
616-
TTranslatedDeclarationEntry(DeclarationEntry entry) { translateDeclarationEntry(entry) } or
712+
TTranslatedDeclarationEntry(IRDeclarationEntry entry) { translateDeclarationEntry(entry) } or
617713
// The dynamic initialization of a static local variable. This is a separate object from the
618714
// declaration entry.
619-
TTranslatedStaticLocalVariableInitialization(DeclarationEntry entry) {
715+
TTranslatedStaticLocalVariableInitialization(IRDeclarationEntry entry) {
620716
translateDeclarationEntry(entry) and
621717
entry.getDeclaration() instanceof StaticLocalVariable
622718
} or
623-
// A compiler-generated variable to implement a range-based for loop. These don't have a
624-
// `DeclarationEntry` in the database, so we have to go by the `Variable` itself.
625-
TTranslatedRangeBasedForVariableDeclaration(RangeBasedForStmt forStmt, LocalVariable var) {
626-
translateStmt(forStmt) and
627-
(
628-
var = forStmt.getRangeVariable() or
629-
var = forStmt.getBeginEndDeclaration().getADeclaration() or
630-
var = forStmt.getVariable()
631-
)
632-
} or
633719
// An allocator call in a `new` or `new[]` expression
634720
TTranslatedAllocatorCall(NewOrNewArrayExpr newExpr) { not ignoreExpr(newExpr) } or
635721
// An allocation size for a `new` or `new[]` expression

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ class TranslatedDeclStmt extends TranslatedStmt {
7676

7777
private int getChildCount() { result = count(getDeclarationEntry(_)) }
7878

79+
IRDeclarationEntry getIRDeclarationEntry(int index) {
80+
result.hasIndex(index) and
81+
result.getStmt() = stmt
82+
}
83+
84+
IRDeclarationEntry getAnIRDeclarationEntry() { result = this.getIRDeclarationEntry(_) }
85+
7986
/**
8087
* Gets the `TranslatedDeclarationEntry` child at zero-based index `index`. Since not all
8188
* `DeclarationEntry` objects have a `TranslatedDeclarationEntry` (e.g. extern functions), we map
@@ -85,7 +92,7 @@ class TranslatedDeclStmt extends TranslatedStmt {
8592
private TranslatedDeclarationEntry getDeclarationEntry(int index) {
8693
result =
8794
rank[index + 1](TranslatedDeclarationEntry entry, int originalIndex |
88-
entry = getTranslatedDeclarationEntry(stmt.getDeclarationEntry(originalIndex))
95+
entry = getTranslatedDeclarationEntry(this.getIRDeclarationEntry(originalIndex))
8996
|
9097
entry order by originalIndex
9198
)
@@ -597,36 +604,32 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
597604
override RangeBasedForStmt stmt;
598605

599606
override TranslatedElement getChild(int id) {
600-
id = 0 and result = getRangeVariableDeclaration()
607+
id = 0 and result = getRangeVariableDeclStmt()
601608
or
602-
id = 1 and result = getBeginVariableDeclaration()
609+
// Note: `__begin` and `__end` are declared by the same `DeclStmt`
610+
id = 1 and result = getBeginEndVariableDeclStmt()
603611
or
604-
id = 2 and result = getEndVariableDeclaration()
612+
id = 2 and result = getCondition()
605613
or
606-
id = 3 and result = getCondition()
614+
id = 3 and result = getUpdate()
607615
or
608-
id = 4 and result = getUpdate()
616+
id = 4 and result = getVariableDeclStmt()
609617
or
610-
id = 5 and result = getVariableDeclaration()
611-
or
612-
id = 6 and result = getBody()
618+
id = 5 and result = getBody()
613619
}
614620

615621
override Instruction getFirstInstruction() {
616-
result = getRangeVariableDeclaration().getFirstInstruction()
622+
result = getRangeVariableDeclStmt().getFirstInstruction()
617623
}
618624

619625
override Instruction getChildSuccessor(TranslatedElement child) {
620-
child = getRangeVariableDeclaration() and
621-
result = getBeginVariableDeclaration().getFirstInstruction()
622-
or
623-
child = getBeginVariableDeclaration() and
624-
result = getEndVariableDeclaration().getFirstInstruction()
626+
child = getRangeVariableDeclStmt() and
627+
result = getBeginEndVariableDeclStmt().getFirstInstruction()
625628
or
626-
child = getEndVariableDeclaration() and
629+
child = getBeginEndVariableDeclStmt() and
627630
result = getCondition().getFirstInstruction()
628631
or
629-
child = getVariableDeclaration() and
632+
child = getVariableDeclStmt() and
630633
result = getBody().getFirstInstruction()
631634
or
632635
child = getBody() and
@@ -643,23 +646,25 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
643646
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
644647

645648
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
646-
child = getCondition() and result = getVariableDeclaration().getFirstInstruction()
649+
child = getCondition() and result = getVariableDeclStmt().getFirstInstruction()
647650
}
648651

649652
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
650653
child = getCondition() and result = getParent().getChildSuccessor(this)
651654
}
652655

653-
private TranslatedRangeBasedForVariableDeclaration getRangeVariableDeclaration() {
654-
result = getTranslatedRangeBasedForVariableDeclaration(stmt.getRangeVariable())
655-
}
656-
657-
private TranslatedRangeBasedForVariableDeclaration getBeginVariableDeclaration() {
658-
result = getTranslatedRangeBasedForVariableDeclaration(stmt.getBeginVariable())
656+
private TranslatedDeclStmt getRangeVariableDeclStmt() {
657+
exists(IRVariableDeclarationEntry entry |
658+
entry.getDeclaration() = stmt.getRangeVariable() and
659+
result.getAnIRDeclarationEntry() = entry
660+
)
659661
}
660662

661-
private TranslatedRangeBasedForVariableDeclaration getEndVariableDeclaration() {
662-
result = getTranslatedRangeBasedForVariableDeclaration(stmt.getEndVariable())
663+
private TranslatedDeclStmt getBeginEndVariableDeclStmt() {
664+
exists(IRVariableDeclarationEntry entry |
665+
entry.getStmt() = stmt.getBeginEndDeclaration() and
666+
result.getAnIRDeclarationEntry() = entry
667+
)
663668
}
664669

665670
// Public for getInstructionBackEdgeSuccessor
@@ -672,8 +677,11 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
672677
result = getTranslatedExpr(stmt.getUpdate().getFullyConverted())
673678
}
674679

675-
private TranslatedRangeBasedForVariableDeclaration getVariableDeclaration() {
676-
result = getTranslatedRangeBasedForVariableDeclaration(stmt.getVariable())
680+
private TranslatedDeclStmt getVariableDeclStmt() {
681+
exists(IRVariableDeclarationEntry entry |
682+
entry.getDeclaration() = stmt.getVariable() and
683+
result.getAnIRDeclarationEntry() = entry
684+
)
677685
}
678686

679687
private TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) }

0 commit comments

Comments
 (0)