mirror of
https://github.com/github/codeql.git
synced 2026-05-01 11:45:14 +02:00
Fix IR for member accesses on prvalues
This fixes the IR generation for member accesses where the qualifier is a prvalue that is _not_ the load of a `TemporaryObjectExpr`. We synthesize a temporary variable during IR generation instead. It fits into the IR construction code at the same spot as `TranslatedLoad`, since it's basically the opposite of `TranslatedLoad` (prvalue->glvalue instead of vice versa). Note that array prvalues require special treatment. This fixes some consistency errors in the `syntax-zoo`. It introduces three new ones in `dataflow-ir-consistency.expected`, but those are along the same lines as tons of existing failures.
This commit is contained in:
@@ -227,6 +227,49 @@ private predicate usedAsCondition(Expr expr) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `expr` is the result of a field access whose qualifier was a prvalue and whose result is
|
||||
* a prvalue. These accesses are not marked as having loads, but we do need a load in the IR.
|
||||
*/
|
||||
private predicate isPRValueFieldAccessWithImplicitLoad(Expr expr) {
|
||||
expr instanceof ValueFieldAccess and
|
||||
expr.isPRValueCategory() and
|
||||
// No need to do a load if we're replacing the result with a constant anyway.
|
||||
not isIRConstant(expr) and
|
||||
// Model an array prvalue as the address of the array, just like an array glvalue.
|
||||
not expr.getUnspecifiedType() instanceof ArrayType
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `expr` is a prvalue of class type that is used directly as the qualifier for a member
|
||||
* access, or is used after undergoing a prvalue adjustment conversion.
|
||||
*/
|
||||
private predicate isClassPRValueForMemberAccessQualifier(Expr expr) {
|
||||
exists(Expr qualifier |
|
||||
exists(FieldAccess access | qualifier = access.getQualifier().getFullyConverted())
|
||||
or
|
||||
exists(Call call | qualifier = call.getQualifier().getFullyConverted())
|
||||
|
|
||||
// The qualifier is a prvalue of class type.
|
||||
qualifier.getUnspecifiedType() instanceof Class and
|
||||
qualifier.isPRValueCategory() and
|
||||
(
|
||||
expr = qualifier and not expr instanceof PrvalueAdjustmentConversion
|
||||
or
|
||||
// If the qualifier is a prvalue adjustment conversion, the actual object with be provided by
|
||||
// the operand of that conversion. For example:
|
||||
// ```c++
|
||||
// std::string("s").c_str();
|
||||
// ```
|
||||
// The object for the qualifier is a prvalue(load) of type `std::string`, but the actual
|
||||
// fully-converted qualifier of the call to `c_str()` is a prvalue adjustment conversion that
|
||||
// converts the type to `const std::string` to match the type of the `this` pointer of the
|
||||
// member function.
|
||||
expr = qualifier.(PrvalueAdjustmentConversion).getExpr()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `expr` has an lvalue-to-rvalue conversion that should be ignored
|
||||
* when generating IR. This occurs for conversion from an lvalue of function type
|
||||
@@ -249,30 +292,9 @@ predicate ignoreLoad(Expr expr) {
|
||||
or
|
||||
// The extractor represents the qualifier of a field access or member function call as a load of
|
||||
// the temporary object if the original qualifier was a prvalue. For IR purposes, we always want
|
||||
// to use the address of the temporary object as the base of a field access or the `this`
|
||||
// to use the address of the temporary object as the qualifier of a field access or the `this`
|
||||
// argument to a member function call.
|
||||
exists(Expr qualifier |
|
||||
exists(FieldAccess access | qualifier = access.getQualifier().getFullyConverted())
|
||||
or
|
||||
exists(Call call | qualifier = call.getQualifier().getFullyConverted())
|
||||
|
|
||||
// The qualifier has a class type.
|
||||
qualifier.getUnspecifiedType() instanceof Class and
|
||||
(
|
||||
expr = qualifier
|
||||
or
|
||||
// If the qualifier is a prvalue adjustment conversion, the load will be on the operand of
|
||||
// that conversion. For example:
|
||||
// ```c++
|
||||
// std::string("s").c_str();
|
||||
// ```
|
||||
// The temporary object for the qualifier is a prvalue(load) of type `std::string`, but the
|
||||
// actual fully converted qualifier of the call to `c_str()` is a prvalue adjustment
|
||||
// conversion that converts the type to `const std::string` to match the type of the `this`
|
||||
// pointer of the member function.
|
||||
expr = qualifier.(PrvalueAdjustmentConversion).getExpr()
|
||||
)
|
||||
)
|
||||
isClassPRValueForMemberAccessQualifier(expr)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -308,6 +330,8 @@ predicate hasTranslatedLoad(Expr expr) {
|
||||
expr.hasLValueToRValueConversion()
|
||||
or
|
||||
needsLoadForParentExpr(expr)
|
||||
or
|
||||
isPRValueFieldAccessWithImplicitLoad(expr)
|
||||
) and
|
||||
not ignoreExpr(expr) and
|
||||
not isNativeCondition(expr) and
|
||||
@@ -315,6 +339,16 @@ predicate hasTranslatedLoad(Expr expr) {
|
||||
not ignoreLoad(expr)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `expr` should have a `TranslatedSyntheticTemporaryObject` on it.
|
||||
*/
|
||||
predicate hasTranslatedSyntheticTemporaryObject(Expr expr) {
|
||||
not ignoreExpr(expr) and
|
||||
isClassPRValueForMemberAccessQualifier(expr) and
|
||||
// If it's a load, we'll just ignore the load in `ignoreLoad()`.
|
||||
not expr.hasLValueToRValueConversion()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the specified `DeclarationEntry` needs an IR translation. An IR translation is only
|
||||
* necessary for automatic local variables, or for static local variables with dynamic
|
||||
@@ -345,6 +379,9 @@ newtype TTranslatedElement =
|
||||
// A separate element to handle the lvalue-to-rvalue conversion step of an
|
||||
// expression.
|
||||
TTranslatedLoad(Expr expr) { hasTranslatedLoad(expr) } or
|
||||
// A temporary object that we had to synthesize ourselves, so that we could do a field access or
|
||||
// method call on a prvalue.
|
||||
TTranslatedSyntheticTemporaryObject(Expr expr) { hasTranslatedSyntheticTemporaryObject(expr) } or
|
||||
// For expressions that would not otherwise generate an instruction.
|
||||
TTranslatedResultCopy(Expr expr) {
|
||||
not ignoreExpr(expr) and
|
||||
|
||||
@@ -110,9 +110,10 @@ abstract class TranslatedCoreExpr extends TranslatedExpr {
|
||||
}
|
||||
|
||||
final override predicate producesExprResult() {
|
||||
// If there's no load, then this is the only TranslatedExpr for this
|
||||
// If there's no load or temp object, then this is the only TranslatedExpr for this
|
||||
// expression.
|
||||
not hasTranslatedLoad(expr) and
|
||||
not hasTranslatedSyntheticTemporaryObject(expr) and
|
||||
// If there's a result copy, then this expression's result is the copy.
|
||||
not exprNeedsCopyIfNotLoaded(expr)
|
||||
}
|
||||
@@ -246,19 +247,35 @@ class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext,
|
||||
private TranslatedCondition getCondition() { result = getTranslatedCondition(expr) }
|
||||
}
|
||||
|
||||
/**
|
||||
* The IR translation of a node synthesized to adjust the value category of its operand.
|
||||
* One of:
|
||||
* - `TranslatedLoad` - Convert from glvalue to prvalue by loading from the location.
|
||||
* - `TranslatedSyntheticTemporaryObject` - Convert from prvalue to glvalue by storing to a
|
||||
* temporary variable.
|
||||
*/
|
||||
abstract class TranslatedValueCategoryAdjustment extends TranslatedExpr {
|
||||
final override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() }
|
||||
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() }
|
||||
|
||||
final override predicate producesExprResult() {
|
||||
// A temp object always produces the result of the expression.
|
||||
any()
|
||||
}
|
||||
|
||||
final TranslatedCoreExpr getOperand() { result.getExpr() = expr }
|
||||
}
|
||||
|
||||
/**
|
||||
* IR translation of an implicit lvalue-to-rvalue conversion on the result of
|
||||
* an expression.
|
||||
*/
|
||||
class TranslatedLoad extends TranslatedExpr, TTranslatedLoad {
|
||||
class TranslatedLoad extends TranslatedValueCategoryAdjustment, TTranslatedLoad {
|
||||
TranslatedLoad() { this = TTranslatedLoad(expr) }
|
||||
|
||||
override string toString() { result = "Load of " + expr.toString() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() }
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getOperand() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = LoadTag() and
|
||||
opcode instanceof Opcode::Load and
|
||||
@@ -286,18 +303,75 @@ class TranslatedLoad extends TranslatedExpr, TTranslatedLoad {
|
||||
result = getOperand().getResult()
|
||||
)
|
||||
}
|
||||
|
||||
final override predicate producesExprResult() {
|
||||
// A load always produces the result of the expression.
|
||||
any()
|
||||
}
|
||||
|
||||
TranslatedCoreExpr getOperand() { result.getExpr() = expr }
|
||||
}
|
||||
|
||||
/**
|
||||
* IR translation of an implicit lvalue-to-rvalue conversion on the result of
|
||||
* an expression.
|
||||
* The IR translation of a temporary object synthesized by the IR to hold a class prvalue on which
|
||||
* a member access is going to be performed. This differs from `TranslatedTemporaryObjectExpr` in
|
||||
* that instances of `TranslatedSyntheticTemporaryObject` are synthesized during IR construction,
|
||||
* whereas `TranslatedTemporaryObjectExpr` instances are created from `TemporaryObjectExpr` nodes
|
||||
* from the AST.
|
||||
*/
|
||||
class TranslatedSyntheticTemporaryObject extends TranslatedValueCategoryAdjustment,
|
||||
TTranslatedSyntheticTemporaryObject {
|
||||
TranslatedSyntheticTemporaryObject() { this = TTranslatedSyntheticTemporaryObject(expr) }
|
||||
|
||||
override string toString() { result = "Temporary materialization of " + expr.toString() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getTypeForGLValue(expr.getType())
|
||||
or
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getTypeForPRValue(expr.getType())
|
||||
}
|
||||
|
||||
override predicate isResultGLValue() { any() }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
result = getInstruction(InitializerStoreTag()) and
|
||||
kind instanceof GotoEdge
|
||||
or
|
||||
tag = InitializerStoreTag() and
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getOperand() and result = getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
override Instruction getResult() { result = getInstruction(InitializerVariableAddressTag()) }
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = InitializerStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = getOperand().getResult()
|
||||
)
|
||||
}
|
||||
|
||||
final override predicate hasTempVariable(TempVariableTag tag, CppType type) {
|
||||
tag = TempObjectTempVar() and
|
||||
type = getTypeForPRValue(expr.getType())
|
||||
}
|
||||
|
||||
final override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
result = getIRTempVariable(expr, TempObjectTempVar())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* IR translation of an expression that simply returns its result. We generate an otherwise useless
|
||||
* `CopyValue` instruction for these expressions so that there is at least one instruction
|
||||
* associated with the expression.
|
||||
*/
|
||||
class TranslatedResultCopy extends TranslatedExpr, TTranslatedResultCopy {
|
||||
TranslatedResultCopy() { this = TTranslatedResultCopy(expr) }
|
||||
|
||||
@@ -10656,6 +10656,8 @@ ir.cpp:
|
||||
# 1363| params:
|
||||
# 1363| [TemplateFunction,TopLevelFunction] T returnValue<T>()
|
||||
# 1363| params:
|
||||
# 1363| [FunctionTemplateInstantiation,TopLevelFunction] UnusualFields returnValue<UnusualFields>()
|
||||
# 1363| params:
|
||||
# 1363| [FunctionTemplateInstantiation,TopLevelFunction] copy_constructor returnValue<copy_constructor>()
|
||||
# 1363| params:
|
||||
# 1363| [FunctionTemplateInstantiation,TopLevelFunction] destructor_only returnValue<destructor_only>()
|
||||
@@ -11061,6 +11063,104 @@ ir.cpp:
|
||||
# 1413| Type = [Struct] Point
|
||||
# 1413| ValueCategory = prvalue
|
||||
# 1414| 7: [ReturnStmt] return ...
|
||||
# 1416| [CopyAssignmentOperator] UnusualFields& UnusualFields::operator=(UnusualFields const&)
|
||||
# 1416| params:
|
||||
#-----| 0: [Parameter] (unnamed parameter 0)
|
||||
#-----| Type = [LValueReferenceType] const UnusualFields &
|
||||
# 1416| [Constructor] void UnusualFields::UnusualFields()
|
||||
# 1416| params:
|
||||
# 1416| [CopyConstructor] void UnusualFields::UnusualFields(UnusualFields const&)
|
||||
# 1416| params:
|
||||
#-----| 0: [Parameter] (unnamed parameter 0)
|
||||
#-----| Type = [LValueReferenceType] const UnusualFields &
|
||||
# 1416| [MoveConstructor] void UnusualFields::UnusualFields(UnusualFields&&)
|
||||
# 1416| params:
|
||||
#-----| 0: [Parameter] (unnamed parameter 0)
|
||||
#-----| Type = [RValueReferenceType] UnusualFields &&
|
||||
# 1421| [TopLevelFunction] void temporary_unusual_fields()
|
||||
# 1421| params:
|
||||
# 1421| body: [BlockStmt] { ... }
|
||||
# 1422| 0: [DeclStmt] declaration
|
||||
# 1422| 0: [VariableDeclarationEntry] definition of rx
|
||||
# 1422| Type = [LValueReferenceType] const int &
|
||||
# 1422| init: [Initializer] initializer for rx
|
||||
# 1422| expr: [ReferenceToExpr] (reference to)
|
||||
# 1422| Type = [LValueReferenceType] const int &
|
||||
# 1422| ValueCategory = prvalue
|
||||
# 1422| expr: [CStyleCast] (const int)...
|
||||
# 1422| Conversion = [GlvalueConversion] glvalue conversion
|
||||
# 1422| Type = [SpecifiedType] const int
|
||||
# 1422| ValueCategory = lvalue
|
||||
# 1422| expr: [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 1422| Type = [IntType] int
|
||||
# 1422| ValueCategory = lvalue
|
||||
# 1422| expr: [ValueFieldAccess] r
|
||||
# 1422| Type = [LValueReferenceType] int &
|
||||
# 1422| ValueCategory = prvalue
|
||||
# 1422| -1: [FunctionCall] call to returnValue
|
||||
# 1422| Type = [Struct] UnusualFields
|
||||
# 1422| ValueCategory = prvalue
|
||||
# 1423| 1: [DeclStmt] declaration
|
||||
# 1423| 0: [VariableDeclarationEntry] definition of x
|
||||
# 1423| Type = [IntType] int
|
||||
# 1423| init: [Initializer] initializer for x
|
||||
# 1423| expr: [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 1423| Type = [IntType] int
|
||||
# 1423| ValueCategory = prvalue(load)
|
||||
# 1423| expr: [ValueFieldAccess] r
|
||||
# 1423| Type = [LValueReferenceType] int &
|
||||
# 1423| ValueCategory = prvalue
|
||||
# 1423| -1: [FunctionCall] call to returnValue
|
||||
# 1423| Type = [Struct] UnusualFields
|
||||
# 1423| ValueCategory = prvalue
|
||||
# 1425| 2: [DeclStmt] declaration
|
||||
# 1425| 0: [VariableDeclarationEntry] definition of rf
|
||||
# 1425| Type = [LValueReferenceType] const float &
|
||||
# 1425| init: [Initializer] initializer for rf
|
||||
# 1425| expr: [ReferenceToExpr] (reference to)
|
||||
# 1425| Type = [LValueReferenceType] const float &
|
||||
# 1425| ValueCategory = prvalue
|
||||
# 1425| expr: [CStyleCast] (const float)...
|
||||
# 1425| Conversion = [GlvalueConversion] glvalue conversion
|
||||
# 1425| Type = [SpecifiedType] const float
|
||||
# 1425| ValueCategory = lvalue
|
||||
# 1425| expr: [ArrayExpr] access to array
|
||||
# 1425| Type = [FloatType] float
|
||||
# 1425| ValueCategory = lvalue
|
||||
# 1425| 0: [ArrayToPointerConversion] array to pointer conversion
|
||||
# 1425| Type = [PointerType] float *
|
||||
# 1425| ValueCategory = prvalue
|
||||
# 1425| expr: [ValueFieldAccess] a
|
||||
# 1425| Type = [ArrayType] float[10]
|
||||
# 1425| ValueCategory = prvalue
|
||||
# 1425| -1: [FunctionCall] call to returnValue
|
||||
# 1425| Type = [Struct] UnusualFields
|
||||
# 1425| ValueCategory = prvalue
|
||||
# 1425| 1: [Literal] 3
|
||||
# 1425| Type = [IntType] int
|
||||
# 1425| Value = [Literal] 3
|
||||
# 1425| ValueCategory = prvalue
|
||||
# 1426| 3: [DeclStmt] declaration
|
||||
# 1426| 0: [VariableDeclarationEntry] definition of f
|
||||
# 1426| Type = [FloatType] float
|
||||
# 1426| init: [Initializer] initializer for f
|
||||
# 1426| expr: [ArrayExpr] access to array
|
||||
# 1426| Type = [FloatType] float
|
||||
# 1426| ValueCategory = prvalue(load)
|
||||
# 1426| 0: [ArrayToPointerConversion] array to pointer conversion
|
||||
# 1426| Type = [PointerType] float *
|
||||
# 1426| ValueCategory = prvalue
|
||||
# 1426| expr: [ValueFieldAccess] a
|
||||
# 1426| Type = [ArrayType] float[10]
|
||||
# 1426| ValueCategory = prvalue
|
||||
# 1426| -1: [FunctionCall] call to returnValue
|
||||
# 1426| Type = [Struct] UnusualFields
|
||||
# 1426| ValueCategory = prvalue
|
||||
# 1426| 1: [Literal] 5
|
||||
# 1426| Type = [IntType] int
|
||||
# 1426| Value = [Literal] 5
|
||||
# 1426| ValueCategory = prvalue
|
||||
# 1427| 4: [ReturnStmt] return ...
|
||||
perf-regression.cpp:
|
||||
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
|
||||
# 4| params:
|
||||
|
||||
@@ -22,7 +22,6 @@ wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
nonUniqueEnclosingIRFunction
|
||||
fieldAddressOnNonPointer
|
||||
| ir.cpp:1411:34:1411:34 | FieldAddress: y | FieldAddress instruction 'FieldAddress: y' has an object address operand that is not an address, in function '$@'. | ir.cpp:1404:6:1404:20 | void temporary_point() | void temporary_point() |
|
||||
thisArgumentIsNonPointer
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -22,7 +22,6 @@ wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
nonUniqueEnclosingIRFunction
|
||||
fieldAddressOnNonPointer
|
||||
| ir.cpp:1411:34:1411:34 | FieldAddress: y | FieldAddress instruction 'FieldAddress: y' has an object address operand that is not an address, in function '$@'. | ir.cpp:1404:6:1404:20 | void temporary_point() | void temporary_point() |
|
||||
thisArgumentIsNonPointer
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -1413,4 +1413,17 @@ void temporary_point() {
|
||||
defaultConstruct<Point>();
|
||||
}
|
||||
|
||||
struct UnusualFields {
|
||||
int& r;
|
||||
float a[10];
|
||||
};
|
||||
|
||||
void temporary_unusual_fields() {
|
||||
const int& rx = returnValue<UnusualFields>().r;
|
||||
int x = returnValue<UnusualFields>().r;
|
||||
|
||||
const float& rf = returnValue<UnusualFields>().a[3];
|
||||
float f = returnValue<UnusualFields>().a[5];
|
||||
}
|
||||
|
||||
// semmle-extractor-options: -std=c++17 --clang
|
||||
|
||||
@@ -22,7 +22,6 @@ wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
nonUniqueEnclosingIRFunction
|
||||
fieldAddressOnNonPointer
|
||||
| ir.cpp:1411:34:1411:34 | FieldAddress: y | FieldAddress instruction 'FieldAddress: y' has an object address operand that is not an address, in function '$@'. | ir.cpp:1404:6:1404:20 | void temporary_point() | void temporary_point() |
|
||||
thisArgumentIsNonPointer
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -7753,7 +7753,8 @@ ir.cpp:
|
||||
# 1401| mu1401_5(unknown) = ^CallSideEffect : ~m?
|
||||
# 1401| mu1401_6(copy_constructor) = Store[#temp1401:13] : &:r1401_2, r1401_4
|
||||
# 1401| r1401_7(glval<int>) = FieldAddress[y] : r1401_2
|
||||
# 1401| mu1401_8(int) = Store[y] : &:r1401_1, r1401_7
|
||||
# 1401| r1401_8(int) = Load[?] : &:r1401_7, ~m?
|
||||
# 1401| mu1401_9(int) = Store[y] : &:r1401_1, r1401_8
|
||||
# 1402| v1402_1(void) = NoOp :
|
||||
# 1391| v1391_4(void) = ReturnVoid :
|
||||
# 1391| v1391_5(void) = AliasedUse : ~m?
|
||||
@@ -7796,8 +7797,11 @@ ir.cpp:
|
||||
# 1411| r1411_2(glval<unknown>) = FunctionAddress[returnValue] :
|
||||
# 1411| r1411_3(Point) = Call[returnValue] : func:r1411_2
|
||||
# 1411| mu1411_4(unknown) = ^CallSideEffect : ~m?
|
||||
# 1411| r1411_5(glval<int>) = FieldAddress[y] : r1411_3
|
||||
# 1411| mu1411_6(int) = Store[y] : &:r1411_1, r1411_5
|
||||
# 1411| r1411_5(glval<Point>) = VariableAddress[#temp1411:13] :
|
||||
# 1411| mu1411_6(Point) = Store[#temp1411:13] : &:r1411_5, r1411_3
|
||||
# 1411| r1411_7(glval<int>) = FieldAddress[y] : r1411_5
|
||||
# 1411| r1411_8(int) = Load[?] : &:r1411_7, ~m?
|
||||
# 1411| mu1411_9(int) = Store[y] : &:r1411_1, r1411_8
|
||||
# 1413| r1413_1(glval<unknown>) = FunctionAddress[defaultConstruct] :
|
||||
# 1413| r1413_2(Point) = Call[defaultConstruct] : func:r1413_1
|
||||
# 1413| mu1413_3(unknown) = ^CallSideEffect : ~m?
|
||||
@@ -7806,6 +7810,63 @@ ir.cpp:
|
||||
# 1404| v1404_5(void) = AliasedUse : ~m?
|
||||
# 1404| v1404_6(void) = ExitFunction :
|
||||
|
||||
# 1421| void temporary_unusual_fields()
|
||||
# 1421| Block 0
|
||||
# 1421| v1421_1(void) = EnterFunction :
|
||||
# 1421| mu1421_2(unknown) = AliasedDefinition :
|
||||
# 1421| mu1421_3(unknown) = InitializeNonLocal :
|
||||
# 1422| r1422_1(glval<int &>) = VariableAddress[rx] :
|
||||
# 1422| r1422_2(glval<unknown>) = FunctionAddress[returnValue] :
|
||||
# 1422| r1422_3(UnusualFields) = Call[returnValue] : func:r1422_2
|
||||
# 1422| mu1422_4(unknown) = ^CallSideEffect : ~m?
|
||||
# 1422| r1422_5(glval<UnusualFields>) = VariableAddress[#temp1422:21] :
|
||||
# 1422| mu1422_6(UnusualFields) = Store[#temp1422:21] : &:r1422_5, r1422_3
|
||||
# 1422| r1422_7(glval<int &>) = FieldAddress[r] : r1422_5
|
||||
# 1422| r1422_8(int &) = Load[?] : &:r1422_7, ~m?
|
||||
# 1422| r1422_9(glval<int>) = CopyValue : r1422_8
|
||||
# 1422| r1422_10(glval<int>) = Convert : r1422_9
|
||||
# 1422| r1422_11(int &) = CopyValue : r1422_10
|
||||
# 1422| mu1422_12(int &) = Store[rx] : &:r1422_1, r1422_11
|
||||
# 1423| r1423_1(glval<int>) = VariableAddress[x] :
|
||||
# 1423| r1423_2(glval<unknown>) = FunctionAddress[returnValue] :
|
||||
# 1423| r1423_3(UnusualFields) = Call[returnValue] : func:r1423_2
|
||||
# 1423| mu1423_4(unknown) = ^CallSideEffect : ~m?
|
||||
# 1423| r1423_5(glval<UnusualFields>) = VariableAddress[#temp1423:13] :
|
||||
# 1423| mu1423_6(UnusualFields) = Store[#temp1423:13] : &:r1423_5, r1423_3
|
||||
# 1423| r1423_7(glval<int &>) = FieldAddress[r] : r1423_5
|
||||
# 1423| r1423_8(int &) = Load[?] : &:r1423_7, ~m?
|
||||
# 1423| r1423_9(int) = Load[?] : &:r1423_8, ~m?
|
||||
# 1423| mu1423_10(int) = Store[x] : &:r1423_1, r1423_9
|
||||
# 1425| r1425_1(glval<float &>) = VariableAddress[rf] :
|
||||
# 1425| r1425_2(glval<unknown>) = FunctionAddress[returnValue] :
|
||||
# 1425| r1425_3(UnusualFields) = Call[returnValue] : func:r1425_2
|
||||
# 1425| mu1425_4(unknown) = ^CallSideEffect : ~m?
|
||||
# 1425| r1425_5(glval<UnusualFields>) = VariableAddress[#temp1425:23] :
|
||||
# 1425| mu1425_6(UnusualFields) = Store[#temp1425:23] : &:r1425_5, r1425_3
|
||||
# 1425| r1425_7(glval<float[10]>) = FieldAddress[a] : r1425_5
|
||||
# 1425| r1425_8(float *) = Convert : r1425_7
|
||||
# 1425| r1425_9(int) = Constant[3] :
|
||||
# 1425| r1425_10(glval<float>) = PointerAdd[4] : r1425_8, r1425_9
|
||||
# 1425| r1425_11(glval<float>) = Convert : r1425_10
|
||||
# 1425| r1425_12(float &) = CopyValue : r1425_11
|
||||
# 1425| mu1425_13(float &) = Store[rf] : &:r1425_1, r1425_12
|
||||
# 1426| r1426_1(glval<float>) = VariableAddress[f] :
|
||||
# 1426| r1426_2(glval<unknown>) = FunctionAddress[returnValue] :
|
||||
# 1426| r1426_3(UnusualFields) = Call[returnValue] : func:r1426_2
|
||||
# 1426| mu1426_4(unknown) = ^CallSideEffect : ~m?
|
||||
# 1426| r1426_5(glval<UnusualFields>) = VariableAddress[#temp1426:15] :
|
||||
# 1426| mu1426_6(UnusualFields) = Store[#temp1426:15] : &:r1426_5, r1426_3
|
||||
# 1426| r1426_7(glval<float[10]>) = FieldAddress[a] : r1426_5
|
||||
# 1426| r1426_8(float *) = Convert : r1426_7
|
||||
# 1426| r1426_9(int) = Constant[5] :
|
||||
# 1426| r1426_10(glval<float>) = PointerAdd[4] : r1426_8, r1426_9
|
||||
# 1426| r1426_11(float) = Load[?] : &:r1426_10, ~m?
|
||||
# 1426| mu1426_12(float) = Store[f] : &:r1426_1, r1426_11
|
||||
# 1427| v1427_1(void) = NoOp :
|
||||
# 1421| v1421_4(void) = ReturnVoid :
|
||||
# 1421| v1421_5(void) = AliasedUse : ~m?
|
||||
# 1421| v1421_6(void) = ExitFunction :
|
||||
|
||||
perf-regression.cpp:
|
||||
# 6| void Big::Big()
|
||||
# 6| Block 0
|
||||
|
||||
@@ -22,7 +22,6 @@ wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
nonUniqueEnclosingIRFunction
|
||||
fieldAddressOnNonPointer
|
||||
| ir.cpp:1411:34:1411:34 | FieldAddress: y | FieldAddress instruction 'FieldAddress: y' has an object address operand that is not an address, in function '$@'. | ir.cpp:1404:6:1404:20 | void temporary_point() | void temporary_point() |
|
||||
thisArgumentIsNonPointer
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -22,7 +22,6 @@ wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
nonUniqueEnclosingIRFunction
|
||||
fieldAddressOnNonPointer
|
||||
| ir.cpp:1411:34:1411:34 | FieldAddress: y | FieldAddress instruction 'FieldAddress: y' has an object address operand that is not an address, in function '$@'. | ir.cpp:1404:6:1404:20 | void temporary_point() | void temporary_point() |
|
||||
thisArgumentIsNonPointer
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -13,7 +13,6 @@ instructionWithoutSuccessor
|
||||
| condition_decls.cpp:41:22:41:23 | Chi: call to BoxedInt | Instruction 'Chi: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:40:6:40:20 | void while_decl_bind(int) | void while_decl_bind(int) |
|
||||
| condition_decls.cpp:48:52:48:53 | Chi: call to BoxedInt | Instruction 'Chi: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:47:6:47:18 | void for_decl_bind(int) | void for_decl_bind(int) |
|
||||
| misc.c:171:10:171:13 | Uninitialized: definition of str2 | Instruction 'Uninitialized: definition of str2' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() |
|
||||
| misc.c:219:47:219:48 | InitializeIndirection: sp | Instruction 'InitializeIndirection: sp' has no successors in function '$@'. | misc.c:219:5:219:26 | int assign_designated_init(someStruct*) | int assign_designated_init(someStruct*) |
|
||||
| ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x | Instruction 'Uninitialized: definition of x' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) |
|
||||
| ms_try_mix.cpp:11:12:11:15 | Chi: call to C | Instruction 'Chi: call to C' has no successors in function '$@'. | ms_try_mix.cpp:10:6:10:18 | void ms_except_mix(int) | void ms_except_mix(int) |
|
||||
| ms_try_mix.cpp:28:12:28:15 | Chi: call to C | Instruction 'Chi: call to C' has no successors in function '$@'. | ms_try_mix.cpp:27:6:27:19 | void ms_finally_mix(int) | void ms_finally_mix(int) |
|
||||
|
||||
@@ -1558,6 +1558,9 @@ postWithInFlow
|
||||
| misc.c:158:14:158:18 | Chi | PostUpdateNode should not be the target of local flow. |
|
||||
| misc.c:160:31:160:33 | Chi | PostUpdateNode should not be the target of local flow. |
|
||||
| misc.c:160:31:160:33 | Chi | PostUpdateNode should not be the target of local flow. |
|
||||
| misc.c:220:3:223:3 | Chi | PostUpdateNode should not be the target of local flow. |
|
||||
| misc.c:221:10:221:10 | Chi | PostUpdateNode should not be the target of local flow. |
|
||||
| misc.c:222:10:222:10 | Chi | PostUpdateNode should not be the target of local flow. |
|
||||
| range_analysis.c:102:5:102:15 | Chi | PostUpdateNode should not be the target of local flow. |
|
||||
| static_init_templates.cpp:3:2:3:8 | Chi | PostUpdateNode should not be the target of local flow. |
|
||||
| static_init_templates.cpp:21:2:21:12 | Chi | PostUpdateNode should not be the target of local flow. |
|
||||
|
||||
@@ -4,9 +4,6 @@ missingOperand
|
||||
| condition_decls.cpp:41:9:41:23 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:40:6:40:20 | void while_decl_bind(int) | void while_decl_bind(int) |
|
||||
| condition_decls.cpp:48:39:48:53 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:47:6:47:18 | void for_decl_bind(int) | void for_decl_bind(int) |
|
||||
| misc.c:125:5:125:11 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:97:6:97:10 | void misc3() | void misc3() |
|
||||
| misc.c:220:3:223:3 | Store: ... = ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | misc.c:219:5:219:26 | int assign_designated_init(someStruct*) | int assign_designated_init(someStruct*) |
|
||||
| misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | int assign_designated_init(someStruct*) | int assign_designated_init(someStruct*) |
|
||||
| misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | int assign_designated_init(someStruct*) | int assign_designated_init(someStruct*) |
|
||||
| try_catch.cpp:23:5:23:18 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | try_catch.cpp:19:6:19:23 | void throw_from_nonstmt(int) | void throw_from_nonstmt(int) |
|
||||
unexpectedOperand
|
||||
duplicateOperand
|
||||
@@ -34,9 +31,6 @@ instructionWithoutSuccessor
|
||||
| misc.c:174:17:174:22 | CallSideEffect: call to getInt | Instruction 'CallSideEffect: call to getInt' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() |
|
||||
| misc.c:174:30:174:35 | CallSideEffect: call to getInt | Instruction 'CallSideEffect: call to getInt' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() |
|
||||
| misc.c:174:55:174:60 | Store: (char ****)... | Instruction 'Store: (char ****)...' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() |
|
||||
| misc.c:219:47:219:48 | InitializeIndirection: sp | Instruction 'InitializeIndirection: sp' has no successors in function '$@'. | misc.c:219:5:219:26 | int assign_designated_init(someStruct*) | int assign_designated_init(someStruct*) |
|
||||
| misc.c:221:10:221:10 | Store: 1 | Instruction 'Store: 1' has no successors in function '$@'. | misc.c:219:5:219:26 | int assign_designated_init(someStruct*) | int assign_designated_init(someStruct*) |
|
||||
| misc.c:222:10:222:10 | Store: 2 | Instruction 'Store: 2' has no successors in function '$@'. | misc.c:219:5:219:26 | int assign_designated_init(someStruct*) | int assign_designated_init(someStruct*) |
|
||||
| ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x | Instruction 'Uninitialized: definition of x' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) |
|
||||
| ms_try_except.cpp:7:13:7:17 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) |
|
||||
| ms_try_except.cpp:9:19:9:19 | Load: j | Instruction 'Load: j' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) |
|
||||
@@ -150,8 +144,6 @@ wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
nonUniqueEnclosingIRFunction
|
||||
fieldAddressOnNonPointer
|
||||
| misc.c:220:9:223:3 | FieldAddress: {...} | FieldAddress instruction 'FieldAddress: {...}' has an object address operand that is not an address, in function '$@'. | misc.c:219:5:219:26 | int assign_designated_init(someStruct*) | int assign_designated_init(someStruct*) |
|
||||
| misc.c:220:9:223:3 | FieldAddress: {...} | FieldAddress instruction 'FieldAddress: {...}' has an object address operand that is not an address, in function '$@'. | misc.c:219:5:219:26 | int assign_designated_init(someStruct*) | int assign_designated_init(someStruct*) |
|
||||
thisArgumentIsNonPointer
|
||||
| pmcallexpr.cpp:8:2:8:15 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() |
|
||||
| pointer_to_member.cpp:23:5:23:54 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) |
|
||||
|
||||
@@ -13,7 +13,6 @@ instructionWithoutSuccessor
|
||||
| condition_decls.cpp:41:22:41:23 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:40:6:40:20 | void while_decl_bind(int) | void while_decl_bind(int) |
|
||||
| condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:47:6:47:18 | void for_decl_bind(int) | void for_decl_bind(int) |
|
||||
| misc.c:171:10:171:13 | Uninitialized: definition of str2 | Instruction 'Uninitialized: definition of str2' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() |
|
||||
| misc.c:219:47:219:48 | InitializeIndirection: sp | Instruction 'InitializeIndirection: sp' has no successors in function '$@'. | misc.c:219:5:219:26 | int assign_designated_init(someStruct*) | int assign_designated_init(someStruct*) |
|
||||
| ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x | Instruction 'Uninitialized: definition of x' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) |
|
||||
| ms_try_mix.cpp:11:12:11:15 | IndirectMayWriteSideEffect: call to C | Instruction 'IndirectMayWriteSideEffect: call to C' has no successors in function '$@'. | ms_try_mix.cpp:10:6:10:18 | void ms_except_mix(int) | void ms_except_mix(int) |
|
||||
| ms_try_mix.cpp:28:12:28:15 | IndirectMayWriteSideEffect: call to C | Instruction 'IndirectMayWriteSideEffect: call to C' has no successors in function '$@'. | ms_try_mix.cpp:27:6:27:19 | void ms_finally_mix(int) | void ms_finally_mix(int) |
|
||||
|
||||
Reference in New Issue
Block a user