C++: Handle FunctionAccesses with qualifiers

Also fix the IR generation for these and add more IR tests involving value
categories.
This commit is contained in:
Jeroen Ketema
2023-07-18 16:35:39 +02:00
parent d41d2bc29e
commit aad094bdd0
7 changed files with 380 additions and 3 deletions

View File

@@ -741,6 +741,8 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
or
expr.(VariableAccess).getQualifier() = ele and pred = "getQualifier()"
or
expr.(FunctionAccess).getQualifier() = ele and pred = "getQualifier()"
or
exists(Field f |
expr.(ClassAggregateLiteral).getAFieldExpr(f) = ele and
pred = "getAFieldExpr(" + f.toString() + ")"

View File

@@ -368,6 +368,11 @@ class FunctionAccess extends Access, @routineexpr {
/** Gets the accessed function. */
override Function getTarget() { funbind(underlyingElement(this), unresolveElement(result)) }
/**
* Gets the expression generating the function being accessed.
*/
Expr getQualifier() { this.getChild(-1) = result }
/** Gets a textual representation of this function access. */
override string toString() {
if exists(this.getTarget())

View File

@@ -991,9 +991,19 @@ class TranslatedStructuredBindingVariableAccess extends TranslatedNonConstantExp
class TranslatedFunctionAccess extends TranslatedNonConstantExpr {
override FunctionAccess expr;
override TranslatedElement getChild(int id) { none() }
override TranslatedElement getChild(int id) {
id = 0 and result = this.getQualifier() // Might not exist
}
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
final TranslatedExpr getQualifier() {
result = getTranslatedExpr(expr.getQualifier().getFullyConverted())
}
override Instruction getFirstInstruction() {
if exists(this.getQualifier())
then result = this.getQualifier().getFirstInstruction()
else result = this.getInstruction(OnlyInstructionTag())
}
override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) }
@@ -1014,7 +1024,9 @@ class TranslatedFunctionAccess extends TranslatedNonConstantExpr {
result = expr.getTarget()
}
override Instruction getChildSuccessor(TranslatedElement child) { none() }
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getQualifier() and result = this.getInstruction(OnlyInstructionTag())
}
}
/**

View File

@@ -14731,6 +14731,163 @@ ir.cpp:
# 1970| Type = [IntType] int
# 1970| ValueCategory = prvalue(load)
# 1971| getStmt(2): [ReturnStmt] return ...
# 1973| [CopyAssignmentOperator] ValCat& ValCat::operator=(ValCat const&)
# 1973| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const ValCat &
# 1973| [MoveAssignmentOperator] ValCat& ValCat::operator=(ValCat&&)
# 1973| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] ValCat &&
# 1974| [MemberFunction] ValCat& ValCat::lvalue()
# 1974| <params>:
# 1975| [MemberFunction] ValCat&& ValCat::xvalue()
# 1975| <params>:
# 1976| [MemberFunction] ValCat ValCat::prvalue()
# 1976| <params>:
# 1979| [TopLevelFunction] void value_category_test()
# 1979| <params>:
# 1979| getEntryPoint(): [BlockStmt] { ... }
# 1980| getStmt(0): [DeclStmt] declaration
# 1980| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c
# 1980| Type = [Struct] ValCat
# 1982| getStmt(1): [ExprStmt] ExprStmt
# 1982| getExpr(): [AssignExpr] ... = ...
# 1982| Type = [Struct] ValCat
# 1982| ValueCategory = lvalue
# 1982| getLValue(): [FunctionCall] call to lvalue
# 1982| Type = [LValueReferenceType] ValCat &
# 1982| ValueCategory = prvalue
# 1982| getQualifier(): [VariableAccess] c
# 1982| Type = [Struct] ValCat
# 1982| ValueCategory = lvalue
# 1982| getRValue(): [ClassAggregateLiteral] {...}
# 1982| Type = [Struct] ValCat
# 1982| ValueCategory = prvalue
# 1982| getLValue().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1982| Type = [Struct] ValCat
# 1982| ValueCategory = lvalue
#-----| getRValue().getFullyConverted(): [TemporaryObjectExpr] temporary object
#-----| Type = [Struct] ValCat
#-----| ValueCategory = prvalue(load)
# 1983| getStmt(2): [ExprStmt] ExprStmt
# 1983| getExpr(): [AssignExpr] ... = ...
# 1983| Type = [Struct] ValCat
# 1983| ValueCategory = lvalue
# 1983| getLValue(): [FunctionCall] call to xvalue
# 1983| Type = [RValueReferenceType] ValCat &&
# 1983| ValueCategory = prvalue
# 1983| getQualifier(): [VariableAccess] c
# 1983| Type = [Struct] ValCat
# 1983| ValueCategory = lvalue
# 1983| getRValue(): [ClassAggregateLiteral] {...}
# 1983| Type = [Struct] ValCat
# 1983| ValueCategory = prvalue
# 1983| getLValue().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1983| Type = [Struct] ValCat
# 1983| ValueCategory = lvalue
#-----| getRValue().getFullyConverted(): [TemporaryObjectExpr] temporary object
#-----| Type = [Struct] ValCat
#-----| ValueCategory = prvalue(load)
# 1984| getStmt(3): [ExprStmt] ExprStmt
# 1984| getExpr(): [AssignExpr] ... = ...
# 1984| Type = [Struct] ValCat
# 1984| ValueCategory = lvalue
# 1984| getLValue(): [FunctionCall] call to prvalue
# 1984| Type = [Struct] ValCat
# 1984| ValueCategory = prvalue
# 1984| getQualifier(): [VariableAccess] c
# 1984| Type = [Struct] ValCat
# 1984| ValueCategory = lvalue
# 1984| getRValue(): [ClassAggregateLiteral] {...}
# 1984| Type = [Struct] ValCat
# 1984| ValueCategory = prvalue
# 1984| getLValue().getFullyConverted(): [TemporaryObjectExpr] temporary object
# 1984| Type = [Struct] ValCat
# 1984| ValueCategory = lvalue
#-----| getRValue().getFullyConverted(): [TemporaryObjectExpr] temporary object
#-----| Type = [Struct] ValCat
#-----| ValueCategory = prvalue(load)
# 1985| getStmt(4): [ExprStmt] ExprStmt
# 1985| getExpr(): [AssignExpr] ... = ...
# 1985| Type = [Struct] ValCat
# 1985| ValueCategory = lvalue
# 1985| getLValue(): [FunctionCall] call to lvalue
# 1985| Type = [LValueReferenceType] ValCat &
# 1985| ValueCategory = prvalue
# 1985| getRValue(): [ClassAggregateLiteral] {...}
# 1985| Type = [Struct] ValCat
# 1985| ValueCategory = prvalue
# 1985| getLValue().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1985| Type = [Struct] ValCat
# 1985| ValueCategory = lvalue
#-----| getRValue().getFullyConverted(): [TemporaryObjectExpr] temporary object
#-----| Type = [Struct] ValCat
#-----| ValueCategory = prvalue(load)
# 1986| getStmt(5): [ExprStmt] ExprStmt
# 1986| getExpr(): [AssignExpr] ... = ...
# 1986| Type = [Struct] ValCat
# 1986| ValueCategory = lvalue
# 1986| getLValue(): [FunctionCall] call to xvalue
# 1986| Type = [RValueReferenceType] ValCat &&
# 1986| ValueCategory = prvalue
# 1986| getRValue(): [ClassAggregateLiteral] {...}
# 1986| Type = [Struct] ValCat
# 1986| ValueCategory = prvalue
# 1986| getLValue().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1986| Type = [Struct] ValCat
# 1986| ValueCategory = lvalue
#-----| getRValue().getFullyConverted(): [TemporaryObjectExpr] temporary object
#-----| Type = [Struct] ValCat
#-----| ValueCategory = prvalue(load)
# 1987| getStmt(6): [ExprStmt] ExprStmt
# 1987| getExpr(): [AssignExpr] ... = ...
# 1987| Type = [Struct] ValCat
# 1987| ValueCategory = lvalue
# 1987| getLValue(): [FunctionCall] call to prvalue
# 1987| Type = [Struct] ValCat
# 1987| ValueCategory = prvalue
# 1987| getRValue(): [ClassAggregateLiteral] {...}
# 1987| Type = [Struct] ValCat
# 1987| ValueCategory = prvalue
# 1987| getLValue().getFullyConverted(): [TemporaryObjectExpr] temporary object
# 1987| Type = [Struct] ValCat
# 1987| ValueCategory = lvalue
#-----| getRValue().getFullyConverted(): [TemporaryObjectExpr] temporary object
#-----| Type = [Struct] ValCat
#-----| ValueCategory = prvalue(load)
# 1988| getStmt(7): [ReturnStmt] return ...
# 1990| [TopLevelFunction] void SetStaticFuncPtr()
# 1990| <params>:
# 1990| getEntryPoint(): [BlockStmt] { ... }
# 1991| getStmt(0): [DeclStmt] declaration
# 1991| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c
# 1991| Type = [Class] C
# 1991| getVariable().getInitializer(): [Initializer] initializer for c
# 1991| getExpr(): [ConstructorCall] call to C
# 1991| Type = [VoidType] void
# 1991| ValueCategory = prvalue
# 1992| getStmt(1): [DeclStmt] declaration
# 1992| getDeclarationEntry(0): [VariableDeclarationEntry] definition of pfn
# 1992| Type = [FunctionPointerType] ..(*)(..)
# 1992| getVariable().getInitializer(): [Initializer] initializer for pfn
# 1992| getExpr(): [FunctionAccess] StaticMemberFunction
# 1992| Type = [FunctionPointerType] ..(*)(..)
# 1992| ValueCategory = prvalue(load)
# 1993| getStmt(2): [ExprStmt] ExprStmt
# 1993| getExpr(): [AssignExpr] ... = ...
# 1993| Type = [FunctionPointerType] ..(*)(..)
# 1993| ValueCategory = lvalue
# 1993| getLValue(): [VariableAccess] pfn
# 1993| Type = [FunctionPointerType] ..(*)(..)
# 1993| ValueCategory = lvalue
# 1993| getRValue(): [FunctionAccess] StaticMemberFunction
# 1993| Type = [FunctionPointerType] ..(*)(..)
# 1993| ValueCategory = prvalue
# 1993| getQualifier(): [VariableAccess] c
# 1993| Type = [Class] C
# 1993| ValueCategory = lvalue
# 1994| getStmt(3): [ReturnStmt] return ...
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| <params>:

View File

@@ -1970,4 +1970,27 @@ void test_volatile() {
x;
}
struct ValCat {
static ValCat& lvalue();
static ValCat&& xvalue();
static ValCat prvalue();
};
void value_category_test() {
ValCat c;
c.lvalue() = {};
c.xvalue() = {};
c.prvalue() = {};
ValCat::lvalue() = {};
ValCat::xvalue() = {};
ValCat::prvalue() = {};
}
void SetStaticFuncPtr() {
C c;
int (*pfn)(int) = C::StaticMemberFunction;
pfn = c.StaticMemberFunction;
}
// semmle-extractor-options: -std=c++17 --clang

View File

@@ -678,6 +678,8 @@
| file://:0:0:0:0 | Address | &:r0_1 |
| file://:0:0:0:0 | Address | &:r0_1 |
| file://:0:0:0:0 | Address | &:r0_1 |
| file://:0:0:0:0 | Address | &:r0_1 |
| file://:0:0:0:0 | Address | &:r0_1 |
| file://:0:0:0:0 | Address | &:r0_2 |
| file://:0:0:0:0 | Address | &:r0_3 |
| file://:0:0:0:0 | Address | &:r0_3 |
@@ -702,6 +704,8 @@
| file://:0:0:0:0 | Address | &:r0_3 |
| file://:0:0:0:0 | Address | &:r0_3 |
| file://:0:0:0:0 | Address | &:r0_3 |
| file://:0:0:0:0 | Address | &:r0_4 |
| file://:0:0:0:0 | Address | &:r0_4 |
| file://:0:0:0:0 | Address | &:r0_5 |
| file://:0:0:0:0 | Address | &:r0_5 |
| file://:0:0:0:0 | Address | &:r0_5 |
@@ -714,6 +718,8 @@
| file://:0:0:0:0 | Address | &:r0_6 |
| file://:0:0:0:0 | Address | &:r0_7 |
| file://:0:0:0:0 | Address | &:r0_7 |
| file://:0:0:0:0 | Address | &:r0_7 |
| file://:0:0:0:0 | Address | &:r0_7 |
| file://:0:0:0:0 | Address | &:r0_8 |
| file://:0:0:0:0 | Address | &:r0_8 |
| file://:0:0:0:0 | Address | &:r0_8 |
@@ -724,16 +730,22 @@
| file://:0:0:0:0 | Address | &:r0_9 |
| file://:0:0:0:0 | Address | &:r0_9 |
| file://:0:0:0:0 | Address | &:r0_10 |
| file://:0:0:0:0 | Address | &:r0_10 |
| file://:0:0:0:0 | Address | &:r0_10 |
| file://:0:0:0:0 | Address | &:r0_11 |
| file://:0:0:0:0 | Address | &:r0_11 |
| file://:0:0:0:0 | Address | &:r0_11 |
| file://:0:0:0:0 | Address | &:r0_13 |
| file://:0:0:0:0 | Address | &:r0_13 |
| file://:0:0:0:0 | Address | &:r0_13 |
| file://:0:0:0:0 | Address | &:r0_15 |
| file://:0:0:0:0 | Address | &:r0_15 |
| file://:0:0:0:0 | Address | &:r0_15 |
| file://:0:0:0:0 | Address | &:r0_15 |
| file://:0:0:0:0 | Address | &:r0_16 |
| file://:0:0:0:0 | Address | &:r0_16 |
| file://:0:0:0:0 | Address | &:r0_16 |
| file://:0:0:0:0 | Address | &:r0_16 |
| file://:0:0:0:0 | Address | &:r0_17 |
| file://:0:0:0:0 | Address | &:r0_18 |
| file://:0:0:0:0 | Address | &:r0_18 |
@@ -786,6 +798,12 @@
| file://:0:0:0:0 | Load | m0_2 |
| file://:0:0:0:0 | Load | m0_2 |
| file://:0:0:0:0 | Load | m0_2 |
| file://:0:0:0:0 | Load | m0_2 |
| file://:0:0:0:0 | Load | m0_5 |
| file://:0:0:0:0 | Load | m0_8 |
| file://:0:0:0:0 | Load | m0_11 |
| file://:0:0:0:0 | Load | m0_14 |
| file://:0:0:0:0 | Load | m0_17 |
| file://:0:0:0:0 | Load | m745_6 |
| file://:0:0:0:0 | Load | m754_6 |
| file://:0:0:0:0 | Load | m763_6 |
@@ -843,14 +861,20 @@
| file://:0:0:0:0 | StoreValue | r0_1 |
| file://:0:0:0:0 | StoreValue | r0_1 |
| file://:0:0:0:0 | StoreValue | r0_3 |
| file://:0:0:0:0 | StoreValue | r0_3 |
| file://:0:0:0:0 | StoreValue | r0_4 |
| file://:0:0:0:0 | StoreValue | r0_4 |
| file://:0:0:0:0 | StoreValue | r0_6 |
| file://:0:0:0:0 | StoreValue | r0_6 |
| file://:0:0:0:0 | StoreValue | r0_7 |
| file://:0:0:0:0 | StoreValue | r0_9 |
| file://:0:0:0:0 | StoreValue | r0_9 |
| file://:0:0:0:0 | StoreValue | r0_12 |
| file://:0:0:0:0 | StoreValue | r0_12 |
| file://:0:0:0:0 | StoreValue | r0_13 |
| file://:0:0:0:0 | StoreValue | r0_13 |
| file://:0:0:0:0 | StoreValue | r0_15 |
| file://:0:0:0:0 | StoreValue | r0_18 |
| file://:0:0:0:0 | StoreValue | r0_19 |
| file://:0:0:0:0 | StoreValue | r0_20 |
| file://:0:0:0:0 | StoreValue | r0_22 |
@@ -8968,6 +8992,72 @@
| ir.cpp:1969:18:1969:18 | Address | &:r1969_1 |
| ir.cpp:1970:5:1970:5 | Address | &:r1970_1 |
| ir.cpp:1970:5:1970:5 | Load | m1969_2 |
| ir.cpp:1979:6:1979:24 | ChiPartial | partial:m1979_3 |
| ir.cpp:1979:6:1979:24 | ChiTotal | total:m1979_2 |
| ir.cpp:1979:6:1979:24 | SideEffect | ~m1987_5 |
| ir.cpp:1980:12:1980:12 | Address | &:r1980_1 |
| ir.cpp:1982:5:1982:19 | ChiPartial | partial:m1982_7 |
| ir.cpp:1982:5:1982:19 | ChiTotal | total:m1982_5 |
| ir.cpp:1982:7:1982:12 | CallTarget | func:r1982_2 |
| ir.cpp:1982:7:1982:12 | ChiPartial | partial:m1982_4 |
| ir.cpp:1982:7:1982:12 | ChiTotal | total:m1979_4 |
| ir.cpp:1982:7:1982:12 | SideEffect | ~m1979_4 |
| ir.cpp:1982:7:1982:12 | Unary | r1982_3 |
| ir.cpp:1982:13:1982:16 | Address | &:r1982_6 |
| ir.cpp:1983:5:1983:19 | ChiPartial | partial:m1983_7 |
| ir.cpp:1983:5:1983:19 | ChiTotal | total:m1983_5 |
| ir.cpp:1983:7:1983:12 | CallTarget | func:r1983_2 |
| ir.cpp:1983:7:1983:12 | ChiPartial | partial:m1983_4 |
| ir.cpp:1983:7:1983:12 | ChiTotal | total:m1982_8 |
| ir.cpp:1983:7:1983:12 | SideEffect | ~m1982_8 |
| ir.cpp:1983:7:1983:12 | Unary | r1983_3 |
| ir.cpp:1983:13:1983:16 | Address | &:r1983_6 |
| ir.cpp:1984:5:1984:15 | Address | &:r1984_1 |
| ir.cpp:1984:5:1984:15 | Address | &:r1984_1 |
| ir.cpp:1984:7:1984:13 | CallTarget | func:r1984_3 |
| ir.cpp:1984:7:1984:13 | ChiPartial | partial:m1984_5 |
| ir.cpp:1984:7:1984:13 | ChiTotal | total:m1983_8 |
| ir.cpp:1984:7:1984:13 | SideEffect | ~m1983_8 |
| ir.cpp:1984:7:1984:13 | StoreValue | r1984_4 |
| ir.cpp:1985:5:1985:18 | CallTarget | func:r1985_1 |
| ir.cpp:1985:5:1985:18 | ChiPartial | partial:m1985_3 |
| ir.cpp:1985:5:1985:18 | ChiTotal | total:m1984_6 |
| ir.cpp:1985:5:1985:18 | SideEffect | ~m1984_6 |
| ir.cpp:1985:5:1985:18 | Unary | r1985_2 |
| ir.cpp:1985:5:1985:25 | ChiPartial | partial:m1985_6 |
| ir.cpp:1985:5:1985:25 | ChiTotal | total:m1985_4 |
| ir.cpp:1985:19:1985:22 | Address | &:r1985_5 |
| ir.cpp:1986:5:1986:18 | CallTarget | func:r1986_1 |
| ir.cpp:1986:5:1986:18 | ChiPartial | partial:m1986_3 |
| ir.cpp:1986:5:1986:18 | ChiTotal | total:m1985_7 |
| ir.cpp:1986:5:1986:18 | SideEffect | ~m1985_7 |
| ir.cpp:1986:5:1986:18 | Unary | r1986_2 |
| ir.cpp:1986:5:1986:25 | ChiPartial | partial:m1986_6 |
| ir.cpp:1986:5:1986:25 | ChiTotal | total:m1986_4 |
| ir.cpp:1986:19:1986:22 | Address | &:r1986_5 |
| ir.cpp:1987:5:1987:19 | CallTarget | func:r1987_2 |
| ir.cpp:1987:5:1987:19 | ChiPartial | partial:m1987_4 |
| ir.cpp:1987:5:1987:19 | ChiTotal | total:m1986_7 |
| ir.cpp:1987:5:1987:19 | SideEffect | ~m1986_7 |
| ir.cpp:1987:5:1987:19 | StoreValue | r1987_3 |
| ir.cpp:1987:5:1987:21 | Address | &:r1987_1 |
| ir.cpp:1987:5:1987:21 | Address | &:r1987_1 |
| ir.cpp:1990:6:1990:21 | ChiPartial | partial:m1990_3 |
| ir.cpp:1990:6:1990:21 | ChiTotal | total:m1990_2 |
| ir.cpp:1990:6:1990:21 | SideEffect | ~m1991_6 |
| ir.cpp:1991:7:1991:7 | Address | &:r1991_1 |
| ir.cpp:1991:7:1991:7 | Address | &:r1991_1 |
| ir.cpp:1991:7:1991:7 | Arg(this) | this:r1991_1 |
| ir.cpp:1991:7:1991:7 | CallTarget | func:r1991_3 |
| ir.cpp:1991:7:1991:7 | ChiPartial | partial:m1991_5 |
| ir.cpp:1991:7:1991:7 | ChiPartial | partial:m1991_7 |
| ir.cpp:1991:7:1991:7 | ChiTotal | total:m1990_4 |
| ir.cpp:1991:7:1991:7 | ChiTotal | total:m1991_2 |
| ir.cpp:1991:7:1991:7 | SideEffect | ~m1990_4 |
| ir.cpp:1992:11:1992:13 | Address | &:r1992_1 |
| ir.cpp:1992:23:1992:45 | StoreValue | r1992_2 |
| ir.cpp:1993:5:1993:7 | Address | &:r1993_3 |
| ir.cpp:1993:13:1993:32 | StoreValue | r1993_2 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_7 |

View File

@@ -10368,6 +10368,94 @@ ir.cpp:
# 1968| v1968_5(void) = AliasedUse : ~m?
# 1968| v1968_6(void) = ExitFunction :
# 1979| void value_category_test()
# 1979| Block 0
# 1979| v1979_1(void) = EnterFunction :
# 1979| mu1979_2(unknown) = AliasedDefinition :
# 1979| mu1979_3(unknown) = InitializeNonLocal :
# 1980| r1980_1(glval<ValCat>) = VariableAddress[c] :
# 1980| mu1980_2(ValCat) = Uninitialized[c] : &:r1980_1
#-----| r0_1(glval<ValCat>) = VariableAddress[#temp0:0] :
#-----| mu0_2(ValCat) = Uninitialized[#temp0:0] : &:r0_1
#-----| r0_3(ValCat) = Load[#temp0:0] : &:r0_1, ~m?
# 1982| r1982_1(glval<ValCat>) = VariableAddress[c] :
# 1982| r1982_2(glval<unknown>) = FunctionAddress[lvalue] :
# 1982| r1982_3(ValCat &) = Call[lvalue] : func:r1982_2
# 1982| mu1982_4(unknown) = ^CallSideEffect : ~m?
# 1982| r1982_5(glval<ValCat>) = CopyValue : r1982_3
# 1982| mu1982_6(ValCat) = Store[?] : &:r1982_5, r0_3
#-----| r0_4(glval<ValCat>) = VariableAddress[#temp0:0] :
#-----| mu0_5(ValCat) = Uninitialized[#temp0:0] : &:r0_4
#-----| r0_6(ValCat) = Load[#temp0:0] : &:r0_4, ~m?
# 1983| r1983_1(glval<ValCat>) = VariableAddress[c] :
# 1983| r1983_2(glval<unknown>) = FunctionAddress[xvalue] :
# 1983| r1983_3(ValCat &&) = Call[xvalue] : func:r1983_2
# 1983| mu1983_4(unknown) = ^CallSideEffect : ~m?
# 1983| r1983_5(glval<ValCat>) = CopyValue : r1983_3
# 1983| mu1983_6(ValCat) = Store[?] : &:r1983_5, r0_6
#-----| r0_7(glval<ValCat>) = VariableAddress[#temp0:0] :
#-----| mu0_8(ValCat) = Uninitialized[#temp0:0] : &:r0_7
#-----| r0_9(ValCat) = Load[#temp0:0] : &:r0_7, ~m?
# 1984| r1984_1(glval<ValCat>) = VariableAddress[#temp1984:5] :
# 1984| r1984_2(glval<ValCat>) = VariableAddress[c] :
# 1984| r1984_3(glval<unknown>) = FunctionAddress[prvalue] :
# 1984| r1984_4(ValCat) = Call[prvalue] : func:r1984_3
# 1984| mu1984_5(unknown) = ^CallSideEffect : ~m?
# 1984| mu1984_6(ValCat) = Store[#temp1984:5] : &:r1984_1, r1984_4
# 1984| mu1984_7(ValCat) = Store[#temp1984:5] : &:r1984_1, r0_9
#-----| r0_10(glval<ValCat>) = VariableAddress[#temp0:0] :
#-----| mu0_11(ValCat) = Uninitialized[#temp0:0] : &:r0_10
#-----| r0_12(ValCat) = Load[#temp0:0] : &:r0_10, ~m?
# 1985| r1985_1(glval<unknown>) = FunctionAddress[lvalue] :
# 1985| r1985_2(ValCat &) = Call[lvalue] : func:r1985_1
# 1985| mu1985_3(unknown) = ^CallSideEffect : ~m?
# 1985| r1985_4(glval<ValCat>) = CopyValue : r1985_2
# 1985| mu1985_5(ValCat) = Store[?] : &:r1985_4, r0_12
#-----| r0_13(glval<ValCat>) = VariableAddress[#temp0:0] :
#-----| mu0_14(ValCat) = Uninitialized[#temp0:0] : &:r0_13
#-----| r0_15(ValCat) = Load[#temp0:0] : &:r0_13, ~m?
# 1986| r1986_1(glval<unknown>) = FunctionAddress[xvalue] :
# 1986| r1986_2(ValCat &&) = Call[xvalue] : func:r1986_1
# 1986| mu1986_3(unknown) = ^CallSideEffect : ~m?
# 1986| r1986_4(glval<ValCat>) = CopyValue : r1986_2
# 1986| mu1986_5(ValCat) = Store[?] : &:r1986_4, r0_15
#-----| r0_16(glval<ValCat>) = VariableAddress[#temp0:0] :
#-----| mu0_17(ValCat) = Uninitialized[#temp0:0] : &:r0_16
#-----| r0_18(ValCat) = Load[#temp0:0] : &:r0_16, ~m?
# 1987| r1987_1(glval<ValCat>) = VariableAddress[#temp1987:5] :
# 1987| r1987_2(glval<unknown>) = FunctionAddress[prvalue] :
# 1987| r1987_3(ValCat) = Call[prvalue] : func:r1987_2
# 1987| mu1987_4(unknown) = ^CallSideEffect : ~m?
# 1987| mu1987_5(ValCat) = Store[#temp1987:5] : &:r1987_1, r1987_3
# 1987| mu1987_6(ValCat) = Store[#temp1987:5] : &:r1987_1, r0_18
# 1988| v1988_1(void) = NoOp :
# 1979| v1979_4(void) = ReturnVoid :
# 1979| v1979_5(void) = AliasedUse : ~m?
# 1979| v1979_6(void) = ExitFunction :
# 1990| void SetStaticFuncPtr()
# 1990| Block 0
# 1990| v1990_1(void) = EnterFunction :
# 1990| mu1990_2(unknown) = AliasedDefinition :
# 1990| mu1990_3(unknown) = InitializeNonLocal :
# 1991| r1991_1(glval<C>) = VariableAddress[c] :
# 1991| mu1991_2(C) = Uninitialized[c] : &:r1991_1
# 1991| r1991_3(glval<unknown>) = FunctionAddress[C] :
# 1991| v1991_4(void) = Call[C] : func:r1991_3, this:r1991_1
# 1991| mu1991_5(unknown) = ^CallSideEffect : ~m?
# 1991| mu1991_6(C) = ^IndirectMayWriteSideEffect[-1] : &:r1991_1
# 1992| r1992_1(glval<..(*)(..)>) = VariableAddress[pfn] :
# 1992| r1992_2(..(*)(..)) = FunctionAddress[StaticMemberFunction] :
# 1992| mu1992_3(..(*)(..)) = Store[pfn] : &:r1992_1, r1992_2
# 1993| r1993_1(glval<C>) = VariableAddress[c] :
# 1993| r1993_2(..(*)(..)) = FunctionAddress[StaticMemberFunction] :
# 1993| r1993_3(glval<..(*)(..)>) = VariableAddress[pfn] :
# 1993| mu1993_4(..(*)(..)) = Store[pfn] : &:r1993_3, r1993_2
# 1994| v1994_1(void) = NoOp :
# 1990| v1990_4(void) = ReturnVoid :
# 1990| v1990_5(void) = AliasedUse : ~m?
# 1990| v1990_6(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0