@@ -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+
461557newtype 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
0 commit comments