diff --git a/liblangutil/ParserBase.cpp b/liblangutil/ParserBase.cpp index c3a15794b..f0ebefd93 100644 --- a/liblangutil/ParserBase.cpp +++ b/liblangutil/ParserBase.cpp @@ -77,9 +77,9 @@ void ParserBase::expectToken(Token _value, bool _advance) { string const expectedToken = ParserBase::tokenName(_value); if (m_parserErrorRecovery) - parserError("Expected " + expectedToken + " but got " + tokenName(tok)); + parserError(6635_error, "Expected " + expectedToken + " but got " + tokenName(tok)); else - fatalParserError("Expected " + expectedToken + " but got " + tokenName(tok)); + fatalParserError(2314_error, "Expected " + expectedToken + " but got " + tokenName(tok)); // Do not advance so that recovery can sync or make use of the current token. // This is especially useful if the expected token // is the only one that is missing and is at the end of a construct. @@ -108,21 +108,21 @@ void ParserBase::expectTokenOrConsumeUntil(Token _value, string const& _currentN // rollback to where the token started, and raise exception to be caught at a higher level. m_scanner->setPosition(startPosition); m_inParserRecovery = true; - fatalParserError(errorLoc, msg); + fatalParserError(1957_error, errorLoc, msg); } else { if (m_inParserRecovery) - parserWarning("Recovered in " + _currentNodeName + " at " + expectedToken + "."); + parserWarning(3796_error, "Recovered in " + _currentNodeName + " at " + expectedToken + "."); else - parserError(errorLoc, msg + "Recovered at next " + expectedToken); + parserError(1054_error, errorLoc, msg + "Recovered at next " + expectedToken); m_inParserRecovery = false; } } else if (m_inParserRecovery) { string expectedToken = ParserBase::tokenName(_value); - parserWarning("Recovered in " + _currentNodeName + " at " + expectedToken + "."); + parserWarning(3347_error, "Recovered in " + _currentNodeName + " at " + expectedToken + "."); m_inParserRecovery = false; } @@ -134,7 +134,7 @@ void ParserBase::increaseRecursionDepth() { m_recursionDepth++; if (m_recursionDepth >= 1200) - fatalParserError("Maximum recursion depth reached during parsing."); + fatalParserError(7319_error, "Maximum recursion depth reached during parsing."); } void ParserBase::decreaseRecursionDepth() @@ -143,27 +143,27 @@ void ParserBase::decreaseRecursionDepth() m_recursionDepth--; } -void ParserBase::parserWarning(string const& _description) +void ParserBase::parserWarning(ErrorId _error, string const& _description) { - m_errorReporter.warning(6635_error, currentLocation(), _description); + m_errorReporter.warning(_error, currentLocation(), _description); } -void ParserBase::parserError(SourceLocation const& _location, string const& _description) +void ParserBase::parserError(ErrorId _error, SourceLocation const& _location, string const& _description) { - m_errorReporter.parserError(2314_error, _location, _description); + m_errorReporter.parserError(_error, _location, _description); } -void ParserBase::parserError(string const& _description) +void ParserBase::parserError(ErrorId _error, string const& _description) { - parserError(currentLocation(), _description); + parserError(_error, currentLocation(), _description); } -void ParserBase::fatalParserError(string const& _description) +void ParserBase::fatalParserError(ErrorId _error, string const& _description) { - fatalParserError(currentLocation(), _description); + fatalParserError(_error, currentLocation(), _description); } -void ParserBase::fatalParserError(SourceLocation const& _location, string const& _description) +void ParserBase::fatalParserError(ErrorId _error, SourceLocation const& _location, string const& _description) { - m_errorReporter.fatalParserError(1957_error, _location, _description); + m_errorReporter.fatalParserError(_error, _location, _description); } diff --git a/liblangutil/ParserBase.h b/liblangutil/ParserBase.h index 575a049e2..8a8073696 100644 --- a/liblangutil/ParserBase.h +++ b/liblangutil/ParserBase.h @@ -32,6 +32,7 @@ namespace solidity::langutil class ErrorReporter; class Scanner; +struct ErrorId; class ParserBase { @@ -88,17 +89,17 @@ protected: /// Creates a @ref ParserError and annotates it with the current position and the /// given @a _description. - void parserError(std::string const& _description); - void parserError(SourceLocation const& _location, std::string const& _description); + void parserError(ErrorId _error, std::string const& _description); + void parserError(ErrorId _error, SourceLocation const& _location, std::string const& _description); /// Creates a @ref ParserWarning and annotates it with the current position and the /// given @a _description. - void parserWarning(std::string const& _description); + void parserWarning(ErrorId _error, std::string const& _description); /// Creates a @ref ParserError and annotates it with the current position and the /// given @a _description. Throws the FatalError. - void fatalParserError(std::string const& _description); - void fatalParserError(SourceLocation const& _location, std::string const& _description); + void fatalParserError(ErrorId _error, std::string const& _description); + void fatalParserError(ErrorId _error, SourceLocation const& _location, std::string const& _description); std::shared_ptr m_scanner; /// The reference to the list of errors and warning to add errors/warnings during parsing diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index d24b0e69f..99b9a2cac 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -103,7 +103,7 @@ ASTPointer Parser::parse(shared_ptr const& _scanner) nodes.push_back(parseEnumDefinition()); break; default: - fatalParserError(string("Expected pragma, import directive or contract/interface/library/struct/enum definition.")); + fatalParserError(7858_error, "Expected pragma, import directive or contract/interface/library/struct/enum definition."); } } solAssert(m_recursionDepth == 0, ""); @@ -163,7 +163,7 @@ ASTPointer Parser::parsePragmaDirective() { Token token = m_scanner->currentToken(); if (token == Token::Illegal) - parserError("Token incompatible with Solidity parser as part of pragma directive."); + parserError(6281_error, "Token incompatible with Solidity parser as part of pragma directive."); else { string literal = m_scanner->currentLiteral(); @@ -241,18 +241,18 @@ ASTPointer Parser::parseImportDirective() unitAlias = expectIdentifierToken(); } else - fatalParserError("Expected string literal (path), \"*\" or alias list."); + fatalParserError(9478_error, "Expected string literal (path), \"*\" or alias list."); // "from" is not a keyword but parsed as an identifier because of backwards // compatibility and because it is a really common word. if (m_scanner->currentToken() != Token::Identifier || m_scanner->currentLiteral() != "from") - fatalParserError("Expected \"from\"."); + fatalParserError(8208_error, "Expected \"from\"."); m_scanner->next(); if (m_scanner->currentToken() != Token::StringLiteral) - fatalParserError("Expected import path."); + fatalParserError(6845_error, "Expected import path."); path = getLiteralAndAdvance(); } if (path->empty()) - fatalParserError("Import path cannot be empty."); + fatalParserError(6326_error, "Import path cannot be empty."); nodeFactory.markEndPosition(); expectToken(Token::Semicolon); return nodeFactory.createNode(path, unitAlias, move(symbolAliases)); @@ -279,7 +279,7 @@ std::pair Parser::parseContractKind() kind = ContractKind::Library; break; default: - parserError("Expected keyword \"contract\", \"interface\" or \"library\"."); + parserError(3515_error, "Expected keyword \"contract\", \"interface\" or \"library\"."); return std::make_pair(ContractKind::Contract, abstract); } m_scanner->next(); @@ -344,7 +344,7 @@ ASTPointer Parser::parseContractDefinition() else if (currentTokenValue == Token::Using) subNodes.push_back(parseUsingDirective()); else - fatalParserError(string("Function, variable, struct or modifier declaration expected.")); + fatalParserError(9182_error, "Function, variable, struct or modifier declaration expected."); } } catch (FatalError const&) @@ -463,6 +463,7 @@ StateMutability Parser::parseStateMutability() case Token::Constant: stateMutability = StateMutability::View; parserError( + 7698_error, "The state mutability modifier \"constant\" was removed in version 0.5.0. " "Use \"view\" or \"pure\" instead." ); @@ -495,11 +496,12 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _isStateVari // Detect this and return early. if (_isStateVariable && (result.visibility == Visibility::External || result.visibility == Visibility::Internal)) break; - parserError(string( + parserError( + 9439_error, "Visibility already specified as \"" + Declaration::visibilityToString(result.visibility) + "\"." - )); + ); m_scanner->next(); } else @@ -509,11 +511,12 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _isStateVari { if (result.stateMutability != StateMutability::NonPayable) { - parserError(string( + parserError( + 9680_error, "State mutability already specified as \"" + stateMutabilityToString(result.stateMutability) + "\"." - )); + ); m_scanner->next(); } else @@ -522,14 +525,14 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _isStateVari else if (!_isStateVariable && token == Token::Override) { if (result.overrides) - parserError("Override already specified."); + parserError(1827_error, "Override already specified."); result.overrides = parseOverrideSpecifier(); } else if (!_isStateVariable && token == Token::Virtual) { if (result.isVirtual) - parserError("Virtual already specified."); + parserError(6879_error, "Virtual already specified."); result.isVirtual = true; m_scanner->next(); @@ -577,9 +580,9 @@ ASTPointer Parser::parseFunctionDefinition() "the \"function\" keyword to define it." }; if (m_scanner->currentToken() == Token::Constructor) - parserError(message); + parserError(3323_error, message); else - parserWarning(message); + parserWarning(3445_error, message); m_scanner->next(); } else @@ -660,10 +663,10 @@ ASTPointer Parser::parseEnumDefinition() break; expectToken(Token::Comma); if (m_scanner->currentToken() != Token::Identifier) - fatalParserError(string("Expected identifier after ','")); + fatalParserError(1612_error, "Expected identifier after ','"); } if (members.empty()) - parserError({"enum with no members is not allowed."}); + parserError(3147_error, "enum with no members is not allowed."); nodeFactory.markEndPosition(); expectToken(Token::RBrace); @@ -690,6 +693,7 @@ ASTPointer Parser::parseVariableDeclaration( if (dynamic_cast(type.get()) && _options.isStateVariable && m_scanner->currentToken() == Token::LBrace) fatalParserError( + 2915_error, "Expected a state variable declaration. If you intended this as a fallback function " "or a function to handle plain ether transactions, use the \"fallback\" keyword " "or the \"receive\" keyword instead." @@ -710,11 +714,12 @@ ASTPointer Parser::parseVariableDeclaration( nodeFactory.markEndPosition(); if (visibility != Visibility::Default) { - parserError(string( + parserError( + 4110_error, "Visibility already specified as \"" + Declaration::visibilityToString(visibility) + "\"." - )); + ); m_scanner->next(); } else @@ -723,7 +728,7 @@ ASTPointer Parser::parseVariableDeclaration( else if (_options.isStateVariable && token == Token::Override) { if (overrides) - parserError("Override already specified."); + parserError(9125_error, "Override already specified."); overrides = parseOverrideSpecifier(); } @@ -735,6 +740,7 @@ ASTPointer Parser::parseVariableDeclaration( { if (mutability != VariableDeclaration::Mutability::Mutable) parserError( + 3109_error, string("Mutability already set to ") + (mutability == VariableDeclaration::Mutability::Constant ? "\"constant\"" : "\"immutable\"") ); @@ -746,9 +752,9 @@ ASTPointer Parser::parseVariableDeclaration( else if (_options.allowLocationSpecifier && TokenTraits::isLocationSpecifier(token)) { if (location != VariableDeclaration::Location::Unspecified) - parserError(string("Location already specified.")); + parserError(3548_error, "Location already specified."); else if (!type) - parserError(string("Location specifier needs explicit type name.")); + parserError(7439_error, "Location specifier needs explicit type name."); else { switch (token) @@ -837,13 +843,13 @@ ASTPointer Parser::parseModifierDefinition() if (m_scanner->currentToken() == Token::Override) { if (overrides) - parserError("Override already specified."); + parserError(9102_error, "Override already specified."); overrides = parseOverrideSpecifier(); } else if (m_scanner->currentToken() == Token::Virtual) { if (isVirtual) - parserError("Virtual already specified."); + parserError(2662_error, "Virtual already specified."); isVirtual = true; m_scanner->next(); @@ -991,7 +997,7 @@ ASTPointer Parser::parseTypeName(bool _allowVar) } else { - parserError("State mutability can only be specified for address types."); + parserError(9106_error, "State mutability can only be specified for address types."); m_scanner->next(); } } @@ -1000,7 +1006,7 @@ ASTPointer Parser::parseTypeName(bool _allowVar) else if (token == Token::Var) { if (!_allowVar) - parserError(string("Expected explicit type name.")); + parserError(7059_error, "Expected explicit type name."); m_scanner->next(); } else if (token == Token::Function) @@ -1010,7 +1016,7 @@ ASTPointer Parser::parseTypeName(bool _allowVar) else if (token == Token::Identifier) type = parseUserDefinedTypeName(); else - fatalParserError(string("Expected type name")); + fatalParserError(3546_error, "Expected type name"); if (type) // Parse "[...]" postfixes for arrays. @@ -1053,7 +1059,7 @@ ASTPointer Parser::parseMapping() m_scanner->next(); } else - fatalParserError(string("Expected elementary type name or identifier for mapping key type")); + fatalParserError(1005_error, "Expected elementary type name or identifier for mapping key type"); expectToken(Token::Arrow); bool const allowVar = false; ASTPointer valueType = parseTypeName(allowVar); @@ -1079,7 +1085,7 @@ ASTPointer Parser::parseParameterList( while (m_scanner->currentToken() != Token::RParen) { if (m_scanner->currentToken() == Token::Comma && m_scanner->peekNextToken() == Token::RParen) - fatalParserError("Unexpected trailing comma in parameter list."); + fatalParserError(7591_error, "Unexpected trailing comma in parameter list."); expectToken(Token::Comma); parameters.push_back(parseVariableDeclaration(options)); } @@ -1214,7 +1220,7 @@ ASTPointer Parser::parseInlineAssembly(ASTPointer con if (m_scanner->currentToken() == Token::StringLiteral) { if (m_scanner->currentLiteral() != "evmasm") - fatalParserError("Only \"evmasm\" supported."); + fatalParserError(4531_error, "Only \"evmasm\" supported."); // This can be used in the future to set the dialect. m_scanner->next(); } @@ -1377,7 +1383,7 @@ ASTPointer Parser::parseEmitStatement(ASTPointer const ASTNodeFactory eventCallNodeFactory(*this); if (m_scanner->currentToken() != Token::Identifier) - fatalParserError("Expected event name or path."); + fatalParserError(5620_error, "Expected event name or path."); IndexAccessedPath iap; while (true) @@ -1845,7 +1851,7 @@ ASTPointer Parser::parsePrimaryExpression() nodeFactory.markEndPosition(); m_scanner->next(); if (m_scanner->currentToken() == Token::Illegal) - fatalParserError(to_string(m_scanner->currentError())); + fatalParserError(5428_error, to_string(m_scanner->currentError())); expression = nodeFactory.createNode(token, make_shared(literal)); break; } @@ -1876,7 +1882,7 @@ ASTPointer Parser::parsePrimaryExpression() if (m_scanner->currentToken() != Token::Comma && m_scanner->currentToken() != oppositeToken) components.push_back(parseExpression()); else if (isArray) - parserError("Expected expression (inline array elements cannot be omitted)."); + parserError(4799_error, "Expected expression (inline array elements cannot be omitted)."); else components.push_back(ASTPointer()); @@ -1891,7 +1897,7 @@ ASTPointer Parser::parsePrimaryExpression() break; } case Token::Illegal: - fatalParserError(to_string(m_scanner->currentError())); + fatalParserError(8936_error, to_string(m_scanner->currentError())); break; default: if (TokenTraits::isElementaryTypeName(token)) @@ -1907,7 +1913,7 @@ ASTPointer Parser::parsePrimaryExpression() m_scanner->next(); } else - fatalParserError(string("Expected primary expression.")); + fatalParserError(6933_error, "Expected primary expression."); break; } return expression; @@ -1965,7 +1971,7 @@ pair>, vector>> Parser::pars m_scanner->peekNextToken() == Token::RBrace ) { - parserError("Unexpected trailing comma."); + parserError(2074_error, "Unexpected trailing comma."); m_scanner->next(); } @@ -2084,7 +2090,7 @@ ASTPointer Parser::typeNameFromIndexAccessStructure(Parser::IndexAcces for (auto const& lengthExpression: _iap.indices) { if (lengthExpression.end) - parserError(lengthExpression.location, "Expected array length expression."); + parserError(5464_error, lengthExpression.location, "Expected array length expression."); nodeFactory.setLocation(lengthExpression.location); type = nodeFactory.createNode(type, lengthExpression.start); } diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 13b96839b..19574446d 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -122,11 +122,11 @@ Statement Parser::parseStatement() if (currentToken() == Token::Default) _switch.cases.emplace_back(parseCase()); if (currentToken() == Token::Default) - fatalParserError("Only one default case allowed."); + fatalParserError(6931_error, "Only one default case allowed."); else if (currentToken() == Token::Case) - fatalParserError("Case not allowed after default case."); + fatalParserError(4904_error, "Case not allowed after default case."); if (_switch.cases.empty()) - fatalParserError("Switch statement without any cases."); + fatalParserError(2418_error, "Switch statement without any cases."); _switch.location.end = _switch.cases.back().body.location.end; return Statement{move(_switch)}; } @@ -184,6 +184,7 @@ Statement Parser::parseStatement() auto const token = currentToken() == Token::Comma ? "," : ":="; fatalParserError( + 2856_error, std::string("Variable name must precede \"") + token + "\"" + @@ -194,7 +195,7 @@ Statement Parser::parseStatement() auto const& identifier = std::get(elementary); if (m_dialect.builtin(identifier.name)) - fatalParserError("Cannot assign to builtin function \"" + identifier.name.str() + "\"."); + fatalParserError(6272_error, "Cannot assign to builtin function \"" + identifier.name.str() + "\"."); variableNames.emplace_back(identifier); @@ -218,7 +219,7 @@ Statement Parser::parseStatement() return Statement{std::move(assignment)}; } default: - fatalParserError("Call or assignment expected."); + fatalParserError(6913_error, "Call or assignment expected."); break; } @@ -250,7 +251,7 @@ Case Parser::parseCase() advance(); ElementaryOperation literal = parseElementaryOperation(); if (!holds_alternative(literal)) - fatalParserError("Literal expected."); + fatalParserError(4805_error, "Literal expected."); _case.value = make_unique(std::get(std::move(literal))); } else @@ -353,7 +354,7 @@ Parser::ElementaryOperation Parser::parseElementaryOperation() break; case Token::Number: if (!isValidNumberLiteral(currentLiteral())) - fatalParserError("Invalid number literal."); + fatalParserError(4828_error, "Invalid number literal."); kind = LiteralKind::Number; break; case Token::TrueLiteral: @@ -382,7 +383,7 @@ Parser::ElementaryOperation Parser::parseElementaryOperation() break; } default: - fatalParserError("Literal or identifier expected."); + fatalParserError(1856_error, "Literal or identifier expected."); } return ret; } @@ -472,7 +473,7 @@ Expression Parser::parseCall(Parser::ElementaryOperation&& _initialOp) else if (holds_alternative(_initialOp)) ret = std::move(std::get(_initialOp)); else - fatalParserError("Function name expected."); + fatalParserError(9980_error, "Function name expected."); expectToken(Token::LParen); if (currentToken() != Token::RParen) @@ -525,7 +526,7 @@ YulString Parser::expectAsmIdentifier() } if (m_dialect.builtin(name)) - fatalParserError("Cannot use builtin function name \"" + name.str() + "\" as identifier name."); + fatalParserError(5568_error, "Cannot use builtin function name \"" + name.str() + "\" as identifier name."); advance(); return name; } diff --git a/libyul/ObjectParser.cpp b/libyul/ObjectParser.cpp index 74c339f18..7e50fa88e 100644 --- a/libyul/ObjectParser.cpp +++ b/libyul/ObjectParser.cpp @@ -66,7 +66,7 @@ shared_ptr ObjectParser::parseObject(Object* _containingObject) RecursionGuard guard(*this); if (currentToken() != Token::Identifier || currentLiteral() != "object") - fatalParserError("Expected keyword \"object\"."); + fatalParserError(4294_error, "Expected keyword \"object\"."); advance(); shared_ptr ret = make_shared(); @@ -83,7 +83,7 @@ shared_ptr ObjectParser::parseObject(Object* _containingObject) else if (currentToken() == Token::Identifier && currentLiteral() == "data") parseData(*ret); else - fatalParserError("Expected keyword \"data\" or \"object\" or \"}\"."); + fatalParserError(8143_error, "Expected keyword \"data\" or \"object\" or \"}\"."); } if (_containingObject) addNamedSubObject(*_containingObject, ret->name, ret); @@ -96,7 +96,7 @@ shared_ptr ObjectParser::parseObject(Object* _containingObject) shared_ptr ObjectParser::parseCode() { if (currentToken() != Token::Identifier || currentLiteral() != "code") - fatalParserError("Expected keyword \"code\"."); + fatalParserError(4846_error, "Expected keyword \"code\"."); advance(); return parseBlock(); @@ -133,11 +133,11 @@ YulString ObjectParser::parseUniqueName(Object const* _containingObject) expectToken(Token::StringLiteral, false); YulString name{currentLiteral()}; if (name.empty()) - parserError("Object name cannot be empty."); + parserError(3287_error, "Object name cannot be empty."); else if (_containingObject && _containingObject->name == name) - parserError("Object name cannot be the same as the name of the containing object."); + parserError(8311_error, "Object name cannot be the same as the name of the containing object."); else if (_containingObject && _containingObject->subIndexByName.count(name)) - parserError("Object name \"" + name.str() + "\" already exists inside the containing object."); + parserError(8794_error, "Object name \"" + name.str() + "\" already exists inside the containing object."); advance(); return name; }