@@ -3,6 +3,7 @@ private import semmle.code.cpp.ir.implementation.IRType
3
3
private import semmle.code.cpp.ir.implementation.Opcode
4
4
private import semmle.code.cpp.ir.implementation.internal.OperandTag
5
5
private import semmle.code.cpp.ir.internal.CppType
6
+ private import semmle.code.cpp.ir.internal.IRUtilities
6
7
private import semmle.code.cpp.ir.internal.TempVariableTag
7
8
private import InstructionTag
8
9
private import TranslatedCondition
@@ -813,7 +814,9 @@ abstract class TranslatedVariableAccess extends TranslatedNonConstantExpr {
813
814
}
814
815
815
816
class TranslatedNonFieldVariableAccess extends TranslatedVariableAccess {
816
- TranslatedNonFieldVariableAccess ( ) { not expr instanceof FieldAccess }
817
+ TranslatedNonFieldVariableAccess ( ) {
818
+ not expr instanceof FieldAccess and not isNonReferenceStructuredBinding ( expr .getTarget ( ) )
819
+ }
817
820
818
821
override Instruction getFirstInstruction ( ) {
819
822
if exists ( this .getQualifier ( ) )
@@ -860,6 +863,71 @@ class TranslatedFieldAccess extends TranslatedVariableAccess {
860
863
}
861
864
}
862
865
866
+ /**
867
+ * The IR translation of a variable access of a structured binding, where the type
868
+ * of the structured binding is not of a reference type, e.g., `x0` and `x1`
869
+ * in `auto [x0, x1] = xs` where `xs` is an array. Although the type of the
870
+ * structured binding is a non-reference type, the structured binding behaves
871
+ * like a reference. Hence, the translation requires a `VariableAddress` followed
872
+ * by a `Load` instead of only a `VariableAddress` as produced by
873
+ * `TranslatedVariableAccess`.
874
+ */
875
+ class TranslatedStructuredBindingVariableAccess extends TranslatedNonConstantExpr {
876
+ override VariableAccess expr ;
877
+
878
+ TranslatedStructuredBindingVariableAccess ( ) { isNonReferenceStructuredBinding ( expr .getTarget ( ) ) }
879
+
880
+ override Instruction getFirstInstruction ( ) {
881
+ // Structured bindings cannot be qualified.
882
+ result = this .getInstruction ( StructuredBindingAccessTag ( ) )
883
+ }
884
+
885
+ override TranslatedElement getChild ( int id ) {
886
+ // Structured bindings cannot be qualified.
887
+ none ( )
888
+ }
889
+
890
+ override Instruction getResult ( ) { result = this .getInstruction ( LoadTag ( ) ) }
891
+
892
+ override Instruction getInstructionSuccessor ( InstructionTag tag , EdgeKind kind ) {
893
+ tag = StructuredBindingAccessTag ( ) and
894
+ kind instanceof GotoEdge and
895
+ result = this .getInstruction ( LoadTag ( ) )
896
+ or
897
+ tag = LoadTag ( ) and
898
+ kind instanceof GotoEdge and
899
+ result = this .getParent ( ) .getChildSuccessor ( this )
900
+ }
901
+
902
+ override Instruction getChildSuccessor ( TranslatedElement child ) { none ( ) }
903
+
904
+ override predicate hasInstruction ( Opcode opcode , InstructionTag tag , CppType resultType ) {
905
+ tag = StructuredBindingAccessTag ( ) and
906
+ opcode instanceof Opcode:: VariableAddress and
907
+ resultType = getTypeForGLValue ( this .getLValueReferenceType ( ) )
908
+ or
909
+ tag = LoadTag ( ) and
910
+ opcode instanceof Opcode:: Load and
911
+ resultType = getTypeForPRValue ( this .getLValueReferenceType ( ) )
912
+ }
913
+
914
+ private LValueReferenceType getLValueReferenceType ( ) {
915
+ // The extractor ensures `result` exists when `isNonReferenceStructuredBinding(expr.getTarget())` holds.
916
+ result .getBaseType ( ) = expr .getUnspecifiedType ( )
917
+ }
918
+
919
+ override Instruction getInstructionRegisterOperand ( InstructionTag tag , OperandTag operandTag ) {
920
+ tag = LoadTag ( ) and
921
+ operandTag instanceof AddressOperandTag and
922
+ result = this .getInstruction ( StructuredBindingAccessTag ( ) )
923
+ }
924
+
925
+ override IRVariable getInstructionVariable ( InstructionTag tag ) {
926
+ tag = StructuredBindingAccessTag ( ) and
927
+ result = getIRUserVariable ( expr .getEnclosingFunction ( ) , expr .getTarget ( ) )
928
+ }
929
+ }
930
+
863
931
class TranslatedFunctionAccess extends TranslatedNonConstantExpr {
864
932
override FunctionAccess expr ;
865
933
0 commit comments