mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Unimplemented features moved to their own exception (#1361)
Unimplemented features moved to their own exception InternalCompilerError is an exception that really should be reserved for actual internal errors of the compiler. Unimplemented features can now use either solUnimplemented( ) or, if it should be conditional, then solUnimplementedAssert( ). * Revert some unimplemented exceptions, add handlers The jsonCompiler and CommandLineInterface needed handlers for the new UnimplementedFeatureException, and some cases I had moved on to the new exception were better treated as real internal compiler errors. * Standardize on "Unimplemented feature" message
This commit is contained in:
parent
3f74c3c236
commit
58e75c7a48
@ -270,7 +270,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
|
|||||||
|
|
||||||
void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWordBoundaries) const
|
void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWordBoundaries) const
|
||||||
{
|
{
|
||||||
solAssert(
|
solUnimplementedAssert(
|
||||||
!_sourceType.baseType()->isDynamicallySized(),
|
!_sourceType.baseType()->isDynamicallySized(),
|
||||||
"Nested dynamic arrays not implemented here."
|
"Nested dynamic arrays not implemented here."
|
||||||
);
|
);
|
||||||
|
@ -138,7 +138,7 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound
|
|||||||
unsigned numBytes = prepareMemoryStore(_type, _padToWordBoundaries);
|
unsigned numBytes = prepareMemoryStore(_type, _padToWordBoundaries);
|
||||||
if (numBytes > 0)
|
if (numBytes > 0)
|
||||||
{
|
{
|
||||||
solAssert(
|
solUnimplementedAssert(
|
||||||
_type.sizeOnStack() == 1,
|
_type.sizeOnStack() == 1,
|
||||||
"Memory store of types with stack size != 1 not implemented."
|
"Memory store of types with stack size != 1 not implemented."
|
||||||
);
|
);
|
||||||
@ -161,7 +161,7 @@ void CompilerUtils::encodeToMemory(
|
|||||||
solAssert(targetTypes.size() == _givenTypes.size(), "");
|
solAssert(targetTypes.size() == _givenTypes.size(), "");
|
||||||
for (TypePointer& t: targetTypes)
|
for (TypePointer& t: targetTypes)
|
||||||
{
|
{
|
||||||
solAssert(
|
solUnimplementedAssert(
|
||||||
t->mobileType() &&
|
t->mobileType() &&
|
||||||
t->mobileType()->interfaceType(_encodeAsLibraryTypes) &&
|
t->mobileType()->interfaceType(_encodeAsLibraryTypes) &&
|
||||||
t->mobileType()->interfaceType(_encodeAsLibraryTypes)->encodingType(),
|
t->mobileType()->interfaceType(_encodeAsLibraryTypes)->encodingType(),
|
||||||
@ -361,7 +361,7 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Type::Category::FixedPoint:
|
case Type::Category::FixedPoint:
|
||||||
solAssert(false, "Not yet implemented - FixedPointType.");
|
solUnimplemented("Not yet implemented - FixedPointType.");
|
||||||
case Type::Category::Integer:
|
case Type::Category::Integer:
|
||||||
case Type::Category::Contract:
|
case Type::Category::Contract:
|
||||||
case Type::Category::RationalNumber:
|
case Type::Category::RationalNumber:
|
||||||
@ -401,7 +401,7 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
|
|||||||
if (auto typeOnStack = dynamic_cast<IntegerType const*>(&_typeOnStack))
|
if (auto typeOnStack = dynamic_cast<IntegerType const*>(&_typeOnStack))
|
||||||
if (targetFixedPointType.integerBits() > typeOnStack->numBits())
|
if (targetFixedPointType.integerBits() > typeOnStack->numBits())
|
||||||
cleanHigherOrderBits(*typeOnStack);
|
cleanHigherOrderBits(*typeOnStack);
|
||||||
solAssert(false, "Not yet implemented - FixedPointType.");
|
solUnimplemented("Not yet implemented - FixedPointType.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -414,7 +414,7 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
|
|||||||
RationalNumberType const& constType = dynamic_cast<RationalNumberType const&>(_typeOnStack);
|
RationalNumberType const& constType = dynamic_cast<RationalNumberType const&>(_typeOnStack);
|
||||||
// We know that the stack is clean, we only have to clean for a narrowing conversion
|
// We know that the stack is clean, we only have to clean for a narrowing conversion
|
||||||
// where cleanup is forced.
|
// where cleanup is forced.
|
||||||
solAssert(!constType.isFractional(), "Not yet implemented - FixedPointType.");
|
solUnimplementedAssert(!constType.isFractional(), "Not yet implemented - FixedPointType.");
|
||||||
if (targetType.numBits() < constType.integerType()->numBits() && _cleanupNeeded)
|
if (targetType.numBits() < constType.integerType()->numBits() && _cleanupNeeded)
|
||||||
cleanHigherOrderBits(targetType);
|
cleanHigherOrderBits(targetType);
|
||||||
}
|
}
|
||||||
|
@ -296,10 +296,10 @@ void ContractCompiler::appendCalldataUnpacker(TypePointers const& _typeParameter
|
|||||||
if (type->category() == Type::Category::Array)
|
if (type->category() == Type::Category::Array)
|
||||||
{
|
{
|
||||||
auto const& arrayType = dynamic_cast<ArrayType const&>(*type);
|
auto const& arrayType = dynamic_cast<ArrayType const&>(*type);
|
||||||
solAssert(!arrayType.baseType()->isDynamicallySized(), "Nested arrays not yet implemented.");
|
solUnimplementedAssert(!arrayType.baseType()->isDynamicallySized(), "Nested arrays not yet implemented.");
|
||||||
if (_fromMemory)
|
if (_fromMemory)
|
||||||
{
|
{
|
||||||
solAssert(
|
solUnimplementedAssert(
|
||||||
arrayType.baseType()->isValueType(),
|
arrayType.baseType()->isValueType(),
|
||||||
"Nested memory arrays not yet implemented here."
|
"Nested memory arrays not yet implemented here."
|
||||||
);
|
);
|
||||||
|
@ -99,7 +99,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
|
|||||||
if (auto mappingType = dynamic_cast<MappingType const*>(returnType.get()))
|
if (auto mappingType = dynamic_cast<MappingType const*>(returnType.get()))
|
||||||
{
|
{
|
||||||
solAssert(CompilerUtils::freeMemoryPointer >= 0x40, "");
|
solAssert(CompilerUtils::freeMemoryPointer >= 0x40, "");
|
||||||
solAssert(
|
solUnimplementedAssert(
|
||||||
!paramTypes[i]->isDynamicallySized(),
|
!paramTypes[i]->isDynamicallySized(),
|
||||||
"Accessors for mapping with dynamically-sized keys not yet implemented."
|
"Accessors for mapping with dynamically-sized keys not yet implemented."
|
||||||
);
|
);
|
||||||
@ -211,7 +211,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
|
|||||||
Token::Value op = _assignment.assignmentOperator();
|
Token::Value op = _assignment.assignmentOperator();
|
||||||
if (op != Token::Assign) // compound assignment
|
if (op != Token::Assign) // compound assignment
|
||||||
{
|
{
|
||||||
solAssert(_assignment.annotation().type->isValueType(), "Compound operators not implemented for non-value types.");
|
solUnimplementedAssert(_assignment.annotation().type->isValueType(), "Compound operators not implemented for non-value types.");
|
||||||
unsigned lvalueSize = m_currentLValue->sizeOnStack();
|
unsigned lvalueSize = m_currentLValue->sizeOnStack();
|
||||||
unsigned itemSize = _assignment.annotation().type->sizeOnStack();
|
unsigned itemSize = _assignment.annotation().type->sizeOnStack();
|
||||||
if (lvalueSize > 0)
|
if (lvalueSize > 0)
|
||||||
@ -312,7 +312,7 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation)
|
|||||||
if (!_unaryOperation.isPrefixOperation())
|
if (!_unaryOperation.isPrefixOperation())
|
||||||
{
|
{
|
||||||
// store value for later
|
// store value for later
|
||||||
solAssert(_unaryOperation.annotation().type->sizeOnStack() == 1, "Stack size != 1 not implemented.");
|
solUnimplementedAssert(_unaryOperation.annotation().type->sizeOnStack() == 1, "Stack size != 1 not implemented.");
|
||||||
m_context << Instruction::DUP1;
|
m_context << Instruction::DUP1;
|
||||||
if (m_currentLValue->sizeOnStack() > 0)
|
if (m_currentLValue->sizeOnStack() > 0)
|
||||||
for (unsigned i = 1 + m_currentLValue->sizeOnStack(); i > 0; --i)
|
for (unsigned i = 1 + m_currentLValue->sizeOnStack(); i > 0; --i)
|
||||||
@ -1141,7 +1141,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
|
|||||||
break;
|
break;
|
||||||
case DataLocation::CallData:
|
case DataLocation::CallData:
|
||||||
//@todo if we implement this, the value in calldata has to be added to the base offset
|
//@todo if we implement this, the value in calldata has to be added to the base offset
|
||||||
solAssert(!arrayType.baseType()->isDynamicallySized(), "Nested arrays not yet implemented.");
|
solUnimplementedAssert(!arrayType.baseType()->isDynamicallySized(), "Nested arrays not yet implemented.");
|
||||||
if (arrayType.baseType()->isValueType())
|
if (arrayType.baseType()->isValueType())
|
||||||
CompilerUtils(m_context).loadFromMemoryDynamic(
|
CompilerUtils(m_context).loadFromMemoryDynamic(
|
||||||
*arrayType.baseType(),
|
*arrayType.baseType(),
|
||||||
@ -1318,7 +1318,7 @@ void ExpressionCompiler::appendArithmeticOperatorCode(Token::Value _operator, Ty
|
|||||||
bool const c_isSigned = type.isSigned();
|
bool const c_isSigned = type.isSigned();
|
||||||
|
|
||||||
if (_type.category() == Type::Category::FixedPoint)
|
if (_type.category() == Type::Category::FixedPoint)
|
||||||
solAssert(false, "Not yet implemented - FixedPointType.");
|
solUnimplemented("Not yet implemented - FixedPointType.");
|
||||||
|
|
||||||
switch (_operator)
|
switch (_operator)
|
||||||
{
|
{
|
||||||
@ -1372,7 +1372,7 @@ void ExpressionCompiler::appendBitOperatorCode(Token::Value _operator)
|
|||||||
|
|
||||||
void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator)
|
void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator)
|
||||||
{
|
{
|
||||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Shift operators not yet implemented."));
|
BOOST_THROW_EXCEPTION(UnimplementedFeatureError() << errinfo_comment("Shift operators not yet implemented."));
|
||||||
switch (_operator)
|
switch (_operator)
|
||||||
{
|
{
|
||||||
case Token::SHL:
|
case Token::SHL:
|
||||||
@ -1634,7 +1634,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
|
|||||||
|
|
||||||
void ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression)
|
void ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression)
|
||||||
{
|
{
|
||||||
solAssert(_expectedType.isValueType(), "Not implemented for non-value types.");
|
solUnimplementedAssert(_expectedType.isValueType(), "Not implemented for non-value types.");
|
||||||
_expression.accept(*this);
|
_expression.accept(*this);
|
||||||
utils().convertType(*_expression.annotation().type, _expectedType, true);
|
utils().convertType(*_expression.annotation().type, _expectedType, true);
|
||||||
utils().storeInMemoryDynamic(_expectedType);
|
utils().storeInMemoryDynamic(_expectedType);
|
||||||
|
@ -120,7 +120,7 @@ void MemoryItem::storeValue(Type const& _sourceType, SourceLocation const&, bool
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
solAssert(_sourceType == *m_dataType, "Conversion not implemented for assignment to memory.");
|
solUnimplementedAssert(_sourceType == *m_dataType, "Conversion not implemented for assignment to memory.");
|
||||||
|
|
||||||
solAssert(m_dataType->sizeOnStack() == 1, "");
|
solAssert(m_dataType->sizeOnStack() == 1, "");
|
||||||
if (!_move)
|
if (!_move)
|
||||||
@ -181,7 +181,7 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const
|
|||||||
<< u256(0x100) << Instruction::EXP << Instruction::SWAP1 << Instruction::DIV;
|
<< u256(0x100) << Instruction::EXP << Instruction::SWAP1 << Instruction::DIV;
|
||||||
if (m_dataType->category() == Type::Category::FixedPoint)
|
if (m_dataType->category() == Type::Category::FixedPoint)
|
||||||
// implementation should be very similar to the integer case.
|
// implementation should be very similar to the integer case.
|
||||||
solAssert(false, "Not yet implemented - FixedPointType.");
|
solUnimplemented("Not yet implemented - FixedPointType.");
|
||||||
if (m_dataType->category() == Type::Category::FixedBytes)
|
if (m_dataType->category() == Type::Category::FixedBytes)
|
||||||
m_context << (u256(0x1) << (256 - 8 * m_dataType->storageBytes())) << Instruction::MUL;
|
m_context << (u256(0x1) << (256 - 8 * m_dataType->storageBytes())) << Instruction::MUL;
|
||||||
else if (
|
else if (
|
||||||
|
@ -37,6 +37,7 @@ using ErrorList = std::vector<std::shared_ptr<Error const>>;
|
|||||||
struct CompilerError: virtual Exception {};
|
struct CompilerError: virtual Exception {};
|
||||||
struct InternalCompilerError: virtual Exception {};
|
struct InternalCompilerError: virtual Exception {};
|
||||||
struct FatalError: virtual Exception {};
|
struct FatalError: virtual Exception {};
|
||||||
|
struct UnimplementedFeatureError: virtual Exception{};
|
||||||
|
|
||||||
class Error: virtual public Exception
|
class Error: virtual public Exception
|
||||||
{
|
{
|
||||||
|
@ -30,6 +30,7 @@ namespace dev
|
|||||||
namespace solidity
|
namespace solidity
|
||||||
{
|
{
|
||||||
struct InternalCompilerError;
|
struct InternalCompilerError;
|
||||||
|
struct UnimplementedFeatureError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,3 +38,8 @@ struct InternalCompilerError;
|
|||||||
#define solAssert(CONDITION, DESCRIPTION) \
|
#define solAssert(CONDITION, DESCRIPTION) \
|
||||||
assertThrow(CONDITION, ::dev::solidity::InternalCompilerError, DESCRIPTION)
|
assertThrow(CONDITION, ::dev::solidity::InternalCompilerError, DESCRIPTION)
|
||||||
|
|
||||||
|
#define solUnimplementedAssert(CONDITION, DESCRIPTION) \
|
||||||
|
assertThrow(CONDITION, ::dev::solidity::UnimplementedFeatureError, DESCRIPTION)
|
||||||
|
|
||||||
|
#define solUnimplemented(DESCRIPTION) \
|
||||||
|
solUnimplementedAssert(false, DESCRIPTION)
|
||||||
|
@ -604,6 +604,12 @@ bool CommandLineInterface::processInput()
|
|||||||
<< boost::diagnostic_information(_exception);
|
<< boost::diagnostic_information(_exception);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
catch (UnimplementedFeatureError const& _exception)
|
||||||
|
{
|
||||||
|
cerr << "Unimplemented feature:" << endl
|
||||||
|
<< boost::diagnostic_information(_exception);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
catch (Error const& _error)
|
catch (Error const& _error)
|
||||||
{
|
{
|
||||||
if (_error.type() == Error::Type::DocstringParsingError)
|
if (_error.type() == Error::Type::DocstringParsingError)
|
||||||
|
@ -189,6 +189,10 @@ string compile(StringMap const& _sources, bool _optimize, CStyleReadFileCallback
|
|||||||
{
|
{
|
||||||
errors.append(formatError(exception, "Internal compiler error", scannerFromSourceName));
|
errors.append(formatError(exception, "Internal compiler error", scannerFromSourceName));
|
||||||
}
|
}
|
||||||
|
catch (UnimplementedFeatureError const& exception)
|
||||||
|
{
|
||||||
|
errors.append(formatError(exception, "Unimplemented feature", scannerFromSourceName));
|
||||||
|
}
|
||||||
catch (Exception const& exception)
|
catch (Exception const& exception)
|
||||||
{
|
{
|
||||||
errors.append("Exception during compilation: " + boost::diagnostic_information(exception));
|
errors.append("Exception during compilation: " + boost::diagnostic_information(exception));
|
||||||
|
Loading…
Reference in New Issue
Block a user