From 5b1c0506faf865d5ff056bec8094211f0fa90600 Mon Sep 17 00:00:00 2001
From: chriseth <chris@ethereum.org>
Date: Sat, 30 Dec 2017 13:45:39 +0100
Subject: Allow ``memory`` suffix for internal elementary type parsing.

---
 libsolidity/ast/Types.cpp          | 15 +++++++++++++--
 libsolidity/ast/Types.h            |  1 +
 libsolidity/parsing/Token.cpp      |  2 +-
 test/libsolidity/SolidityTypes.cpp |  1 +
 4 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index ac1d3b01..de359ec6 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -233,11 +233,22 @@ TypePointer Type::fromElementaryTypeName(ElementaryTypeNameToken const& _type)
 
 TypePointer Type::fromElementaryTypeName(string const& _name)
 {
+	string name = _name;
+	DataLocation location = DataLocation::Storage;
+	if (boost::algorithm::ends_with(name, " memory"))
+	{
+		name = name.substr(0, name.length() - 7);
+		location = DataLocation::Memory;
+	}
 	unsigned short firstNum;
 	unsigned short secondNum;
 	Token::Value token;
-	tie(token, firstNum, secondNum) = Token::fromIdentifierOrKeyword(_name);
- 	return fromElementaryTypeName(ElementaryTypeNameToken(token, firstNum, secondNum));
+	tie(token, firstNum, secondNum) = Token::fromIdentifierOrKeyword(name);
+	auto t = fromElementaryTypeName(ElementaryTypeNameToken(token, firstNum, secondNum));
+	if (auto* ref = dynamic_cast<ReferenceType const*>(t.get()))
+		return ref->copyForLocation(location, true);
+	else
+		return t;
 }
 
 TypePointer Type::forLiteral(Literal const& _literal)
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index 2c392705..aa46520f 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -150,6 +150,7 @@ public:
 	/// @name Factory functions
 	/// Factory functions that convert an AST @ref TypeName to a Type.
 	static TypePointer fromElementaryTypeName(ElementaryTypeNameToken const& _type);
+	/// Converts a given elementary type name with optional suffix " memory" to a type pointer.
 	static TypePointer fromElementaryTypeName(std::string const& _name);
 	/// @}
 
diff --git a/libsolidity/parsing/Token.cpp b/libsolidity/parsing/Token.cpp
index 9cec0303..5ce74316 100644
--- a/libsolidity/parsing/Token.cpp
+++ b/libsolidity/parsing/Token.cpp
@@ -53,7 +53,7 @@ namespace solidity
 
 void ElementaryTypeNameToken::assertDetails(Token::Value _baseType, unsigned const& _first, unsigned const& _second)
 {
-	solAssert(Token::isElementaryTypeName(_baseType), "");
+	solAssert(Token::isElementaryTypeName(_baseType), "Expected elementary type name: " + string(Token::toString(_baseType)));
 	if (_baseType == Token::BytesM)
 	{
 		solAssert(_second == 0, "There should not be a second size argument to type bytesM.");
diff --git a/test/libsolidity/SolidityTypes.cpp b/test/libsolidity/SolidityTypes.cpp
index bc9f2fe1..738b24bc 100644
--- a/test/libsolidity/SolidityTypes.cpp
+++ b/test/libsolidity/SolidityTypes.cpp
@@ -123,6 +123,7 @@ BOOST_AUTO_TEST_CASE(type_identifiers)
 	BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bytes32")->identifier(), "t_bytes32");
 	BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bool")->identifier(), "t_bool");
 	BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bytes")->identifier(), "t_bytes_storage_ptr");
+	BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bytes memory")->identifier(), "t_bytes_memory_ptr");
 	BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("string")->identifier(), "t_string_storage_ptr");
 	ArrayType largeintArray(DataLocation::Memory, Type::fromElementaryTypeName("int128"), u256("2535301200456458802993406410752"));
 	BOOST_CHECK_EQUAL(largeintArray.identifier(), "t_array$_t_int128_$2535301200456458802993406410752_memory_ptr");
-- 
cgit v1.2.3