mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Replace TypePointer
with Type const*
This commit is contained in:
parent
8c583784c0
commit
e197ebbdd1
@ -308,7 +308,7 @@ void ConstantEvaluator::endVisit(UnaryOperation const& _operation)
|
||||
if (!value)
|
||||
return;
|
||||
|
||||
TypePointer resultType = value->type->unaryOperatorResult(_operation.getOperator());
|
||||
Type const* resultType = value->type->unaryOperatorResult(_operation.getOperator());
|
||||
if (!resultType)
|
||||
return;
|
||||
value = convertType(value, *resultType);
|
||||
@ -340,7 +340,7 @@ void ConstantEvaluator::endVisit(BinaryOperation const& _operation)
|
||||
if (TokenTraits::isCompareOp(_operation.getOperator()))
|
||||
return;
|
||||
|
||||
TypePointer resultType = left->type->binaryOperatorResult(_operation.getOperator(), right->type);
|
||||
Type const* resultType = left->type->binaryOperatorResult(_operation.getOperator(), right->type);
|
||||
if (!resultType)
|
||||
{
|
||||
m_errorReporter.fatalTypeError(
|
||||
|
@ -48,7 +48,7 @@ class ConstantEvaluator: private ASTConstVisitor
|
||||
public:
|
||||
struct TypedRational
|
||||
{
|
||||
TypePointer type;
|
||||
Type const* type;
|
||||
rational value;
|
||||
};
|
||||
|
||||
|
@ -474,7 +474,7 @@ void ContractLevelChecker::checkBaseABICompatibility(ContractDefinition const& _
|
||||
|
||||
auto const& currentLoc = func.second->declaration().location();
|
||||
|
||||
for (TypePointer const& paramType: func.second->parameterTypes() + func.second->returnParameterTypes())
|
||||
for (Type const* paramType: func.second->parameterTypes() + func.second->returnParameterTypes())
|
||||
if (!TypeChecker::typeSupportedByOldABIEncoder(*paramType, false))
|
||||
{
|
||||
errors.append("Type only supported by ABIEncoderV2", currentLoc);
|
||||
|
@ -239,8 +239,8 @@ void DeclarationTypeChecker::endVisit(Mapping const& _mapping)
|
||||
else
|
||||
solAssert(dynamic_cast<ElementaryTypeName const*>(&_mapping.keyType()), "");
|
||||
|
||||
TypePointer keyType = _mapping.keyType().annotation().type;
|
||||
TypePointer valueType = _mapping.valueType().annotation().type;
|
||||
Type const* keyType = _mapping.keyType().annotation().type;
|
||||
Type const* valueType = _mapping.valueType().annotation().type;
|
||||
|
||||
// Convert key type to memory.
|
||||
keyType = TypeProvider::withLocationIfReference(DataLocation::Memory, keyType);
|
||||
@ -255,7 +255,7 @@ void DeclarationTypeChecker::endVisit(ArrayTypeName const& _typeName)
|
||||
if (_typeName.annotation().type)
|
||||
return;
|
||||
|
||||
TypePointer baseType = _typeName.baseType().annotation().type;
|
||||
Type const* baseType = _typeName.baseType().annotation().type;
|
||||
if (!baseType)
|
||||
{
|
||||
solAssert(!m_errorReporter.errors().empty(), "");
|
||||
@ -405,7 +405,7 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable)
|
||||
solAssert(!_variable.hasReferenceOrMappingType(), "Data location not properly set.");
|
||||
}
|
||||
|
||||
TypePointer type = _variable.typeName().annotation().type;
|
||||
Type const* type = _variable.typeName().annotation().type;
|
||||
if (auto ref = dynamic_cast<ReferenceType const*>(type))
|
||||
{
|
||||
bool isPointer = !_variable.isStateVariable();
|
||||
|
@ -76,13 +76,13 @@ bool TypeChecker::checkTypeRequirements(SourceUnit const& _source)
|
||||
return Error::containsOnlyWarnings(m_errorReporter.errors());
|
||||
}
|
||||
|
||||
TypePointer const& TypeChecker::type(Expression const& _expression) const
|
||||
Type const* TypeChecker::type(Expression const& _expression) const
|
||||
{
|
||||
solAssert(!!_expression.annotation().type, "Type requested but not present.");
|
||||
return _expression.annotation().type;
|
||||
}
|
||||
|
||||
TypePointer const& TypeChecker::type(VariableDeclaration const& _variable) const
|
||||
Type const* TypeChecker::type(VariableDeclaration const& _variable) const
|
||||
{
|
||||
solAssert(!!_variable.annotation().type, "Type requested but not present.");
|
||||
return _variable.annotation().type;
|
||||
@ -183,7 +183,7 @@ TypePointers TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall c
|
||||
solAssert(typeArgument, "");
|
||||
if (TypeType const* argTypeType = dynamic_cast<TypeType const*>(type(*typeArgument)))
|
||||
{
|
||||
TypePointer actualType = argTypeType->actualType();
|
||||
Type const* actualType = argTypeType->actualType();
|
||||
solAssert(actualType, "");
|
||||
// We force memory because the parser currently cannot handle
|
||||
// data locations. Furthermore, storage can be a little dangerous and
|
||||
@ -237,7 +237,7 @@ TypePointers TypeChecker::typeCheckMetaTypeFunctionAndRetrieveReturnType(Functio
|
||||
toString(arguments.size()) +
|
||||
" were provided."
|
||||
);
|
||||
TypePointer firstArgType = type(*arguments.front());
|
||||
Type const* firstArgType = type(*arguments.front());
|
||||
|
||||
bool wrongType = false;
|
||||
if (firstArgType->category() == Type::Category::TypeType)
|
||||
@ -502,7 +502,7 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
|
||||
|
||||
// type is filled either by ReferencesResolver directly from the type name or by
|
||||
// TypeChecker at the VariableDeclarationStatement level.
|
||||
TypePointer varType = _variable.annotation().type;
|
||||
Type const* varType = _variable.annotation().type;
|
||||
solAssert(!!varType, "Variable type not provided.");
|
||||
|
||||
if (_variable.value())
|
||||
@ -1152,7 +1152,7 @@ void TypeChecker::endVisit(Return const& _return)
|
||||
m_errorReporter.typeError(8863_error, _return.location(), "Different number of arguments in return statement than in returns declaration.");
|
||||
else
|
||||
{
|
||||
TypePointer const& expected = type(*params->parameters().front());
|
||||
Type const* expected = type(*params->parameters().front());
|
||||
BoolResult result = type(*_return.expression())->isImplicitlyConvertibleTo(*expected);
|
||||
if (!result)
|
||||
m_errorReporter.typeErrorConcatenateDescriptions(
|
||||
@ -1236,7 +1236,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
|
||||
continue;
|
||||
VariableDeclaration const& var = *variables[i];
|
||||
solAssert(!var.value(), "Value has to be tied to statement.");
|
||||
TypePointer const& valueComponentType = valueTypes[i];
|
||||
Type const* valueComponentType = valueTypes[i];
|
||||
solAssert(!!valueComponentType, "");
|
||||
solAssert(var.annotation().type, "");
|
||||
|
||||
@ -1322,10 +1322,10 @@ bool TypeChecker::visit(Conditional const& _conditional)
|
||||
_conditional.trueExpression().accept(*this);
|
||||
_conditional.falseExpression().accept(*this);
|
||||
|
||||
TypePointer trueType = type(_conditional.trueExpression())->mobileType();
|
||||
TypePointer falseType = type(_conditional.falseExpression())->mobileType();
|
||||
Type const* trueType = type(_conditional.trueExpression())->mobileType();
|
||||
Type const* falseType = type(_conditional.falseExpression())->mobileType();
|
||||
|
||||
TypePointer commonType = nullptr;
|
||||
Type const* commonType = nullptr;
|
||||
|
||||
if (!trueType)
|
||||
m_errorReporter.typeError(9717_error, _conditional.trueExpression().location(), "Invalid mobile type in true expression.");
|
||||
@ -1387,7 +1387,7 @@ void TypeChecker::checkExpressionAssignment(Type const& _type, Expression const&
|
||||
m_errorReporter.typeError(5547_error, _expression.location(), "Empty tuple on the left hand side.");
|
||||
|
||||
auto const* tupleType = dynamic_cast<TupleType const*>(&_type);
|
||||
auto const& types = tupleType && tupleExpression->components().size() != 1 ? tupleType->components() : vector<TypePointer> { &_type };
|
||||
auto const& types = tupleType && tupleExpression->components().size() != 1 ? tupleType->components() : vector<Type const*> { &_type };
|
||||
|
||||
solAssert(
|
||||
tupleExpression->components().size() == types.size() || m_errorReporter.hasErrors(),
|
||||
@ -1419,7 +1419,7 @@ bool TypeChecker::visit(Assignment const& _assignment)
|
||||
_assignment.leftHandSide(),
|
||||
_assignment.assignmentOperator() == Token::Assign
|
||||
);
|
||||
TypePointer t = type(_assignment.leftHandSide());
|
||||
Type const* t = type(_assignment.leftHandSide());
|
||||
_assignment.annotation().type = t;
|
||||
_assignment.annotation().isPure = false;
|
||||
_assignment.annotation().isLValue = false;
|
||||
@ -1450,7 +1450,7 @@ bool TypeChecker::visit(Assignment const& _assignment)
|
||||
{
|
||||
// compound assignment
|
||||
_assignment.rightHandSide().accept(*this);
|
||||
TypePointer resultType = t->binaryOperatorResult(
|
||||
Type const* resultType = t->binaryOperatorResult(
|
||||
TokenTraits::AssignmentToBinaryOp(_assignment.assignmentOperator()),
|
||||
type(_assignment.rightHandSide())
|
||||
);
|
||||
@ -1489,7 +1489,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
|
||||
types.push_back(type(*component));
|
||||
}
|
||||
else
|
||||
types.push_back(TypePointer());
|
||||
types.push_back(nullptr);
|
||||
if (components.size() == 1)
|
||||
_tuple.annotation().type = type(*components[0]);
|
||||
else
|
||||
@ -1501,7 +1501,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
|
||||
else
|
||||
{
|
||||
bool isPure = true;
|
||||
TypePointer inlineArrayType = nullptr;
|
||||
Type const* inlineArrayType = nullptr;
|
||||
|
||||
for (size_t i = 0; i < components.size(); ++i)
|
||||
{
|
||||
@ -1581,8 +1581,8 @@ bool TypeChecker::visit(UnaryOperation const& _operation)
|
||||
requireLValue(_operation.subExpression(), false);
|
||||
else
|
||||
_operation.subExpression().accept(*this);
|
||||
TypePointer const& subExprType = type(_operation.subExpression());
|
||||
TypePointer t = type(_operation.subExpression())->unaryOperatorResult(op);
|
||||
Type const* subExprType = type(_operation.subExpression());
|
||||
Type const* t = type(_operation.subExpression())->unaryOperatorResult(op);
|
||||
if (!t)
|
||||
{
|
||||
string description = "Unary operator " + string(TokenTraits::toString(op)) + " cannot be applied to type " + subExprType->toString();
|
||||
@ -1604,10 +1604,10 @@ bool TypeChecker::visit(UnaryOperation const& _operation)
|
||||
|
||||
void TypeChecker::endVisit(BinaryOperation const& _operation)
|
||||
{
|
||||
TypePointer const& leftType = type(_operation.leftExpression());
|
||||
TypePointer const& rightType = type(_operation.rightExpression());
|
||||
Type const* leftType = type(_operation.leftExpression());
|
||||
Type const* rightType = type(_operation.rightExpression());
|
||||
TypeResult result = leftType->binaryOperatorResult(_operation.getOperator(), rightType);
|
||||
TypePointer commonType = result.get();
|
||||
Type const* commonType = result.get();
|
||||
if (!commonType)
|
||||
{
|
||||
m_errorReporter.typeError(
|
||||
@ -1669,17 +1669,17 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
|
||||
}
|
||||
}
|
||||
|
||||
TypePointer TypeChecker::typeCheckTypeConversionAndRetrieveReturnType(
|
||||
Type const* TypeChecker::typeCheckTypeConversionAndRetrieveReturnType(
|
||||
FunctionCall const& _functionCall
|
||||
)
|
||||
{
|
||||
solAssert(*_functionCall.annotation().kind == FunctionCallKind::TypeConversion, "");
|
||||
TypePointer const& expressionType = type(_functionCall.expression());
|
||||
Type const* expressionType = type(_functionCall.expression());
|
||||
|
||||
vector<ASTPointer<Expression const>> const& arguments = _functionCall.arguments();
|
||||
bool const isPositionalCall = _functionCall.names().empty();
|
||||
|
||||
TypePointer resultType = dynamic_cast<TypeType const&>(*expressionType).actualType();
|
||||
Type const* resultType = dynamic_cast<TypeType const&>(*expressionType).actualType();
|
||||
if (arguments.size() != 1)
|
||||
m_errorReporter.typeError(
|
||||
2558_error,
|
||||
@ -2358,7 +2358,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
|
||||
case Type::Category::TypeType:
|
||||
{
|
||||
// Determine type for type conversion or struct construction expressions
|
||||
TypePointer const& actualType = dynamic_cast<TypeType const&>(*expressionType).actualType();
|
||||
Type const* actualType = dynamic_cast<TypeType const&>(*expressionType).actualType();
|
||||
solAssert(!!actualType, "");
|
||||
|
||||
if (actualType->category() == Type::Category::Struct)
|
||||
@ -2610,7 +2610,7 @@ bool TypeChecker::visit(FunctionCallOptions const& _functionCallOptions)
|
||||
|
||||
void TypeChecker::endVisit(NewExpression const& _newExpression)
|
||||
{
|
||||
TypePointer type = _newExpression.typeName().annotation().type;
|
||||
Type const* type = _newExpression.typeName().annotation().type;
|
||||
solAssert(!!type, "Type name not resolved.");
|
||||
|
||||
_newExpression.annotation().isConstant = false;
|
||||
@ -2684,7 +2684,7 @@ void TypeChecker::endVisit(NewExpression const& _newExpression)
|
||||
bool TypeChecker::visit(MemberAccess const& _memberAccess)
|
||||
{
|
||||
_memberAccess.expression().accept(*this);
|
||||
TypePointer exprType = type(_memberAccess.expression());
|
||||
Type const* exprType = type(_memberAccess.expression());
|
||||
ASTString const& memberName = _memberAccess.memberName();
|
||||
|
||||
auto& annotation = _memberAccess.annotation();
|
||||
@ -2972,8 +2972,8 @@ bool TypeChecker::visit(IndexAccess const& _access)
|
||||
{
|
||||
_access.annotation().isConstant = false;
|
||||
_access.baseExpression().accept(*this);
|
||||
TypePointer baseType = type(_access.baseExpression());
|
||||
TypePointer resultType = nullptr;
|
||||
Type const* baseType = type(_access.baseExpression());
|
||||
Type const* resultType = nullptr;
|
||||
bool isLValue = false;
|
||||
bool isPure = *_access.baseExpression().annotation().isPure;
|
||||
Expression const* index = _access.indexExpression();
|
||||
@ -3109,7 +3109,7 @@ bool TypeChecker::visit(IndexRangeAccess const& _access)
|
||||
_access.annotation().isLValue = isLValue;
|
||||
_access.annotation().isPure = isPure;
|
||||
|
||||
TypePointer exprType = type(_access.baseExpression());
|
||||
Type const* exprType = type(_access.baseExpression());
|
||||
if (exprType->category() == Type::Category::TypeType)
|
||||
{
|
||||
m_errorReporter.typeError(1760_error, _access.location(), "Types cannot be sliced.");
|
||||
@ -3157,7 +3157,7 @@ vector<Declaration const*> TypeChecker::cleanOverloadedDeclarations(
|
||||
functionType = declaration->functionType(true);
|
||||
solAssert(functionType, "Failed to determine the function type of the overloaded.");
|
||||
|
||||
for (TypePointer parameter: functionType->parameterTypes() + functionType->returnParameterTypes())
|
||||
for (Type const* parameter: functionType->parameterTypes() + functionType->returnParameterTypes())
|
||||
if (!parameter)
|
||||
m_errorReporter.fatalDeclarationError(3893_error, _identifier.location(), "Function type can not be used in this context.");
|
||||
|
||||
|
@ -57,10 +57,10 @@ public:
|
||||
bool checkTypeRequirements(SourceUnit const& _source);
|
||||
|
||||
/// @returns the type of an expression and asserts that it is present.
|
||||
TypePointer const& type(Expression const& _expression) const;
|
||||
Type const* type(Expression const& _expression) const;
|
||||
/// @returns the type of the given variable and throws if the type is not present
|
||||
/// (this can happen for variables with non-explicit types before their types are resolved)
|
||||
TypePointer const& type(VariableDeclaration const& _variable) const;
|
||||
Type const* type(VariableDeclaration const& _variable) const;
|
||||
|
||||
static bool typeSupportedByOldABIEncoder(Type const& _type, bool _isLibraryCall);
|
||||
|
||||
@ -85,7 +85,7 @@ private:
|
||||
TypePointers typeCheckMetaTypeFunctionAndRetrieveReturnType(FunctionCall const& _functionCall);
|
||||
|
||||
/// Performs type checks and determines result types for type conversion FunctionCall nodes.
|
||||
TypePointer typeCheckTypeConversionAndRetrieveReturnType(
|
||||
Type const* typeCheckTypeConversionAndRetrieveReturnType(
|
||||
FunctionCall const& _functionCall
|
||||
);
|
||||
|
||||
|
@ -78,7 +78,7 @@ ImportAnnotation& ImportDirective::annotation() const
|
||||
return initAnnotation<ImportAnnotation>();
|
||||
}
|
||||
|
||||
TypePointer ImportDirective::type() const
|
||||
Type const* ImportDirective::type() const
|
||||
{
|
||||
solAssert(!!annotation().sourceUnit, "");
|
||||
return TypeProvider::module(*annotation().sourceUnit);
|
||||
@ -206,7 +206,7 @@ uint32_t ContractDefinition::interfaceId() const
|
||||
return result;
|
||||
}
|
||||
|
||||
TypePointer ContractDefinition::type() const
|
||||
Type const* ContractDefinition::type() const
|
||||
{
|
||||
return TypeProvider::typeType(TypeProvider::contract(*this));
|
||||
}
|
||||
@ -252,7 +252,7 @@ TypeNameAnnotation& TypeName::annotation() const
|
||||
return initAnnotation<TypeNameAnnotation>();
|
||||
}
|
||||
|
||||
TypePointer StructDefinition::type() const
|
||||
Type const* StructDefinition::type() const
|
||||
{
|
||||
solAssert(annotation().recursive.has_value(), "Requested struct type before DeclarationTypeChecker.");
|
||||
return TypeProvider::typeType(TypeProvider::structType(*this, DataLocation::Storage));
|
||||
@ -263,14 +263,14 @@ StructDeclarationAnnotation& StructDefinition::annotation() const
|
||||
return initAnnotation<StructDeclarationAnnotation>();
|
||||
}
|
||||
|
||||
TypePointer EnumValue::type() const
|
||||
Type const* EnumValue::type() const
|
||||
{
|
||||
auto parentDef = dynamic_cast<EnumDefinition const*>(scope());
|
||||
solAssert(parentDef, "Enclosing Scope of EnumValue was not set");
|
||||
return TypeProvider::enumType(*parentDef);
|
||||
}
|
||||
|
||||
TypePointer EnumDefinition::type() const
|
||||
Type const* EnumDefinition::type() const
|
||||
{
|
||||
return TypeProvider::typeType(TypeProvider::enumType(*this));
|
||||
}
|
||||
@ -328,13 +328,13 @@ FunctionTypePointer FunctionDefinition::functionType(bool _internal) const
|
||||
return {};
|
||||
}
|
||||
|
||||
TypePointer FunctionDefinition::type() const
|
||||
Type const* FunctionDefinition::type() const
|
||||
{
|
||||
solAssert(visibility() != Visibility::External, "");
|
||||
return TypeProvider::function(*this, FunctionType::Kind::Internal);
|
||||
}
|
||||
|
||||
TypePointer FunctionDefinition::typeViaContractName() const
|
||||
Type const* FunctionDefinition::typeViaContractName() const
|
||||
{
|
||||
if (libraryFunction())
|
||||
{
|
||||
@ -395,7 +395,7 @@ FunctionDefinition const& FunctionDefinition::resolveVirtual(
|
||||
return *this; // not reached
|
||||
}
|
||||
|
||||
TypePointer ModifierDefinition::type() const
|
||||
Type const* ModifierDefinition::type() const
|
||||
{
|
||||
return TypeProvider::modifier(*this);
|
||||
}
|
||||
@ -432,7 +432,7 @@ ModifierDefinition const& ModifierDefinition::resolveVirtual(
|
||||
}
|
||||
|
||||
|
||||
TypePointer EventDefinition::type() const
|
||||
Type const* EventDefinition::type() const
|
||||
{
|
||||
return TypeProvider::function(*this);
|
||||
}
|
||||
@ -672,7 +672,7 @@ string VariableDeclaration::externalIdentifierHex() const
|
||||
return TypeProvider::function(*this)->externalIdentifierHex();
|
||||
}
|
||||
|
||||
TypePointer VariableDeclaration::type() const
|
||||
Type const* VariableDeclaration::type() const
|
||||
{
|
||||
return annotation().type;
|
||||
}
|
||||
|
@ -272,11 +272,11 @@ public:
|
||||
|
||||
/// @returns the type of expressions referencing this declaration.
|
||||
/// This can only be called once types of variable declarations have already been resolved.
|
||||
virtual TypePointer type() const = 0;
|
||||
virtual Type const* type() const = 0;
|
||||
|
||||
/// @returns the type for members of the containing contract type that refer to this declaration.
|
||||
/// This can only be called once types of variable declarations have already been resolved.
|
||||
virtual TypePointer typeViaContractName() const { return type(); }
|
||||
virtual Type const* typeViaContractName() const { return type(); }
|
||||
|
||||
/// @param _internal false indicates external interface is concerned, true indicates internal interface is concerned.
|
||||
/// @returns null when it is not accessible as a function.
|
||||
@ -366,7 +366,7 @@ public:
|
||||
}
|
||||
ImportAnnotation& annotation() const override;
|
||||
|
||||
TypePointer type() const override;
|
||||
Type const* type() const override;
|
||||
|
||||
private:
|
||||
ASTPointer<ASTString> m_path;
|
||||
@ -539,7 +539,7 @@ public:
|
||||
|
||||
std::string fullyQualifiedName() const { return sourceUnitName() + ":" + name(); }
|
||||
|
||||
TypePointer type() const override;
|
||||
Type const* type() const override;
|
||||
|
||||
ContractDefinitionAnnotation& annotation() const override;
|
||||
|
||||
@ -658,7 +658,7 @@ public:
|
||||
|
||||
std::vector<ASTPointer<VariableDeclaration>> const& members() const { return m_members; }
|
||||
|
||||
TypePointer type() const override;
|
||||
Type const* type() const override;
|
||||
|
||||
bool isVisibleInDerivedContracts() const override { return true; }
|
||||
bool isVisibleViaContractTypeAccess() const override { return true; }
|
||||
@ -688,7 +688,7 @@ public:
|
||||
|
||||
std::vector<ASTPointer<EnumValue>> const& members() const { return m_members; }
|
||||
|
||||
TypePointer type() const override;
|
||||
Type const* type() const override;
|
||||
|
||||
TypeDeclarationAnnotation& annotation() const override;
|
||||
|
||||
@ -708,7 +708,7 @@ public:
|
||||
void accept(ASTVisitor& _visitor) override;
|
||||
void accept(ASTConstVisitor& _visitor) const override;
|
||||
|
||||
TypePointer type() const override;
|
||||
Type const* type() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -883,8 +883,8 @@ public:
|
||||
/// @returns the external identifier of this function (the hash of the signature) as a hex string.
|
||||
std::string externalIdentifierHex() const;
|
||||
|
||||
TypePointer type() const override;
|
||||
TypePointer typeViaContractName() const override;
|
||||
Type const* type() const override;
|
||||
Type const* typeViaContractName() const override;
|
||||
|
||||
/// @param _internal false indicates external interface is concerned, true indicates internal interface is concerned.
|
||||
/// @returns null when it is not accessible as a function.
|
||||
@ -1010,7 +1010,7 @@ public:
|
||||
/// @returns the external identifier of this variable (the hash of the signature) as a hex string (works only for public state variables).
|
||||
std::string externalIdentifierHex() const;
|
||||
|
||||
TypePointer type() const override;
|
||||
Type const* type() const override;
|
||||
|
||||
/// @param _internal false indicates external interface is concerned, true indicates internal interface is concerned.
|
||||
/// @returns null when it is not accessible as a function.
|
||||
@ -1062,7 +1062,7 @@ public:
|
||||
|
||||
Block const& body() const { solAssert(m_body, ""); return *m_body; }
|
||||
|
||||
TypePointer type() const override;
|
||||
Type const* type() const override;
|
||||
|
||||
Visibility defaultVisibility() const override { return Visibility::Internal; }
|
||||
|
||||
@ -1135,7 +1135,7 @@ public:
|
||||
|
||||
bool isAnonymous() const { return m_anonymous; }
|
||||
|
||||
TypePointer type() const override;
|
||||
Type const* type() const override;
|
||||
FunctionTypePointer functionType(bool /*_internal*/) const override;
|
||||
|
||||
bool isVisibleInDerivedContracts() const override { return true; }
|
||||
@ -1179,7 +1179,7 @@ public:
|
||||
solAssert(m_type->category() == Type::Category::Function, "");
|
||||
return dynamic_cast<FunctionType const*>(m_type);
|
||||
}
|
||||
TypePointer type() const override { return m_type; }
|
||||
Type const* type() const override { return m_type; }
|
||||
|
||||
private:
|
||||
Type const* m_type;
|
||||
|
@ -46,7 +46,6 @@ namespace solidity::frontend
|
||||
{
|
||||
|
||||
class Type;
|
||||
using TypePointer = Type const*;
|
||||
class ArrayType;
|
||||
using namespace util;
|
||||
|
||||
@ -192,7 +191,7 @@ struct ModifierDefinitionAnnotation: CallableDeclarationAnnotation, Structurally
|
||||
struct VariableDeclarationAnnotation: DeclarationAnnotation, StructurallyDocumentedAnnotation
|
||||
{
|
||||
/// Type of variable (type of identifier referencing this variable).
|
||||
TypePointer type = nullptr;
|
||||
Type const* type = nullptr;
|
||||
/// The set of functions this (public state) variable overrides.
|
||||
std::set<CallableDeclaration const*> baseFunctions;
|
||||
};
|
||||
@ -239,7 +238,7 @@ struct TypeNameAnnotation: ASTAnnotation
|
||||
{
|
||||
/// Type declared by this type name, i.e. type of a variable where this type name is used.
|
||||
/// Set during reference resolution stage.
|
||||
TypePointer type = nullptr;
|
||||
Type const* type = nullptr;
|
||||
};
|
||||
|
||||
struct IdentifierPathAnnotation: ASTAnnotation
|
||||
@ -253,7 +252,7 @@ struct IdentifierPathAnnotation: ASTAnnotation
|
||||
struct ExpressionAnnotation: ASTAnnotation
|
||||
{
|
||||
/// Inferred type of the expression.
|
||||
TypePointer type = nullptr;
|
||||
Type const* type = nullptr;
|
||||
/// Whether the expression is a constant variable
|
||||
SetOnce<bool> isConstant;
|
||||
/// Whether the expression is pure, i.e. compile-time constant.
|
||||
@ -305,7 +304,7 @@ struct BinaryOperationAnnotation: ExpressionAnnotation
|
||||
{
|
||||
/// The common type that is used for the operation, not necessarily the result type (which
|
||||
/// e.g. for comparisons is bool).
|
||||
TypePointer commonType = nullptr;
|
||||
Type const* commonType = nullptr;
|
||||
};
|
||||
|
||||
enum class FunctionCallKind
|
||||
|
@ -129,7 +129,7 @@ string ASTJsonConverter::namePathToString(std::vector<ASTString> const& _namePat
|
||||
return boost::algorithm::join(_namePath, ".");
|
||||
}
|
||||
|
||||
Json::Value ASTJsonConverter::typePointerToJson(TypePointer _tp, bool _short)
|
||||
Json::Value ASTJsonConverter::typePointerToJson(Type const* _tp, bool _short)
|
||||
{
|
||||
Json::Value typeDescriptions(Json::objectValue);
|
||||
typeDescriptions["typeString"] = _tp ? Json::Value(_tp->toString(_short)) : Json::nullValue;
|
||||
|
@ -179,7 +179,7 @@ private:
|
||||
|
||||
return json;
|
||||
}
|
||||
static Json::Value typePointerToJson(TypePointer _tp, bool _short = false);
|
||||
static Json::Value typePointerToJson(Type const* _tp, bool _short = false);
|
||||
static Json::Value typePointerToJson(std::optional<FuncCallArguments> const& _tps);
|
||||
void appendExpressionAttributes(
|
||||
std::vector<std::pair<std::string, Json::Value>> &_attributes,
|
||||
|
@ -259,7 +259,7 @@ Type const* TypeProvider::fromElementaryTypeName(ElementaryTypeNameToken const&
|
||||
}
|
||||
}
|
||||
|
||||
TypePointer TypeProvider::fromElementaryTypeName(string const& _name)
|
||||
Type const* TypeProvider::fromElementaryTypeName(string const& _name)
|
||||
{
|
||||
vector<string> nameParts;
|
||||
boost::split(nameParts, _name, boost::is_any_of(" "));
|
||||
@ -339,7 +339,7 @@ ArrayType const* TypeProvider::stringMemory()
|
||||
return m_stringMemory.get();
|
||||
}
|
||||
|
||||
TypePointer TypeProvider::forLiteral(Literal const& _literal)
|
||||
Type const* TypeProvider::forLiteral(Literal const& _literal)
|
||||
{
|
||||
switch (_literal.token())
|
||||
{
|
||||
@ -363,7 +363,7 @@ RationalNumberType const* TypeProvider::rationalNumber(Literal const& _literal)
|
||||
std::tuple<bool, rational> validLiteral = RationalNumberType::isValidLiteral(_literal);
|
||||
if (std::get<0>(validLiteral))
|
||||
{
|
||||
TypePointer compatibleBytesType = nullptr;
|
||||
Type const* compatibleBytesType = nullptr;
|
||||
if (_literal.isHexNumber())
|
||||
{
|
||||
size_t const digitCount = _literal.valueWithoutUnderscores().length() - 2;
|
||||
|
@ -58,7 +58,7 @@ public:
|
||||
|
||||
/// Converts a given elementary type name with optional data location
|
||||
/// suffix " storage", " calldata" or " memory" to a type pointer. If suffix not given, defaults to " storage".
|
||||
static TypePointer fromElementaryTypeName(std::string const& _name);
|
||||
static Type const* fromElementaryTypeName(std::string const& _name);
|
||||
|
||||
/// @returns boolean type.
|
||||
static BoolType const* boolean() noexcept { return &m_boolean; }
|
||||
@ -169,7 +169,7 @@ public:
|
||||
|
||||
/// Auto-detect the proper type for a literal. @returns an empty pointer if the literal does
|
||||
/// not fit any type.
|
||||
static TypePointer forLiteral(Literal const& _literal);
|
||||
static Type const* forLiteral(Literal const& _literal);
|
||||
static RationalNumberType const* rationalNumber(Literal const& _literal);
|
||||
|
||||
static RationalNumberType const* rationalNumber(
|
||||
|
@ -100,7 +100,7 @@ util::Result<TypePointers> transformParametersToExternal(TypePointers const& _pa
|
||||
{
|
||||
if (!type)
|
||||
return util::Result<TypePointers>::err("Type information not present.");
|
||||
else if (TypePointer ext = type->interfaceType(_inLibrary).get())
|
||||
else if (Type const* ext = type->interfaceType(_inLibrary).get())
|
||||
transformed.push_back(ext);
|
||||
else
|
||||
return util::Result<TypePointers>::err("Parameter should have external type.");
|
||||
@ -225,7 +225,7 @@ string richIdentifier(Type const* _type)
|
||||
return _type ? _type->richIdentifier() : "";
|
||||
}
|
||||
|
||||
string identifierList(vector<TypePointer> const& _list)
|
||||
string identifierList(vector<Type const*> const& _list)
|
||||
{
|
||||
return identifierList(_list | boost::adaptors::transformed(richIdentifier));
|
||||
}
|
||||
@ -272,7 +272,7 @@ string Type::identifier() const
|
||||
return ret;
|
||||
}
|
||||
|
||||
TypePointer Type::commonType(Type const* _a, Type const* _b)
|
||||
Type const* Type::commonType(Type const* _a, Type const* _b)
|
||||
{
|
||||
if (!_a || !_b)
|
||||
return nullptr;
|
||||
@ -301,9 +301,9 @@ MemberList const& Type::members(ASTNode const* _currentScope) const
|
||||
return *m_members[_currentScope];
|
||||
}
|
||||
|
||||
TypePointer Type::fullEncodingType(bool _inLibraryCall, bool _encoderV2, bool) const
|
||||
Type const* Type::fullEncodingType(bool _inLibraryCall, bool _encoderV2, bool) const
|
||||
{
|
||||
TypePointer encodingType = mobileType();
|
||||
Type const* encodingType = mobileType();
|
||||
if (encodingType)
|
||||
encodingType = encodingType->interfaceType(_inLibraryCall);
|
||||
if (encodingType)
|
||||
@ -313,7 +313,7 @@ TypePointer Type::fullEncodingType(bool _inLibraryCall, bool _encoderV2, bool) c
|
||||
// - storage struct for a library
|
||||
if (_inLibraryCall && encodingType && encodingType->dataStoredIn(DataLocation::Storage))
|
||||
return encodingType;
|
||||
TypePointer baseType = encodingType;
|
||||
Type const* baseType = encodingType;
|
||||
while (auto const* arrayType = dynamic_cast<ArrayType const*>(baseType))
|
||||
{
|
||||
baseType = arrayType->baseType();
|
||||
@ -969,7 +969,7 @@ BoolResult RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo)
|
||||
if (isNegative() || isFractional() || m_value >= enumType->numberOfMembers())
|
||||
return false;
|
||||
|
||||
TypePointer mobType = mobileType();
|
||||
Type const* mobType = mobileType();
|
||||
return (mobType && mobType->isExplicitlyConvertibleTo(_convertTo));
|
||||
|
||||
}
|
||||
@ -1028,8 +1028,8 @@ TypeResult RationalNumberType::binaryOperatorResult(Token _operator, Type const*
|
||||
// Since we do not have a "BoolConstantType", we have to do the actual comparison
|
||||
// at runtime and convert to mobile typse first. Such a comparison is not a very common
|
||||
// use-case and will be optimized away.
|
||||
TypePointer thisMobile = mobileType();
|
||||
TypePointer otherMobile = other.mobileType();
|
||||
Type const* thisMobile = mobileType();
|
||||
Type const* otherMobile = other.mobileType();
|
||||
if (!thisMobile || !otherMobile)
|
||||
return nullptr;
|
||||
return thisMobile->binaryOperatorResult(_operator, otherMobile);
|
||||
@ -1116,7 +1116,7 @@ u256 RationalNumberType::literalValue(Literal const*) const
|
||||
return value;
|
||||
}
|
||||
|
||||
TypePointer RationalNumberType::mobileType() const
|
||||
Type const* RationalNumberType::mobileType() const
|
||||
{
|
||||
if (!isFractional())
|
||||
return integerType();
|
||||
@ -1245,7 +1245,7 @@ std::string StringLiteralType::toString(bool) const
|
||||
("literal_string hex\"" + util::toHex(util::asBytes(m_value)) + "\"");
|
||||
}
|
||||
|
||||
TypePointer StringLiteralType::mobileType() const
|
||||
Type const* StringLiteralType::mobileType() const
|
||||
{
|
||||
return TypeProvider::stringMemory();
|
||||
}
|
||||
@ -1471,7 +1471,7 @@ bool ReferenceType::isPointer() const
|
||||
return true;
|
||||
}
|
||||
|
||||
TypePointer ReferenceType::copyForLocationIfReference(Type const* _type) const
|
||||
Type const* ReferenceType::copyForLocationIfReference(Type const* _type) const
|
||||
{
|
||||
return TypeProvider::withLocationIfReference(m_location, _type);
|
||||
}
|
||||
@ -1729,7 +1729,7 @@ u256 ArrayType::storageSize() const
|
||||
return max<u256>(1, u256(size));
|
||||
}
|
||||
|
||||
vector<tuple<string, TypePointer>> ArrayType::makeStackItems() const
|
||||
vector<tuple<string, Type const*>> ArrayType::makeStackItems() const
|
||||
{
|
||||
switch (m_location)
|
||||
{
|
||||
@ -1833,7 +1833,7 @@ MemberList::MemberMap ArrayType::nativeMembers(ASTNode const*) const
|
||||
return members;
|
||||
}
|
||||
|
||||
TypePointer ArrayType::encodingType() const
|
||||
Type const* ArrayType::encodingType() const
|
||||
{
|
||||
if (location() == DataLocation::Storage)
|
||||
return TypeProvider::uint256();
|
||||
@ -1841,7 +1841,7 @@ TypePointer ArrayType::encodingType() const
|
||||
return TypeProvider::withLocation(this, DataLocation::Memory, true);
|
||||
}
|
||||
|
||||
TypePointer ArrayType::decodingType() const
|
||||
Type const* ArrayType::decodingType() const
|
||||
{
|
||||
if (location() == DataLocation::Storage)
|
||||
return TypeProvider::uint256();
|
||||
@ -1857,7 +1857,7 @@ TypeResult ArrayType::interfaceType(bool _inLibrary) const
|
||||
if (!_inLibrary && m_interfaceType.has_value())
|
||||
return *m_interfaceType;
|
||||
|
||||
TypeResult result{TypePointer{}};
|
||||
TypeResult result{nullptr};
|
||||
TypeResult baseInterfaceType = m_baseType->interfaceType(_inLibrary);
|
||||
|
||||
if (!baseInterfaceType.get())
|
||||
@ -1946,7 +1946,7 @@ string ArraySliceType::toString(bool _short) const
|
||||
return m_arrayType.toString(_short) + " slice";
|
||||
}
|
||||
|
||||
TypePointer ArraySliceType::mobileType() const
|
||||
Type const* ArraySliceType::mobileType() const
|
||||
{
|
||||
if (
|
||||
m_arrayType.dataStoredIn(DataLocation::CallData) &&
|
||||
@ -1959,7 +1959,7 @@ TypePointer ArraySliceType::mobileType() const
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::tuple<std::string, TypePointer>> ArraySliceType::makeStackItems() const
|
||||
std::vector<std::tuple<std::string, Type const*>> ArraySliceType::makeStackItems() const
|
||||
{
|
||||
return {{"offset", TypeProvider::uint256()}, {"length", TypeProvider::uint256()}};
|
||||
}
|
||||
@ -2041,7 +2041,7 @@ vector<VariableDeclaration const*> ContractType::immutableVariables() const
|
||||
return variables;
|
||||
}
|
||||
|
||||
vector<tuple<string, TypePointer>> ContractType::makeStackItems() const
|
||||
vector<tuple<string, Type const*>> ContractType::makeStackItems() const
|
||||
{
|
||||
if (m_super)
|
||||
return {};
|
||||
@ -2184,7 +2184,7 @@ bool StructType::containsNestedMapping() const
|
||||
{
|
||||
for (auto const& member: _struct->members())
|
||||
{
|
||||
TypePointer memberType = member->annotation().type;
|
||||
Type const* memberType = member->annotation().type;
|
||||
solAssert(memberType, "");
|
||||
|
||||
if (auto arrayType = dynamic_cast<ArrayType const*>(memberType))
|
||||
@ -2220,7 +2220,7 @@ MemberList::MemberMap StructType::nativeMembers(ASTNode const*) const
|
||||
MemberList::MemberMap members;
|
||||
for (ASTPointer<VariableDeclaration> const& variable: m_struct.members())
|
||||
{
|
||||
TypePointer type = variable->annotation().type;
|
||||
Type const* type = variable->annotation().type;
|
||||
solAssert(type, "");
|
||||
solAssert(!(location() != DataLocation::Storage && type->containsNestedMapping()), "");
|
||||
members.emplace_back(
|
||||
@ -2241,7 +2241,7 @@ TypeResult StructType::interfaceType(bool _inLibrary) const
|
||||
m_interfaceType = TypeResult::err("Recursive type not allowed for public or external contract functions.");
|
||||
else
|
||||
{
|
||||
TypeResult result{TypePointer{}};
|
||||
TypeResult result{nullptr};
|
||||
for (ASTPointer<VariableDeclaration> const& member: m_struct.members())
|
||||
{
|
||||
if (!member->annotation().type)
|
||||
@ -2268,7 +2268,7 @@ TypeResult StructType::interfaceType(bool _inLibrary) const
|
||||
else if (m_interfaceType_library.has_value())
|
||||
return *m_interfaceType_library;
|
||||
|
||||
TypeResult result{TypePointer{}};
|
||||
TypeResult result{nullptr};
|
||||
|
||||
if (recursive() && !(_inLibrary && location() == DataLocation::Storage))
|
||||
return TypeResult::err(
|
||||
@ -2374,7 +2374,7 @@ string StructType::signatureInExternalFunction(bool _structsByName) const
|
||||
else
|
||||
{
|
||||
TypePointers memberTypes = memoryMemberTypes();
|
||||
auto memberTypeStrings = memberTypes | boost::adaptors::transformed([&](TypePointer _t) -> string
|
||||
auto memberTypeStrings = memberTypes | boost::adaptors::transformed([&](Type const* _t) -> string
|
||||
{
|
||||
solAssert(_t, "Parameter should have external type.");
|
||||
auto t = _t->interfaceType(_structsByName);
|
||||
@ -2438,7 +2438,7 @@ TypePointers StructType::memoryMemberTypes() const
|
||||
return types;
|
||||
}
|
||||
|
||||
vector<tuple<string, TypePointer>> StructType::makeStackItems() const
|
||||
vector<tuple<string, Type const*>> StructType::makeStackItems() const
|
||||
{
|
||||
switch (m_location)
|
||||
{
|
||||
@ -2460,7 +2460,7 @@ vector<Type const*> StructType::decomposition() const
|
||||
return res;
|
||||
}
|
||||
|
||||
TypePointer EnumType::encodingType() const
|
||||
Type const* EnumType::encodingType() const
|
||||
{
|
||||
solAssert(numberOfMembers() <= 256, "");
|
||||
return TypeProvider::uint(8);
|
||||
@ -2575,9 +2575,9 @@ u256 TupleType::storageSize() const
|
||||
solAssert(false, "Storage size of non-storable tuple type requested.");
|
||||
}
|
||||
|
||||
vector<tuple<string, TypePointer>> TupleType::makeStackItems() const
|
||||
vector<tuple<string, Type const*>> TupleType::makeStackItems() const
|
||||
{
|
||||
vector<tuple<string, TypePointer>> slots;
|
||||
vector<tuple<string, Type const*>> slots;
|
||||
unsigned i = 1;
|
||||
for (auto const& t: components())
|
||||
{
|
||||
@ -2588,7 +2588,7 @@ vector<tuple<string, TypePointer>> TupleType::makeStackItems() const
|
||||
return slots;
|
||||
}
|
||||
|
||||
TypePointer TupleType::mobileType() const
|
||||
Type const* TupleType::mobileType() const
|
||||
{
|
||||
TypePointers mobiles;
|
||||
for (auto const& c: components())
|
||||
@ -2606,7 +2606,7 @@ TypePointer TupleType::mobileType() const
|
||||
return TypeProvider::tuple(move(mobiles));
|
||||
}
|
||||
|
||||
TypePointer TupleType::closestTemporaryType(Type const* _targetType) const
|
||||
Type const* TupleType::closestTemporaryType(Type const* _targetType) const
|
||||
{
|
||||
solAssert(!!_targetType, "");
|
||||
TypePointers const& targetComponents = dynamic_cast<TupleType const&>(*_targetType).components();
|
||||
@ -3051,9 +3051,9 @@ bool FunctionType::nameable() const
|
||||
!m_saltSet;
|
||||
}
|
||||
|
||||
vector<tuple<string, TypePointer>> FunctionType::makeStackItems() const
|
||||
vector<tuple<string, Type const*>> FunctionType::makeStackItems() const
|
||||
{
|
||||
vector<tuple<string, TypePointer>> slots;
|
||||
vector<tuple<string, Type const*>> slots;
|
||||
Kind kind = m_kind;
|
||||
if (m_kind == Kind::SetGas || m_kind == Kind::SetValue)
|
||||
{
|
||||
@ -3234,7 +3234,7 @@ MemberList::MemberMap FunctionType::nativeMembers(ASTNode const* _scope) const
|
||||
}
|
||||
}
|
||||
|
||||
TypePointer FunctionType::encodingType() const
|
||||
Type const* FunctionType::encodingType() const
|
||||
{
|
||||
if (m_gasSet || m_valueSet)
|
||||
return nullptr;
|
||||
@ -3253,7 +3253,7 @@ TypeResult FunctionType::interfaceType(bool /*_inLibrary*/) const
|
||||
return TypeResult::err("Internal type is not allowed for public or external functions.");
|
||||
}
|
||||
|
||||
TypePointer FunctionType::mobileType() const
|
||||
Type const* FunctionType::mobileType() const
|
||||
{
|
||||
if (m_valueSet || m_gasSet || m_saltSet || m_bound)
|
||||
return nullptr;
|
||||
@ -3411,7 +3411,7 @@ string FunctionType::externalSignature() const
|
||||
|
||||
solAssert(extParams.message().empty(), extParams.message());
|
||||
|
||||
auto typeStrings = extParams.get() | boost::adaptors::transformed([&](TypePointer _t) -> string
|
||||
auto typeStrings = extParams.get() | boost::adaptors::transformed([&](Type const* _t) -> string
|
||||
{
|
||||
string typeName = _t->signatureInExternalFunction(inLibrary);
|
||||
|
||||
@ -3461,7 +3461,7 @@ TypePointers FunctionType::parseElementaryTypeVector(strings const& _types)
|
||||
return pointers;
|
||||
}
|
||||
|
||||
TypePointer FunctionType::copyAndSetCallOptions(bool _setGas, bool _setValue, bool _setSalt) const
|
||||
Type const* FunctionType::copyAndSetCallOptions(bool _setGas, bool _setValue, bool _setSalt) const
|
||||
{
|
||||
solAssert(m_kind != Kind::Declaration, "");
|
||||
return TypeProvider::function(
|
||||
@ -3651,7 +3651,7 @@ u256 TypeType::storageSize() const
|
||||
solAssert(false, "Storage size of non-storable type type requested.");
|
||||
}
|
||||
|
||||
vector<tuple<string, TypePointer>> TypeType::makeStackItems() const
|
||||
vector<tuple<string, Type const*>> TypeType::makeStackItems() const
|
||||
{
|
||||
if (auto contractType = dynamic_cast<ContractType const*>(m_actualType))
|
||||
if (contractType->contractDefinition().isLibrary())
|
||||
@ -3982,14 +3982,14 @@ string MagicType::toString(bool _short) const
|
||||
return {};
|
||||
}
|
||||
|
||||
TypePointer MagicType::typeArgument() const
|
||||
Type const* MagicType::typeArgument() const
|
||||
{
|
||||
solAssert(m_kind == Kind::MetaType, "");
|
||||
solAssert(m_typeArgument, "");
|
||||
return m_typeArgument;
|
||||
}
|
||||
|
||||
TypePointer InaccessibleDynamicType::decodingType() const
|
||||
Type const* InaccessibleDynamicType::decodingType() const
|
||||
{
|
||||
return TypeProvider::integer(256, IntegerType::Modifier::Unsigned);
|
||||
}
|
||||
|
@ -48,11 +48,10 @@ namespace solidity::frontend
|
||||
class TypeProvider;
|
||||
class Type; // forward
|
||||
class FunctionType; // forward
|
||||
using TypePointer = Type const*;
|
||||
using FunctionTypePointer = FunctionType const*;
|
||||
using TypePointers = std::vector<TypePointer>;
|
||||
using TypePointers = std::vector<Type const*>;
|
||||
using rational = boost::rational<bigint>;
|
||||
using TypeResult = util::Result<TypePointer>;
|
||||
using TypeResult = util::Result<Type const*>;
|
||||
using BoolResult = util::Result<bool>;
|
||||
|
||||
}
|
||||
@ -122,9 +121,9 @@ public:
|
||||
explicit MemberList(MemberMap _members): m_memberTypes(std::move(_members)) {}
|
||||
|
||||
void combine(MemberList const& _other);
|
||||
TypePointer memberType(std::string const& _name) const
|
||||
Type const* memberType(std::string const& _name) const
|
||||
{
|
||||
TypePointer type = nullptr;
|
||||
Type const* type = nullptr;
|
||||
for (auto const& it: m_memberTypes)
|
||||
if (it.name == _name)
|
||||
{
|
||||
@ -181,7 +180,7 @@ public:
|
||||
};
|
||||
|
||||
/// @returns a pointer to _a or _b if the other is implicitly convertible to it or nullptr otherwise
|
||||
static TypePointer commonType(Type const* _a, Type const* _b);
|
||||
static Type const* commonType(Type const* _a, Type const* _b);
|
||||
|
||||
virtual Category category() const = 0;
|
||||
/// @returns a valid solidity identifier such that two types should compare equal if and
|
||||
@ -292,7 +291,7 @@ public:
|
||||
/// The complete layout of a type on the stack can be obtained from its stack items recursively as follows:
|
||||
/// - Each unnamed stack item is untyped (its type is ``nullptr``) and contributes exactly one stack slot.
|
||||
/// - Each named stack item is typed and contributes the stack slots given by the stack items of its type.
|
||||
std::vector<std::tuple<std::string, TypePointer>> const& stackItems() const
|
||||
std::vector<std::tuple<std::string, Type const*>> const& stackItems() const
|
||||
{
|
||||
if (!m_stackItems)
|
||||
m_stackItems = makeStackItems();
|
||||
@ -321,14 +320,14 @@ public:
|
||||
/// This returns the corresponding IntegerType or FixedPointType for RationalNumberType
|
||||
/// and the pointer type for storage reference types.
|
||||
/// Might return a null pointer if there is no fitting type.
|
||||
virtual TypePointer mobileType() const { return this; }
|
||||
virtual Type const* mobileType() const { return this; }
|
||||
/// @returns true if this is a non-value type and the data of this type is stored at the
|
||||
/// given location.
|
||||
virtual bool dataStoredIn(DataLocation) const { return false; }
|
||||
/// @returns the type of a temporary during assignment to a variable of the given type.
|
||||
/// Specifically, returns the requested itself if it can be dynamically allocated (or is a value type)
|
||||
/// and the mobile type otherwise.
|
||||
virtual TypePointer closestTemporaryType(Type const* _targetType) const
|
||||
virtual Type const* closestTemporaryType(Type const* _targetType) const
|
||||
{
|
||||
return _targetType->dataStoredIn(DataLocation::Storage) ? mobileType() : _targetType;
|
||||
}
|
||||
@ -337,7 +336,7 @@ public:
|
||||
/// @param _currentScope scope in which the members are accessed.
|
||||
MemberList const& members(ASTNode const* _currentScope) const;
|
||||
/// Convenience method, returns the type of the given named member or an empty pointer if no such member exists.
|
||||
TypePointer memberType(std::string const& _name, ASTNode const* _currentScope = nullptr) const
|
||||
Type const* memberType(std::string const& _name, ASTNode const* _currentScope = nullptr) const
|
||||
{
|
||||
return members(_currentScope).memberType(_name);
|
||||
}
|
||||
@ -361,14 +360,14 @@ public:
|
||||
/// @returns a (simpler) type that is encoded in the same way for external function calls.
|
||||
/// This for example returns address for contract types.
|
||||
/// If there is no such type, returns an empty shared pointer.
|
||||
virtual TypePointer encodingType() const { return nullptr; }
|
||||
virtual Type const* encodingType() const { return nullptr; }
|
||||
/// @returns the encoding type used under the given circumstances for the type of an expression
|
||||
/// when used for e.g. abi.encode(...) or the empty pointer if the object
|
||||
/// cannot be encoded.
|
||||
/// This is different from encodingType since it takes implicit conversions into account.
|
||||
TypePointer fullEncodingType(bool _inLibraryCall, bool _encoderV2, bool _packed) const;
|
||||
Type const* fullEncodingType(bool _inLibraryCall, bool _encoderV2, bool _packed) const;
|
||||
/// @returns a (simpler) type that is used when decoding this type in calldata.
|
||||
virtual TypePointer decodingType() const { return encodingType(); }
|
||||
virtual Type const* decodingType() const { return encodingType(); }
|
||||
/// @returns a type that will be used outside of Solidity for e.g. function signatures.
|
||||
/// This for example returns address for contract types.
|
||||
/// If there is no such type, returns an empty shared pointer.
|
||||
@ -392,7 +391,7 @@ protected:
|
||||
}
|
||||
/// Generates the stack items to be returned by ``stackItems()``. Defaults
|
||||
/// to exactly one unnamed and untyped stack item referring to a single stack slot.
|
||||
virtual std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const
|
||||
virtual std::vector<std::tuple<std::string, Type const*>> makeStackItems() const
|
||||
{
|
||||
return {std::make_tuple(std::string(), nullptr)};
|
||||
}
|
||||
@ -400,7 +399,7 @@ protected:
|
||||
|
||||
/// List of member types (parameterised by scape), will be lazy-initialized.
|
||||
mutable std::map<ASTNode const*, std::unique_ptr<MemberList>> m_members;
|
||||
mutable std::optional<std::vector<std::tuple<std::string, TypePointer>>> m_stackItems;
|
||||
mutable std::optional<std::vector<std::tuple<std::string, Type const*>>> m_stackItems;
|
||||
mutable std::optional<size_t> m_stackSize;
|
||||
};
|
||||
|
||||
@ -435,7 +434,7 @@ public:
|
||||
|
||||
u256 literalValue(Literal const* _literal) const override;
|
||||
|
||||
TypePointer encodingType() const override { return this; }
|
||||
Type const* encodingType() const override { return this; }
|
||||
TypeResult interfaceType(bool) const override { return this; }
|
||||
|
||||
StateMutability stateMutability(void) const { return m_stateMutability; }
|
||||
@ -475,7 +474,7 @@ public:
|
||||
|
||||
std::string toString(bool _short) const override;
|
||||
|
||||
TypePointer encodingType() const override { return this; }
|
||||
Type const* encodingType() const override { return this; }
|
||||
TypeResult interfaceType(bool) const override { return this; }
|
||||
|
||||
unsigned numBits() const { return m_bits; }
|
||||
@ -522,7 +521,7 @@ public:
|
||||
|
||||
std::string toString(bool _short) const override;
|
||||
|
||||
TypePointer encodingType() const override { return this; }
|
||||
Type const* encodingType() const override { return this; }
|
||||
TypeResult interfaceType(bool) const override { return this; }
|
||||
|
||||
/// Number of bits used for this type in total.
|
||||
@ -572,7 +571,7 @@ public:
|
||||
|
||||
std::string toString(bool _short) const override;
|
||||
u256 literalValue(Literal const* _literal) const override;
|
||||
TypePointer mobileType() const override;
|
||||
Type const* mobileType() const override;
|
||||
|
||||
/// @returns the underlying raw literal value.
|
||||
///
|
||||
@ -603,7 +602,7 @@ private:
|
||||
|
||||
/// Bytes type to which the rational can be explicitly converted.
|
||||
/// Empty for all rationals that are not directly parsed from hex literals.
|
||||
TypePointer m_compatibleBytesType;
|
||||
Type const* m_compatibleBytesType;
|
||||
|
||||
/// @returns true if the literal is a valid rational number.
|
||||
static std::tuple<bool, rational> parseRational(std::string const& _value);
|
||||
@ -636,12 +635,12 @@ public:
|
||||
bool canBeStored() const override { return false; }
|
||||
|
||||
std::string toString(bool) const override;
|
||||
TypePointer mobileType() const override;
|
||||
Type const* mobileType() const override;
|
||||
|
||||
std::string const& value() const { return m_value; }
|
||||
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override { return {}; }
|
||||
std::vector<std::tuple<std::string, Type const*>> makeStackItems() const override { return {}; }
|
||||
private:
|
||||
std::string m_value;
|
||||
};
|
||||
@ -671,7 +670,7 @@ public:
|
||||
|
||||
std::string toString(bool) const override { return "bytes" + util::toString(m_bytes); }
|
||||
MemberList::MemberMap nativeMembers(ASTNode const*) const override;
|
||||
TypePointer encodingType() const override { return this; }
|
||||
Type const* encodingType() const override { return this; }
|
||||
TypeResult interfaceType(bool) const override { return this; }
|
||||
|
||||
unsigned numBytes() const { return m_bytes; }
|
||||
@ -699,7 +698,7 @@ public:
|
||||
|
||||
std::string toString(bool) const override { return "bool"; }
|
||||
u256 literalValue(Literal const* _literal) const override;
|
||||
TypePointer encodingType() const override { return this; }
|
||||
Type const* encodingType() const override { return this; }
|
||||
TypeResult interfaceType(bool) const override { return this; }
|
||||
};
|
||||
|
||||
@ -756,7 +755,7 @@ public:
|
||||
/// whereas isPointer is only shallowly changed - the deep copy is always a bound reference.
|
||||
virtual std::unique_ptr<ReferenceType> copyForLocation(DataLocation _location, bool _isPointer) const = 0;
|
||||
|
||||
TypePointer mobileType() const override { return withLocation(m_location, true); }
|
||||
Type const* mobileType() const override { return withLocation(m_location, true); }
|
||||
bool dataStoredIn(DataLocation _location) const override { return m_location == _location; }
|
||||
bool hasSimpleZeroValueInMemory() const override { return false; }
|
||||
|
||||
@ -838,8 +837,8 @@ public:
|
||||
std::string canonicalName() const override;
|
||||
std::string signatureInExternalFunction(bool _structsByName) const override;
|
||||
MemberList::MemberMap nativeMembers(ASTNode const* _currentScope) const override;
|
||||
TypePointer encodingType() const override;
|
||||
TypePointer decodingType() const override;
|
||||
Type const* encodingType() const override;
|
||||
Type const* decodingType() const override;
|
||||
TypeResult interfaceType(bool _inLibrary) const override;
|
||||
|
||||
BoolResult validForLocation(DataLocation _loc) const override;
|
||||
@ -865,7 +864,7 @@ public:
|
||||
void clearCache() const override;
|
||||
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override;
|
||||
std::vector<std::tuple<std::string, Type const*>> makeStackItems() const override;
|
||||
std::vector<Type const*> decomposition() const override { return {m_baseType}; }
|
||||
|
||||
private:
|
||||
@ -897,7 +896,7 @@ public:
|
||||
bool isDynamicallySized() const override { return true; }
|
||||
bool isDynamicallyEncoded() const override { return true; }
|
||||
std::string toString(bool _short) const override;
|
||||
TypePointer mobileType() const override;
|
||||
Type const* mobileType() const override;
|
||||
|
||||
BoolResult validForLocation(DataLocation _loc) const override { return m_arrayType.validForLocation(_loc); }
|
||||
|
||||
@ -907,7 +906,7 @@ public:
|
||||
std::unique_ptr<ReferenceType> copyForLocation(DataLocation, bool) const override { solAssert(false, ""); }
|
||||
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override;
|
||||
std::vector<std::tuple<std::string, Type const*>> makeStackItems() const override;
|
||||
std::vector<Type const*> decomposition() const override { return {m_arrayType.baseType()}; }
|
||||
|
||||
private:
|
||||
@ -972,7 +971,7 @@ public:
|
||||
/// @returns a list of all immutable variables (including inherited) of the contract.
|
||||
std::vector<VariableDeclaration const*> immutableVariables() const;
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override;
|
||||
std::vector<std::tuple<std::string, Type const*>> makeStackItems() const override;
|
||||
private:
|
||||
ContractDefinition const& m_contract;
|
||||
/// If true, this is a special "super" type of m_contract containing only members that m_contract inherited
|
||||
@ -1034,7 +1033,7 @@ public:
|
||||
void clearCache() const override;
|
||||
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override;
|
||||
std::vector<std::tuple<std::string, Type const*>> makeStackItems() const override;
|
||||
std::vector<Type const*> decomposition() const override;
|
||||
|
||||
private:
|
||||
@ -1068,7 +1067,7 @@ public:
|
||||
bool nameable() const override { return true; }
|
||||
|
||||
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
|
||||
TypePointer encodingType() const override;
|
||||
Type const* encodingType() const override;
|
||||
TypeResult interfaceType(bool _inLibrary) const override
|
||||
{
|
||||
return _inLibrary ? this : encodingType();
|
||||
@ -1090,7 +1089,7 @@ private:
|
||||
class TupleType: public CompositeType
|
||||
{
|
||||
public:
|
||||
explicit TupleType(std::vector<TypePointer> _types = {}): m_components(std::move(_types)) {}
|
||||
explicit TupleType(std::vector<Type const*> _types = {}): m_components(std::move(_types)) {}
|
||||
|
||||
Category category() const override { return Category::Tuple; }
|
||||
|
||||
@ -1102,14 +1101,14 @@ public:
|
||||
bool canBeStored() const override { return false; }
|
||||
u256 storageSize() const override;
|
||||
bool hasSimpleZeroValueInMemory() const override { return false; }
|
||||
TypePointer mobileType() const override;
|
||||
Type const* mobileType() const override;
|
||||
/// Converts components to their temporary types and performs some wildcard matching.
|
||||
TypePointer closestTemporaryType(Type const* _targetType) const override;
|
||||
Type const* closestTemporaryType(Type const* _targetType) const override;
|
||||
|
||||
std::vector<TypePointer> const& components() const { return m_components; }
|
||||
std::vector<Type const*> const& components() const { return m_components; }
|
||||
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override;
|
||||
std::vector<std::tuple<std::string, Type const*>> makeStackItems() const override;
|
||||
std::vector<Type const*> decomposition() const override
|
||||
{
|
||||
// Currently calling TupleType::decomposition() is not expected, because we cannot declare a variable of a tuple type.
|
||||
@ -1121,7 +1120,7 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<TypePointer> const m_components;
|
||||
std::vector<Type const*> const m_components;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1278,11 +1277,11 @@ public:
|
||||
bool nameable() const override;
|
||||
bool hasSimpleZeroValueInMemory() const override { return false; }
|
||||
MemberList::MemberMap nativeMembers(ASTNode const* _currentScope) const override;
|
||||
TypePointer encodingType() const override;
|
||||
Type const* encodingType() const override;
|
||||
TypeResult interfaceType(bool _inLibrary) const override;
|
||||
TypePointer mobileType() const override;
|
||||
Type const* mobileType() const override;
|
||||
|
||||
/// @returns TypePointer of a new FunctionType object. All input/return parameters are an
|
||||
/// @returns Type const* of a new FunctionType object. All input/return parameters are an
|
||||
/// appropriate external types (i.e. the interfaceType()s) of input/return parameters of
|
||||
/// current function.
|
||||
/// @returns an empty shared pointer if one of the input/return parameters does not have an
|
||||
@ -1360,7 +1359,7 @@ public:
|
||||
|
||||
/// @returns a copy of this type, where gas or value are set manually. This will never set one
|
||||
/// of the parameters to false.
|
||||
TypePointer copyAndSetCallOptions(bool _setGas, bool _setValue, bool _setSalt) const;
|
||||
Type const* copyAndSetCallOptions(bool _setGas, bool _setValue, bool _setSalt) const;
|
||||
|
||||
/// @returns a copy of this function type with the `bound` flag set to true.
|
||||
/// Should only be called on library functions.
|
||||
@ -1374,7 +1373,7 @@ public:
|
||||
FunctionTypePointer asExternallyCallableFunction(bool _inLibrary) const;
|
||||
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override;
|
||||
std::vector<std::tuple<std::string, Type const*>> makeStackItems() const override;
|
||||
private:
|
||||
static TypePointers parseElementaryTypeVector(strings const& _types);
|
||||
|
||||
@ -1427,8 +1426,8 @@ protected:
|
||||
std::vector<Type const*> decomposition() const override { return {m_valueType}; }
|
||||
|
||||
private:
|
||||
TypePointer m_keyType;
|
||||
TypePointer m_valueType;
|
||||
Type const* m_keyType;
|
||||
Type const* m_valueType;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1455,9 +1454,9 @@ public:
|
||||
|
||||
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override;
|
||||
std::vector<std::tuple<std::string, Type const*>> makeStackItems() const override;
|
||||
private:
|
||||
TypePointer m_actualType;
|
||||
Type const* m_actualType;
|
||||
};
|
||||
|
||||
|
||||
@ -1479,7 +1478,7 @@ public:
|
||||
bool operator==(Type const& _other) const override;
|
||||
std::string toString(bool _short) const override;
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override { return {}; }
|
||||
std::vector<std::tuple<std::string, Type const*>> makeStackItems() const override { return {}; }
|
||||
private:
|
||||
TypePointers m_parameterTypes;
|
||||
};
|
||||
@ -1506,7 +1505,7 @@ public:
|
||||
std::string toString(bool _short) const override;
|
||||
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override { return {}; }
|
||||
std::vector<std::tuple<std::string, Type const*>> makeStackItems() const override { return {}; }
|
||||
private:
|
||||
SourceUnit const& m_sourceUnit;
|
||||
};
|
||||
@ -1546,14 +1545,14 @@ public:
|
||||
|
||||
Kind kind() const { return m_kind; }
|
||||
|
||||
TypePointer typeArgument() const;
|
||||
Type const* typeArgument() const;
|
||||
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override { return {}; }
|
||||
std::vector<std::tuple<std::string, Type const*>> makeStackItems() const override { return {}; }
|
||||
private:
|
||||
Kind m_kind;
|
||||
/// Contract type used for contract metadata magic.
|
||||
TypePointer m_typeArgument;
|
||||
Type const* m_typeArgument;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1574,7 +1573,7 @@ public:
|
||||
bool isValueType() const override { return true; }
|
||||
bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); }
|
||||
std::string toString(bool) const override { return "inaccessible dynamic type"; }
|
||||
TypePointer decodingType() const override;
|
||||
Type const* decodingType() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ string ABIFunctions::abiEncodingFunction(
|
||||
EncodingOptions const& _options
|
||||
)
|
||||
{
|
||||
TypePointer toInterface = _to.fullEncodingType(_options.encodeAsLibraryTypes, true, false);
|
||||
Type const* toInterface = _to.fullEncodingType(_options.encodeAsLibraryTypes, true, false);
|
||||
solUnimplementedAssert(toInterface, "Encoding type \"" + _to.toString() + "\" not yet implemented.");
|
||||
Type const& to = *toInterface;
|
||||
|
||||
@ -871,7 +871,7 @@ string ABIFunctions::abiEncodingFunctionStruct(
|
||||
{
|
||||
solAssert(member.type, "");
|
||||
solAssert(!member.type->containsNestedMapping(), "");
|
||||
TypePointer memberTypeTo = member.type->fullEncodingType(_options.encodeAsLibraryTypes, true, false);
|
||||
Type const* memberTypeTo = member.type->fullEncodingType(_options.encodeAsLibraryTypes, true, false);
|
||||
solUnimplementedAssert(memberTypeTo, "Encoding type \"" + member.type->toString() + "\" not yet implemented.");
|
||||
auto memberTypeFrom = _from.memberType(member.name);
|
||||
solAssert(memberTypeFrom, "");
|
||||
@ -1074,7 +1074,7 @@ string ABIFunctions::abiDecodingFunction(Type const& _type, bool _fromMemory, bo
|
||||
// Conversely, bounds checks have to be performed before the decoding function
|
||||
// of a value type is called.
|
||||
|
||||
TypePointer decodingType = _type.decodingType();
|
||||
Type const* decodingType = _type.decodingType();
|
||||
solAssert(decodingType, "");
|
||||
|
||||
if (auto arrayType = dynamic_cast<ArrayType const*>(decodingType))
|
||||
@ -1105,7 +1105,7 @@ string ABIFunctions::abiDecodingFunction(Type const& _type, bool _fromMemory, bo
|
||||
|
||||
string ABIFunctions::abiDecodingFunctionValueType(Type const& _type, bool _fromMemory)
|
||||
{
|
||||
TypePointer decodingType = _type.decodingType();
|
||||
Type const* decodingType = _type.decodingType();
|
||||
solAssert(decodingType, "");
|
||||
solAssert(decodingType->sizeOnStack() == 1, "");
|
||||
solAssert(decodingType->isValueType(), "");
|
||||
|
@ -41,8 +41,7 @@ class Type;
|
||||
class ArrayType;
|
||||
class StructType;
|
||||
class FunctionType;
|
||||
using TypePointer = Type const*;
|
||||
using TypePointers = std::vector<TypePointer>;
|
||||
using TypePointers = std::vector<Type const*>;
|
||||
|
||||
/**
|
||||
* Class to generate encoding and decoding functions. Also maintains a collection
|
||||
|
@ -49,9 +49,9 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
|
||||
// stack layout: [source_ref] [source length] target_ref (top)
|
||||
solAssert(_targetType.location() == DataLocation::Storage, "");
|
||||
|
||||
TypePointer uint256 = TypeProvider::uint256();
|
||||
TypePointer targetBaseType = _targetType.isByteArray() ? uint256 : _targetType.baseType();
|
||||
TypePointer sourceBaseType = _sourceType.isByteArray() ? uint256 : _sourceType.baseType();
|
||||
Type const* uint256 = TypeProvider::uint256();
|
||||
Type const* targetBaseType = _targetType.isByteArray() ? uint256 : _targetType.baseType();
|
||||
Type const* sourceBaseType = _sourceType.isByteArray() ? uint256 : _sourceType.baseType();
|
||||
|
||||
// TODO unroll loop for small sizes
|
||||
|
||||
@ -79,8 +79,8 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
|
||||
}
|
||||
|
||||
// stack: target_ref source_ref source_length
|
||||
TypePointer targetType = &_targetType;
|
||||
TypePointer sourceType = &_sourceType;
|
||||
Type const* targetType = &_targetType;
|
||||
Type const* sourceType = &_sourceType;
|
||||
m_context.callLowLevelFunction(
|
||||
"$copyArrayToStorage_" + sourceType->identifier() + "_to_" + targetType->identifier(),
|
||||
3,
|
||||
@ -549,7 +549,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
|
||||
|
||||
void ArrayUtils::clearArray(ArrayType const& _typeIn) const
|
||||
{
|
||||
TypePointer type = &_typeIn;
|
||||
Type const* type = &_typeIn;
|
||||
m_context.callLowLevelFunction(
|
||||
"$clearArray_" + _typeIn.identifier(),
|
||||
2,
|
||||
@ -654,7 +654,7 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const
|
||||
|
||||
void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
|
||||
{
|
||||
TypePointer type = &_typeIn;
|
||||
Type const* type = &_typeIn;
|
||||
m_context.callLowLevelFunction(
|
||||
"$resizeDynamicArray_" + _typeIn.identifier(),
|
||||
2,
|
||||
@ -934,7 +934,7 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayUtils::clearStorageLoop(TypePointer _type) const
|
||||
void ArrayUtils::clearStorageLoop(Type const* _type) const
|
||||
{
|
||||
solAssert(_type->storageBytes() >= 32, "");
|
||||
m_context.callLowLevelFunction(
|
||||
|
@ -31,7 +31,6 @@ namespace solidity::frontend
|
||||
class CompilerContext;
|
||||
class Type;
|
||||
class ArrayType;
|
||||
using TypePointer = Type const*;
|
||||
|
||||
/**
|
||||
* Class that provides code generation for handling arrays.
|
||||
@ -80,7 +79,7 @@ public:
|
||||
/// Appends a loop that clears a sequence of storage slots of the given type (excluding end).
|
||||
/// Stack pre: end_ref start_ref
|
||||
/// Stack post: end_ref
|
||||
void clearStorageLoop(TypePointer _type) const;
|
||||
void clearStorageLoop(Type const* _type) const;
|
||||
/// Converts length to size (number of storage slots or calldata/memory bytes).
|
||||
/// if @a _pad then add padding to multiples of 32 bytes for calldata/memory.
|
||||
/// Stack pre: length
|
||||
|
@ -97,7 +97,7 @@ vector<string> CompilerContext::immutableVariableSlotNames(VariableDeclaration c
|
||||
if (_variable.annotation().type->sizeOnStack() == 1)
|
||||
return {baseName};
|
||||
vector<string> names;
|
||||
auto collectSlotNames = [&](string const& _baseName, TypePointer type, auto const& _recurse) -> void {
|
||||
auto collectSlotNames = [&](string const& _baseName, Type const* type, auto const& _recurse) -> void {
|
||||
for (auto const& [slot, type]: type->stackItems())
|
||||
if (type)
|
||||
_recurse(_baseName + " " + slot, type, _recurse);
|
||||
|
@ -257,10 +257,10 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
|
||||
|
||||
// Retain the offset pointer as base_offset, the point from which the data offsets are computed.
|
||||
m_context << Instruction::DUP1;
|
||||
for (TypePointer const& parameterType: _typeParameters)
|
||||
for (Type const* parameterType: _typeParameters)
|
||||
{
|
||||
// stack: v1 v2 ... v(k-1) input_end base_offset current_offset
|
||||
TypePointer type = parameterType->decodingType();
|
||||
Type const* type = parameterType->decodingType();
|
||||
solUnimplementedAssert(type, "No decoding type found.");
|
||||
if (type->category() == Type::Category::Array)
|
||||
{
|
||||
@ -328,7 +328,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
|
||||
else
|
||||
{
|
||||
// first load from calldata and potentially convert to memory if arrayType is memory
|
||||
TypePointer calldataType = TypeProvider::withLocation(&arrayType, DataLocation::CallData, false);
|
||||
Type const* calldataType = TypeProvider::withLocation(&arrayType, DataLocation::CallData, false);
|
||||
if (calldataType->isDynamicallySized())
|
||||
{
|
||||
// put on stack: data_pointer length
|
||||
@ -415,9 +415,9 @@ void CompilerUtils::encodeToMemory(
|
||||
bool const encoderV2 = m_context.useABICoderV2();
|
||||
TypePointers targetTypes = _targetTypes.empty() ? _givenTypes : _targetTypes;
|
||||
solAssert(targetTypes.size() == _givenTypes.size(), "");
|
||||
for (TypePointer& t: targetTypes)
|
||||
for (Type const*& t: targetTypes)
|
||||
{
|
||||
TypePointer tEncoding = t->fullEncodingType(_encodeAsLibraryTypes, encoderV2, !_padToWordBoundaries);
|
||||
Type const* tEncoding = t->fullEncodingType(_encodeAsLibraryTypes, encoderV2, !_padToWordBoundaries);
|
||||
solUnimplementedAssert(tEncoding, "Encoding type \"" + t->toString() + "\" not yet implemented.");
|
||||
t = std::move(tEncoding);
|
||||
}
|
||||
@ -450,7 +450,7 @@ void CompilerUtils::encodeToMemory(
|
||||
unsigned dynPointers = 0; // number of dynamic head pointers on the stack
|
||||
for (size_t i = 0; i < _givenTypes.size(); ++i)
|
||||
{
|
||||
TypePointer targetType = targetTypes[i];
|
||||
Type const* targetType = targetTypes[i];
|
||||
solAssert(!!targetType, "Externalable type expected.");
|
||||
if (targetType->isDynamicallySized() && !_copyDynamicDataInPlace)
|
||||
{
|
||||
@ -468,7 +468,7 @@ void CompilerUtils::encodeToMemory(
|
||||
bool needCleanup = true;
|
||||
copyToStackTop(argSize - stackPos + dynPointers + 2, _givenTypes[i]->sizeOnStack());
|
||||
solAssert(!!targetType, "Externalable type expected.");
|
||||
TypePointer type = targetType;
|
||||
Type const* type = targetType;
|
||||
if (_givenTypes[i]->dataStoredIn(DataLocation::Storage) && targetType->isValueType())
|
||||
{
|
||||
// special case: convert storage reference type to value type - this is only
|
||||
@ -513,7 +513,7 @@ void CompilerUtils::encodeToMemory(
|
||||
unsigned thisDynPointer = 0;
|
||||
for (size_t i = 0; i < _givenTypes.size(); ++i)
|
||||
{
|
||||
TypePointer targetType = targetTypes[i];
|
||||
Type const* targetType = targetTypes[i];
|
||||
solAssert(!!targetType, "Externalable type expected.");
|
||||
if (targetType->isDynamicallySized() && !_copyDynamicDataInPlace)
|
||||
{
|
||||
@ -1103,7 +1103,7 @@ void CompilerUtils::convertType(
|
||||
_context << offsets.first << Instruction::DUP3 << Instruction::ADD;
|
||||
_context << u256(offsets.second);
|
||||
StorageItem(_context, *member.type).retrieveValue(SourceLocation(), true);
|
||||
TypePointer targetMemberType = targetType->memberType(member.name);
|
||||
Type const* targetMemberType = targetType->memberType(member.name);
|
||||
solAssert(!!targetMemberType, "Member not found in target type.");
|
||||
utils.convertType(*member.type, *targetMemberType, true);
|
||||
utils.storeInMemoryDynamic(*targetMemberType, true);
|
||||
@ -1160,8 +1160,8 @@ void CompilerUtils::convertType(
|
||||
unsigned depth = sourceTuple.sizeOnStack();
|
||||
for (size_t i = 0; i < sourceTuple.components().size(); ++i)
|
||||
{
|
||||
TypePointer sourceType = sourceTuple.components()[i];
|
||||
TypePointer targetType = targetTuple.components()[i];
|
||||
Type const* sourceType = sourceTuple.components()[i];
|
||||
Type const* targetType = targetTuple.components()[i];
|
||||
if (!sourceType)
|
||||
{
|
||||
solAssert(!targetType, "");
|
||||
@ -1279,7 +1279,7 @@ void CompilerUtils::pushZeroValue(Type const& _type)
|
||||
return;
|
||||
}
|
||||
|
||||
TypePointer type = &_type;
|
||||
Type const* type = &_type;
|
||||
m_context.callLowLevelFunction(
|
||||
"$pushZeroValue_" + referenceType->identifier(),
|
||||
0,
|
||||
@ -1408,7 +1408,7 @@ void CompilerUtils::popAndJump(unsigned _toHeight, evmasm::AssemblyItem const& _
|
||||
unsigned CompilerUtils::sizeOnStack(vector<Type const*> const& _variableTypes)
|
||||
{
|
||||
unsigned size = 0;
|
||||
for (Type const* const& type: _variableTypes)
|
||||
for (Type const* type: _variableTypes)
|
||||
size += type->sizeOnStack();
|
||||
return size;
|
||||
}
|
||||
|
@ -739,7 +739,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
||||
}
|
||||
else if (Literal const* literal = dynamic_cast<Literal const*>(variable->value().get()))
|
||||
{
|
||||
TypePointer type = literal->annotation().type;
|
||||
Type const* type = literal->annotation().type;
|
||||
|
||||
switch (type->category())
|
||||
{
|
||||
@ -949,7 +949,7 @@ bool ContractCompiler::visit(TryStatement const& _tryStatement)
|
||||
TryCatchClause const& successClause = *_tryStatement.clauses().front();
|
||||
if (successClause.parameters())
|
||||
{
|
||||
vector<TypePointer> exprTypes{_tryStatement.externalCall().annotation().type};
|
||||
vector<Type const*> exprTypes{_tryStatement.externalCall().annotation().type};
|
||||
if (auto tupleType = dynamic_cast<TupleType const*>(exprTypes.front()))
|
||||
exprTypes = tupleType->components();
|
||||
vector<ASTPointer<VariableDeclaration>> const& params = successClause.parameters()->parameters();
|
||||
@ -1251,7 +1251,7 @@ bool ContractCompiler::visit(Return const& _return)
|
||||
for (auto const& retVariable: returnParameters)
|
||||
types.push_back(retVariable->annotation().type);
|
||||
|
||||
TypePointer expectedType;
|
||||
Type const* expectedType;
|
||||
if (expression->annotation().type->category() == Type::Category::Tuple || types.size() != 1)
|
||||
expectedType = TypeProvider::tuple(move(types));
|
||||
else
|
||||
@ -1470,7 +1470,7 @@ void ContractCompiler::appendStackVariableInitialisation(
|
||||
CompilerUtils(m_context).pushZeroValue(*_variable.annotation().type);
|
||||
}
|
||||
|
||||
void ContractCompiler::compileExpression(Expression const& _expression, TypePointer const& _targetType)
|
||||
void ContractCompiler::compileExpression(Expression const& _expression, Type const* _targetType)
|
||||
{
|
||||
ExpressionCompiler expressionCompiler(m_context, m_optimiserSettings.runOrderLiterals);
|
||||
expressionCompiler.compile(_expression);
|
||||
|
@ -134,7 +134,7 @@ private:
|
||||
/// If the default value is complex (needs memory allocation) and @a _provideDefaultValue
|
||||
/// is false, this might be skipped.
|
||||
void appendStackVariableInitialisation(VariableDeclaration const& _variable, bool _provideDefaultValue);
|
||||
void compileExpression(Expression const& _expression, TypePointer const& _targetType = TypePointer());
|
||||
void compileExpression(Expression const& _expression, Type const* _targetType = nullptr);
|
||||
|
||||
/// Frees the variables of a certain scope (to be used when leaving).
|
||||
void popScopedVariables(ASTNode const* _node);
|
||||
|
@ -58,7 +58,7 @@ void ExpressionCompiler::appendStateVariableInitialization(VariableDeclaration c
|
||||
{
|
||||
if (!_varDecl.value())
|
||||
return;
|
||||
TypePointer type = _varDecl.value()->annotation().type;
|
||||
Type const* type = _varDecl.value()->annotation().type;
|
||||
solAssert(!!type, "Type information not available.");
|
||||
CompilerContext::LocationSetter locationSetter(m_context, _varDecl);
|
||||
_varDecl.value()->accept(*this);
|
||||
@ -111,7 +111,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
|
||||
m_context << location.first << u256(location.second);
|
||||
}
|
||||
|
||||
TypePointer returnType = _varDecl.annotation().type;
|
||||
Type const* returnType = _varDecl.annotation().type;
|
||||
|
||||
for (size_t i = 0; i < paramTypes.size(); ++i)
|
||||
{
|
||||
@ -214,7 +214,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
|
||||
continue;
|
||||
pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]);
|
||||
m_context << Instruction::DUP1 << u256(offsets.first) << Instruction::ADD << u256(offsets.second);
|
||||
TypePointer memberType = structType->memberType(names[i]);
|
||||
Type const* memberType = structType->memberType(names[i]);
|
||||
StorageItem(m_context, *memberType).retrieveValue(SourceLocation(), true);
|
||||
utils().convertType(*memberType, *returnTypes[i]);
|
||||
utils().moveToStackTop(returnTypes[i]->sizeOnStack());
|
||||
@ -279,7 +279,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
|
||||
_assignment.rightHandSide().accept(*this);
|
||||
// Perform some conversion already. This will convert storage types to memory and literals
|
||||
// to their actual type, but will not convert e.g. memory to storage.
|
||||
TypePointer rightIntermediateType;
|
||||
Type const* rightIntermediateType;
|
||||
if (op != Token::Assign && TokenTraits::isShiftOp(binOp))
|
||||
rightIntermediateType = _assignment.rightHandSide().annotation().type->mobileType();
|
||||
else
|
||||
@ -474,7 +474,7 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
|
||||
Expression const& leftExpression = _binaryOperation.leftExpression();
|
||||
Expression const& rightExpression = _binaryOperation.rightExpression();
|
||||
solAssert(!!_binaryOperation.annotation().commonType, "");
|
||||
TypePointer const& commonType = _binaryOperation.annotation().commonType;
|
||||
Type const* commonType = _binaryOperation.annotation().commonType;
|
||||
Token const c_op = _binaryOperation.getOperator();
|
||||
|
||||
if (c_op == Token::And || c_op == Token::Or) // special case: short-circuiting
|
||||
@ -485,8 +485,8 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
|
||||
{
|
||||
bool cleanupNeeded = cleanupNeededForOp(commonType->category(), c_op, m_context.arithmetic());
|
||||
|
||||
TypePointer leftTargetType = commonType;
|
||||
TypePointer rightTargetType =
|
||||
Type const* leftTargetType = commonType;
|
||||
Type const* rightTargetType =
|
||||
TokenTraits::isShiftOp(c_op) || c_op == Token::Exp ?
|
||||
rightExpression.annotation().type->mobileType() :
|
||||
commonType;
|
||||
@ -818,7 +818,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
{
|
||||
solAssert(arguments.size() == 1, "");
|
||||
solAssert(!function.padArguments(), "");
|
||||
TypePointer const& argType = arguments.front()->annotation().type;
|
||||
Type const* argType = arguments.front()->annotation().type;
|
||||
solAssert(argType, "");
|
||||
arguments.front()->accept(*this);
|
||||
if (auto const* stringLiteral = dynamic_cast<StringLiteralType const*>(argType))
|
||||
@ -979,13 +979,13 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
{
|
||||
solAssert(function.parameterTypes().size() == 1, "");
|
||||
solAssert(!!function.parameterTypes()[0], "");
|
||||
TypePointer paramType = function.parameterTypes()[0];
|
||||
Type const* paramType = function.parameterTypes()[0];
|
||||
ArrayType const* arrayType = dynamic_cast<ArrayType const*>(function.selfType());
|
||||
solAssert(arrayType, "");
|
||||
|
||||
// stack: ArrayReference
|
||||
arguments[0]->accept(*this);
|
||||
TypePointer const& argType = arguments[0]->annotation().type;
|
||||
Type const* argType = arguments[0]->annotation().type;
|
||||
// stack: ArrayReference argValue
|
||||
utils().moveToStackTop(argType->sizeOnStack(), 1);
|
||||
// stack: argValue ArrayReference
|
||||
@ -998,7 +998,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
// stack: argValue storageSlot slotOffset
|
||||
utils().moveToStackTop(2, argType->sizeOnStack());
|
||||
// stack: storageSlot slotOffset argValue
|
||||
TypePointer type = arguments[0]->annotation().type->closestTemporaryType(arrayType->baseType());
|
||||
Type const* type = arguments[0]->annotation().type->closestTemporaryType(arrayType->baseType());
|
||||
solAssert(type, "");
|
||||
utils().convertType(*argType, *type);
|
||||
utils().moveToStackTop(1 + type->sizeOnStack());
|
||||
@ -1170,9 +1170,9 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
{
|
||||
// stack: <selector> <memory pointer>
|
||||
solAssert(arguments.size() >= 1, "");
|
||||
TypePointer const& selectorType = arguments[0]->annotation().type;
|
||||
Type const* selectorType = arguments[0]->annotation().type;
|
||||
utils().moveIntoStack(selectorType->sizeOnStack());
|
||||
TypePointer dataOnStack = selectorType;
|
||||
Type const* dataOnStack = selectorType;
|
||||
// stack: <memory pointer> <selector>
|
||||
if (function.kind() == FunctionType::Kind::ABIEncodeWithSignature)
|
||||
{
|
||||
@ -1220,7 +1220,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
case FunctionType::Kind::ABIDecode:
|
||||
{
|
||||
arguments.front()->accept(*this);
|
||||
TypePointer firstArgType = arguments.front()->annotation().type;
|
||||
Type const* firstArgType = arguments.front()->annotation().type;
|
||||
TypePointers targetTypes;
|
||||
if (TupleType const* targetTupleType = dynamic_cast<TupleType const*>(_functionCall.annotation().type))
|
||||
targetTypes = targetTupleType->components();
|
||||
@ -1652,7 +1652,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
solAssert(false, "Blockhash has been removed.");
|
||||
else if (member == "creationCode" || member == "runtimeCode")
|
||||
{
|
||||
TypePointer arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
|
||||
Type const* arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
|
||||
auto const& contractType = dynamic_cast<ContractType const&>(*arg);
|
||||
solAssert(!contractType.isSuper(), "");
|
||||
ContractDefinition const& contract = contractType.contractDefinition();
|
||||
@ -1671,7 +1671,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
}
|
||||
else if (member == "name")
|
||||
{
|
||||
TypePointer arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
|
||||
Type const* arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
|
||||
auto const& contractType = dynamic_cast<ContractType const&>(*arg);
|
||||
ContractDefinition const& contract = contractType.isSuper() ?
|
||||
*contractType.contractDefinition().superContract(m_context.mostDerivedContract()) :
|
||||
@ -1685,7 +1685,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
}
|
||||
else if (member == "interfaceId")
|
||||
{
|
||||
TypePointer arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
|
||||
Type const* arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
|
||||
ContractDefinition const& contract = dynamic_cast<ContractType const&>(*arg).contractDefinition();
|
||||
m_context << (u256{contract.interfaceId()} << (256 - 32));
|
||||
}
|
||||
@ -1709,7 +1709,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
case Type::Category::Struct:
|
||||
{
|
||||
StructType const& type = dynamic_cast<StructType const&>(*_memberAccess.expression().annotation().type);
|
||||
TypePointer const& memberType = _memberAccess.annotation().type;
|
||||
Type const* memberType = _memberAccess.annotation().type;
|
||||
switch (type.location())
|
||||
{
|
||||
case DataLocation::Storage:
|
||||
@ -1865,7 +1865,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
|
||||
case Type::Category::Mapping:
|
||||
{
|
||||
// stack: storage_base_ref
|
||||
TypePointer keyType = dynamic_cast<MappingType const&>(baseType).keyType();
|
||||
Type const* keyType = dynamic_cast<MappingType const&>(baseType).keyType();
|
||||
solAssert(_indexAccess.indexExpression(), "Index expression expected.");
|
||||
if (keyType->isDynamicallySized())
|
||||
{
|
||||
@ -2076,7 +2076,7 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier)
|
||||
void ExpressionCompiler::endVisit(Literal const& _literal)
|
||||
{
|
||||
CompilerContext::LocationSetter locationSetter(m_context, _literal);
|
||||
TypePointer type = _literal.annotation().type;
|
||||
Type const* type = _literal.annotation().type;
|
||||
|
||||
switch (type->category())
|
||||
{
|
||||
|
@ -369,9 +369,9 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
|
||||
for (auto const& member: structType.members(nullptr))
|
||||
{
|
||||
// assign each member that can live outside of storage
|
||||
TypePointer const& memberType = member.type;
|
||||
Type const* memberType = member.type;
|
||||
solAssert(memberType->nameable(), "");
|
||||
TypePointer sourceMemberType = sourceType.memberType(member.name);
|
||||
Type const* sourceMemberType = sourceType.memberType(member.name);
|
||||
if (sourceType.location() == DataLocation::Storage)
|
||||
{
|
||||
// stack layout: source_ref target_ref
|
||||
@ -431,7 +431,7 @@ void StorageItem::setToZero(SourceLocation const&, bool _removeReference) const
|
||||
for (auto const& member: structType.members(nullptr))
|
||||
{
|
||||
// zero each member that is not a mapping
|
||||
TypePointer const& memberType = member.type;
|
||||
Type const* memberType = member.type;
|
||||
if (memberType->category() == Type::Category::Mapping)
|
||||
continue;
|
||||
pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name);
|
||||
@ -558,7 +558,7 @@ void TupleObject::storeValue(Type const& _sourceType, SourceLocation const& _loc
|
||||
for (size_t i = 0; i < m_lvalues.size(); ++i)
|
||||
{
|
||||
unique_ptr<LValue> const& lvalue = m_lvalues[m_lvalues.size() - i - 1];
|
||||
TypePointer const& valType = valueTypes[valueTypes.size() - i - 1];
|
||||
Type const* valType = valueTypes[valueTypes.size() - i - 1];
|
||||
unsigned stackHeight = m_context.stackHeight();
|
||||
solAssert(!valType == !lvalue, "");
|
||||
if (!lvalue)
|
||||
|
@ -35,7 +35,7 @@ struct ReturnInfo
|
||||
{
|
||||
ReturnInfo(langutil::EVMVersion const& _evmVersion, FunctionType const& _functionType);
|
||||
|
||||
/// Vector of TypePointer, for each return variable. Dynamic types are already replaced if required.
|
||||
/// Vector of Type const*, for each return variable. Dynamic types are already replaced if required.
|
||||
TypePointers returnTypes = {};
|
||||
|
||||
/// Boolean, indicating whether or not return size is only known at runtime.
|
||||
|
@ -215,7 +215,7 @@ public:
|
||||
/// @param _fromType represents the type of the element being pushed.
|
||||
/// If _fromType is ReferenceType the function will perform deep copy.
|
||||
/// signature: (array, value)
|
||||
std::string storageArrayPushFunction(ArrayType const& _type, TypePointer _fromType = nullptr);
|
||||
std::string storageArrayPushFunction(ArrayType const& _type, Type const* _fromType = nullptr);
|
||||
|
||||
/// @returns the name of a function that pushes the base type's zero element to a storage array and returns storage slot and offset of the added element.
|
||||
/// signature: (array) -> slot, offset
|
||||
|
@ -537,7 +537,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
// In each iteration of the loop below, we consume one parameter, perform an
|
||||
// index access, reassign the yul variable `slot` and move @a currentType further "down".
|
||||
// The initial value of @a currentType is only used if we skip the loop completely.
|
||||
TypePointer currentType = _varDecl.annotation().type;
|
||||
Type const* currentType = _varDecl.annotation().type;
|
||||
|
||||
vector<string> parameters;
|
||||
vector<string> returnVariables;
|
||||
|
@ -135,7 +135,7 @@ private:
|
||||
}
|
||||
else if (auto const* literal = dynamic_cast<Literal const*>(variable->value().get()))
|
||||
{
|
||||
TypePointer type = literal->annotation().type;
|
||||
Type const* type = literal->annotation().type;
|
||||
|
||||
switch (type->category())
|
||||
{
|
||||
@ -738,7 +738,7 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp)
|
||||
setLocation(_binOp);
|
||||
|
||||
solAssert(!!_binOp.annotation().commonType, "");
|
||||
TypePointer commonType = _binOp.annotation().commonType;
|
||||
Type const* commonType = _binOp.annotation().commonType;
|
||||
langutil::Token op = _binOp.getOperator();
|
||||
|
||||
if (op == Token::And || op == Token::Or)
|
||||
@ -1157,7 +1157,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
<?+retVars>let <retVars> := </+retVars> <abiDecode>(<offset>, add(<offset>, <length>))
|
||||
)");
|
||||
|
||||
TypePointer firstArgType = arguments.front()->annotation().type;
|
||||
Type const* firstArgType = arguments.front()->annotation().type;
|
||||
TypePointers targetTypes;
|
||||
|
||||
if (TupleType const* targetTupleType = dynamic_cast<TupleType const*>(_functionCall.annotation().type))
|
||||
@ -1756,7 +1756,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
solAssert(false, "Blockhash has been removed.");
|
||||
else if (member == "creationCode" || member == "runtimeCode")
|
||||
{
|
||||
TypePointer arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
|
||||
Type const* arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
|
||||
auto const& contractType = dynamic_cast<ContractType const&>(*arg);
|
||||
solAssert(!contractType.isSuper(), "");
|
||||
ContractDefinition const& contract = contractType.contractDefinition();
|
||||
@ -1774,13 +1774,13 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
}
|
||||
else if (member == "name")
|
||||
{
|
||||
TypePointer arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
|
||||
Type const* arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
|
||||
ContractDefinition const& contract = dynamic_cast<ContractType const&>(*arg).contractDefinition();
|
||||
define(IRVariable(_memberAccess)) << m_utils.copyLiteralToMemoryFunction(contract.name()) << "()\n";
|
||||
}
|
||||
else if (member == "interfaceId")
|
||||
{
|
||||
TypePointer arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
|
||||
Type const* arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
|
||||
auto const& contractType = dynamic_cast<ContractType const&>(*arg);
|
||||
solAssert(!contractType.isSuper(), "");
|
||||
ContractDefinition const& contract = contractType.contractDefinition();
|
||||
|
@ -569,7 +569,7 @@ pair<smtutil::Expression, smtutil::Expression> BMC::arithmeticOperation(
|
||||
Token _op,
|
||||
smtutil::Expression const& _left,
|
||||
smtutil::Expression const& _right,
|
||||
TypePointer const& _commonType,
|
||||
Type const* _commonType,
|
||||
Expression const& _expression
|
||||
)
|
||||
{
|
||||
|
@ -119,7 +119,7 @@ private:
|
||||
Token _op,
|
||||
smtutil::Expression const& _left,
|
||||
smtutil::Expression const& _right,
|
||||
TypePointer const& _commonType,
|
||||
Type const* _commonType,
|
||||
Expression const& _expression
|
||||
) override;
|
||||
|
||||
|
@ -787,7 +787,7 @@ pair<smtutil::Expression, smtutil::Expression> CHC::arithmeticOperation(
|
||||
Token _op,
|
||||
smtutil::Expression const& _left,
|
||||
smtutil::Expression const& _right,
|
||||
TypePointer const& _commonType,
|
||||
Type const* _commonType,
|
||||
frontend::Expression const& _expression
|
||||
)
|
||||
{
|
||||
|
@ -102,7 +102,7 @@ private:
|
||||
Token _op,
|
||||
smtutil::Expression const& _left,
|
||||
smtutil::Expression const& _right,
|
||||
TypePointer const& _commonType,
|
||||
Type const* _commonType,
|
||||
Expression const& _expression
|
||||
) override;
|
||||
//@}
|
||||
|
@ -308,7 +308,7 @@ vector<optional<string>> Predicate::summaryPostOutputValues(vector<smtutil::Expr
|
||||
return formatExpressions(outValues, outTypes);
|
||||
}
|
||||
|
||||
vector<optional<string>> Predicate::formatExpressions(vector<smtutil::Expression> const& _exprs, vector<TypePointer> const& _types) const
|
||||
vector<optional<string>> Predicate::formatExpressions(vector<smtutil::Expression> const& _exprs, vector<Type const*> const& _types) const
|
||||
{
|
||||
solAssert(_exprs.size() == _types.size(), "");
|
||||
vector<optional<string>> strExprs;
|
||||
@ -317,7 +317,7 @@ vector<optional<string>> Predicate::formatExpressions(vector<smtutil::Expression
|
||||
return strExprs;
|
||||
}
|
||||
|
||||
optional<string> Predicate::expressionToString(smtutil::Expression const& _expr, TypePointer _type) const
|
||||
optional<string> Predicate::expressionToString(smtutil::Expression const& _expr, Type const* _type) const
|
||||
{
|
||||
if (smt::isNumber(*_type))
|
||||
{
|
||||
@ -456,7 +456,7 @@ bool Predicate::fillArray(smtutil::Expression const& _expr, vector<string>& _arr
|
||||
|
||||
map<string, optional<string>> Predicate::readTxVars(smtutil::Expression const& _tx) const
|
||||
{
|
||||
map<string, TypePointer> const txVars{
|
||||
map<string, Type const*> const txVars{
|
||||
{"block.chainid", TypeProvider::uint256()},
|
||||
{"block.coinbase", TypeProvider::address()},
|
||||
{"block.difficulty", TypeProvider::uint256()},
|
||||
|
@ -145,10 +145,10 @@ public:
|
||||
|
||||
private:
|
||||
/// @returns the formatted version of the given SMT expressions. Those expressions must be SMT constants.
|
||||
std::vector<std::optional<std::string>> formatExpressions(std::vector<smtutil::Expression> const& _exprs, std::vector<TypePointer> const& _types) const;
|
||||
std::vector<std::optional<std::string>> formatExpressions(std::vector<smtutil::Expression> const& _exprs, std::vector<Type const*> const& _types) const;
|
||||
|
||||
/// @returns a string representation of the SMT expression based on a Solidity type.
|
||||
std::optional<std::string> expressionToString(smtutil::Expression const& _expr, TypePointer _type) const;
|
||||
std::optional<std::string> expressionToString(smtutil::Expression const& _expr, Type const* _type) const;
|
||||
|
||||
/// Recursively fills _array from _expr.
|
||||
/// _expr should have the form `store(store(...(const_array(x_0), i_0, e_0), i_m, e_m), i_k, e_k)`.
|
||||
|
@ -978,7 +978,7 @@ void SMTEncoder::endVisit(ElementaryTypeNameExpression const& _typeName)
|
||||
namespace // helpers for SMTEncoder::visitPublicGetter
|
||||
{
|
||||
|
||||
bool isReturnedFromStructGetter(TypePointer _type)
|
||||
bool isReturnedFromStructGetter(Type const* _type)
|
||||
{
|
||||
// So far it seems that only Mappings and ordinary Arrays are not returned.
|
||||
auto category = _type->category();
|
||||
@ -1016,7 +1016,7 @@ void SMTEncoder::visitPublicGetter(FunctionCall const& _funCall)
|
||||
|
||||
// See FunctionType::FunctionType(VariableDeclaration const& _varDecl)
|
||||
// to understand the return types of public getters.
|
||||
TypePointer type = var->type();
|
||||
Type const* type = var->type();
|
||||
smtutil::Expression currentExpr = currentValue(*var);
|
||||
while (true)
|
||||
{
|
||||
@ -1450,7 +1450,7 @@ void SMTEncoder::endVisit(IndexAccess const& _indexAccess)
|
||||
|
||||
auto arrayVar = dynamic_pointer_cast<smt::SymbolicArrayVariable>(array);
|
||||
solAssert(arrayVar, "");
|
||||
TypePointer baseType = _indexAccess.baseExpression().annotation().type;
|
||||
Type const* baseType = _indexAccess.baseExpression().annotation().type;
|
||||
defineExpr(_indexAccess, smtutil::Expression::select(
|
||||
arrayVar->elements(),
|
||||
expr(*_indexAccess.indexExpression(), keyType(baseType))
|
||||
@ -1486,7 +1486,7 @@ void SMTEncoder::indexOrMemberAssignment(Expression const& _expr, smtutil::Expre
|
||||
if (dynamic_cast<Identifier const*>(&base))
|
||||
base.accept(*this);
|
||||
|
||||
TypePointer baseType = base.annotation().type;
|
||||
Type const* baseType = base.annotation().type;
|
||||
auto indexExpr = expr(*indexAccess->indexExpression(), keyType(baseType));
|
||||
auto symbArray = dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(base));
|
||||
solAssert(symbArray, "");
|
||||
@ -1735,7 +1735,7 @@ pair<smtutil::Expression, smtutil::Expression> SMTEncoder::arithmeticOperation(
|
||||
Token _op,
|
||||
smtutil::Expression const& _left,
|
||||
smtutil::Expression const& _right,
|
||||
TypePointer const& _commonType,
|
||||
Type const* _commonType,
|
||||
Expression const& _operation
|
||||
)
|
||||
{
|
||||
@ -1826,7 +1826,7 @@ smtutil::Expression SMTEncoder::bitwiseOperation(
|
||||
Token _op,
|
||||
smtutil::Expression const& _left,
|
||||
smtutil::Expression const& _right,
|
||||
TypePointer const& _commonType
|
||||
Type const* _commonType
|
||||
)
|
||||
{
|
||||
static set<Token> validOperators{
|
||||
@ -1995,7 +1995,7 @@ pair<smtutil::Expression, smtutil::Expression> SMTEncoder::divModWithSlacks(
|
||||
void SMTEncoder::assignment(
|
||||
Expression const& _left,
|
||||
smtutil::Expression const& _right,
|
||||
TypePointer const& _type
|
||||
Type const* _type
|
||||
)
|
||||
{
|
||||
solAssert(
|
||||
@ -2156,7 +2156,7 @@ void SMTEncoder::assignment(VariableDeclaration const& _variable, Expression con
|
||||
|
||||
void SMTEncoder::assignment(VariableDeclaration const& _variable, smtutil::Expression const& _value)
|
||||
{
|
||||
TypePointer type = _variable.type();
|
||||
Type const* type = _variable.type();
|
||||
if (type->category() == Type::Category::Mapping)
|
||||
arrayAssignment();
|
||||
assignment(*m_context.variable(_variable), _value);
|
||||
@ -2315,16 +2315,16 @@ void SMTEncoder::resetReferences(VariableDeclaration const& _varDecl)
|
||||
});
|
||||
}
|
||||
|
||||
void SMTEncoder::resetReferences(TypePointer _type)
|
||||
void SMTEncoder::resetReferences(Type const* _type)
|
||||
{
|
||||
m_context.resetVariables([&](VariableDeclaration const& _var) {
|
||||
return sameTypeOrSubtype(_var.type(), _type);
|
||||
});
|
||||
}
|
||||
|
||||
bool SMTEncoder::sameTypeOrSubtype(TypePointer _a, TypePointer _b)
|
||||
bool SMTEncoder::sameTypeOrSubtype(Type const* _a, Type const* _b)
|
||||
{
|
||||
TypePointer prefix = _a;
|
||||
Type const* prefix = _a;
|
||||
while (
|
||||
prefix->category() == Type::Category::Mapping ||
|
||||
prefix->category() == Type::Category::Array
|
||||
@ -2348,7 +2348,7 @@ bool SMTEncoder::sameTypeOrSubtype(TypePointer _a, TypePointer _b)
|
||||
return false;
|
||||
}
|
||||
|
||||
TypePointer SMTEncoder::typeWithoutPointer(TypePointer const& _type)
|
||||
Type const* SMTEncoder::typeWithoutPointer(Type const* _type)
|
||||
{
|
||||
if (auto refType = dynamic_cast<ReferenceType const*>(_type))
|
||||
return TypeProvider::withLocationIfReference(refType->location(), _type);
|
||||
@ -2419,7 +2419,7 @@ bool SMTEncoder::createVariable(VariableDeclaration const& _varDecl)
|
||||
return true;
|
||||
}
|
||||
|
||||
smtutil::Expression SMTEncoder::expr(Expression const& _e, TypePointer _targetType)
|
||||
smtutil::Expression SMTEncoder::expr(Expression const& _e, Type const* _targetType)
|
||||
{
|
||||
if (!m_context.knownExpression(_e))
|
||||
{
|
||||
@ -2587,7 +2587,7 @@ Expression const* SMTEncoder::leftmostBase(IndexAccess const& _indexAccess)
|
||||
return base;
|
||||
}
|
||||
|
||||
TypePointer SMTEncoder::keyType(TypePointer _type)
|
||||
Type const* SMTEncoder::keyType(Type const* _type)
|
||||
{
|
||||
if (auto const* mappingType = dynamic_cast<MappingType const*>(_type))
|
||||
return mappingType->keyType();
|
||||
|
@ -62,7 +62,7 @@ public:
|
||||
/// @returns the key type in _type.
|
||||
/// _type must allow IndexAccess, that is,
|
||||
/// it must be either ArrayType or MappingType
|
||||
static TypePointer keyType(TypePointer _type);
|
||||
static Type const* keyType(Type const* _type);
|
||||
|
||||
/// @returns the innermost element in a chain of 1-tuples if applicable,
|
||||
/// otherwise _expr.
|
||||
@ -166,7 +166,7 @@ protected:
|
||||
Token _op,
|
||||
smtutil::Expression const& _left,
|
||||
smtutil::Expression const& _right,
|
||||
TypePointer const& _commonType,
|
||||
Type const* _commonType,
|
||||
Expression const& _expression
|
||||
);
|
||||
|
||||
@ -174,7 +174,7 @@ protected:
|
||||
Token _op,
|
||||
smtutil::Expression const& _left,
|
||||
smtutil::Expression const& _right,
|
||||
TypePointer const& _commonType
|
||||
Type const* _commonType
|
||||
);
|
||||
|
||||
void compareOperation(BinaryOperation const& _op);
|
||||
@ -251,7 +251,7 @@ protected:
|
||||
void assignment(
|
||||
Expression const& _left,
|
||||
smtutil::Expression const& _right,
|
||||
TypePointer const& _type
|
||||
Type const* _type
|
||||
);
|
||||
/// Handle assignments between tuples.
|
||||
void tupleAssignment(Expression const& _left, Expression const& _right);
|
||||
@ -284,11 +284,11 @@ protected:
|
||||
/// a subexpression of the same type as _varDecl.
|
||||
void resetReferences(VariableDeclaration const& _varDecl);
|
||||
/// Resets all references/pointers that have type _type.
|
||||
void resetReferences(TypePointer _type);
|
||||
void resetReferences(Type const* _type);
|
||||
/// @returns the type without storage pointer information if it has it.
|
||||
TypePointer typeWithoutPointer(TypePointer const& _type);
|
||||
Type const* typeWithoutPointer(Type const* _type);
|
||||
/// @returns whether _a or a subtype of _a is the same as _b.
|
||||
bool sameTypeOrSubtype(TypePointer _a, TypePointer _b);
|
||||
bool sameTypeOrSubtype(Type const* _a, Type const* _b);
|
||||
|
||||
/// Given two different branches and the touched variables,
|
||||
/// merge the touched variables into after-branch ite variables
|
||||
@ -306,7 +306,7 @@ protected:
|
||||
/// Returns the expression corresponding to the AST node.
|
||||
/// If _targetType is not null apply conversion.
|
||||
/// Throws if the expression does not exist.
|
||||
smtutil::Expression expr(Expression const& _e, TypePointer _targetType = nullptr);
|
||||
smtutil::Expression expr(Expression const& _e, Type const* _targetType = nullptr);
|
||||
/// Creates the expression (value can be arbitrary)
|
||||
void createExpr(Expression const& _e);
|
||||
/// Creates the expression and sets its value.
|
||||
|
@ -208,8 +208,8 @@ void SymbolicState::buildABIFunctions(set<FunctionCall const*> const& _abiFuncti
|
||||
|
||||
/// Since each abi.* function may have a different number of input/output parameters,
|
||||
/// we generically compute those types.
|
||||
vector<TypePointer> inTypes;
|
||||
vector<TypePointer> outTypes;
|
||||
vector<frontend::Type const*> inTypes;
|
||||
vector<frontend::Type const*> outTypes;
|
||||
if (t->kind() == FunctionType::Kind::ABIDecode)
|
||||
{
|
||||
/// abi.decode : (bytes, tuple_of_types(return_types)) -> (return_types)
|
||||
|
@ -150,8 +150,8 @@ public:
|
||||
smtutil::Expression abiFunction(FunctionCall const* _funCall);
|
||||
using SymbolicABIFunction = std::tuple<
|
||||
std::string,
|
||||
std::vector<TypePointer>,
|
||||
std::vector<TypePointer>
|
||||
std::vector<frontend::Type const*>,
|
||||
std::vector<frontend::Type const*>
|
||||
>;
|
||||
SymbolicABIFunction const& abiFunctionTypes(FunctionCall const* _funCall) const;
|
||||
|
||||
|
@ -166,7 +166,7 @@ SortPointer smtSort(frontend::Type const& _type)
|
||||
}
|
||||
}
|
||||
|
||||
vector<SortPointer> smtSort(vector<frontend::TypePointer> const& _types)
|
||||
vector<SortPointer> smtSort(vector<frontend::Type const*> const& _types)
|
||||
{
|
||||
vector<SortPointer> sorts;
|
||||
for (auto const& type: _types)
|
||||
@ -181,7 +181,7 @@ SortPointer smtSortAbstractFunction(frontend::Type const& _type)
|
||||
return smtSort(_type);
|
||||
}
|
||||
|
||||
vector<SortPointer> smtSortAbstractFunction(vector<frontend::TypePointer> const& _types)
|
||||
vector<SortPointer> smtSortAbstractFunction(vector<frontend::Type const*> const& _types)
|
||||
{
|
||||
vector<SortPointer> sorts;
|
||||
for (auto const& type: _types)
|
||||
@ -232,7 +232,7 @@ pair<bool, shared_ptr<SymbolicVariable>> newSymbolicVariable(
|
||||
{
|
||||
bool abstract = false;
|
||||
shared_ptr<SymbolicVariable> var;
|
||||
frontend::TypePointer type = &_type;
|
||||
frontend::Type const* type = &_type;
|
||||
if (!isSupportedTypeDeclaration(_type))
|
||||
{
|
||||
abstract = true;
|
||||
@ -249,7 +249,7 @@ pair<bool, shared_ptr<SymbolicVariable>> newSymbolicVariable(
|
||||
return find_if(
|
||||
begin(params),
|
||||
end(params),
|
||||
[&](TypePointer _paramType) { return _paramType->category() == frontend::Type::Category::Function; }
|
||||
[&](frontend::Type const* _paramType) { return _paramType->category() == frontend::Type::Category::Function; }
|
||||
);
|
||||
};
|
||||
if (
|
||||
@ -391,7 +391,7 @@ smtutil::Expression minValue(frontend::IntegerType const& _type)
|
||||
return smtutil::Expression(_type.minValue());
|
||||
}
|
||||
|
||||
smtutil::Expression minValue(frontend::TypePointer _type)
|
||||
smtutil::Expression minValue(frontend::Type const* _type)
|
||||
{
|
||||
solAssert(isNumber(*_type), "");
|
||||
if (auto const* intType = dynamic_cast<IntegerType const*>(_type))
|
||||
@ -413,7 +413,7 @@ smtutil::Expression maxValue(frontend::IntegerType const& _type)
|
||||
return smtutil::Expression(_type.maxValue());
|
||||
}
|
||||
|
||||
smtutil::Expression maxValue(frontend::TypePointer _type)
|
||||
smtutil::Expression maxValue(frontend::Type const* _type)
|
||||
{
|
||||
solAssert(isNumber(*_type), "");
|
||||
if (auto const* intType = dynamic_cast<IntegerType const*>(_type))
|
||||
@ -437,13 +437,13 @@ void setSymbolicZeroValue(SymbolicVariable const& _variable, EncodingContext& _c
|
||||
setSymbolicZeroValue(_variable.currentValue(), _variable.type(), _context);
|
||||
}
|
||||
|
||||
void setSymbolicZeroValue(smtutil::Expression _expr, frontend::TypePointer const& _type, EncodingContext& _context)
|
||||
void setSymbolicZeroValue(smtutil::Expression _expr, frontend::Type const* _type, EncodingContext& _context)
|
||||
{
|
||||
solAssert(_type, "");
|
||||
_context.addAssertion(_expr == zeroValue(_type));
|
||||
}
|
||||
|
||||
smtutil::Expression zeroValue(frontend::TypePointer const& _type)
|
||||
smtutil::Expression zeroValue(frontend::Type const* _type)
|
||||
{
|
||||
solAssert(_type, "");
|
||||
if (isSupportedType(*_type))
|
||||
@ -496,7 +496,7 @@ smtutil::Expression zeroValue(frontend::TypePointer const& _type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool isSigned(TypePointer const& _type)
|
||||
bool isSigned(frontend::Type const* _type)
|
||||
{
|
||||
solAssert(smt::isNumber(*_type), "");
|
||||
bool isSigned = false;
|
||||
@ -519,7 +519,7 @@ bool isSigned(TypePointer const& _type)
|
||||
return isSigned;
|
||||
}
|
||||
|
||||
pair<unsigned, bool> typeBvSizeAndSignedness(frontend::TypePointer const& _type)
|
||||
pair<unsigned, bool> typeBvSizeAndSignedness(frontend::Type const* _type)
|
||||
{
|
||||
if (auto const* intType = dynamic_cast<IntegerType const*>(_type))
|
||||
return {intType->numBits(), intType->isSigned()};
|
||||
@ -536,12 +536,12 @@ void setSymbolicUnknownValue(SymbolicVariable const& _variable, EncodingContext&
|
||||
setSymbolicUnknownValue(_variable.currentValue(), _variable.type(), _context);
|
||||
}
|
||||
|
||||
void setSymbolicUnknownValue(smtutil::Expression _expr, frontend::TypePointer const& _type, EncodingContext& _context)
|
||||
void setSymbolicUnknownValue(smtutil::Expression _expr, frontend::Type const* _type, EncodingContext& _context)
|
||||
{
|
||||
_context.addAssertion(symbolicUnknownConstraints(_expr, _type));
|
||||
}
|
||||
|
||||
smtutil::Expression symbolicUnknownConstraints(smtutil::Expression _expr, frontend::TypePointer const& _type)
|
||||
smtutil::Expression symbolicUnknownConstraints(smtutil::Expression _expr, frontend::Type const* _type)
|
||||
{
|
||||
solAssert(_type, "");
|
||||
if (isEnum(*_type) || isInteger(*_type) || isAddress(*_type) || isFixedBytes(*_type))
|
||||
@ -553,7 +553,7 @@ smtutil::Expression symbolicUnknownConstraints(smtutil::Expression _expr, fronte
|
||||
return smtutil::Expression(true);
|
||||
}
|
||||
|
||||
optional<smtutil::Expression> symbolicTypeConversion(TypePointer _from, TypePointer _to)
|
||||
optional<smtutil::Expression> symbolicTypeConversion(frontend::Type const* _from, frontend::Type const* _to)
|
||||
{
|
||||
if (_to && _from)
|
||||
// StringLiterals are encoded as SMT arrays in the generic case,
|
||||
|
@ -29,11 +29,11 @@ class EncodingContext;
|
||||
|
||||
/// Returns the SMT sort that models the Solidity type _type.
|
||||
smtutil::SortPointer smtSort(frontend::Type const& _type);
|
||||
std::vector<smtutil::SortPointer> smtSort(std::vector<frontend::TypePointer> const& _types);
|
||||
std::vector<smtutil::SortPointer> smtSort(std::vector<frontend::Type const*> const& _types);
|
||||
/// If _type has type Function, abstract it to Integer.
|
||||
/// Otherwise return smtSort(_type).
|
||||
smtutil::SortPointer smtSortAbstractFunction(frontend::Type const& _type);
|
||||
std::vector<smtutil::SortPointer> smtSortAbstractFunction(std::vector<frontend::TypePointer> const& _types);
|
||||
std::vector<smtutil::SortPointer> smtSortAbstractFunction(std::vector<frontend::Type const*> const& _types);
|
||||
/// Returns the SMT kind that models the Solidity type type category _category.
|
||||
smtutil::Kind smtKind(frontend::Type const& _type);
|
||||
|
||||
@ -66,19 +66,19 @@ bool isNonRecursiveStruct(frontend::Type const& _type);
|
||||
std::pair<bool, std::shared_ptr<SymbolicVariable>> newSymbolicVariable(frontend::Type const& _type, std::string const& _uniqueName, EncodingContext& _context);
|
||||
|
||||
smtutil::Expression minValue(frontend::IntegerType const& _type);
|
||||
smtutil::Expression minValue(frontend::TypePointer _type);
|
||||
smtutil::Expression minValue(frontend::Type const* _type);
|
||||
smtutil::Expression maxValue(frontend::IntegerType const& _type);
|
||||
smtutil::Expression maxValue(frontend::TypePointer _type);
|
||||
smtutil::Expression zeroValue(frontend::TypePointer const& _type);
|
||||
bool isSigned(frontend::TypePointer const& _type);
|
||||
smtutil::Expression maxValue(frontend::Type const* _type);
|
||||
smtutil::Expression zeroValue(frontend::Type const* _type);
|
||||
bool isSigned(frontend::Type const* _type);
|
||||
|
||||
std::pair<unsigned, bool> typeBvSizeAndSignedness(frontend::TypePointer const& type);
|
||||
std::pair<unsigned, bool> typeBvSizeAndSignedness(frontend::Type const* type);
|
||||
|
||||
void setSymbolicZeroValue(SymbolicVariable const& _variable, EncodingContext& _context);
|
||||
void setSymbolicZeroValue(smtutil::Expression _expr, frontend::TypePointer const& _type, EncodingContext& _context);
|
||||
void setSymbolicZeroValue(smtutil::Expression _expr, frontend::Type const* _type, EncodingContext& _context);
|
||||
void setSymbolicUnknownValue(SymbolicVariable const& _variable, EncodingContext& _context);
|
||||
void setSymbolicUnknownValue(smtutil::Expression _expr, frontend::TypePointer const& _type, EncodingContext& _context);
|
||||
smtutil::Expression symbolicUnknownConstraints(smtutil::Expression _expr, frontend::TypePointer const& _type);
|
||||
void setSymbolicUnknownValue(smtutil::Expression _expr, frontend::Type const* _type, EncodingContext& _context);
|
||||
smtutil::Expression symbolicUnknownConstraints(smtutil::Expression _expr, frontend::Type const* _type);
|
||||
|
||||
std::optional<smtutil::Expression> symbolicTypeConversion(TypePointer _from, TypePointer _to);
|
||||
std::optional<smtutil::Expression> symbolicTypeConversion(frontend::Type const* _from, frontend::Type const* _to);
|
||||
}
|
||||
|
@ -32,8 +32,8 @@ using namespace solidity::frontend;
|
||||
using namespace solidity::frontend::smt;
|
||||
|
||||
SymbolicVariable::SymbolicVariable(
|
||||
TypePointer _type,
|
||||
TypePointer _originalType,
|
||||
frontend::Type const* _type,
|
||||
frontend::Type const* _originalType,
|
||||
string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
@ -61,7 +61,7 @@ SymbolicVariable::SymbolicVariable(
|
||||
solAssert(m_sort, "");
|
||||
}
|
||||
|
||||
smtutil::Expression SymbolicVariable::currentValue(frontend::TypePointer const&) const
|
||||
smtutil::Expression SymbolicVariable::currentValue(frontend::Type const*) const
|
||||
{
|
||||
return valueAtIndex(m_ssa->index());
|
||||
}
|
||||
@ -105,7 +105,7 @@ smtutil::Expression SymbolicVariable::increaseIndex()
|
||||
}
|
||||
|
||||
SymbolicBoolVariable::SymbolicBoolVariable(
|
||||
frontend::TypePointer _type,
|
||||
frontend::Type const* _type,
|
||||
string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
@ -115,8 +115,8 @@ SymbolicBoolVariable::SymbolicBoolVariable(
|
||||
}
|
||||
|
||||
SymbolicIntVariable::SymbolicIntVariable(
|
||||
frontend::TypePointer _type,
|
||||
frontend::TypePointer _originalType,
|
||||
frontend::Type const* _type,
|
||||
frontend::Type const* _originalType,
|
||||
string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
@ -134,7 +134,7 @@ SymbolicAddressVariable::SymbolicAddressVariable(
|
||||
}
|
||||
|
||||
SymbolicFixedBytesVariable::SymbolicFixedBytesVariable(
|
||||
frontend::TypePointer _originalType,
|
||||
frontend::Type const* _originalType,
|
||||
unsigned _numBytes,
|
||||
string _uniqueName,
|
||||
EncodingContext& _context
|
||||
@ -144,7 +144,7 @@ SymbolicFixedBytesVariable::SymbolicFixedBytesVariable(
|
||||
}
|
||||
|
||||
SymbolicFunctionVariable::SymbolicFunctionVariable(
|
||||
frontend::TypePointer _type,
|
||||
frontend::Type const* _type,
|
||||
string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
@ -165,7 +165,7 @@ SymbolicFunctionVariable::SymbolicFunctionVariable(
|
||||
solAssert(m_sort->kind == Kind::Function, "");
|
||||
}
|
||||
|
||||
smtutil::Expression SymbolicFunctionVariable::currentValue(frontend::TypePointer const& _targetType) const
|
||||
smtutil::Expression SymbolicFunctionVariable::currentValue(frontend::Type const* _targetType) const
|
||||
{
|
||||
return m_abstract.currentValue(_targetType);
|
||||
}
|
||||
@ -216,7 +216,7 @@ void SymbolicFunctionVariable::resetDeclaration()
|
||||
}
|
||||
|
||||
SymbolicEnumVariable::SymbolicEnumVariable(
|
||||
frontend::TypePointer _type,
|
||||
frontend::Type const* _type,
|
||||
string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
@ -226,7 +226,7 @@ SymbolicEnumVariable::SymbolicEnumVariable(
|
||||
}
|
||||
|
||||
SymbolicTupleVariable::SymbolicTupleVariable(
|
||||
frontend::TypePointer _type,
|
||||
frontend::Type const* _type,
|
||||
string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
@ -245,7 +245,7 @@ SymbolicTupleVariable::SymbolicTupleVariable(
|
||||
solAssert(m_sort->kind == Kind::Tuple, "");
|
||||
}
|
||||
|
||||
smtutil::Expression SymbolicTupleVariable::currentValue(frontend::TypePointer const& _targetType) const
|
||||
smtutil::Expression SymbolicTupleVariable::currentValue(frontend::Type const* _targetType) const
|
||||
{
|
||||
if (!_targetType || sort() == smtSort(*_targetType))
|
||||
return SymbolicVariable::currentValue();
|
||||
@ -272,8 +272,8 @@ vector<SortPointer> const& SymbolicTupleVariable::components() const
|
||||
|
||||
smtutil::Expression SymbolicTupleVariable::component(
|
||||
size_t _index,
|
||||
TypePointer _fromType,
|
||||
TypePointer _toType
|
||||
frontend::Type const* _fromType,
|
||||
frontend::Type const* _toType
|
||||
) const
|
||||
{
|
||||
optional<smtutil::Expression> conversion = symbolicTypeConversion(_fromType, _toType);
|
||||
@ -284,8 +284,8 @@ smtutil::Expression SymbolicTupleVariable::component(
|
||||
}
|
||||
|
||||
SymbolicArrayVariable::SymbolicArrayVariable(
|
||||
frontend::TypePointer _type,
|
||||
frontend::TypePointer _originalType,
|
||||
frontend::Type const* _type,
|
||||
frontend::Type const* _originalType,
|
||||
string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
@ -318,7 +318,7 @@ SymbolicArrayVariable::SymbolicArrayVariable(
|
||||
solAssert(m_sort->kind == Kind::Array, "");
|
||||
}
|
||||
|
||||
smtutil::Expression SymbolicArrayVariable::currentValue(frontend::TypePointer const& _targetType) const
|
||||
smtutil::Expression SymbolicArrayVariable::currentValue(frontend::Type const* _targetType) const
|
||||
{
|
||||
optional<smtutil::Expression> conversion = symbolicTypeConversion(m_originalType, _targetType);
|
||||
if (conversion)
|
||||
@ -343,7 +343,7 @@ smtutil::Expression SymbolicArrayVariable::length() const
|
||||
}
|
||||
|
||||
SymbolicStructVariable::SymbolicStructVariable(
|
||||
frontend::TypePointer _type,
|
||||
frontend::Type const* _type,
|
||||
string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
|
@ -40,8 +40,8 @@ class SymbolicVariable
|
||||
{
|
||||
public:
|
||||
SymbolicVariable(
|
||||
frontend::TypePointer _type,
|
||||
frontend::TypePointer _originalType,
|
||||
frontend::Type const* _type,
|
||||
frontend::Type const* _originalType,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
);
|
||||
@ -55,7 +55,7 @@ public:
|
||||
|
||||
virtual ~SymbolicVariable() = default;
|
||||
|
||||
virtual smtutil::Expression currentValue(frontend::TypePointer const& _targetType = TypePointer{}) const;
|
||||
virtual smtutil::Expression currentValue(frontend::Type const* _targetType = nullptr) const;
|
||||
std::string currentName() const;
|
||||
virtual smtutil::Expression valueAtIndex(unsigned _index) const;
|
||||
virtual std::string nameAtIndex(unsigned _index) const;
|
||||
@ -71,8 +71,8 @@ public:
|
||||
unsigned& index() { return m_ssa->index(); }
|
||||
|
||||
smtutil::SortPointer const& sort() const { return m_sort; }
|
||||
frontend::TypePointer const& type() const { return m_type; }
|
||||
frontend::TypePointer const& originalType() const { return m_originalType; }
|
||||
frontend::Type const* type() const { return m_type; }
|
||||
frontend::Type const* originalType() const { return m_originalType; }
|
||||
|
||||
protected:
|
||||
std::string uniqueSymbol(unsigned _index) const;
|
||||
@ -80,9 +80,9 @@ protected:
|
||||
/// SMT sort.
|
||||
smtutil::SortPointer m_sort;
|
||||
/// Solidity type, used for size and range in number types.
|
||||
frontend::TypePointer m_type;
|
||||
frontend::Type const* m_type;
|
||||
/// Solidity original type, used for type conversion if necessary.
|
||||
frontend::TypePointer m_originalType;
|
||||
frontend::Type const* m_originalType;
|
||||
std::string m_uniqueName;
|
||||
EncodingContext& m_context;
|
||||
std::unique_ptr<SSAVariable> m_ssa;
|
||||
@ -95,7 +95,7 @@ class SymbolicBoolVariable: public SymbolicVariable
|
||||
{
|
||||
public:
|
||||
SymbolicBoolVariable(
|
||||
frontend::TypePointer _type,
|
||||
frontend::Type const* _type,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
);
|
||||
@ -108,8 +108,8 @@ class SymbolicIntVariable: public SymbolicVariable
|
||||
{
|
||||
public:
|
||||
SymbolicIntVariable(
|
||||
frontend::TypePointer _type,
|
||||
frontend::TypePointer _originalType,
|
||||
frontend::Type const* _type,
|
||||
frontend::Type const* _originalType,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
);
|
||||
@ -134,7 +134,7 @@ class SymbolicFixedBytesVariable: public SymbolicIntVariable
|
||||
{
|
||||
public:
|
||||
SymbolicFixedBytesVariable(
|
||||
frontend::TypePointer _originalType,
|
||||
frontend::Type const* _originalType,
|
||||
unsigned _numBytes,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
@ -153,7 +153,7 @@ class SymbolicFunctionVariable: public SymbolicVariable
|
||||
{
|
||||
public:
|
||||
SymbolicFunctionVariable(
|
||||
frontend::TypePointer _type,
|
||||
frontend::Type const* _type,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
);
|
||||
@ -163,7 +163,7 @@ public:
|
||||
EncodingContext& _context
|
||||
);
|
||||
|
||||
smtutil::Expression currentValue(frontend::TypePointer const& _targetType = TypePointer{}) const override;
|
||||
smtutil::Expression currentValue(frontend::Type const* _targetType = nullptr) const override;
|
||||
|
||||
// Explicit request the function declaration.
|
||||
smtutil::Expression currentFunctionValue() const;
|
||||
@ -202,7 +202,7 @@ class SymbolicEnumVariable: public SymbolicVariable
|
||||
{
|
||||
public:
|
||||
SymbolicEnumVariable(
|
||||
frontend::TypePointer _type,
|
||||
frontend::Type const* _type,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
);
|
||||
@ -215,7 +215,7 @@ class SymbolicTupleVariable: public SymbolicVariable
|
||||
{
|
||||
public:
|
||||
SymbolicTupleVariable(
|
||||
frontend::TypePointer _type,
|
||||
frontend::Type const* _type,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
);
|
||||
@ -225,13 +225,13 @@ public:
|
||||
EncodingContext& _context
|
||||
);
|
||||
|
||||
smtutil::Expression currentValue(frontend::TypePointer const& _targetType = TypePointer{}) const override;
|
||||
smtutil::Expression currentValue(frontend::Type const* _targetType = nullptr) const override;
|
||||
|
||||
std::vector<smtutil::SortPointer> const& components() const;
|
||||
smtutil::Expression component(
|
||||
size_t _index,
|
||||
TypePointer _fromType = nullptr,
|
||||
TypePointer _toType = nullptr
|
||||
frontend::Type const* _fromType = nullptr,
|
||||
frontend::Type const* _toType = nullptr
|
||||
) const;
|
||||
};
|
||||
|
||||
@ -242,8 +242,8 @@ class SymbolicArrayVariable: public SymbolicVariable
|
||||
{
|
||||
public:
|
||||
SymbolicArrayVariable(
|
||||
frontend::TypePointer _type,
|
||||
frontend::TypePointer _originalTtype,
|
||||
frontend::Type const* _type,
|
||||
frontend::Type const* _originalTtype,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
);
|
||||
@ -255,7 +255,7 @@ public:
|
||||
|
||||
SymbolicArrayVariable(SymbolicArrayVariable&&) = default;
|
||||
|
||||
smtutil::Expression currentValue(frontend::TypePointer const& _targetType = TypePointer{}) const override;
|
||||
smtutil::Expression currentValue(frontend::Type const* _targetType = nullptr) const override;
|
||||
smtutil::Expression valueAtIndex(unsigned _index) const override;
|
||||
smtutil::Expression resetIndex() override { SymbolicVariable::resetIndex(); return m_pair.resetIndex(); }
|
||||
smtutil::Expression setIndex(unsigned _index) override { SymbolicVariable::setIndex(_index); return m_pair.setIndex(_index); }
|
||||
@ -276,7 +276,7 @@ class SymbolicStructVariable: public SymbolicVariable
|
||||
{
|
||||
public:
|
||||
SymbolicStructVariable(
|
||||
frontend::TypePointer _type,
|
||||
frontend::Type const* _type,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
);
|
||||
|
@ -31,7 +31,7 @@ namespace
|
||||
{
|
||||
bool anyDataStoredInStorage(TypePointers const& _pointers)
|
||||
{
|
||||
for (TypePointer const& pointer: _pointers)
|
||||
for (Type const* pointer: _pointers)
|
||||
if (pointer->dataStoredIn(DataLocation::Storage))
|
||||
return true;
|
||||
|
||||
@ -129,8 +129,8 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef)
|
||||
|
||||
Json::Value ABI::formatTypeList(
|
||||
vector<string> const& _names,
|
||||
vector<TypePointer> const& _encodingTypes,
|
||||
vector<TypePointer> const& _solidityTypes,
|
||||
vector<Type const*> const& _encodingTypes,
|
||||
vector<Type const*> const& _solidityTypes,
|
||||
bool _forLibrary
|
||||
)
|
||||
{
|
||||
|
@ -31,7 +31,6 @@ namespace solidity::frontend
|
||||
// Forward declarations
|
||||
class ContractDefinition;
|
||||
class Type;
|
||||
using TypePointer = Type const*;
|
||||
|
||||
class ABI
|
||||
{
|
||||
@ -48,8 +47,8 @@ private:
|
||||
/// ABI types used for the actual encoding.
|
||||
static Json::Value formatTypeList(
|
||||
std::vector<std::string> const& _names,
|
||||
std::vector<TypePointer> const& _encodingTypes,
|
||||
std::vector<TypePointer> const& _solidityTypes,
|
||||
std::vector<Type const*> const& _encodingTypes,
|
||||
std::vector<Type const*> const& _solidityTypes,
|
||||
bool _forLibrary
|
||||
);
|
||||
/// @returns a Json object with "name", "type", "internalType" and potentially
|
||||
|
@ -48,7 +48,7 @@ Json::Value StorageLayout::generate(ContractDefinition const& _contractDef)
|
||||
Json::Value StorageLayout::generate(VariableDeclaration const& _var, u256 const& _slot, unsigned _offset)
|
||||
{
|
||||
Json::Value varEntry;
|
||||
TypePointer varType = _var.type();
|
||||
Type const* varType = _var.type();
|
||||
|
||||
varEntry["label"] = _var.name();
|
||||
varEntry["astId"] = static_cast<int>(_var.id());
|
||||
@ -62,7 +62,7 @@ Json::Value StorageLayout::generate(VariableDeclaration const& _var, u256 const&
|
||||
return varEntry;
|
||||
}
|
||||
|
||||
void StorageLayout::generate(TypePointer _type)
|
||||
void StorageLayout::generate(Type const* _type)
|
||||
{
|
||||
if (m_types.isMember(typeKeyName(_type)))
|
||||
return;
|
||||
@ -112,7 +112,7 @@ void StorageLayout::generate(TypePointer _type)
|
||||
solAssert(typeInfo.isMember("encoding"), "");
|
||||
}
|
||||
|
||||
string StorageLayout::typeKeyName(TypePointer _type)
|
||||
string StorageLayout::typeKeyName(Type const* _type)
|
||||
{
|
||||
if (auto refType = dynamic_cast<ReferenceType const*>(_type))
|
||||
return TypeProvider::withLocationIfReference(refType->location(), _type)->richIdentifier();
|
||||
|
@ -42,10 +42,10 @@ private:
|
||||
Json::Value generate(VariableDeclaration const& _var, u256 const& _slot, unsigned _offset);
|
||||
|
||||
/// Generates the JSON information for @param _type
|
||||
void generate(TypePointer _type);
|
||||
void generate(Type const* _type);
|
||||
|
||||
/// The key for the JSON object describing a type.
|
||||
std::string typeKeyName(TypePointer _type);
|
||||
std::string typeKeyName(Type const* _type);
|
||||
|
||||
Json::Value m_types;
|
||||
|
||||
|
@ -33,7 +33,6 @@ namespace solidity::frontend
|
||||
{
|
||||
class Type;
|
||||
class FunctionType;
|
||||
using TypePointer = Type const*;
|
||||
using FunctionTypePointer = FunctionType const*;
|
||||
}
|
||||
|
||||
|
@ -175,8 +175,8 @@ BOOST_AUTO_TEST_CASE(type_identifiers)
|
||||
BOOST_CHECK_EQUAL(TypeProvider::fromElementaryTypeName("string calldata")->identifier(), "t_string_calldata_ptr");
|
||||
ArrayType largeintArray(DataLocation::Memory, TypeProvider::fromElementaryTypeName("int128"), u256("2535301200456458802993406410752"));
|
||||
BOOST_CHECK_EQUAL(largeintArray.identifier(), "t_array$_t_int128_$2535301200456458802993406410752_memory_ptr");
|
||||
TypePointer stringArray = TypeProvider::array(DataLocation::Storage, TypeProvider::fromElementaryTypeName("string"), u256("20"));
|
||||
TypePointer multiArray = TypeProvider::array(DataLocation::Storage, stringArray);
|
||||
Type const* stringArray = TypeProvider::array(DataLocation::Storage, TypeProvider::fromElementaryTypeName("string"), u256("20"));
|
||||
Type const* multiArray = TypeProvider::array(DataLocation::Storage, stringArray);
|
||||
BOOST_CHECK_EQUAL(multiArray->identifier(), "t_array$_t_array$_t_string_storage_$20_storage_$dyn_storage_ptr");
|
||||
|
||||
ContractDefinition c(++id, SourceLocation{}, make_shared<string>("MyContract$"), SourceLocation{}, {}, {}, {}, ContractKind::Contract);
|
||||
@ -193,13 +193,13 @@ BOOST_AUTO_TEST_CASE(type_identifiers)
|
||||
TupleType t({e.type(), s.type(), stringArray, nullptr});
|
||||
BOOST_CHECK_EQUAL(t.identifier(), "t_tuple$_t_type$_t_enum$_Enum_$4_$_$_t_type$_t_struct$_Struct_$3_storage_ptr_$_$_t_array$_t_string_storage_$20_storage_ptr_$__$");
|
||||
|
||||
TypePointer keccak256fun = TypeProvider::function(strings{}, strings{}, FunctionType::Kind::KECCAK256);
|
||||
Type const* keccak256fun = TypeProvider::function(strings{}, strings{}, FunctionType::Kind::KECCAK256);
|
||||
BOOST_CHECK_EQUAL(keccak256fun->identifier(), "t_function_keccak256_nonpayable$__$returns$__$");
|
||||
|
||||
FunctionType metaFun(TypePointers{keccak256fun}, TypePointers{s.type()}, strings{""}, strings{""});
|
||||
BOOST_CHECK_EQUAL(metaFun.identifier(), "t_function_internal_nonpayable$_t_function_keccak256_nonpayable$__$returns$__$_$returns$_t_type$_t_struct$_Struct_$3_storage_ptr_$_$");
|
||||
|
||||
TypePointer m = TypeProvider::mapping(TypeProvider::fromElementaryTypeName("bytes32"), s.type());
|
||||
Type const* m = TypeProvider::mapping(TypeProvider::fromElementaryTypeName("bytes32"), s.type());
|
||||
MappingType m2(TypeProvider::fromElementaryTypeName("uint64"), m);
|
||||
BOOST_CHECK_EQUAL(m2.identifier(), "t_mapping$_t_uint64_$_t_mapping$_t_bytes32_$_t_type$_t_struct$_Struct_$3_storage_ptr_$_$_$");
|
||||
|
||||
|
@ -22,7 +22,7 @@ using namespace solidity::tools;
|
||||
|
||||
void DotSyntax::endVisit(FunctionCall const& _functionCall)
|
||||
{
|
||||
TypePointer type = _functionCall.annotation().type;
|
||||
Type const* type = _functionCall.annotation().type;
|
||||
if (auto const funcType = dynamic_cast<FunctionType const*>(type))
|
||||
{
|
||||
if (funcType->valueSet())
|
||||
|
Loading…
Reference in New Issue
Block a user