aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/ast
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/ast')
-rw-r--r--libsolidity/ast/AST.cpp45
-rw-r--r--libsolidity/ast/AST.h38
-rw-r--r--libsolidity/ast/ASTJsonConverter.cpp10
-rw-r--r--libsolidity/ast/Types.cpp169
-rw-r--r--libsolidity/ast/Types.h41
5 files changed, 194 insertions, 109 deletions
diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp
index 403f4b79..1d68231e 100644
--- a/libsolidity/ast/AST.cpp
+++ b/libsolidity/ast/AST.cpp
@@ -84,13 +84,35 @@ SourceUnitAnnotation& SourceUnit::annotation() const
return dynamic_cast<SourceUnitAnnotation&>(*m_annotation);
}
-string Declaration::sourceUnitName() const
+set<SourceUnit const*> SourceUnit::referencedSourceUnits(bool _recurse, set<SourceUnit const*> _skipList) const
+{
+ set<SourceUnit const*> sourceUnits;
+ for (ImportDirective const* importDirective: filteredNodes<ImportDirective>(nodes()))
+ {
+ auto const& sourceUnit = importDirective->annotation().sourceUnit;
+ if (!_skipList.count(sourceUnit))
+ {
+ _skipList.insert(sourceUnit);
+ sourceUnits.insert(sourceUnit);
+ if (_recurse)
+ sourceUnits += sourceUnit->referencedSourceUnits(true, _skipList);
+ }
+ }
+ return sourceUnits;
+}
+
+SourceUnit const& Declaration::sourceUnit() const
{
solAssert(!!m_scope, "");
ASTNode const* scope = m_scope;
while (dynamic_cast<Declaration const*>(scope) && dynamic_cast<Declaration const*>(scope)->m_scope)
scope = dynamic_cast<Declaration const*>(scope)->m_scope;
- return dynamic_cast<SourceUnit const&>(*scope).annotation().path;
+ return dynamic_cast<SourceUnit const&>(*scope);
+}
+
+string Declaration::sourceUnitName() const
+{
+ return sourceUnit().annotation().path;
}
ImportAnnotation& ImportDirective::annotation() const
@@ -140,7 +162,7 @@ FunctionDefinition const* ContractDefinition::fallbackFunction() const
{
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
for (FunctionDefinition const* f: contract->definedFunctions())
- if (f->name().empty())
+ if (f->isFallback())
return f;
return nullptr;
}
@@ -416,6 +438,23 @@ bool VariableDeclaration::isCallableParameter() const
return false;
}
+bool VariableDeclaration::isLocalOrReturn() const
+{
+ return isReturnParameter() || (isLocalVariable() && !isCallableParameter());
+}
+
+bool VariableDeclaration::isReturnParameter() const
+{
+ auto const* callable = dynamic_cast<CallableDeclaration const*>(scope());
+ if (!callable)
+ return false;
+ if (callable->returnParameterList())
+ for (auto const& variable: callable->returnParameterList()->parameters())
+ if (variable.get() == this)
+ return true;
+ return false;
+}
+
bool VariableDeclaration::isExternalCallableParameter() const
{
auto const* callable = dynamic_cast<CallableDeclaration const*>(scope());
diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h
index e8831dc0..3e97286b 100644
--- a/libsolidity/ast/AST.h
+++ b/libsolidity/ast/AST.h
@@ -23,19 +23,24 @@
#pragma once
-#include <string>
-#include <vector>
-#include <memory>
-#include <boost/noncopyable.hpp>
-#include <libevmasm/SourceLocation.h>
-#include <libevmasm/Instruction.h>
#include <libsolidity/ast/ASTForward.h>
#include <libsolidity/parsing/Token.h>
#include <libsolidity/ast/Types.h>
#include <libsolidity/interface/Exceptions.h>
#include <libsolidity/ast/ASTAnnotations.h>
+
+#include <libevmasm/SourceLocation.h>
+#include <libevmasm/Instruction.h>
+
+#include <libdevcore/FixedHash.h>
#include <json/json.h>
+#include <boost/noncopyable.hpp>
+
+#include <string>
+#include <vector>
+#include <memory>
+
namespace dev
{
namespace solidity
@@ -131,6 +136,9 @@ public:
std::vector<ASTPointer<ASTNode>> nodes() const { return m_nodes; }
+ /// @returns a set of referenced SourceUnits. Recursively if @a _recurse is true.
+ std::set<SourceUnit const*> referencedSourceUnits(bool _recurse = false, std::set<SourceUnit const*> _skipList = std::set<SourceUnit const*>()) const;
+
private:
std::vector<ASTPointer<ASTNode>> m_nodes;
};
@@ -163,6 +171,9 @@ public:
ASTNode const* scope() const { return m_scope; }
void setScope(ASTNode const* _scope) { m_scope = _scope; }
+ /// @returns the source unit this declaration is present in.
+ SourceUnit const& sourceUnit() const;
+
/// @returns the source name this declaration is present in.
/// Can be combined with annotation().canonicalName to form a globally unique name.
std::string sourceUnitName() const;
@@ -578,6 +589,7 @@ public:
virtual void accept(ASTConstVisitor& _visitor) const override;
bool isConstructor() const { return m_isConstructor; }
+ bool isFallback() const { return name().empty(); }
bool isDeclaredConst() const { return m_isDeclaredConst; }
bool isPayable() const { return m_isPayable; }
std::vector<ASTPointer<ModifierInvocation>> const& modifiers() const { return m_functionModifiers; }
@@ -585,9 +597,9 @@ public:
Block const& body() const { solAssert(m_body, ""); return *m_body; }
virtual bool isVisibleInContract() const override
{
- return Declaration::isVisibleInContract() && !isConstructor() && !name().empty();
+ return Declaration::isVisibleInContract() && !isConstructor() && !isFallback();
}
- virtual bool isPartOfExternalInterface() const override { return isPublic() && !m_isConstructor && !name().empty(); }
+ virtual bool isPartOfExternalInterface() const override { return isPublic() && !isConstructor() && !isFallback(); }
/// @returns the external signature of the function
/// That consists of the name of the function followed by the types of the
@@ -650,6 +662,10 @@ public:
bool isLocalVariable() const { return !!dynamic_cast<CallableDeclaration const*>(scope()); }
/// @returns true if this variable is a parameter or return parameter of a function.
bool isCallableParameter() const;
+ /// @returns true if this variable is a return parameter of a function.
+ bool isReturnParameter() const;
+ /// @returns true if this variable is a local variable or return parameter.
+ bool isLocalOrReturn() const;
/// @returns true if this variable is a parameter (not return parameter) of an external function.
bool isExternalCallableParameter() const;
/// @returns true if the type of the variable does not need to be specified, i.e. it is declared
@@ -695,7 +711,7 @@ public:
ASTPointer<ParameterList> const& _parameters,
ASTPointer<Block> const& _body
):
- CallableDeclaration(_location, _name, Visibility::Default, _parameters),
+ CallableDeclaration(_location, _name, Visibility::Internal, _parameters),
Documented(_documentation),
m_body(_body)
{
@@ -782,11 +798,11 @@ public:
Declaration(SourceLocation(), std::make_shared<ASTString>(_name)), m_type(_type) {}
virtual void accept(ASTVisitor&) override
{
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("MagicVariableDeclaration used inside real AST."));
+ solAssert(false, "MagicVariableDeclaration used inside real AST.");
}
virtual void accept(ASTConstVisitor&) const override
{
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("MagicVariableDeclaration used inside real AST."));
+ solAssert(false, "MagicVariableDeclaration used inside real AST.");
}
virtual TypePointer type() const override { return m_type; }
diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp
index a90debb2..eda70b63 100644
--- a/libsolidity/ast/ASTJsonConverter.cpp
+++ b/libsolidity/ast/ASTJsonConverter.cpp
@@ -743,7 +743,7 @@ string ASTJsonConverter::visibility(Declaration::Visibility const& _visibility)
case Declaration::Visibility::External:
return "external";
default:
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown declaration visibility."));
+ solAssert(false, "Unknown declaration visibility.");
}
}
@@ -758,7 +758,7 @@ string ASTJsonConverter::location(VariableDeclaration::Location _location)
case VariableDeclaration::Location::Memory:
return "memory";
default:
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown declaration location."));
+ solAssert(false, "Unknown declaration location.");
}
}
@@ -773,7 +773,7 @@ string ASTJsonConverter::contractKind(ContractDefinition::ContractKind _kind)
case ContractDefinition::ContractKind::Library:
return "library";
default:
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown kind of contract."));
+ solAssert(false, "Unknown kind of contract.");
}
}
@@ -788,7 +788,7 @@ string ASTJsonConverter::functionCallKind(FunctionCallKind _kind)
case FunctionCallKind::StructConstructorCall:
return "structConstructorCall";
default:
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown kind of function call ."));
+ solAssert(false, "Unknown kind of function call.");
}
}
@@ -804,7 +804,7 @@ string ASTJsonConverter::literalTokenKind(Token::Value _token)
case dev::solidity::Token::FalseLiteral:
return "bool";
default:
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown kind of literal token."));
+ solAssert(false, "Unknown kind of literal token.");
}
}
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index 7dc6c4a6..3f8da501 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -196,9 +196,9 @@ TypePointer Type::fromElementaryTypeName(ElementaryTypeNameToken const& _type)
case Token::UInt:
return make_shared<IntegerType>(256, IntegerType::Modifier::Unsigned);
case Token::Fixed:
- return make_shared<FixedPointType>(128, 128, FixedPointType::Modifier::Signed);
+ return make_shared<FixedPointType>(128, 19, FixedPointType::Modifier::Signed);
case Token::UFixed:
- return make_shared<FixedPointType>(128, 128, FixedPointType::Modifier::Unsigned);
+ return make_shared<FixedPointType>(128, 19, FixedPointType::Modifier::Unsigned);
case Token::Byte:
return make_shared<FixedBytesType>(1);
case Token::Address:
@@ -211,9 +211,10 @@ TypePointer Type::fromElementaryTypeName(ElementaryTypeNameToken const& _type)
return make_shared<ArrayType>(DataLocation::Storage, true);
//no types found
default:
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment(
+ solAssert(
+ false,
"Unable to convert elementary typename " + _type.toString() + " to type."
- ));
+ );
}
}
@@ -352,12 +353,11 @@ bool IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const
else if (_convertTo.category() == Category::FixedPoint)
{
FixedPointType const& convertTo = dynamic_cast<FixedPointType const&>(_convertTo);
- if (convertTo.integerBits() < m_bits || isAddress())
+
+ if (isAddress())
return false;
- else if (isSigned())
- return convertTo.isSigned();
else
- return !convertTo.isSigned() || convertTo.integerBits() > m_bits;
+ return maxValue() <= convertTo.maxIntegerValue() && minValue() >= convertTo.minIntegerValue();
}
else
return false;
@@ -413,6 +413,22 @@ u256 IntegerType::literalValue(Literal const* _literal) const
return u256(_literal->value());
}
+bigint IntegerType::minValue() const
+{
+ if (isSigned())
+ return -(bigint(1) << (m_bits - 1));
+ else
+ return bigint(0);
+}
+
+bigint IntegerType::maxValue() const
+{
+ if (isSigned())
+ return (bigint(1) << (m_bits - 1)) - 1;
+ else
+ return (bigint(1) << m_bits) - 1;
+}
+
TypePointer IntegerType::binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const
{
if (
@@ -471,22 +487,20 @@ MemberList::MemberMap IntegerType::nativeMembers(ContractDefinition const*) cons
return MemberList::MemberMap();
}
-FixedPointType::FixedPointType(int _integerBits, int _fractionalBits, FixedPointType::Modifier _modifier):
- m_integerBits(_integerBits), m_fractionalBits(_fractionalBits), m_modifier(_modifier)
+FixedPointType::FixedPointType(int _totalBits, int _fractionalDigits, FixedPointType::Modifier _modifier):
+ m_totalBits(_totalBits), m_fractionalDigits(_fractionalDigits), m_modifier(_modifier)
{
solAssert(
- m_integerBits + m_fractionalBits > 0 &&
- m_integerBits + m_fractionalBits <= 256 &&
- m_integerBits % 8 == 0 &&
- m_fractionalBits % 8 == 0,
+ 8 <= m_totalBits && m_totalBits <= 256 && m_totalBits % 8 == 0 &&
+ 0 <= m_fractionalDigits && m_fractionalDigits <= 80,
"Invalid bit number(s) for fixed type: " +
- dev::toString(_integerBits) + "x" + dev::toString(_fractionalBits)
- );
+ dev::toString(_totalBits) + "x" + dev::toString(_fractionalDigits)
+ );
}
string FixedPointType::identifier() const
{
- return "t_" + string(isSigned() ? "" : "u") + "fixed" + std::to_string(integerBits()) + "x" + std::to_string(fractionalBits());
+ return "t_" + string(isSigned() ? "" : "u") + "fixed" + std::to_string(m_totalBits) + "x" + std::to_string(m_fractionalDigits);
}
bool FixedPointType::isImplicitlyConvertibleTo(Type const& _convertTo) const
@@ -494,12 +508,10 @@ bool FixedPointType::isImplicitlyConvertibleTo(Type const& _convertTo) const
if (_convertTo.category() == category())
{
FixedPointType const& convertTo = dynamic_cast<FixedPointType const&>(_convertTo);
- if (convertTo.m_integerBits < m_integerBits || convertTo.m_fractionalBits < m_fractionalBits)
+ if (convertTo.numBits() < m_totalBits || convertTo.fractionalDigits() < m_fractionalDigits)
return false;
- else if (isSigned())
- return convertTo.isSigned();
else
- return !convertTo.isSigned() || (convertTo.m_integerBits > m_integerBits);
+ return convertTo.maxIntegerValue() >= maxIntegerValue() && convertTo.minIntegerValue() <= minIntegerValue();
}
return false;
}
@@ -533,13 +545,30 @@ bool FixedPointType::operator==(Type const& _other) const
if (_other.category() != category())
return false;
FixedPointType const& other = dynamic_cast<FixedPointType const&>(_other);
- return other.m_integerBits == m_integerBits && other.m_fractionalBits == m_fractionalBits && other.m_modifier == m_modifier;
+ return other.m_totalBits == m_totalBits && other.m_fractionalDigits == m_fractionalDigits && other.m_modifier == m_modifier;
}
string FixedPointType::toString(bool) const
{
string prefix = isSigned() ? "fixed" : "ufixed";
- return prefix + dev::toString(m_integerBits) + "x" + dev::toString(m_fractionalBits);
+ return prefix + dev::toString(m_totalBits) + "x" + dev::toString(m_fractionalDigits);
+}
+
+bigint FixedPointType::maxIntegerValue() const
+{
+ bigint maxValue = (bigint(1) << (m_totalBits - (isSigned() ? 1 : 0))) - 1;
+ return maxValue / pow(bigint(10), m_fractionalDigits);
+}
+
+bigint FixedPointType::minIntegerValue() const
+{
+ if (isSigned())
+ {
+ bigint minValue = -(bigint(1) << (m_totalBits - (isSigned() ? 1 : 0)));
+ return minValue / pow(bigint(10), m_fractionalDigits);
+ }
+ else
+ return bigint(0);
}
TypePointer FixedPointType::binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const
@@ -727,13 +756,9 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
else if (_convertTo.category() == Category::FixedPoint)
{
if (auto fixed = fixedPointType())
- {
- // We disallow implicit conversion if we would have to truncate (fixedPointType()
- // can return a type that requires truncation).
- rational value = m_value * (bigint(1) << fixed->fractionalBits());
- return value.denominator() == 1 && fixed->isImplicitlyConvertibleTo(_convertTo);
- }
- return false;
+ return fixed->isImplicitlyConvertibleTo(_convertTo);
+ else
+ return false;
}
else if (_convertTo.category() == Category::FixedBytes)
{
@@ -937,10 +962,9 @@ u256 RationalNumberType::literalValue(Literal const*) const
else
{
auto fixed = fixedPointType();
- solAssert(!!fixed, "");
- rational shifted = m_value * (bigint(1) << fixed->fractionalBits());
- // truncate
- shiftedValue = shifted.numerator() / shifted.denominator();
+ solAssert(fixed, "");
+ int fractionalDigits = fixed->fractionalDigits();
+ shiftedValue = (m_value.numerator() / m_value.denominator()) * pow(bigint(10), fractionalDigits);
}
// we ignore the literal and hope that the type was correctly determined
@@ -981,22 +1005,21 @@ shared_ptr<IntegerType const> RationalNumberType::integerType() const
shared_ptr<FixedPointType const> RationalNumberType::fixedPointType() const
{
bool negative = (m_value < 0);
- unsigned fractionalBits = 0;
+ unsigned fractionalDigits = 0;
rational value = abs(m_value); // We care about the sign later.
rational maxValue = negative ?
rational(bigint(1) << 255, 1):
rational((bigint(1) << 256) - 1, 1);
- while (value * 0x100 <= maxValue && value.denominator() != 1 && fractionalBits < 256)
+ while (value * 10 <= maxValue && value.denominator() != 1 && fractionalDigits < 80)
{
- value *= 0x100;
- fractionalBits += 8;
+ value *= 10;
+ fractionalDigits++;
}
if (value > maxValue)
return shared_ptr<FixedPointType const>();
- // u256(v) is the actual value that will be put on the stack
- // From here on, very similar to integerType()
+ // This means we round towards zero for positive and negative values.
bigint v = value.numerator() / value.denominator();
if (negative)
// modify value to satisfy bit requirements for negative numbers:
@@ -1006,26 +1029,11 @@ shared_ptr<FixedPointType const> RationalNumberType::fixedPointType() const
if (v > u256(-1))
return shared_ptr<FixedPointType const>();
- unsigned totalBits = bytesRequired(v) * 8;
+ unsigned totalBits = max(bytesRequired(v), 1u) * 8;
solAssert(totalBits <= 256, "");
- unsigned integerBits = totalBits >= fractionalBits ? totalBits - fractionalBits : 0;
- // Special case: Numbers between -1 and 0 have their sign bit in the fractional part.
- if (negative && abs(m_value) < 1 && totalBits > fractionalBits)
- {
- fractionalBits += 8;
- integerBits = 0;
- }
-
- if (integerBits > 256 || fractionalBits > 256 || fractionalBits + integerBits > 256)
- return shared_ptr<FixedPointType const>();
- if (integerBits == 0 && fractionalBits == 0)
- {
- integerBits = 0;
- fractionalBits = 8;
- }
return make_shared<FixedPointType>(
- integerBits, fractionalBits,
+ totalBits, fractionalDigits,
negative ? FixedPointType::Modifier::Signed : FixedPointType::Modifier::Unsigned
);
}
@@ -1169,7 +1177,7 @@ u256 BoolType::literalValue(Literal const* _literal) const
else if (_literal->token() == Token::FalseLiteral)
return u256(0);
else
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Bool type constructed from non-boolean literal."));
+ solAssert(false, "Bool type constructed from non-boolean literal.");
}
TypePointer BoolType::unaryOperatorResult(Token::Value _operator) const
@@ -1214,6 +1222,12 @@ bool ContractType::isExplicitlyConvertibleTo(Type const& _convertTo) const
_convertTo.category() == Category::Contract;
}
+bool ContractType::isPayable() const
+{
+ auto fallbackFunction = m_contract.fallbackFunction();
+ return fallbackFunction && fallbackFunction->isPayable();
+}
+
TypePointer ContractType::unaryOperatorResult(Token::Value _operator) const
{
return _operator == Token::Delete ? make_shared<TupleType>() : TypePointer();
@@ -1373,12 +1387,23 @@ bool ArrayType::operator==(Type const& _other) const
return isDynamicallySized() || length() == other.length();
}
-unsigned ArrayType::calldataEncodedSize(bool _padded) const
+bool ArrayType::validForCalldata() const
+{
+ return unlimitedCalldataEncodedSize(true) <= numeric_limits<unsigned>::max();
+}
+
+bigint ArrayType::unlimitedCalldataEncodedSize(bool _padded) const
{
if (isDynamicallySized())
return 32;
bigint size = bigint(length()) * (isByteArray() ? 1 : baseType()->calldataEncodedSize(_padded));
size = ((size + 31) / 32) * 32;
+ return size;
+}
+
+unsigned ArrayType::calldataEncodedSize(bool _padded) const
+{
+ bigint size = unlimitedCalldataEncodedSize(_padded);
solAssert(size <= numeric_limits<unsigned>::max(), "Array size does not fit unsigned.");
return unsigned(size);
}
@@ -1914,10 +1939,7 @@ string TupleType::toString(bool _short) const
u256 TupleType::storageSize() const
{
- BOOST_THROW_EXCEPTION(
- InternalCompilerError() <<
- errinfo_comment("Storage size of non-storable tuple type requested.")
- );
+ solAssert(false, "Storage size of non-storable tuple type requested.");
}
unsigned TupleType::sizeOnStack() const
@@ -2299,9 +2321,7 @@ u256 FunctionType::storageSize() const
if (m_kind == Kind::External || m_kind == Kind::Internal)
return 1;
else
- BOOST_THROW_EXCEPTION(
- InternalCompilerError()
- << errinfo_comment("Storage size of non-storable function type requested."));
+ solAssert(false, "Storage size of non-storable function type requested.");
}
unsigned FunctionType::storageBytes() const
@@ -2311,9 +2331,7 @@ unsigned FunctionType::storageBytes() const
else if (m_kind == Kind::Internal)
return 8; // it should really not be possible to create larger programs
else
- BOOST_THROW_EXCEPTION(
- InternalCompilerError()
- << errinfo_comment("Storage size of non-storable function type requested."));
+ solAssert(false, "Storage size of non-storable function type requested.");
}
unsigned FunctionType::sizeOnStack() const
@@ -2506,6 +2524,7 @@ bool FunctionType::isBareCall() const
string FunctionType::externalSignature() const
{
solAssert(m_declaration != nullptr, "External signature of function needs declaration");
+ solAssert(!m_declaration->name().empty(), "Fallback function has no signature.");
bool _inLibrary = dynamic_cast<ContractDefinition const&>(*m_declaration->scope()).isLibrary();
@@ -2671,9 +2690,7 @@ bool TypeType::operator==(Type const& _other) const
u256 TypeType::storageSize() const
{
- BOOST_THROW_EXCEPTION(
- InternalCompilerError()
- << errinfo_comment("Storage size of non-storable type type requested."));
+ solAssert(false, "Storage size of non-storable type type requested.");
}
unsigned TypeType::sizeOnStack() const
@@ -2740,9 +2757,7 @@ ModifierType::ModifierType(const ModifierDefinition& _modifier)
u256 ModifierType::storageSize() const
{
- BOOST_THROW_EXCEPTION(
- InternalCompilerError()
- << errinfo_comment("Storage size of non-storable type type requested."));
+ solAssert(false, "Storage size of non-storable type type requested.");
}
string ModifierType::identifier() const
@@ -2851,7 +2866,7 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const
{"gasprice", make_shared<IntegerType>(256)}
});
default:
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown kind of magic."));
+ solAssert(false, "Unknown kind of magic.");
}
}
@@ -2866,6 +2881,6 @@ string MagicType::toString(bool) const
case Kind::Transaction:
return "tx";
default:
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown kind of magic."));
+ solAssert(false, "Unknown kind of magic.");
}
}
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index f7a73ab5..1db46355 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -28,7 +28,6 @@
#include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h>
-#include <libdevcore/UndefMacros.h>
#include <boost/noncopyable.hpp>
#include <boost/rational.hpp>
@@ -246,10 +245,7 @@ public:
virtual std::string canonicalName(bool /*_addDataLocation*/) const { return toString(true); }
virtual u256 literalValue(Literal const*) const
{
- BOOST_THROW_EXCEPTION(
- InternalCompilerError() <<
- errinfo_comment("Literal value requested for type without literals.")
- );
+ solAssert(false, "Literal value requested for type without literals.");
}
/// @returns a (simpler) type that is encoded in the same way for external function calls.
@@ -323,6 +319,9 @@ public:
bool isAddress() const { return m_modifier == Modifier::Address; }
bool isSigned() const { return m_modifier == Modifier::Signed; }
+ bigint minValue() const;
+ bigint maxValue() const;
+
private:
int m_bits;
Modifier m_modifier;
@@ -340,7 +339,7 @@ public:
};
virtual Category category() const override { return Category::FixedPoint; }
- explicit FixedPointType(int _integerBits, int _fractionalBits, Modifier _modifier = Modifier::Unsigned);
+ explicit FixedPointType(int _totalBits, int _fractionalDigits, Modifier _modifier = Modifier::Unsigned);
virtual std::string identifier() const override;
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
@@ -350,8 +349,8 @@ public:
virtual bool operator==(Type const& _other) const override;
- virtual unsigned calldataEncodedSize(bool _padded = true) const override { return _padded ? 32 : (m_integerBits + m_fractionalBits) / 8; }
- virtual unsigned storageBytes() const override { return (m_integerBits + m_fractionalBits) / 8; }
+ virtual unsigned calldataEncodedSize(bool _padded = true) const override { return _padded ? 32 : m_totalBits / 8; }
+ virtual unsigned storageBytes() const override { return m_totalBits / 8; }
virtual bool isValueType() const override { return true; }
virtual std::string toString(bool _short) const override;
@@ -359,14 +358,21 @@ public:
virtual TypePointer encodingType() const override { return shared_from_this(); }
virtual TypePointer interfaceType(bool) const override { return shared_from_this(); }
- int numBits() const { return m_integerBits + m_fractionalBits; }
- int integerBits() const { return m_integerBits; }
- int fractionalBits() const { return m_fractionalBits; }
+ /// Number of bits used for this type in total.
+ int numBits() const { return m_totalBits; }
+ /// Number of decimal digits after the radix point.
+ int fractionalDigits() const { return m_fractionalDigits; }
bool isSigned() const { return m_modifier == Modifier::Signed; }
+ /// @returns the largest integer value this type con hold. Note that this is not the
+ /// largest value in general.
+ bigint maxIntegerValue() const;
+ /// @returns the smallest integer value this type can hold. Note hat this is not the
+ /// smallest value in general.
+ bigint minIntegerValue() const;
private:
- int m_integerBits;
- int m_fractionalBits;
+ int m_totalBits;
+ int m_fractionalDigits;
Modifier m_modifier;
};
@@ -614,6 +620,9 @@ public:
virtual TypePointer interfaceType(bool _inLibrary) const override;
virtual bool canBeUsedExternally(bool _inLibrary) const override;
+ /// @returns true if this is valid to be stored in calldata
+ bool validForCalldata() const;
+
/// @returns true if this is a byte array or a string
bool isByteArray() const { return m_arrayKind != ArrayKind::Ordinary; }
/// @returns true if this is a string
@@ -628,6 +637,8 @@ private:
/// String is interpreted as a subtype of Bytes.
enum class ArrayKind { Ordinary, Bytes, String };
+ bigint unlimitedCalldataEncodedSize(bool _padded) const;
+
///< Byte arrays ("bytes") and strings have different semantics from ordinary arrays.
ArrayKind m_arrayKind = ArrayKind::Ordinary;
TypePointer m_baseType;
@@ -673,6 +684,10 @@ public:
}
bool isSuper() const { return m_super; }
+
+ // @returns true if and only if the contract has a payable fallback function
+ bool isPayable() const;
+
ContractDefinition const& contractDefinition() const { return m_contract; }
/// Returns the function type of the constructor modified to return an object of the contract's type.