Skip to content
2 changes: 1 addition & 1 deletion libsolidity/ast/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,7 @@ class FunctionType: public Type
/// @returns TypePointer of a new FunctionType object. All input/return parameters are an
/// appropriate external types (i.e. the interfaceType()s) of input/return parameters of
/// current function.
/// Returns an empty shared pointer if one of the input/return parameters does not have an
/// @returns an empty shared pointer if one of the input/return parameters does not have an
/// external type.
FunctionTypePointer interfaceFunctionType() const;

Expand Down
2 changes: 1 addition & 1 deletion libsolidity/formal/Why3Translator.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class Why3Translator: private ASTConstVisitor
std::string translation() const;

private:
/// Returns an error.
/// Creates an error and adds it to errors list.
void error(ASTNode const& _node, std::string const& _description);
/// Reports a fatal error and throws.
void fatalError(ASTNode const& _node, std::string const& _description);
Expand Down
8 changes: 4 additions & 4 deletions libsolidity/interface/CompilerStack.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class CompilerStack: boost::noncopyable
/// Sets the given source code as the only source unit apart from standard sources and parses it.
/// @returns false on error.
bool parse(std::string const& _sourceCode);
/// Returns a list of the contract names in the sources.
/// @returns a list of the contract names in the sources.
std::vector<std::string> contractNames() const;
std::string defaultContractName() const;

Expand Down Expand Up @@ -144,13 +144,13 @@ class CompilerStack: boost::noncopyable
/// Prerequisite: Successful compilation.
Json::Value streamAssembly(std::ostream& _outStream, std::string const& _contractName = "", StringMap _sourceCodes = StringMap(), bool _inJsonFormat = false) const;

/// Returns a string representing the contract interface in JSON.
/// @returns a string representing the contract interface in JSON.
/// Prerequisite: Successful call to parse or compile.
std::string const& interface(std::string const& _contractName = "") const;
/// Returns a string representing the contract interface in Solidity.
/// @returns a string representing the contract interface in Solidity.
/// Prerequisite: Successful call to parse or compile.
std::string const& solidityInterface(std::string const& _contractName = "") const;
/// Returns a string representing the contract's documentation in JSON.
/// @returns a string representing the contract's documentation in JSON.
/// Prerequisite: Successful call to parse or compile.
/// @param type The type of the documentation to get.
/// Can be one of 4 types defined at @c DocumentationType
Expand Down
2 changes: 1 addition & 1 deletion libsolidity/interface/InterfaceHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class InterfaceHandler
static std::string devDocumentation(ContractDefinition const& _contractDef);

private:
/// Returns concatenation of all content under the given tag name.
/// @returns concatenation of all content under the given tag name.
static std::string extractDoc(std::multimap<std::string, DocTag> const& _tags, std::string const& _name);
};

Expand Down
4 changes: 2 additions & 2 deletions libsolidity/parsing/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,12 @@ class Parser: public ParserBase
/// For source code of the form "a[][8]" ("IndexAccessStructure"), this is not possible to
/// decide with constant look-ahead.
LookAheadInfo peekStatementType() const;
/// Returns a typename parsed in look-ahead fashion from something like "a.b[8][2**70]".
/// @returns a typename parsed in look-ahead fashion from something like "a.b[8][2**70]".
ASTPointer<TypeName> typeNameIndexAccessStructure(
std::vector<ASTPointer<PrimaryExpression>> const& _path,
std::vector<std::pair<ASTPointer<Expression>, SourceLocation>> const& _indices
);
/// Returns an expression parsed in look-ahead fashion from something like "a.b[8][2**70]".
/// @returns an expression parsed in look-ahead fashion from something like "a.b[8][2**70]".
ASTPointer<Expression> expressionFromIndexAccessStructure(
std::vector<ASTPointer<PrimaryExpression>> const& _path,
std::vector<std::pair<ASTPointer<Expression>, SourceLocation>> const& _indices
Expand Down
6 changes: 3 additions & 3 deletions libsolidity/parsing/Scanner.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,13 @@ class Scanner
/// Resets scanner to the start of input.
void reset();

/// Returns the next token and advances input
/// @returns the next token and advances input
Token::Value next();

///@{
///@name Information about the current token

/// Returns the current token
/// @returns the current token
Token::Value currentToken()
{
return m_currentToken.token;
Expand All @@ -138,7 +138,7 @@ class Scanner
///@{
///@name Information about the next token

/// Returns the next token without advancing input.
/// @returns the next token without advancing input.
Token::Value peekNextToken() const { return m_nextToken.token; }
SourceLocation peekLocation() const { return m_nextToken.location; }
std::string const& peekLiteral() const { return m_nextToken.literal; }
Expand Down
39 changes: 33 additions & 6 deletions libsolidity/parsing/Token.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

#include <map>
#include <libsolidity/parsing/Token.h>
#include <boost/range/iterator_range.hpp>

using namespace std;

Expand All @@ -66,6 +67,13 @@ void ElementaryTypeNameToken::assertDetails(Token::Value _baseType, unsigned con
"No elementary type " + string(Token::toString(_baseType)) + to_string(_first) + "."
);
}
else if (_baseType == Token::UFixedMxN || _baseType == Token::FixedMxN)
{
solAssert(
_first + _second <= 256 && _first % 8 == 0 && _second % 8 == 0,
"No elementary type " + string(Token::toString(_baseType)) + to_string(_first) + "x" + to_string(_second) + "."
);
}
m_token = _baseType;
m_firstNumber = _first;
m_secondNumber = _second;
Expand Down Expand Up @@ -101,26 +109,26 @@ char const Token::m_tokenType[] =
{
TOKEN_LIST(KT, KK)
};
unsigned Token::extractM(string const& _literal)
int Token::parseSize(string::const_iterator _begin, string::const_iterator _end)
{
try
{
unsigned short m = stoi(_literal);
unsigned int m = boost::lexical_cast<int>(boost::make_iterator_range(_begin, _end));
return m;
}
catch(out_of_range& e)
catch(boost::bad_lexical_cast const&)
{
return 0;
return -1;
}
}
tuple<Token::Value, unsigned short, unsigned short> Token::fromIdentifierOrKeyword(string const& _literal)
tuple<Token::Value, unsigned int, unsigned int> Token::fromIdentifierOrKeyword(string const& _literal)
{
auto positionM = find_if(_literal.begin(), _literal.end(), ::isdigit);
if (positionM != _literal.end())
{
string baseType(_literal.begin(), positionM);
auto positionX = find_if_not(positionM, _literal.end(), ::isdigit);
unsigned short m = extractM(string(positionM, positionX));
int m = parseSize(positionM, positionX);
Token::Value keyword = keywordByName(baseType);
if (keyword == Token::Bytes)
{
Expand All @@ -137,6 +145,25 @@ tuple<Token::Value, unsigned short, unsigned short> Token::fromIdentifierOrKeywo
return make_tuple(Token::IntM, m, 0);
}
}
else if (keyword == Token::UFixed || keyword == Token::Fixed)
{
auto positionN = find_if_not(++positionX, _literal.end(), ::isdigit);
int n = parseSize(++positionX, positionN);
if (
0 < m + n &&
m + n <= 256 &&
m % 8 == 0 &&
n % 8 == 0 &&
positionN == _literal.end() &&
*positionX == 'x'
)
{
if (keyword == Token::UFixed)
return make_tuple(Token::UFixed, m, n);
else
return make_tuple(Token::Fixed, m, n);
}
}
return make_tuple(Token::Identifier, 0, 0);
}
return make_tuple(keywordByName(_literal), 0, 0);
Expand Down
23 changes: 13 additions & 10 deletions libsolidity/parsing/Token.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ namespace solidity
\
/* Keywords */ \
K(Anonymous, "anonymous", 0) \
K(Assembly, "assembly", 0) \
K(Break, "break", 0) \
K(Const, "constant", 0) \
K(Continue, "continue", 0) \
Expand Down Expand Up @@ -198,8 +199,10 @@ namespace solidity
K(String, "string", 0) \
K(Address, "address", 0) \
K(Bool, "bool", 0) \
K(Real, "real", 0) \
K(UReal, "ureal", 0) \
K(Fixed, "fixed", 0) \
T(FixedMxN, "fixedMxN", 0) \
K(UFixed, "ufixed", 0) \
T(UFixedMxN, "ufixedMxN", 0) \
T(TypesEnd, NULL, 0) /* used as type enum end marker */ \
\
/* Literals */ \
Expand All @@ -218,6 +221,7 @@ namespace solidity
K(Case, "case", 0) \
K(Catch, "catch", 0) \
K(Final, "final", 0) \
K(Inline, "inline", 0) \
K(Let, "let", 0) \
K(Match, "match", 0) \
K(Of, "of", 0) \
Expand All @@ -227,6 +231,7 @@ namespace solidity
K(Type, "type", 0) \
K(TypeOf, "typeof", 0) \
K(Using, "using", 0) \
T(Timestamp, "timestamp", 0) \
/* Illegal token - not able to scan. */ \
T(Illegal, "ILLEGAL", 0) \
\
Expand All @@ -249,7 +254,7 @@ class Token
};
#undef T

// Returns a string corresponding to the C++ token name
// @returns a string corresponding to the C++ token name
// (e.g. "LT" for the token LT).
static char const* name(Value tok)
{
Expand Down Expand Up @@ -283,7 +288,7 @@ class Token
static bool isEtherSubdenomination(Value op) { return op == SubWei || op == SubSzabo || op == SubFinney || op == SubEther; }
static bool isTimeSubdenomination(Value op) { return op == SubSecond || op == SubMinute || op == SubHour || op == SubDay || op == SubWeek || op == SubYear; }

// Returns a string corresponding to the JS token string
// @returns a string corresponding to the JS token string
// (.e., "<" for the token LT) or NULL if the token doesn't
// have a (unique) string (e.g. an IDENTIFIER).
static char const* toString(Value tok)
Expand All @@ -292,21 +297,19 @@ class Token
return m_string[tok];
}

// Returns the precedence > 0 for binary and compare
// @returns the precedence > 0 for binary and compare
// operators; returns 0 otherwise.
static int precedence(Value tok)
{
solAssert(tok < NUM_TOKENS, "");
return m_precedence[tok];
}

static std::tuple<Token::Value, unsigned short, unsigned short> fromIdentifierOrKeyword(std::string const& _literal);
static std::tuple<Token::Value, unsigned int, unsigned int> fromIdentifierOrKeyword(std::string const& _literal);

private:
// extractM provides a safe way to extract numbers,
// if out_of_range error is thrown, they returns 0s, therefore securing
// the variable's identity as an identifier.
static unsigned extractM(std::string const& _literal);
// @returns -1 on error (invalid digit or number too large)
static int parseSize(std::string::const_iterator _begin, std::string::const_iterator _end);
// @returns the keyword with name @a _name or Token::Identifier of no such keyword exists.
static Token::Value keywordByName(std::string const& _name);
static char const* const m_name[NUM_TOKENS];
Expand Down
13 changes: 13 additions & 0 deletions test/libsolidity/SolidityNameAndTypeResolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3232,6 +3232,19 @@ BOOST_AUTO_TEST_CASE(int10abc_is_identifier)
BOOST_CHECK(success(text));
}

BOOST_AUTO_TEST_CASE(invalid_fixed_types)
{
char const* text = R"(
contract test {
function f() {
fixed0x7 a = .3;
fixed99999999999999999999999999999999999999x7 b = 9.5;
}
}
)";
BOOST_CHECK(!success(text));
}

BOOST_AUTO_TEST_SUITE_END()

}
Expand Down