From 6bef0f8e0a6594557035b0b33b89cec6f1af1be8 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Thu, 14 Mar 2024 09:47:40 +0100 Subject: [PATCH] C++: Output destructors of temporary objects --- .../library-tests/ir/ir/PrintAST.expected | 272 ++++++++++++- .../conditional_destructors/cfg.expected | 362 +++++++++--------- 2 files changed, 459 insertions(+), 175 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index 624954838d6e..ca7a673fa799 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -1781,6 +1781,12 @@ destructors_for_temps.cpp: # 15| getQualifier(): [ConstructorCall] call to ClassWithDestructor2 # 15| Type = [VoidType] void # 15| ValueCategory = prvalue +# 15| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2 +# 15| Type = [VoidType] void +# 15| ValueCategory = prvalue +# 15| getQualifier(): [ReuseExpr] reuse of temporary object +# 15| Type = [Class] ClassWithDestructor2 +# 15| ValueCategory = xvalue # 15| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object # 15| Type = [Class] ClassWithDestructor2 # 15| ValueCategory = prvalue(load) @@ -1804,6 +1810,12 @@ destructors_for_temps.cpp: # 16| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object # 16| Type = [Class] ClassWithDestructor2 # 16| ValueCategory = prvalue(load) +# 16| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2 +# 16| Type = [VoidType] void +# 16| ValueCategory = prvalue +# 16| getQualifier(): [ReuseExpr] reuse of temporary object +# 16| Type = [Class] ClassWithDestructor2 +# 16| ValueCategory = xvalue # 17| getStmt(2): [ReturnStmt] return ... # 17| getExpr(): [FunctionCall] call to get_x # 17| Type = [PlainCharType] char @@ -1811,9 +1823,21 @@ destructors_for_temps.cpp: # 17| getQualifier(): [ConstructorCall] call to ClassWithDestructor2 # 17| Type = [VoidType] void # 17| ValueCategory = prvalue +# 17| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2 +# 17| Type = [VoidType] void +# 17| ValueCategory = prvalue +# 17| getQualifier(): [ReuseExpr] reuse of temporary object +# 17| Type = [Class] ClassWithDestructor2 +# 17| ValueCategory = xvalue # 17| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object # 17| Type = [Class] ClassWithDestructor2 # 17| ValueCategory = prvalue(load) +# 18| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2 +# 18| Type = [VoidType] void +# 18| ValueCategory = prvalue +# 18| getQualifier(): [ReuseExpr] reuse of temporary object +# 18| Type = [Class] ClassWithDestructor2 +# 18| ValueCategory = xvalue # 21| [TopLevelFunction] char temp_test2() # 21| : # 21| getEntryPoint(): [BlockStmt] { ... } @@ -1846,6 +1870,18 @@ destructors_for_temps.cpp: # 23| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object # 23| Type = [Class] ClassWithDestructor2 # 23| ValueCategory = prvalue(load) +# 23| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2 +# 23| Type = [VoidType] void +# 23| ValueCategory = prvalue +# 23| getQualifier(): [ReuseExpr] reuse of temporary object +# 23| Type = [Class] ClassWithDestructor2 +# 23| ValueCategory = xvalue +# 23| getImplicitDestructorCall(1): [DestructorCall] call to ~ClassWithDestructor2 +# 23| Type = [VoidType] void +# 23| ValueCategory = prvalue +# 23| getQualifier(): [ReuseExpr] reuse of temporary object +# 23| Type = [Class] ClassWithDestructor2 +# 23| ValueCategory = xvalue # 23| getLeftOperand().getFullyConverted(): [CStyleCast] (int)... # 23| Conversion = [IntegralConversion] integral conversion # 23| Type = [IntType] int @@ -1883,6 +1919,12 @@ destructors_for_temps.cpp: # 30| Type = [Class] ClassWithDestructor2 # 30| ValueCategory = lvalue # 31| getStmt(1): [ReturnStmt] return ... +# 31| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2 +# 31| Type = [VoidType] void +# 31| ValueCategory = prvalue +# 31| getQualifier(): [ReuseExpr] reuse of temporary object +# 31| Type = [Class] ClassWithDestructor2 +# 31| ValueCategory = xvalue # 33| [TopLevelFunction] void temp_test4() # 33| : # 33| getEntryPoint(): [BlockStmt] { ... } @@ -1914,6 +1956,12 @@ destructors_for_temps.cpp: # 36| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2 # 36| Type = [VoidType] void # 36| ValueCategory = prvalue +# 36| getQualifier(): [ReuseExpr] reuse of temporary object +# 36| Type = [Class] ClassWithDestructor2 +# 36| ValueCategory = xvalue +# 36| getImplicitDestructorCall(1): [DestructorCall] call to ~ClassWithDestructor2 +# 36| Type = [VoidType] void +# 36| ValueCategory = prvalue # 36| getQualifier(): [VariableAccess] c # 36| Type = [Class] ClassWithDestructor2 # 36| ValueCategory = lvalue @@ -1935,6 +1983,12 @@ destructors_for_temps.cpp: # 39| getElse(): [ConstructorCall] call to ClassWithDestructor2 # 39| Type = [VoidType] void # 39| ValueCategory = prvalue +# 39| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2 +# 39| Type = [VoidType] void +# 39| ValueCategory = prvalue +# 39| getQualifier(): [ReuseExpr] reuse of temporary object +# 39| Type = [Class] ClassWithDestructor2 +# 39| ValueCategory = xvalue # 39| getThen().getFullyConverted(): [TemporaryObjectExpr] temporary object # 39| Type = [Class] ClassWithDestructor2 # 39| ValueCategory = prvalue(load) @@ -1982,7 +2036,13 @@ destructors_for_temps.cpp: # 45| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object # 45| Type = [Class] ClassWithDestructor2 # 45| ValueCategory = prvalue(load) -# 47| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2 +# 46| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2 +# 46| Type = [VoidType] void +# 46| ValueCategory = prvalue +# 46| getQualifier(): [ReuseExpr] reuse of temporary object +# 46| Type = [Class] ClassWithDestructor2 +# 46| ValueCategory = xvalue +# 47| getImplicitDestructorCall(1): [DestructorCall] call to ~ClassWithDestructor2 # 47| Type = [VoidType] void # 47| ValueCategory = prvalue # 47| getQualifier(): [VariableAccess] c @@ -2036,12 +2096,36 @@ destructors_for_temps.cpp: # 52| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2 # 52| Type = [VoidType] void # 52| ValueCategory = prvalue +# 52| getQualifier(): [ReuseExpr] reuse of temporary object +# 52| Type = [Class] ClassWithDestructor2 +# 52| ValueCategory = xvalue +# 52| getImplicitDestructorCall(1): [DestructorCall] call to ~ClassWithDestructor2 +# 52| Type = [VoidType] void +# 52| ValueCategory = prvalue # 52| getQualifier(): [VariableAccess] c # 52| Type = [Class] ClassWithDestructor2 # 52| ValueCategory = lvalue # 51| getElse(): [ConstructorCall] call to ClassWithDestructor2 # 51| Type = [VoidType] void # 51| ValueCategory = prvalue +# 51| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2 +# 51| Type = [VoidType] void +# 51| ValueCategory = prvalue +# 51| getQualifier(): [ReuseExpr] reuse of temporary object +# 51| Type = [Class] ClassWithDestructor2 +# 51| ValueCategory = xvalue +# 51| getImplicitDestructorCall(1): [DestructorCall] call to ~ClassWithDestructor2 +# 51| Type = [VoidType] void +# 51| ValueCategory = prvalue +# 51| getQualifier(): [ReuseExpr] reuse of temporary object +# 51| Type = [Class] ClassWithDestructor2 +# 51| ValueCategory = xvalue +# 51| getImplicitDestructorCall(2): [DestructorCall] call to ~ClassWithDestructor2 +# 51| Type = [VoidType] void +# 51| ValueCategory = prvalue +# 51| getQualifier(): [ReuseExpr] reuse of temporary object +# 51| Type = [Class] ClassWithDestructor2 +# 51| ValueCategory = xvalue # 51| getElse().getFullyConverted(): [TemporaryObjectExpr] temporary object # 51| Type = [Class] ClassWithDestructor2 # 51| ValueCategory = prvalue(load) @@ -2086,9 +2170,33 @@ destructors_for_temps.cpp: # 55| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object # 55| Type = [Class] ClassWithDestructor2 # 55| ValueCategory = prvalue(load) +# 56| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2 +# 56| Type = [VoidType] void +# 56| ValueCategory = prvalue +# 56| getQualifier(): [ReuseExpr] reuse of temporary object +# 56| Type = [Class] ClassWithDestructor2 +# 56| ValueCategory = xvalue # 55| getElse(): [ConstructorCall] call to ClassWithDestructor2 # 55| Type = [VoidType] void # 55| ValueCategory = prvalue +# 55| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2 +# 55| Type = [VoidType] void +# 55| ValueCategory = prvalue +# 55| getQualifier(): [ReuseExpr] reuse of temporary object +# 55| Type = [Class] ClassWithDestructor2 +# 55| ValueCategory = xvalue +# 55| getImplicitDestructorCall(1): [DestructorCall] call to ~ClassWithDestructor2 +# 55| Type = [VoidType] void +# 55| ValueCategory = prvalue +# 55| getQualifier(): [ReuseExpr] reuse of temporary object +# 55| Type = [Class] ClassWithDestructor2 +# 55| ValueCategory = xvalue +# 55| getImplicitDestructorCall(2): [DestructorCall] call to ~ClassWithDestructor2 +# 55| Type = [VoidType] void +# 55| ValueCategory = prvalue +# 55| getQualifier(): [ReuseExpr] reuse of temporary object +# 55| Type = [Class] ClassWithDestructor2 +# 55| ValueCategory = xvalue # 55| getElse().getFullyConverted(): [TemporaryObjectExpr] temporary object # 55| Type = [Class] ClassWithDestructor2 # 55| ValueCategory = prvalue(load) @@ -7221,6 +7329,12 @@ ir.cpp: # 809| Conversion = [BaseClassConversion] base class conversion # 809| Type = [SpecifiedType] const Base # 809| ValueCategory = lvalue +# 809| getImplicitDestructorCall(0): [DestructorCall] call to ~Base +# 809| Type = [VoidType] void +# 809| ValueCategory = prvalue +# 809| getQualifier(): [ReuseExpr] reuse of temporary object +# 809| Type = [Struct,VirtualBaseClass] Base +# 809| ValueCategory = xvalue # 809| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to) # 809| Type = [LValueReferenceType] const Base & # 809| ValueCategory = prvalue @@ -7254,6 +7368,12 @@ ir.cpp: # 810| Conversion = [BaseClassConversion] base class conversion # 810| Type = [SpecifiedType] const Base # 810| ValueCategory = lvalue +# 810| getImplicitDestructorCall(0): [DestructorCall] call to ~Base +# 810| Type = [VoidType] void +# 810| ValueCategory = prvalue +# 810| getQualifier(): [ReuseExpr] reuse of temporary object +# 810| Type = [Struct,VirtualBaseClass] Base +# 810| ValueCategory = xvalue # 810| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to) # 810| Type = [LValueReferenceType] const Base & # 810| ValueCategory = prvalue @@ -7461,6 +7581,12 @@ ir.cpp: # 823| Conversion = [BaseClassConversion] base class conversion # 823| Type = [SpecifiedType] const Middle # 823| ValueCategory = lvalue +# 823| getImplicitDestructorCall(0): [DestructorCall] call to ~Base +# 823| Type = [VoidType] void +# 823| ValueCategory = prvalue +# 823| getQualifier(): [ReuseExpr] reuse of temporary object +# 823| Type = [Struct,VirtualBaseClass] Base +# 823| ValueCategory = xvalue # 823| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to) # 823| Type = [LValueReferenceType] const Base & # 823| ValueCategory = prvalue @@ -7498,6 +7624,12 @@ ir.cpp: # 824| Conversion = [BaseClassConversion] base class conversion # 824| Type = [SpecifiedType] const Middle # 824| ValueCategory = lvalue +# 824| getImplicitDestructorCall(0): [DestructorCall] call to ~Base +# 824| Type = [VoidType] void +# 824| ValueCategory = prvalue +# 824| getQualifier(): [ReuseExpr] reuse of temporary object +# 824| Type = [Struct,VirtualBaseClass] Base +# 824| ValueCategory = xvalue # 824| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to) # 824| Type = [LValueReferenceType] const Base & # 824| ValueCategory = prvalue @@ -11543,6 +11675,12 @@ ir.cpp: # 1372| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion # 1372| Type = [PointerType] const char * # 1372| ValueCategory = prvalue +# 1372| getImplicitDestructorCall(0): [DestructorCall] call to ~String +# 1372| Type = [VoidType] void +# 1372| ValueCategory = prvalue +# 1372| getQualifier(): [ReuseExpr] reuse of temporary object +# 1372| Type = [SpecifiedType] const String +# 1372| ValueCategory = xvalue # 1372| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to) # 1372| Type = [LValueReferenceType] const String & # 1372| ValueCategory = prvalue @@ -11566,6 +11704,12 @@ ir.cpp: # 1373| Conversion = [GlvalueConversion] glvalue conversion # 1373| Type = [SpecifiedType] const String # 1373| ValueCategory = lvalue +# 1373| getImplicitDestructorCall(0): [DestructorCall] call to ~String +# 1373| Type = [VoidType] void +# 1373| ValueCategory = prvalue +# 1373| getQualifier(): [ReuseExpr] reuse of temporary object +# 1373| Type = [Struct] String +# 1373| ValueCategory = xvalue # 1373| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object # 1373| Type = [Struct] String # 1373| ValueCategory = lvalue @@ -11583,6 +11727,12 @@ ir.cpp: # 1374| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion # 1374| Type = [PointerType] const char * # 1374| ValueCategory = prvalue +# 1374| getImplicitDestructorCall(0): [DestructorCall] call to ~String +# 1374| Type = [VoidType] void +# 1374| ValueCategory = prvalue +# 1374| getQualifier(): [ReuseExpr] reuse of temporary object +# 1374| Type = [Struct] String +# 1374| ValueCategory = xvalue # 1374| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object # 1374| Type = [Struct] String # 1374| ValueCategory = lvalue @@ -11593,6 +11743,12 @@ ir.cpp: # 1375| getQualifier(): [ConstructorCall] call to String # 1375| Type = [VoidType] void # 1375| ValueCategory = prvalue +# 1375| getImplicitDestructorCall(0): [DestructorCall] call to ~String +# 1375| Type = [VoidType] void +# 1375| ValueCategory = prvalue +# 1375| getQualifier(): [ReuseExpr] reuse of temporary object +# 1375| Type = [Struct] String +# 1375| ValueCategory = xvalue # 1375| getQualifier().getFullyConverted(): [CStyleCast] (const String)... # 1375| Conversion = [PrvalueAdjustmentConversion] prvalue adjustment conversion # 1375| Type = [SpecifiedType] const String @@ -11607,6 +11763,12 @@ ir.cpp: # 1376| getQualifier(): [FunctionCall] call to returnValue # 1376| Type = [Struct] String # 1376| ValueCategory = prvalue +# 1376| getImplicitDestructorCall(0): [DestructorCall] call to ~String +# 1376| Type = [VoidType] void +# 1376| ValueCategory = prvalue +# 1376| getQualifier(): [ReuseExpr] reuse of temporary object +# 1376| Type = [Struct] String +# 1376| ValueCategory = xvalue # 1376| getQualifier().getFullyConverted(): [CStyleCast] (const String)... # 1376| Conversion = [PrvalueAdjustmentConversion] prvalue adjustment conversion # 1376| Type = [SpecifiedType] const String @@ -11618,6 +11780,12 @@ ir.cpp: # 1378| getExpr(): [FunctionCall] call to defaultConstruct # 1378| Type = [Struct] String # 1378| ValueCategory = prvalue +# 1378| getImplicitDestructorCall(0): [DestructorCall] call to ~String +# 1378| Type = [VoidType] void +# 1378| ValueCategory = prvalue +# 1378| getQualifier(): [ReuseExpr] reuse of temporary object +# 1378| Type = [Struct] String +# 1378| ValueCategory = xvalue # 1378| getExpr().getFullyConverted(): [TemporaryObjectExpr] temporary object # 1378| Type = [Struct] String # 1378| ValueCategory = prvalue @@ -11625,6 +11793,12 @@ ir.cpp: # 1379| getImplicitDestructorCall(0): [DestructorCall] call to ~String # 1379| Type = [VoidType] void # 1379| ValueCategory = prvalue +# 1379| getQualifier(): [ReuseExpr] reuse of temporary object +# 1379| Type = [Struct] String +# 1379| ValueCategory = xvalue +# 1379| getImplicitDestructorCall(1): [DestructorCall] call to ~String +# 1379| Type = [VoidType] void +# 1379| ValueCategory = prvalue # 1379| getQualifier(): [VariableAccess] s # 1379| Type = [Struct] String # 1379| ValueCategory = lvalue @@ -11679,6 +11853,12 @@ ir.cpp: # 1386| getArgument(0): [VariableAccess] d # 1386| Type = [Class] destructor_only # 1386| ValueCategory = prvalue(load) +# 1386| getImplicitDestructorCall(0): [DestructorCall] call to ~destructor_only +# 1386| Type = [VoidType] void +# 1386| ValueCategory = prvalue +# 1386| getQualifier(): [ReuseExpr] reuse of temporary object +# 1386| Type = [Class] destructor_only +# 1386| ValueCategory = xvalue # 1386| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object # 1386| Type = [Class] destructor_only # 1386| ValueCategory = lvalue @@ -11690,6 +11870,12 @@ ir.cpp: # 1387| Type = [Class] destructor_only # 1387| Value = [Literal] 0 # 1387| ValueCategory = prvalue +# 1387| getImplicitDestructorCall(0): [DestructorCall] call to ~destructor_only +# 1387| Type = [VoidType] void +# 1387| ValueCategory = prvalue +# 1387| getQualifier(): [ReuseExpr] reuse of temporary object +# 1387| Type = [Class] destructor_only +# 1387| ValueCategory = xvalue # 1387| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object # 1387| Type = [Class] destructor_only # 1387| ValueCategory = prvalue(load) @@ -11700,6 +11886,12 @@ ir.cpp: # 1388| getQualifier(): [FunctionCall] call to returnValue # 1388| Type = [Class] destructor_only # 1388| ValueCategory = prvalue +# 1388| getImplicitDestructorCall(0): [DestructorCall] call to ~destructor_only +# 1388| Type = [VoidType] void +# 1388| ValueCategory = prvalue +# 1388| getQualifier(): [ReuseExpr] reuse of temporary object +# 1388| Type = [Class] destructor_only +# 1388| ValueCategory = xvalue # 1388| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object # 1388| Type = [Class] destructor_only # 1388| ValueCategory = prvalue(load) @@ -11707,6 +11899,12 @@ ir.cpp: # 1390| getExpr(): [FunctionCall] call to defaultConstruct # 1390| Type = [Class] destructor_only # 1390| ValueCategory = prvalue +# 1390| getImplicitDestructorCall(0): [DestructorCall] call to ~destructor_only +# 1390| Type = [VoidType] void +# 1390| ValueCategory = prvalue +# 1390| getQualifier(): [ReuseExpr] reuse of temporary object +# 1390| Type = [Class] destructor_only +# 1390| ValueCategory = xvalue # 1390| getExpr().getFullyConverted(): [TemporaryObjectExpr] temporary object # 1390| Type = [Class] destructor_only # 1390| ValueCategory = prvalue @@ -11720,6 +11918,12 @@ ir.cpp: # 1391| getImplicitDestructorCall(1): [DestructorCall] call to ~destructor_only # 1391| Type = [VoidType] void # 1391| ValueCategory = prvalue +# 1391| getQualifier(): [ReuseExpr] reuse of temporary object +# 1391| Type = [Class] destructor_only +# 1391| ValueCategory = xvalue +# 1391| getImplicitDestructorCall(2): [DestructorCall] call to ~destructor_only +# 1391| Type = [VoidType] void +# 1391| ValueCategory = prvalue # 1391| getQualifier(): [VariableAccess] d # 1391| Type = [Class] destructor_only # 1391| ValueCategory = lvalue @@ -16075,6 +16279,12 @@ ir.cpp: # 2021| getElse().getFullyConverted(): [TemporaryObjectExpr] temporary object # 2021| Type = [Struct] TernaryNonPodObj # 2021| ValueCategory = prvalue(load) +# 2021| getImplicitDestructorCall(0): [DestructorCall] call to ~TernaryNonPodObj +# 2021| Type = [VoidType] void +# 2021| ValueCategory = prvalue +# 2021| getQualifier(): [ReuseExpr] reuse of temporary object +# 2021| Type = [Struct] TernaryNonPodObj +# 2021| ValueCategory = xvalue # 2021| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to) # 2021| Type = [LValueReferenceType] const TernaryNonPodObj & # 2021| ValueCategory = prvalue @@ -16113,6 +16323,12 @@ ir.cpp: # 2022| getElse().getFullyConverted(): [TemporaryObjectExpr] temporary object # 2022| Type = [Struct] TernaryNonPodObj # 2022| ValueCategory = prvalue(load) +# 2022| getImplicitDestructorCall(0): [DestructorCall] call to ~TernaryNonPodObj +# 2022| Type = [VoidType] void +# 2022| ValueCategory = prvalue +# 2022| getQualifier(): [ReuseExpr] reuse of temporary object +# 2022| Type = [Struct] TernaryNonPodObj +# 2022| ValueCategory = xvalue # 2022| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to) # 2022| Type = [LValueReferenceType] const TernaryNonPodObj & # 2022| ValueCategory = prvalue @@ -16158,6 +16374,12 @@ ir.cpp: # 2023| getArgument(0): [ConstructorCall] call to TernaryNonPodObj # 2023| Type = [VoidType] void # 2023| ValueCategory = prvalue +# 2023| getImplicitDestructorCall(0): [DestructorCall] call to ~TernaryNonPodObj +# 2023| Type = [VoidType] void +# 2023| ValueCategory = prvalue +# 2023| getQualifier(): [ReuseExpr] reuse of temporary object +# 2023| Type = [Struct] TernaryNonPodObj +# 2023| ValueCategory = xvalue # 2023| getQualifier().getFullyConverted(): [ParenthesisExpr] (...) # 2023| Type = [Struct] TernaryNonPodObj # 2023| ValueCategory = lvalue @@ -17951,6 +18173,12 @@ ir.cpp: # 2246| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion # 2246| Type = [PointerType] const char * # 2246| ValueCategory = prvalue +# 2246| getImplicitDestructorCall(0): [DestructorCall] call to ~String +# 2246| Type = [VoidType] void +# 2246| ValueCategory = prvalue +# 2246| getQualifier(): [ReuseExpr] reuse of temporary object +# 2246| Type = [Struct] String +# 2246| ValueCategory = xvalue # 2246| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object # 2246| Type = [Struct] String # 2246| ValueCategory = lvalue @@ -18542,6 +18770,12 @@ smart_ptr.cpp: # 12| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to) # 12| Type = [LValueReferenceType] unique_ptr> & # 12| ValueCategory = prvalue +# 12| getImplicitDestructorCall(0): [DestructorCall] call to ~unique_ptr +# 12| Type = [VoidType] void +# 12| ValueCategory = prvalue +# 12| getQualifier(): [ReuseExpr] reuse of temporary object +# 12| Type = [ClassTemplateInstantiation] unique_ptr> +# 12| ValueCategory = xvalue # 12| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object # 12| Type = [ClassTemplateInstantiation] unique_ptr> # 12| ValueCategory = lvalue @@ -18591,6 +18825,12 @@ smart_ptr.cpp: # 19| Conversion = [GlvalueConversion] glvalue conversion # 19| Type = [SpecifiedType] const shared_ptr # 19| ValueCategory = lvalue +# 19| getImplicitDestructorCall(0): [DestructorCall] call to ~shared_ptr +# 19| Type = [VoidType] void +# 19| ValueCategory = prvalue +# 19| getQualifier(): [ReuseExpr] reuse of temporary object +# 19| Type = [ClassTemplateInstantiation] shared_ptr +# 19| ValueCategory = xvalue # 19| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object # 19| Type = [ClassTemplateInstantiation] shared_ptr # 19| ValueCategory = lvalue @@ -18644,6 +18884,12 @@ smart_ptr.cpp: # 31| Conversion = [GlvalueConversion] glvalue conversion # 31| Type = [SpecifiedType] const shared_ptr # 31| ValueCategory = lvalue +# 31| getImplicitDestructorCall(0): [DestructorCall] call to ~shared_ptr +# 31| Type = [VoidType] void +# 31| ValueCategory = prvalue +# 31| getQualifier(): [ReuseExpr] reuse of temporary object +# 31| Type = [ClassTemplateInstantiation] shared_ptr +# 31| ValueCategory = xvalue # 31| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object # 31| Type = [ClassTemplateInstantiation] shared_ptr # 31| ValueCategory = lvalue @@ -18667,6 +18913,12 @@ smart_ptr.cpp: # 35| Conversion = [GlvalueConversion] glvalue conversion # 35| Type = [SpecifiedType] const shared_ptr # 35| ValueCategory = lvalue +# 35| getImplicitDestructorCall(0): [DestructorCall] call to ~shared_ptr +# 35| Type = [VoidType] void +# 35| ValueCategory = prvalue +# 35| getQualifier(): [ReuseExpr] reuse of temporary object +# 35| Type = [ClassTemplateInstantiation] shared_ptr +# 35| ValueCategory = xvalue # 35| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object # 35| Type = [ClassTemplateInstantiation] shared_ptr # 35| ValueCategory = lvalue @@ -18690,6 +18942,12 @@ smart_ptr.cpp: # 39| Conversion = [GlvalueConversion] glvalue conversion # 39| Type = [SpecifiedType] const shared_ptr> # 39| ValueCategory = lvalue +# 39| getImplicitDestructorCall(0): [DestructorCall] call to ~shared_ptr +# 39| Type = [VoidType] void +# 39| ValueCategory = prvalue +# 39| getQualifier(): [ReuseExpr] reuse of temporary object +# 39| Type = [ClassTemplateInstantiation] shared_ptr> +# 39| ValueCategory = xvalue # 39| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object # 39| Type = [ClassTemplateInstantiation] shared_ptr> # 39| ValueCategory = lvalue @@ -18713,6 +18971,12 @@ smart_ptr.cpp: # 43| Conversion = [GlvalueConversion] glvalue conversion # 43| Type = [SpecifiedType] const shared_ptr> # 43| ValueCategory = lvalue +# 43| getImplicitDestructorCall(0): [DestructorCall] call to ~shared_ptr +# 43| Type = [VoidType] void +# 43| ValueCategory = prvalue +# 43| getQualifier(): [ReuseExpr] reuse of temporary object +# 43| Type = [ClassTemplateInstantiation] shared_ptr> +# 43| ValueCategory = xvalue # 43| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object # 43| Type = [ClassTemplateInstantiation] shared_ptr> # 43| ValueCategory = lvalue @@ -18736,6 +19000,12 @@ smart_ptr.cpp: # 47| Conversion = [GlvalueConversion] glvalue conversion # 47| Type = [SpecifiedType] const shared_ptr> # 47| ValueCategory = lvalue +# 47| getImplicitDestructorCall(0): [DestructorCall] call to ~shared_ptr +# 47| Type = [VoidType] void +# 47| ValueCategory = prvalue +# 47| getQualifier(): [ReuseExpr] reuse of temporary object +# 47| Type = [ClassTemplateInstantiation] shared_ptr> +# 47| ValueCategory = xvalue # 47| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object # 47| Type = [ClassTemplateInstantiation] shared_ptr> # 47| ValueCategory = lvalue diff --git a/cpp/ql/test/successor-tests/conditional_destructors/cfg.expected b/cpp/ql/test/successor-tests/conditional_destructors/cfg.expected index a47bcaf6fbf4..006ed12e35f2 100644 --- a/cpp/ql/test/successor-tests/conditional_destructors/cfg.expected +++ b/cpp/ql/test/successor-tests/conditional_destructors/cfg.expected @@ -1,175 +1,189 @@ -| C1::C1 | false | 237 | 237 | C1 | -| C1::C1 | false | 359 | 359 | C1 | -| C1::C1 | false | 363 | 363 | C1 | -| C1::C1 | false | 398 | 398 | ExprStmt | -| C1::C1 | false | 400 | 400 | this | -| C1::C1 | false | 401 | 401 | val | -| C1::C1 | false | 403 | 403 | x | -| C1::C1 | false | 405 | 405 | ... = ... | -| C1::C1 | false | 407 | 407 | return ... | -| C1::C1 | false | 409 | 409 | { ... } | -| C1::C1 | true | 398 | 403 | | -| C1::C1 | true | 400 | 401 | | -| C1::C1 | true | 401 | 405 | | -| C1::C1 | true | 403 | 400 | | -| C1::C1 | true | 405 | 407 | | -| C1::C1 | true | 407 | 237 | | -| C1::C1 | true | 409 | 398 | | -| C1::operator= | false | 348 | 348 | operator= | -| C1::operator= | false | 355 | 355 | operator= | -| C1::operator== | false | 226 | 226 | operator== | -| C1::operator== | false | 376 | 376 | return ... | -| C1::operator== | false | 378 | 378 | this | -| C1::operator== | false | 379 | 379 | val | -| C1::operator== | false | 382 | 382 | other | -| C1::operator== | false | 384 | 384 | (reference dereference) | -| C1::operator== | false | 385 | 385 | val | -| C1::operator== | false | 387 | 387 | ... == ... | -| C1::operator== | false | 389 | 389 | { ... } | -| C1::operator== | true | 376 | 378 | | -| C1::operator== | true | 378 | 379 | | -| C1::operator== | true | 379 | 382 | | -| C1::operator== | true | 382 | 385 | | -| C1::operator== | true | 385 | 387 | | -| C1::operator== | true | 387 | 226 | | -| C1::operator== | true | 389 | 376 | | -| C2::C2 | false | 170 | 170 | C2 | -| C2::C2 | false | 288 | 288 | C2 | -| C2::C2 | false | 334 | 334 | ExprStmt | -| C2::C2 | false | 336 | 336 | this | -| C2::C2 | false | 337 | 337 | val | -| C2::C2 | false | 339 | 339 | x | -| C2::C2 | false | 341 | 341 | ... = ... | -| C2::C2 | false | 343 | 343 | return ... | -| C2::C2 | false | 345 | 345 | { ... } | -| C2::C2 | true | 334 | 339 | | -| C2::C2 | true | 336 | 337 | | -| C2::C2 | true | 337 | 341 | | -| C2::C2 | true | 339 | 336 | | -| C2::C2 | true | 341 | 343 | | -| C2::C2 | true | 343 | 170 | | -| C2::C2 | true | 345 | 334 | | -| C2::operator= | false | 282 | 282 | operator= | -| C2::operator== | false | 159 | 159 | operator== | -| C2::operator== | false | 301 | 301 | return ... | -| C2::operator== | false | 303 | 303 | this | -| C2::operator== | false | 304 | 304 | val | -| C2::operator== | false | 307 | 307 | other | -| C2::operator== | false | 309 | 309 | (reference dereference) | -| C2::operator== | false | 310 | 310 | val | -| C2::operator== | false | 312 | 312 | ... == ... | -| C2::operator== | false | 314 | 314 | { ... } | -| C2::operator== | true | 301 | 303 | | -| C2::operator== | true | 303 | 304 | | -| C2::operator== | true | 304 | 307 | | -| C2::operator== | true | 307 | 310 | | -| C2::operator== | true | 310 | 312 | | -| C2::operator== | true | 312 | 159 | | -| C2::operator== | true | 314 | 301 | | -| C2::~C2 | false | 316 | 316 | ~C2 | -| C2::~C2 | false | 321 | 321 | ; | -| C2::~C2 | false | 323 | 323 | return ... | -| C2::~C2 | false | 325 | 325 | { ... } | -| C2::~C2 | true | 321 | 323 | | -| C2::~C2 | true | 323 | 316 | | -| C2::~C2 | true | 325 | 321 | | -| __va_list_tag::operator= | false | 57 | 57 | operator= | -| __va_list_tag::operator= | false | 63 | 63 | operator= | -| f1 | false | 215 | 215 | f1 | -| f1 | false | 220 | 220 | if (...) ... | -| f1 | false | 234 | 234 | call to operator== | -| f1 | false | 235 | 235 | call to C1 | -| f1 | false | 240 | 240 | 1 | -| f1 | false | 241 | 241 | temporary object | -| f1 | false | 242 | 242 | (const C1)... | -| f1 | false | 243 | 243 | call to C1 | -| f1 | false | 247 | 247 | 2 | -| f1 | false | 248 | 248 | temporary object | -| f1 | false | 249 | 249 | (const C1)... | -| f1 | false | 250 | 250 | (reference to) | -| f1 | false | 251 | 251 | ; | -| f1 | false | 253 | 253 | { ... } | -| f1 | false | 255 | 255 | if (...) ... | -| f1 | false | 258 | 258 | call to operator== | -| f1 | false | 259 | 259 | call to C1 | -| f1 | false | 263 | 263 | 3 | -| f1 | false | 264 | 264 | temporary object | -| f1 | false | 265 | 265 | (const C1)... | -| f1 | false | 266 | 266 | call to C1 | -| f1 | false | 270 | 270 | 3 | -| f1 | false | 271 | 271 | temporary object | -| f1 | false | 272 | 272 | (const C1)... | -| f1 | false | 273 | 273 | (reference to) | -| f1 | false | 274 | 274 | ; | -| f1 | false | 276 | 276 | { ... } | -| f1 | false | 278 | 278 | return ... | -| f1 | false | 280 | 280 | { ... } | -| f1 | true | 220 | 247 | | -| f1 | true | 234 | 253 | T | -| f1 | true | 234 | 255 | F | -| f1 | true | 235 | 234 | | -| f1 | true | 240 | 235 | | -| f1 | true | 243 | 240 | | -| f1 | true | 247 | 243 | | -| f1 | true | 251 | 255 | | -| f1 | true | 253 | 251 | | -| f1 | true | 255 | 270 | | -| f1 | true | 258 | 276 | T | -| f1 | true | 258 | 278 | F | -| f1 | true | 259 | 258 | | -| f1 | true | 263 | 259 | | -| f1 | true | 266 | 263 | | -| f1 | true | 270 | 266 | | -| f1 | true | 274 | 278 | | -| f1 | true | 276 | 274 | | -| f1 | true | 278 | 215 | | -| f1 | true | 280 | 220 | | -| f2 | false | 148 | 148 | f2 | -| f2 | false | 153 | 153 | if (...) ... | -| f2 | false | 167 | 167 | call to operator== | -| f2 | false | 168 | 168 | call to C2 | -| f2 | false | 173 | 173 | 1 | -| f2 | false | 174 | 174 | temporary object | -| f2 | false | 175 | 175 | (const C2)... | -| f2 | false | 176 | 176 | call to C2 | -| f2 | false | 180 | 180 | 2 | -| f2 | false | 181 | 181 | temporary object | -| f2 | false | 182 | 182 | (const C2)... | -| f2 | false | 183 | 183 | (reference to) | -| f2 | false | 184 | 184 | ; | -| f2 | false | 186 | 186 | { ... } | -| f2 | false | 188 | 188 | if (...) ... | -| f2 | false | 191 | 191 | call to operator== | -| f2 | false | 192 | 192 | call to C2 | -| f2 | false | 196 | 196 | 3 | -| f2 | false | 197 | 197 | temporary object | +| C1::C1 | false | 305 | 305 | C1 | +| C1::C1 | false | 473 | 473 | C1 | +| C1::C1 | false | 477 | 477 | C1 | +| C1::C1 | false | 521 | 521 | ExprStmt | +| C1::C1 | false | 524 | 524 | this | +| C1::C1 | false | 526 | 526 | val | +| C1::C1 | false | 529 | 529 | x | +| C1::C1 | false | 532 | 532 | ... = ... | +| C1::C1 | false | 535 | 535 | return ... | +| C1::C1 | false | 538 | 538 | { ... } | +| C1::C1 | true | 521 | 529 | | +| C1::C1 | true | 524 | 526 | | +| C1::C1 | true | 526 | 532 | | +| C1::C1 | true | 529 | 524 | | +| C1::C1 | true | 532 | 535 | | +| C1::C1 | true | 535 | 305 | | +| C1::C1 | true | 538 | 521 | | +| C1::operator= | false | 462 | 462 | operator= | +| C1::operator= | false | 469 | 469 | operator= | +| C1::operator== | false | 292 | 292 | operator== | +| C1::operator== | false | 491 | 491 | return ... | +| C1::operator== | false | 494 | 494 | this | +| C1::operator== | false | 496 | 496 | val | +| C1::operator== | false | 500 | 500 | other | +| C1::operator== | false | 503 | 503 | (reference dereference) | +| C1::operator== | false | 505 | 505 | val | +| C1::operator== | false | 508 | 508 | ... == ... | +| C1::operator== | false | 511 | 511 | { ... } | +| C1::operator== | true | 491 | 494 | | +| C1::operator== | true | 494 | 496 | | +| C1::operator== | true | 496 | 500 | | +| C1::operator== | true | 500 | 505 | | +| C1::operator== | true | 505 | 508 | | +| C1::operator== | true | 508 | 292 | | +| C1::operator== | true | 511 | 491 | | +| C2::C2 | false | 189 | 189 | C2 | +| C2::C2 | false | 385 | 385 | C2 | +| C2::C2 | false | 442 | 442 | ExprStmt | +| C2::C2 | false | 445 | 445 | this | +| C2::C2 | false | 447 | 447 | val | +| C2::C2 | false | 450 | 450 | x | +| C2::C2 | false | 453 | 453 | ... = ... | +| C2::C2 | false | 456 | 456 | return ... | +| C2::C2 | false | 459 | 459 | { ... } | +| C2::C2 | true | 442 | 450 | | +| C2::C2 | true | 445 | 447 | | +| C2::C2 | true | 447 | 453 | | +| C2::C2 | true | 450 | 445 | | +| C2::C2 | true | 453 | 456 | | +| C2::C2 | true | 456 | 189 | | +| C2::C2 | true | 459 | 442 | | +| C2::operator= | false | 379 | 379 | operator= | +| C2::operator== | false | 176 | 176 | operator== | +| C2::operator== | false | 399 | 399 | return ... | +| C2::operator== | false | 402 | 402 | this | +| C2::operator== | false | 404 | 404 | val | +| C2::operator== | false | 408 | 408 | other | +| C2::operator== | false | 411 | 411 | (reference dereference) | +| C2::operator== | false | 413 | 413 | val | +| C2::operator== | false | 416 | 416 | ... == ... | +| C2::operator== | false | 419 | 419 | { ... } | +| C2::operator== | true | 399 | 402 | | +| C2::operator== | true | 402 | 404 | | +| C2::operator== | true | 404 | 408 | | +| C2::operator== | true | 408 | 413 | | +| C2::operator== | true | 413 | 416 | | +| C2::operator== | true | 416 | 176 | | +| C2::operator== | true | 419 | 399 | | +| C2::~C2 | false | 267 | 267 | ~C2 | +| C2::~C2 | false | 426 | 426 | ; | +| C2::~C2 | false | 429 | 429 | return ... | +| C2::~C2 | false | 432 | 432 | { ... } | +| C2::~C2 | true | 426 | 429 | | +| C2::~C2 | true | 429 | 267 | | +| C2::~C2 | true | 432 | 426 | | +| __va_list_tag::operator= | false | 66 | 66 | operator= | +| __va_list_tag::operator= | false | 72 | 72 | operator= | +| f1 | false | 280 | 280 | f1 | +| f1 | false | 286 | 286 | if (...) ... | +| f1 | false | 301 | 301 | call to operator== | +| f1 | false | 303 | 303 | call to C1 | +| f1 | false | 310 | 310 | 1 | +| f1 | false | 312 | 312 | temporary object | +| f1 | false | 314 | 314 | (const C1)... | +| f1 | false | 316 | 316 | call to C1 | +| f1 | false | 322 | 322 | 2 | +| f1 | false | 324 | 324 | temporary object | +| f1 | false | 326 | 326 | (const C1)... | +| f1 | false | 328 | 328 | (reference to) | +| f1 | false | 330 | 330 | ; | +| f1 | false | 333 | 333 | { ... } | +| f1 | false | 336 | 336 | if (...) ... | +| f1 | false | 340 | 340 | call to operator== | +| f1 | false | 342 | 342 | call to C1 | +| f1 | false | 348 | 348 | 3 | +| f1 | false | 350 | 350 | temporary object | +| f1 | false | 352 | 352 | (const C1)... | +| f1 | false | 354 | 354 | call to C1 | +| f1 | false | 360 | 360 | 3 | +| f1 | false | 362 | 362 | temporary object | +| f1 | false | 364 | 364 | (const C1)... | +| f1 | false | 366 | 366 | (reference to) | +| f1 | false | 368 | 368 | ; | +| f1 | false | 371 | 371 | { ... } | +| f1 | false | 374 | 374 | return ... | +| f1 | false | 377 | 377 | { ... } | +| f1 | true | 286 | 322 | | +| f1 | true | 301 | 333 | T | +| f1 | true | 301 | 336 | F | +| f1 | true | 303 | 301 | | +| f1 | true | 310 | 303 | | +| f1 | true | 316 | 310 | | +| f1 | true | 322 | 316 | | +| f1 | true | 330 | 336 | | +| f1 | true | 333 | 330 | | +| f1 | true | 336 | 360 | | +| f1 | true | 340 | 371 | T | +| f1 | true | 340 | 374 | F | +| f1 | true | 342 | 340 | | +| f1 | true | 348 | 342 | | +| f1 | true | 354 | 348 | | +| f1 | true | 360 | 354 | | +| f1 | true | 368 | 374 | | +| f1 | true | 371 | 368 | | +| f1 | true | 374 | 280 | | +| f1 | true | 377 | 286 | | +| f2 | false | 164 | 164 | f2 | +| f2 | false | 170 | 170 | if (...) ... | +| f2 | false | 185 | 185 | call to operator== | +| f2 | false | 187 | 187 | call to C2 | +| f2 | false | 194 | 194 | 1 | +| f2 | false | 196 | 196 | temporary object | | f2 | false | 198 | 198 | (const C2)... | -| f2 | false | 199 | 199 | call to C2 | -| f2 | false | 203 | 203 | 3 | -| f2 | false | 204 | 204 | temporary object | -| f2 | false | 205 | 205 | (const C2)... | -| f2 | false | 206 | 206 | (reference to) | -| f2 | false | 207 | 207 | ; | -| f2 | false | 209 | 209 | { ... } | -| f2 | false | 211 | 211 | return ... | -| f2 | false | 213 | 213 | { ... } | -| f2 | true | 153 | 180 | | -| f2 | true | 167 | 186 | T | -| f2 | true | 167 | 188 | F | -| f2 | true | 168 | 167 | | -| f2 | true | 173 | 168 | | -| f2 | true | 176 | 173 | | -| f2 | true | 180 | 176 | | -| f2 | true | 184 | 188 | | -| f2 | true | 186 | 184 | | -| f2 | true | 188 | 203 | | -| f2 | true | 191 | 209 | T | -| f2 | true | 191 | 211 | F | -| f2 | true | 192 | 191 | | -| f2 | true | 196 | 192 | | -| f2 | true | 199 | 196 | | -| f2 | true | 203 | 199 | | -| f2 | true | 207 | 211 | | -| f2 | true | 209 | 207 | | -| f2 | true | 211 | 148 | | -| f2 | true | 213 | 153 | | +| f2 | false | 200 | 200 | call to C2 | +| f2 | false | 206 | 206 | 2 | +| f2 | false | 208 | 208 | temporary object | +| f2 | false | 210 | 210 | (const C2)... | +| f2 | false | 212 | 212 | (reference to) | +| f2 | false | 214 | 214 | ; | +| f2 | false | 217 | 217 | { ... } | +| f2 | false | 220 | 220 | if (...) ... | +| f2 | false | 224 | 224 | call to operator== | +| f2 | false | 226 | 226 | call to C2 | +| f2 | false | 232 | 232 | 3 | +| f2 | false | 234 | 234 | temporary object | +| f2 | false | 236 | 236 | (const C2)... | +| f2 | false | 238 | 238 | call to C2 | +| f2 | false | 244 | 244 | 3 | +| f2 | false | 246 | 246 | temporary object | +| f2 | false | 248 | 248 | (const C2)... | +| f2 | false | 250 | 250 | (reference to) | +| f2 | false | 252 | 252 | ; | +| f2 | false | 255 | 255 | { ... } | +| f2 | false | 258 | 258 | return ... | +| f2 | false | 261 | 261 | { ... } | +| f2 | false | 264 | 264 | reuse of temporary object | +| f2 | false | 266 | 266 | call to ~C2 | +| f2 | false | 269 | 269 | reuse of temporary object | +| f2 | false | 271 | 271 | call to ~C2 | +| f2 | false | 273 | 273 | reuse of temporary object | +| f2 | false | 275 | 275 | call to ~C2 | +| f2 | false | 277 | 277 | reuse of temporary object | +| f2 | false | 279 | 279 | call to ~C2 | +| f2 | true | 170 | 206 | | +| f2 | true | 185 | 217 | T | +| f2 | true | 185 | 220 | F | +| f2 | true | 187 | 185 | | +| f2 | true | 194 | 187 | | +| f2 | true | 200 | 194 | | +| f2 | true | 206 | 200 | | +| f2 | true | 214 | 220 | | +| f2 | true | 217 | 214 | | +| f2 | true | 220 | 244 | | +| f2 | true | 224 | 255 | T | +| f2 | true | 224 | 258 | F | +| f2 | true | 226 | 224 | | +| f2 | true | 232 | 226 | | +| f2 | true | 238 | 232 | | +| f2 | true | 244 | 238 | | +| f2 | true | 252 | 258 | | +| f2 | true | 255 | 252 | | +| f2 | true | 258 | 164 | | +| f2 | true | 261 | 170 | | +| f2 | true | 264 | 266 | | +| f2 | true | 269 | 271 | | +| f2 | true | 271 | 264 | | +| f2 | true | 273 | 275 | | +| f2 | true | 277 | 279 | | +| f2 | true | 279 | 273 | |