Merge remote-tracking branch 'origin/develop' into breaking

This commit is contained in:
chriseth
2020-05-26 10:11:23 +02:00
65 changed files with 763 additions and 205 deletions
+52 -31
View File
@@ -50,7 +50,8 @@ bool DeclarationTypeChecker::visit(ElementaryTypeName const& _typeName)
_typeName.annotation().type = TypeProvider::address();
break;
default:
typeError(
m_errorReporter.typeError(
2311_error,
_typeName.location(),
"Address types can only be payable or non-payable."
);
@@ -102,7 +103,11 @@ bool DeclarationTypeChecker::visit(StructDefinition const& _struct)
auto visitor = [&](StructDefinition const& _struct, auto& _cycleDetector, size_t _depth)
{
if (_depth >= 256)
fatalDeclarationError(_struct.location(), "Struct definition exhausts cyclic dependency validator.");
m_errorReporter.fatalDeclarationError(
5651_error,
_struct.location(),
"Struct definition exhausts cyclic dependency validator."
);
for (ASTPointer<VariableDeclaration> const& member: _struct.members())
{
@@ -119,7 +124,7 @@ bool DeclarationTypeChecker::visit(StructDefinition const& _struct)
}
};
if (util::CycleDetector<StructDefinition>(visitor).run(_struct) != nullptr)
fatalTypeError(_struct.location(), "Recursive struct definition.");
m_errorReporter.fatalTypeError(2046_error, _struct.location(), "Recursive struct definition.");
return false;
}
@@ -145,9 +150,14 @@ void DeclarationTypeChecker::endVisit(UserDefinedTypeName const& _typeName)
else
{
_typeName.annotation().type = TypeProvider::emptyTuple();
fatalTypeError(_typeName.location(), "Name has to refer to a struct, enum or contract.");
m_errorReporter.fatalTypeError(
9755_error,
_typeName.location(),
"Name has to refer to a struct, enum or contract."
);
}
}
bool DeclarationTypeChecker::visit(FunctionTypeName const& _typeName)
{
if (_typeName.annotation().type)
@@ -165,18 +175,27 @@ bool DeclarationTypeChecker::visit(FunctionTypeName const& _typeName)
case Visibility::External:
break;
default:
fatalTypeError(_typeName.location(), "Invalid visibility, can only be \"external\" or \"internal\".");
m_errorReporter.fatalTypeError(
7653_error,
_typeName.location(),
"Invalid visibility, can only be \"external\" or \"internal\"."
);
return false;
}
if (_typeName.isPayable() && _typeName.visibility() != Visibility::External)
{
fatalTypeError(_typeName.location(), "Only external function types can be payable.");
m_errorReporter.fatalTypeError(
6138_error,
_typeName.location(),
"Only external function types can be payable."
);
return false;
}
_typeName.annotation().type = TypeProvider::function(_typeName);
return false;
}
void DeclarationTypeChecker::endVisit(Mapping const& _mapping)
{
if (_mapping.annotation().type)
@@ -226,7 +245,11 @@ void DeclarationTypeChecker::endVisit(ArrayTypeName const& _typeName)
return;
}
if (baseType->storageBytes() == 0)
fatalTypeError(_typeName.baseType().location(), "Illegal base type of storage size zero for array.");
m_errorReporter.fatalTypeError(
9390_error,
_typeName.baseType().location(),
"Illegal base type of storage size zero for array."
);
if (Expression const* length = _typeName.length())
{
TypePointer& lengthTypeGeneric = length->annotation().type;
@@ -235,13 +258,17 @@ void DeclarationTypeChecker::endVisit(ArrayTypeName const& _typeName)
RationalNumberType const* lengthType = dynamic_cast<RationalNumberType const*>(lengthTypeGeneric);
u256 lengthValue = 0;
if (!lengthType || !lengthType->mobileType())
typeError(length->location(), "Invalid array length, expected integer literal or constant expression.");
m_errorReporter.typeError(
8922_error,
length->location(),
"Invalid array length, expected integer literal or constant expression."
);
else if (lengthType->isZero())
typeError(length->location(), "Array with zero length specified.");
m_errorReporter.typeError(1220_error, length->location(), "Array with zero length specified.");
else if (lengthType->isFractional())
typeError(length->location(), "Array with fractional length specified.");
m_errorReporter.typeError(4323_error, length->location(), "Array with fractional length specified.");
else if (lengthType->isNegative())
typeError(length->location(), "Array with negative length specified.");
m_errorReporter.typeError(9308_error, length->location(), "Array with negative length specified.");
else
lengthValue = lengthType->literalValue(nullptr);
_typeName.annotation().type = TypeProvider::array(DataLocation::Storage, baseType, lengthValue);
@@ -249,15 +276,24 @@ void DeclarationTypeChecker::endVisit(ArrayTypeName const& _typeName)
else
_typeName.annotation().type = TypeProvider::array(DataLocation::Storage, baseType);
}
void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable)
{
if (_variable.annotation().type)
return;
if (_variable.isConstant() && !_variable.isStateVariable())
m_errorReporter.declarationError(1788_error, _variable.location(), "The \"constant\" keyword can only be used for state variables.");
m_errorReporter.declarationError(
1788_error,
_variable.location(),
"The \"constant\" keyword can only be used for state variables."
);
if (_variable.immutable() && !_variable.isStateVariable())
m_errorReporter.declarationError(8297_error, _variable.location(), "The \"immutable\" keyword can only be used for state variables.");
m_errorReporter.declarationError(
8297_error,
_variable.location(),
"The \"immutable\" keyword can only be used for state variables."
);
if (!_variable.typeName())
{
@@ -309,7 +345,7 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable)
errorString += " for variable";
}
errorString += ", but " + locationToString(varLoc) + " was given.";
typeError(_variable.location(), errorString);
m_errorReporter.typeError(6160_error, _variable.location(), errorString);
solAssert(!allowedDataLocations.empty(), "");
varLoc = *allowedDataLocations.begin();
@@ -359,24 +395,9 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable)
}
void DeclarationTypeChecker::typeError(SourceLocation const& _location, string const& _description)
{
m_errorReporter.typeError(2311_error, _location, _description);
}
void DeclarationTypeChecker::fatalTypeError(SourceLocation const& _location, string const& _description)
{
m_errorReporter.fatalTypeError(5651_error, _location, _description);
}
void DeclarationTypeChecker::fatalDeclarationError(SourceLocation const& _location, string const& _description)
{
m_errorReporter.fatalDeclarationError(2046_error, _location, _description);
}
bool DeclarationTypeChecker::check(ASTNode const& _node)
{
unsigned errorCount = m_errorReporter.errorCount();
auto watcher = m_errorReporter.errorWatcher();
_node.accept(*this);
return m_errorReporter.errorCount() == errorCount;
return watcher.ok();
}
@@ -59,15 +59,6 @@ private:
void endVisit(VariableDeclaration const& _variable) override;
bool visit(StructDefinition const& _struct) override;
/// Adds a new error to the list of errors.
void typeError(langutil::SourceLocation const& _location, std::string const& _description);
/// Adds a new error to the list of errors and throws to abort reference resolving.
void fatalTypeError(langutil::SourceLocation const& _location, std::string const& _description);
/// Adds a new error to the list of errors and throws to abort reference resolving.
void fatalDeclarationError(langutil::SourceLocation const& _location, std::string const& _description);
langutil::ErrorReporter& m_errorReporter;
langutil::EVMVersion m_evmVersion;
bool m_insideFunctionType = false;
+18 -15
View File
@@ -68,14 +68,16 @@ bool DocStringAnalyser::visit(VariableDeclaration const& _variable)
parseDocStrings(_variable, _variable.annotation(), validPublicTags, "non-public state variables");
if (_variable.annotation().docTags.count("notice") > 0)
m_errorReporter.warning(
9098_error, _variable.documentation()->location(),
"Documentation tag on non-public state variables will be disallowed in 0.7.0. You will need to use the @dev tag explicitly."
7816_error, _variable.documentation()->location(),
"Documentation tag on non-public state variables will be disallowed in 0.7.0. "
"You will need to use the @dev tag explicitly."
);
}
if (_variable.annotation().docTags.count("title") > 0 || _variable.annotation().docTags.count("author") > 0)
m_errorReporter.warning(
4822_error, _variable.documentation()->location(),
"Documentation tag @title and @author is only allowed on contract definitions. It will be disallowed in 0.7.0."
8532_error, _variable.documentation()->location(),
"Documentation tag @title and @author is only allowed on contract definitions. "
"It will be disallowed in 0.7.0."
);
}
return false;
@@ -110,7 +112,8 @@ void DocStringAnalyser::checkParameters(
auto paramRange = _annotation.docTags.equal_range("param");
for (auto i = paramRange.first; i != paramRange.second; ++i)
if (!validParams.count(i->second.paramName))
appendError(
m_errorReporter.docstringParsingError(
3881_error,
_node.documentation()->location(),
"Documented parameter \"" +
i->second.paramName +
@@ -159,7 +162,8 @@ void DocStringAnalyser::parseDocStrings(
for (auto const& docTag: _annotation.docTags)
{
if (!_validTags.count(docTag.first))
appendError(
m_errorReporter.docstringParsingError(
6546_error,
_node.documentation()->location(),
"Documentation tag @" + docTag.first + " not valid for " + _nodeName + "."
);
@@ -170,12 +174,14 @@ void DocStringAnalyser::parseDocStrings(
if (auto* varDecl = dynamic_cast<VariableDeclaration const*>(&_node))
{
if (!varDecl->isPublic())
appendError(
m_errorReporter.docstringParsingError(
9440_error,
_node.documentation()->location(),
"Documentation tag \"@" + docTag.first + "\" is only allowed on public state-variables."
);
if (returnTagsVisited > 1)
appendError(
m_errorReporter.docstringParsingError(
5256_error,
_node.documentation()->location(),
"Documentation tag \"@" + docTag.first + "\" is only allowed once on state-variables."
);
@@ -186,7 +192,8 @@ void DocStringAnalyser::parseDocStrings(
string firstWord = content.substr(0, content.find_first_of(" \t"));
if (returnTagsVisited > function->returnParameters().size())
appendError(
m_errorReporter.docstringParsingError(
2604_error,
_node.documentation()->location(),
"Documentation tag \"@" + docTag.first + " " + docTag.second.content + "\"" +
" exceeds the number of return parameters."
@@ -195,7 +202,8 @@ void DocStringAnalyser::parseDocStrings(
{
auto parameter = function->returnParameters().at(returnTagsVisited - 1);
if (!parameter->name().empty() && parameter->name() != firstWord)
appendError(
m_errorReporter.docstringParsingError(
5856_error,
_node.documentation()->location(),
"Documentation tag \"@" + docTag.first + " " + docTag.second.content + "\"" +
" does not contain the name of its return parameter."
@@ -205,8 +213,3 @@ void DocStringAnalyser::parseDocStrings(
}
}
}
void DocStringAnalyser::appendError(SourceLocation const& _location, string const& _description)
{
m_errorReporter.docstringParsingError(7816_error, _location, _description);
}
-2
View File
@@ -81,8 +81,6 @@ private:
std::string const& _nodeName
);
void appendError(langutil::SourceLocation const& _location, std::string const& _description);
langutil::ErrorReporter& m_errorReporter;
};
+24 -22
View File
@@ -119,7 +119,7 @@ bool ReferencesResolver::visit(Identifier const& _identifier)
else
errorMessage += " Did you mean " + std::move(suggestions) + "?";
}
declarationError(_identifier.location(), errorMessage);
m_errorReporter.declarationError(8051_error, _identifier.location(), errorMessage);
}
else if (declarations.size() == 1)
_identifier.annotation().referencedDeclaration = declarations.front();
@@ -157,7 +157,7 @@ void ReferencesResolver::endVisit(UserDefinedTypeName const& _typeName)
Declaration const* declaration = m_resolver.pathFromCurrentScope(_typeName.namePath());
if (!declaration)
{
fatalDeclarationError(_typeName.location(), "Identifier not found or not unique.");
m_errorReporter.fatalDeclarationError(7556_error, _typeName.location(), "Identifier not found or not unique.");
return;
}
@@ -209,14 +209,22 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
));
if (realName.empty())
{
declarationError(_identifier.location, "In variable names _slot and _offset can only be used as a suffix.");
m_errorReporter.declarationError(
9553_error,
_identifier.location,
"In variable names _slot and _offset can only be used as a suffix."
);
return;
}
declarations = m_resolver.nameFromCurrentScope(realName);
}
if (declarations.size() > 1)
{
declarationError(_identifier.location, "Multiple matching identifiers. Resolving overloaded identifiers is not supported.");
m_errorReporter.declarationError(
8827_error,
_identifier.location,
"Multiple matching identifiers. Resolving overloaded identifiers is not supported."
);
return;
}
else if (declarations.size() == 0)
@@ -224,7 +232,11 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
if (auto var = dynamic_cast<VariableDeclaration const*>(declarations.front()))
if (var->isLocalVariable() && m_yulInsideFunction)
{
declarationError(_identifier.location, "Cannot access local Solidity variables from inside an inline assembly function.");
m_errorReporter.declarationError(
8477_error,
_identifier.location,
"Cannot access local Solidity variables from inside an inline assembly function."
);
return;
}
@@ -242,7 +254,11 @@ void ReferencesResolver::operator()(yul::VariableDeclaration const& _varDecl)
string namePrefix = identifier.name.str().substr(0, identifier.name.str().find('.'));
if (isSlot || isOffset)
declarationError(identifier.location, "In variable declarations _slot and _offset can not be used as a suffix.");
m_errorReporter.declarationError(
8820_error,
identifier.location,
"In variable declarations _slot and _offset can not be used as a suffix."
);
else if (
auto declarations = m_resolver.nameFromCurrentScope(namePrefix);
!declarations.empty()
@@ -252,7 +268,8 @@ void ReferencesResolver::operator()(yul::VariableDeclaration const& _varDecl)
for (auto const* decl: declarations)
ssl.append("The shadowed declaration is here:", decl->location());
if (!ssl.infos.empty())
declarationError(
m_errorReporter.declarationError(
6005_error,
identifier.location,
ssl,
namePrefix.size() < identifier.name.str().size() ?
@@ -266,19 +283,4 @@ void ReferencesResolver::operator()(yul::VariableDeclaration const& _varDecl)
visit(*_varDecl.value);
}
void ReferencesResolver::declarationError(SourceLocation const& _location, string const& _description)
{
m_errorReporter.declarationError(8532_error, _location, _description);
}
void ReferencesResolver::declarationError(SourceLocation const& _location, SecondarySourceLocation const& _ssl, string const& _description)
{
m_errorReporter.declarationError(3881_error, _location, _ssl, _description);
}
void ReferencesResolver::fatalDeclarationError(SourceLocation const& _location, string const& _description)
{
m_errorReporter.fatalDeclarationError(6546_error, _location, _description);
}
}
@@ -88,15 +88,6 @@ private:
void operator()(yul::Identifier const& _identifier) override;
void operator()(yul::VariableDeclaration const& _varDecl) override;
/// Adds a new error to the list of errors.
void declarationError(langutil::SourceLocation const& _location, std::string const& _description);
/// Adds a new error to the list of errors.
void declarationError(langutil::SourceLocation const& _location, langutil::SecondarySourceLocation const& _ssl, std::string const& _description);
/// Adds a new error to the list of errors and throws to abort reference resolving.
void fatalDeclarationError(langutil::SourceLocation const& _location, std::string const& _description);
langutil::ErrorReporter& m_errorReporter;
NameAndTypeResolver& m_resolver;
langutil::EVMVersion m_evmVersion;
+1 -1
View File
@@ -250,7 +250,7 @@ struct ExpressionAnnotation: ASTAnnotation
bool lValueOfOrdinaryAssignment = false;
/// Types and - if given - names of arguments if the expr. is a function
/// that is called, used for overload resoultion
/// that is called, used for overload resolution
std::optional<FuncCallArguments> arguments;
};
+7
View File
@@ -185,6 +185,13 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
{
solAssert(byteOffsetSize == 0, "Byte offset for array as base type.");
auto const& sourceBaseArrayType = dynamic_cast<ArrayType const&>(*sourceBaseType);
solUnimplementedAssert(
_sourceType.location() != DataLocation::CallData ||
!_sourceType.isDynamicallyEncoded() ||
!sourceBaseArrayType.isDynamicallySized(),
"Copying nested calldata dynamic arrays to storage is not implemented in the old code generator."
);
_context << Instruction::DUP3;
if (sourceBaseArrayType.location() == DataLocation::Memory)
_context << Instruction::MLOAD;
+8
View File
@@ -974,6 +974,14 @@ void CompilerUtils::convertType(
}
else
{
if (auto baseType = dynamic_cast<ArrayType const*>(typeOnStack.baseType()))
solUnimplementedAssert(
typeOnStack.location() != DataLocation::CallData ||
!typeOnStack.isDynamicallyEncoded() ||
!baseType->isDynamicallySized(),
"Copying nested dynamic calldata arrays to memory is not implemented in the old code generator."
);
m_context << u256(0) << Instruction::SWAP1;
// stack: <mem start> <source ref> (variably sized) <length> <counter> <mem data pos>
auto repeat = m_context.newTag();
+1 -1
View File
@@ -286,7 +286,7 @@ public:
/// Appends code that computes the Keccak-256 hash of the topmost stack element of 32 byte type.
void computeHashStatic();
/// Apppends code that copies the code of the given contract to memory.
/// Appends code that copies the code of the given contract to memory.
/// Stack pre: Memory position
/// Stack post: Updated memory position
/// @param creation if true, copies creation code, if false copies runtime code.
+1 -1
View File
@@ -1912,7 +1912,7 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier)
// If the identifier is called right away, this code is executed in visit(FunctionCall...), because
// we want to avoid having a reference to the runtime function entry point in the
// constructor context, since this would force the compiler to include unreferenced
// internal functions in the runtime contex.
// internal functions in the runtime context.
utils().pushCombinedFunctionEntryLabel(functionDef->resolveVirtual(m_context.mostDerivedContract()));
else if (auto variable = dynamic_cast<VariableDeclaration const*>(declaration))
appendVariable(*variable, static_cast<Expression const&>(_identifier));
+10
View File
@@ -99,3 +99,13 @@ string IRNames::zeroValue(Type const& _type, string const& _variableName)
{
return "zero_value_for_type_" + _type.identifier() + _variableName;
}
FunctionDefinition const* IRHelpers::referencedFunctionDeclaration(Expression const& _expression)
{
if (auto memberAccess = dynamic_cast<MemberAccess const*>(&_expression))
return dynamic_cast<FunctionDefinition const*>(memberAccess->annotation().referencedDeclaration);
else if (auto identifier = dynamic_cast<Identifier const*>(&_expression))
return dynamic_cast<FunctionDefinition const*>(identifier->annotation().referencedDeclaration);
else
return nullptr;
}
+5
View File
@@ -62,6 +62,11 @@ struct IRNames
static std::string zeroValue(Type const& _type, std::string const& _variableName);
};
struct IRHelpers
{
static FunctionDefinition const* referencedFunctionDeclaration(Expression const& _expression);
};
}
// Overloading std::less() makes it possible to use YulArity as a map key. We could define operator<
@@ -625,15 +625,22 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
arguments.push_back(callArguments[std::distance(callArgumentNames.begin(), it)]);
}
if (auto memberAccess = dynamic_cast<MemberAccess const*>(&_functionCall.expression()))
auto memberAccess = dynamic_cast<MemberAccess const*>(&_functionCall.expression());
if (memberAccess)
{
if (auto expressionType = dynamic_cast<TypeType const*>(memberAccess->expression().annotation().type))
{
solAssert(!functionType->bound(), "");
if (auto contractType = dynamic_cast<ContractType const*>(expressionType->actualType()))
solUnimplementedAssert(
!contractType->contractDefinition().isLibrary() || functionType->kind() == FunctionType::Kind::Internal,
"Only internal function calls implemented for libraries"
);
}
}
else
solAssert(!functionType->bound(), "");
solUnimplementedAssert(!functionType->bound(), "");
switch (functionType->kind())
{
case FunctionType::Kind::Declaration:
@@ -641,53 +648,40 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
break;
case FunctionType::Kind::Internal:
{
optional<FunctionDefinition const*> functionDef;
if (auto memberAccess = dynamic_cast<MemberAccess const*>(&_functionCall.expression()))
{
solUnimplementedAssert(!functionType->bound(), "Internal calls to bound functions are not yet implemented for libraries and not allowed for contracts");
auto identifier = dynamic_cast<Identifier const*>(&_functionCall.expression());
FunctionDefinition const* functionDef = IRHelpers::referencedFunctionDeclaration(_functionCall.expression());
functionDef = dynamic_cast<FunctionDefinition const*>(memberAccess->annotation().referencedDeclaration);
if (functionDef.value() != nullptr)
solAssert(functionType->declaration() == *memberAccess->annotation().referencedDeclaration, "");
else
{
solAssert(dynamic_cast<VariableDeclaration const*>(memberAccess->annotation().referencedDeclaration), "");
solAssert(!functionType->hasDeclaration(), "");
}
}
else if (auto identifier = dynamic_cast<Identifier const*>(&_functionCall.expression()))
if (functionDef)
{
solAssert(!functionType->bound(), "");
solAssert(memberAccess || identifier, "");
solAssert(functionType->declaration() == *functionDef, "");
if (auto unresolvedFunctionDef = dynamic_cast<FunctionDefinition const*>(identifier->annotation().referencedDeclaration))
{
functionDef = &unresolvedFunctionDef->resolveVirtual(m_context.mostDerivedContract());
solAssert(functionType->declaration() == *identifier->annotation().referencedDeclaration, "");
}
else
{
functionDef = nullptr;
solAssert(dynamic_cast<VariableDeclaration const*>(identifier->annotation().referencedDeclaration), "");
solAssert(!functionType->hasDeclaration(), "");
}
if (identifier)
functionDef = &functionDef->resolveVirtual(m_context.mostDerivedContract());
solAssert(functionDef->isImplemented(), "");
}
else
// Not a simple expression like x or A.x
functionDef = nullptr;
solAssert(!functionType->hasDeclaration(), "");
solAssert(functionDef.has_value(), "");
solAssert(functionDef.value() == nullptr || functionDef.value()->isImplemented(), "");
solAssert(!functionType->takesArbitraryParameters(), "");
vector<string> args;
for (size_t i = 0; i < arguments.size(); ++i)
if (functionType->takesArbitraryParameters())
args += IRVariable(*arguments[i]).stackSlots();
else
args += convert(*arguments[i], *parameterTypes[i]).stackSlots();
if (functionType->bound())
{
solAssert(memberAccess && functionDef, "");
solAssert(functionDef->parameters().size() == arguments.size() + 1, "");
args += convert(memberAccess->expression(), *functionDef->parameters()[0]->type()).stackSlots();
}
else
solAssert(!functionDef || functionDef->parameters().size() == arguments.size(), "");
if (functionDef.value() != nullptr)
for (size_t i = 0; i < arguments.size(); ++i)
args += convert(*arguments[i], *parameterTypes[i]).stackSlots();
if (functionDef)
define(_functionCall) <<
m_context.enqueueFunctionForCodeGeneration(*functionDef.value()) <<
m_context.enqueueFunctionForCodeGeneration(*functionDef) <<
"(" <<
joinHumanReadable(args) <<
")\n";
@@ -1237,13 +1231,27 @@ void IRGeneratorForStatements::endVisit(FunctionCallOptions const& _options)
void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
{
ASTString const& member = _memberAccess.memberName();
if (auto funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type))
if (funType->bound())
{
solUnimplementedAssert(false, "");
}
auto memberFunctionType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type);
Type::Category objectCategory = _memberAccess.expression().annotation().type->category();
switch (_memberAccess.expression().annotation().type->category())
if (memberFunctionType && memberFunctionType->bound())
{
solAssert((set<Type::Category>{
Type::Category::Contract,
Type::Category::Bool,
Type::Category::Integer,
Type::Category::Address,
Type::Category::Function,
Type::Category::Struct,
Type::Category::Enum,
Type::Category::Mapping,
Type::Category::Array,
Type::Category::FixedBytes,
}).count(objectCategory) > 0, "");
return;
}
switch (objectCategory)
{
case Type::Category::Contract:
{
@@ -1476,9 +1484,9 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
{
if (auto const* variable = dynamic_cast<VariableDeclaration const*>(_memberAccess.annotation().referencedDeclaration))
handleVariableReference(*variable, _memberAccess);
else if (auto const* funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type))
else if (memberFunctionType)
{
switch (funType->kind())
switch (memberFunctionType->kind())
{
case FunctionType::Kind::Declaration:
break;
@@ -1497,7 +1505,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
break;
case FunctionType::Kind::DelegateCall:
define(IRVariable(_memberAccess).part("address"), _memberAccess.expression());
define(IRVariable(_memberAccess).part("functionIdentifier")) << formatNumber(funType->externalIdentifier()) << "\n";
define(IRVariable(_memberAccess).part("functionIdentifier")) << formatNumber(memberFunctionType->externalIdentifier()) << "\n";
break;
case FunctionType::Kind::External:
case FunctionType::Kind::Creation:
+2 -2
View File
@@ -178,7 +178,7 @@ bool isArtifactRequested(Json::Value const& _outputSelection, string const& _art
}
///
/// @a _outputSelection is a JSON object containining a two-level hashmap, where the first level is the filename,
/// @a _outputSelection is a JSON object containing a two-level hashmap, where the first level is the filename,
/// the second level is the contract name and the value is an array of artifact names to be requested for that contract.
/// @a _file is the current file
/// @a _contract is the current contract
@@ -229,7 +229,7 @@ bool isBinaryRequested(Json::Value const& _outputSelection)
if (!_outputSelection.isObject())
return false;
// This does not inculde "evm.methodIdentifiers" on purpose!
// This does not include "evm.methodIdentifiers" on purpose!
static vector<string> const outputsThatRequireBinaries{
"*",
"ir", "irOptimized",
+6 -8
View File
@@ -96,7 +96,10 @@ void DocStringParser::parse(string const& _docString, ErrorReporter& _errorRepor
auto tagNameEndPos = firstWhitespaceOrNewline(tagPos, end);
if (tagNameEndPos == end)
{
appendError("End of tag " + string(tagPos, tagNameEndPos) + " not found");
m_errorReporter->docstringParsingError(
9222_error,
"End of tag " + string(tagPos, tagNameEndPos) + " not found"
);
break;
}
@@ -138,7 +141,7 @@ DocStringParser::iter DocStringParser::parseDocTagParam(iter _pos, iter _end)
auto nameStartPos = skipWhitespace(_pos, _end);
if (nameStartPos == _end)
{
appendError("No param name given");
m_errorReporter->docstringParsingError(3335_error, "No param name given");
return _end;
}
auto nameEndPos = firstNonIdentifier(nameStartPos, _end);
@@ -149,7 +152,7 @@ DocStringParser::iter DocStringParser::parseDocTagParam(iter _pos, iter _end)
if (descStartPos == nlPos)
{
appendError("No description given for param " + paramName);
m_errorReporter->docstringParsingError(9942_error, "No description given for param " + paramName);
return _end;
}
@@ -189,8 +192,3 @@ void DocStringParser::newTag(string const& _tagName)
{
m_lastTag = &m_docTags.insert(make_pair(_tagName, DocTag()))->second;
}
void DocStringParser::appendError(string const& _description)
{
m_errorReporter->docstringParsingError(9440_error, _description);
}
-2
View File
@@ -58,8 +58,6 @@ private:
/// Creates and inserts a new tag and adjusts m_lastTag.
void newTag(std::string const& _tagName);
void appendError(std::string const& _description);
/// Mapping tag name -> content.
std::multimap<std::string, DocTag> m_docTags;
DocTag* m_lastTag = nullptr;