From 751705978e346b372e9aa1242c78e32892fae985 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 23 Feb 2018 18:27:27 +0100 Subject: Add helpers escapeIdentifier to Types --- libsolidity/ast/Types.cpp | 20 ++++++++++++++++++++ libsolidity/ast/Types.h | 8 +++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index e4b7e4fd..bf5745a6 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -170,6 +170,26 @@ string parenthesizeUserIdentifier(string const& _internal) } +string Type::escapeIdentifier(string const& _identifier) +{ + string ret = _identifier; + boost::algorithm::replace_all(ret, "$", "_$$$_"); + boost::algorithm::replace_all(ret, ",", "_$_"); + boost::algorithm::replace_all(ret, "(", "$_"); + boost::algorithm::replace_all(ret, ")", "_$"); + return ret; +} + +string Type::unescapeIdentifier(string const& _identifier) +{ + string ret = _identifier; + boost::algorithm::replace_all(ret, "_$_", ","); + boost::algorithm::replace_all(ret, "_$$$_", "$"); + boost::algorithm::replace_all(ret, "$_", "("); + boost::algorithm::replace_all(ret, "_$", ")"); + return ret; +} + TypePointer Type::fromElementaryTypeName(ElementaryTypeNameToken const& _type) { solAssert(Token::isElementaryTypeName(_type.token()), diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 2e7d05ba..ef898f37 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -163,10 +163,16 @@ public: /// @returns a valid solidity identifier such that two types should compare equal if and /// only if they have the same identifier. /// The identifier should start with "t_". + virtual std::string identifier() const = 0; + /// More complex identifier strings use "parentheses", where $_ is interpreted as as /// "opening parenthesis", _$ as "closing parenthesis", _$_ as "comma" and any $ that /// appears as part of a user-supplied identifier is escaped as _$$$_. - virtual std::string identifier() const = 0; + /// @returns an escaped identifier (will not contain any parenthesis or commas) + static std::string escapeIdentifier(std::string const& _identifier); + /// @returns an unescaped identifier + static std::string unescapeIdentifier(std::string const& _identifier); + virtual bool isImplicitlyConvertibleTo(Type const& _other) const { return *this == _other; } virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const { -- cgit From 2e7067fbe421872e0e7d0a4a4373199e56a9b7d0 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 23 Feb 2018 18:32:46 +0100 Subject: Rename Types::identifier to Types::richIdentifier --- libsolidity/ast/Types.cpp | 32 ++++++++++++++++---------------- libsolidity/ast/Types.h | 44 +++++++++++++++++++++++++------------------- 2 files changed, 41 insertions(+), 35 deletions(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index bf5745a6..97e7a922 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -354,7 +354,7 @@ IntegerType::IntegerType(int _bits, IntegerType::Modifier _modifier): ); } -string IntegerType::identifier() const +string IntegerType::richIdentifier() const { if (isAddress()) return "t_address"; @@ -524,7 +524,7 @@ FixedPointType::FixedPointType(int _totalBits, int _fractionalDigits, FixedPoint ); } -string FixedPointType::identifier() const +string FixedPointType::richIdentifier() const { return "t_" + string(isSigned() ? "" : "u") + "fixed" + std::to_string(m_totalBits) + "x" + std::to_string(m_fractionalDigits); } @@ -956,7 +956,7 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ } } -string RationalNumberType::identifier() const +string RationalNumberType::richIdentifier() const { return "t_rational_" + m_value.numerator().str() + "_by_" + m_value.denominator().str(); } @@ -1097,7 +1097,7 @@ bool StringLiteralType::isImplicitlyConvertibleTo(Type const& _convertTo) const return false; } -string StringLiteralType::identifier() const +string StringLiteralType::richIdentifier() const { // Since we have to return a valid identifier and the string itself may contain // anything, we hash it. @@ -1197,7 +1197,7 @@ MemberList::MemberMap FixedBytesType::nativeMembers(const ContractDefinition*) c return MemberList::MemberMap{MemberList::Member{"length", make_shared(8)}}; } -string FixedBytesType::identifier() const +string FixedBytesType::richIdentifier() const { return "t_bytes" + std::to_string(m_bytes); } @@ -1390,7 +1390,7 @@ bool ArrayType::isExplicitlyConvertibleTo(const Type& _convertTo) const return true; } -string ArrayType::identifier() const +string ArrayType::richIdentifier() const { string id; if (isString()) @@ -1624,7 +1624,7 @@ TypePointer ArrayType::copyForLocation(DataLocation _location, bool _isPointer) return copy; } -string ContractType::identifier() const +string ContractType::richIdentifier() const { return (m_super ? "t_super" : "t_contract") + parenthesizeUserIdentifier(m_contract.name()) + std::to_string(m_contract.id()); } @@ -1776,7 +1776,7 @@ bool StructType::isImplicitlyConvertibleTo(const Type& _convertTo) const return this->m_struct == convertTo.m_struct; } -string StructType::identifier() const +string StructType::richIdentifier() const { return "t_struct" + parenthesizeUserIdentifier(m_struct.name()) + std::to_string(m_struct.id()) + identifierLocationSuffix(); } @@ -2008,7 +2008,7 @@ TypePointer EnumType::unaryOperatorResult(Token::Value _operator) const return _operator == Token::Delete ? make_shared() : TypePointer(); } -string EnumType::identifier() const +string EnumType::richIdentifier() const { return "t_enum" + parenthesizeUserIdentifier(m_enum.name()) + std::to_string(m_enum.id()); } @@ -2094,7 +2094,7 @@ bool TupleType::isImplicitlyConvertibleTo(Type const& _other) const return false; } -string TupleType::identifier() const +string TupleType::richIdentifier() const { return "t_tuple" + identifierList(components()); } @@ -2354,7 +2354,7 @@ TypePointers FunctionType::parameterTypes() const return TypePointers(m_parameterTypes.cbegin() + 1, m_parameterTypes.cend()); } -string FunctionType::identifier() const +string FunctionType::richIdentifier() const { string id = "t_function_"; switch (m_kind) @@ -2847,7 +2847,7 @@ ASTPointer FunctionType::documentation() const return ASTPointer(); } -string MappingType::identifier() const +string MappingType::richIdentifier() const { return "t_mapping" + identifierList(m_keyType, m_valueType); } @@ -2870,7 +2870,7 @@ string MappingType::canonicalName() const return "mapping(" + keyType()->canonicalName() + " => " + valueType()->canonicalName() + ")"; } -string TypeType::identifier() const +string TypeType::richIdentifier() const { return "t_type" + identifierList(actualType()); } @@ -2955,7 +2955,7 @@ u256 ModifierType::storageSize() const solAssert(false, "Storage size of non-storable type type requested."); } -string ModifierType::identifier() const +string ModifierType::richIdentifier() const { return "t_modifier" + identifierList(m_parameterTypes); } @@ -2984,7 +2984,7 @@ string ModifierType::toString(bool _short) const return name + ")"; } -string ModuleType::identifier() const +string ModuleType::richIdentifier() const { return "t_module_" + std::to_string(m_sourceUnit.id()); } @@ -3010,7 +3010,7 @@ string ModuleType::toString(bool) const return string("module \"") + m_sourceUnit.annotation().path + string("\""); } -string MagicType::identifier() const +string MagicType::richIdentifier() const { switch (m_kind) { diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index ef898f37..a12b7063 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -163,7 +163,13 @@ public: /// @returns a valid solidity identifier such that two types should compare equal if and /// only if they have the same identifier. /// The identifier should start with "t_". - virtual std::string identifier() const = 0; + /// Can contain characters which are invalid in identifiers. + virtual std::string richIdentifier() const = 0; + /// @returns a valid solidity identifier such that two types should compare equal if and + /// only if they have the same identifier. + /// The identifier should start with "t_". + /// Will not contain any character which would be invalid as an identifier. + std::string identifier() const { return escapeIdentifier(richIdentifier()); } /// More complex identifier strings use "parentheses", where $_ is interpreted as as /// "opening parenthesis", _$ as "closing parenthesis", _$_ as "comma" and any $ that @@ -312,7 +318,7 @@ public: explicit IntegerType(int _bits, Modifier _modifier = Modifier::Unsigned); - virtual std::string identifier() const override; + virtual std::string richIdentifier() const override; virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; @@ -359,7 +365,7 @@ public: explicit FixedPointType(int _totalBits, int _fractionalDigits, Modifier _modifier = Modifier::Unsigned); - virtual std::string identifier() const override; + virtual std::string richIdentifier() const override; virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; @@ -416,7 +422,7 @@ public: virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; virtual TypePointer binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const override; - virtual std::string identifier() const override; + virtual std::string richIdentifier() const override; virtual bool operator==(Type const& _other) const override; virtual bool canBeStored() const override { return false; } @@ -465,7 +471,7 @@ public: return TypePointer(); } - virtual std::string identifier() const override; + virtual std::string richIdentifier() const override; virtual bool operator==(Type const& _other) const override; virtual bool canBeStored() const override { return false; } @@ -499,7 +505,7 @@ public: virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual std::string identifier() const override; + virtual std::string richIdentifier() const override; virtual bool operator==(Type const& _other) const override; virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; virtual TypePointer binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const override; @@ -527,7 +533,7 @@ class BoolType: public Type public: BoolType() {} virtual Category category() const override { return Category::Bool; } - virtual std::string identifier() const override { return "t_bool"; } + virtual std::string richIdentifier() const override { return "t_bool"; } virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; virtual TypePointer binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const override; @@ -627,7 +633,7 @@ public: virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual std::string identifier() const override; + virtual std::string richIdentifier() const override; virtual bool operator==(const Type& _other) const override; virtual unsigned calldataEncodedSize(bool _padded) const override; virtual bool isDynamicallySized() const override { return m_hasDynamicLength; } @@ -684,7 +690,7 @@ public: /// Contracts can be converted to themselves and to integers. virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; - virtual std::string identifier() const override; + virtual std::string richIdentifier() const override; virtual bool operator==(Type const& _other) const override; virtual unsigned calldataEncodedSize(bool _padded ) const override { @@ -742,7 +748,7 @@ public: explicit StructType(StructDefinition const& _struct, DataLocation _location = DataLocation::Storage): ReferenceType(_location), m_struct(_struct) {} virtual bool isImplicitlyConvertibleTo(const Type& _convertTo) const override; - virtual std::string identifier() const override; + virtual std::string richIdentifier() const override; virtual bool operator==(Type const& _other) const override; virtual unsigned calldataEncodedSize(bool _padded) const override; virtual bool isDynamicallyEncoded() const override; @@ -797,7 +803,7 @@ public: virtual Category category() const override { return Category::Enum; } explicit EnumType(EnumDefinition const& _enum): m_enum(_enum) {} virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; - virtual std::string identifier() const override; + virtual std::string richIdentifier() const override; virtual bool operator==(Type const& _other) const override; virtual unsigned calldataEncodedSize(bool _padded) const override { @@ -838,7 +844,7 @@ public: virtual Category category() const override { return Category::Tuple; } explicit TupleType(std::vector const& _types = std::vector()): m_components(_types) {} virtual bool isImplicitlyConvertibleTo(Type const& _other) const override; - virtual std::string identifier() const override; + virtual std::string richIdentifier() const override; virtual bool operator==(Type const& _other) const override; virtual TypePointer binaryOperatorResult(Token::Value, TypePointer const&) const override { return TypePointer(); } virtual std::string toString(bool) const override; @@ -972,7 +978,7 @@ public: /// @returns the "self" parameter type for a bound function TypePointer const& selfType() const; - virtual std::string identifier() const override; + virtual std::string richIdentifier() const override; virtual bool operator==(Type const& _other) const override; virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; @@ -1076,7 +1082,7 @@ public: MappingType(TypePointer const& _keyType, TypePointer const& _valueType): m_keyType(_keyType), m_valueType(_valueType) {} - virtual std::string identifier() const override; + virtual std::string richIdentifier() const override; virtual bool operator==(Type const& _other) const override; virtual std::string toString(bool _short) const override; virtual std::string canonicalName() const override; @@ -1113,7 +1119,7 @@ public: TypePointer const& actualType() const { return m_actualType; } virtual TypePointer binaryOperatorResult(Token::Value, TypePointer const&) const override { return TypePointer(); } - virtual std::string identifier() const override; + virtual std::string richIdentifier() const override; virtual bool operator==(Type const& _other) const override; virtual bool canBeStored() const override { return false; } virtual u256 storageSize() const override; @@ -1141,7 +1147,7 @@ public: virtual u256 storageSize() const override; virtual bool canLiveOutsideStorage() const override { return false; } virtual unsigned sizeOnStack() const override { return 0; } - virtual std::string identifier() const override; + virtual std::string richIdentifier() const override; virtual bool operator==(Type const& _other) const override; virtual std::string toString(bool _short) const override; @@ -1162,7 +1168,7 @@ public: explicit ModuleType(SourceUnit const& _source): m_sourceUnit(_source) {} virtual TypePointer binaryOperatorResult(Token::Value, TypePointer const&) const override { return TypePointer(); } - virtual std::string identifier() const override; + virtual std::string richIdentifier() const override; virtual bool operator==(Type const& _other) const override; virtual bool canBeStored() const override { return false; } virtual bool canLiveOutsideStorage() const override { return true; } @@ -1192,7 +1198,7 @@ public: return TypePointer(); } - virtual std::string identifier() const override; + virtual std::string richIdentifier() const override; virtual bool operator==(Type const& _other) const override; virtual bool canBeStored() const override { return false; } virtual bool canLiveOutsideStorage() const override { return true; } @@ -1216,7 +1222,7 @@ class InaccessibleDynamicType: public Type public: virtual Category category() const override { return Category::InaccessibleDynamic; } - virtual std::string identifier() const override { return "t_inaccessible"; } + virtual std::string richIdentifier() const override { return "t_inaccessible"; } virtual bool isImplicitlyConvertibleTo(Type const&) const override { return false; } virtual bool isExplicitlyConvertibleTo(Type const&) const override { return false; } virtual TypePointer binaryOperatorResult(Token::Value, TypePointer const&) const override { return TypePointer(); } -- cgit From b471983e3cacf4d92ecd987eac85620bd8030aff Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Sat, 24 Feb 2018 01:13:34 +0100 Subject: Use new escaping helpers for type identifiers --- libsolidity/ast/Types.cpp | 27 +++++++++------------------ libsolidity/ast/Types.h | 2 -- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 97e7a922..fadaf621 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -131,28 +131,28 @@ namespace string parenthesizeIdentifier(string const& _internal) { - return "$_" + _internal + "_$"; + return "(" + _internal + ")"; } template string identifierList(Range const&& _list) { - return parenthesizeIdentifier(boost::algorithm::join(_list, "_$_")); + return parenthesizeIdentifier(boost::algorithm::join(_list, ",")); } -string identifier(TypePointer const& _type) +string richIdentifier(TypePointer const& _type) { - return _type ? _type->identifier() : ""; + return _type ? _type->richIdentifier() : ""; } string identifierList(vector const& _list) { - return identifierList(_list | boost::adaptors::transformed(identifier)); + return identifierList(_list | boost::adaptors::transformed(richIdentifier)); } string identifierList(TypePointer const& _type) { - return parenthesizeIdentifier(identifier(_type)); + return parenthesizeIdentifier(richIdentifier(_type)); } string identifierList(TypePointer const& _type1, TypePointer const& _type2) @@ -165,7 +165,7 @@ string identifierList(TypePointer const& _type1, TypePointer const& _type2) string parenthesizeUserIdentifier(string const& _internal) { - return parenthesizeIdentifier(boost::algorithm::replace_all_copy(_internal, "$", "$$$")); + return parenthesizeIdentifier(_internal); } } @@ -173,23 +173,14 @@ string parenthesizeUserIdentifier(string const& _internal) string Type::escapeIdentifier(string const& _identifier) { string ret = _identifier; - boost::algorithm::replace_all(ret, "$", "_$$$_"); + // FIXME: should be _$$$_ + boost::algorithm::replace_all(ret, "$", "$$$"); boost::algorithm::replace_all(ret, ",", "_$_"); boost::algorithm::replace_all(ret, "(", "$_"); boost::algorithm::replace_all(ret, ")", "_$"); return ret; } -string Type::unescapeIdentifier(string const& _identifier) -{ - string ret = _identifier; - boost::algorithm::replace_all(ret, "_$_", ","); - boost::algorithm::replace_all(ret, "_$$$_", "$"); - boost::algorithm::replace_all(ret, "$_", "("); - boost::algorithm::replace_all(ret, "_$", ")"); - return ret; -} - TypePointer Type::fromElementaryTypeName(ElementaryTypeNameToken const& _type) { solAssert(Token::isElementaryTypeName(_type.token()), diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index a12b7063..7985521e 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -176,8 +176,6 @@ public: /// appears as part of a user-supplied identifier is escaped as _$$$_. /// @returns an escaped identifier (will not contain any parenthesis or commas) static std::string escapeIdentifier(std::string const& _identifier); - /// @returns an unescaped identifier - static std::string unescapeIdentifier(std::string const& _identifier); virtual bool isImplicitlyConvertibleTo(Type const& _other) const { return *this == _other; } virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const -- cgit From 0736d91eaa0807c21364376b455c0b72c1aeb9be Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 26 Feb 2018 16:25:23 +0100 Subject: Add test for escapeIdentifier --- test/libsolidity/SolidityTypes.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/libsolidity/SolidityTypes.cpp b/test/libsolidity/SolidityTypes.cpp index 9f385a04..bc9f2fe1 100644 --- a/test/libsolidity/SolidityTypes.cpp +++ b/test/libsolidity/SolidityTypes.cpp @@ -88,6 +88,21 @@ BOOST_AUTO_TEST_CASE(storage_layout_arrays) BOOST_CHECK(ArrayType(DataLocation::Storage, make_shared(32), 9).storageSize() == 9); } +BOOST_AUTO_TEST_CASE(type_escaping) +{ + BOOST_CHECK_EQUAL(Type::escapeIdentifier("("), "$_"); + BOOST_CHECK_EQUAL(Type::escapeIdentifier(")"), "_$"); + BOOST_CHECK_EQUAL(Type::escapeIdentifier(","), "_$_"); + BOOST_CHECK_EQUAL(Type::escapeIdentifier("$"), "$$$"); + BOOST_CHECK_EQUAL(Type::escapeIdentifier("()"), "$__$"); + BOOST_CHECK_EQUAL(Type::escapeIdentifier("(,)"), "$__$__$"); + BOOST_CHECK_EQUAL(Type::escapeIdentifier("(,$,)"), "$__$_$$$_$__$"); + BOOST_CHECK_EQUAL( + Type::escapeIdentifier("((__(_$_$$,__($$,,,$$),$,,,)))$$,$$"), + "$_$___$__$$$_$$$$$$_$___$_$$$$$$_$__$__$_$$$$$$_$_$_$$$_$__$__$__$_$_$$$$$$$_$_$$$$$$" + ); +} + BOOST_AUTO_TEST_CASE(type_identifiers) { ASTNode::resetID(); -- cgit