aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/contracts.rst384
-rw-r--r--docs/control-structures.rst2
-rw-r--r--docs/introduction-to-smart-contracts.rst2
-rw-r--r--libsolidity/analysis/NameAndTypeResolver.cpp2
-rw-r--r--libsolidity/ast/AST.h12
-rw-r--r--libsolidity/ast/ASTPrinter.cpp2
-rw-r--r--libsolidity/parsing/Parser.cpp32
-rw-r--r--libsolidity/parsing/Parser.h1
-rw-r--r--test/libsolidity/Imports.cpp2
9 files changed, 221 insertions, 218 deletions
diff --git a/docs/contracts.rst b/docs/contracts.rst
index 1d292c25..45391cd9 100644
--- a/docs/contracts.rst
+++ b/docs/contracts.rst
@@ -61,65 +61,65 @@ This means that cyclic creation dependencies are impossible.
::
contract OwnedToken {
- // TokenCreator is a contract type that is defined below.
- // It is fine to reference it as long as it is not used
- // to create a new contract.
- TokenCreator creator;
- address owner;
- bytes32 name;
- // This is the constructor which registers the
- // creator and the assigned name.
- function OwnedToken(bytes32 _name) {
- owner = msg.sender;
- // We do an explicit type conversion from `address`
- // to `TokenCreator` and assume that the type of
- // the calling contract is TokenCreator, there is
- // no real way to check that.
- creator = TokenCreator(msg.sender);
- name = _name;
- }
- function changeName(bytes32 newName) {
- // Only the creator can alter the name --
- // the comparison is possible since contracts
- // are implicitly convertible to addresses.
- if (msg.sender == creator) name = newName;
- }
- function transfer(address newOwner) {
- // Only the current owner can transfer the token.
- if (msg.sender != owner) return;
- // We also want to ask the creator if the transfer
- // is fine. Note that this calls a function of the
- // contract defined below. If the call fails (e.g.
- // due to out-of-gas), the execution here stops
- // immediately.
- if (creator.isTokenTransferOK(owner, newOwner))
- owner = newOwner;
- }
+ // TokenCreator is a contract type that is defined below.
+ // It is fine to reference it as long as it is not used
+ // to create a new contract.
+ TokenCreator creator;
+ address owner;
+ bytes32 name;
+ // This is the constructor which registers the
+ // creator and the assigned name.
+ function OwnedToken(bytes32 _name) {
+ owner = msg.sender;
+ // We do an explicit type conversion from `address`
+ // to `TokenCreator` and assume that the type of
+ // the calling contract is TokenCreator, there is
+ // no real way to check that.
+ creator = TokenCreator(msg.sender);
+ name = _name;
+ }
+ function changeName(bytes32 newName) {
+ // Only the creator can alter the name --
+ // the comparison is possible since contracts
+ // are implicitly convertible to addresses.
+ if (msg.sender == creator) name = newName;
+ }
+ function transfer(address newOwner) {
+ // Only the current owner can transfer the token.
+ if (msg.sender != owner) return;
+ // We also want to ask the creator if the transfer
+ // is fine. Note that this calls a function of the
+ // contract defined below. If the call fails (e.g.
+ // due to out-of-gas), the execution here stops
+ // immediately.
+ if (creator.isTokenTransferOK(owner, newOwner))
+ owner = newOwner;
+ }
}
contract TokenCreator {
- function createToken(bytes32 name)
+ function createToken(bytes32 name)
returns (OwnedToken tokenAddress)
- {
- // Create a new Token contract and return its address.
- // From the JavaScript side, the return type is simply
- // "address", as this is the closest type available in
- // the ABI.
- return new OwnedToken(name);
- }
- function changeName(OwnedToken tokenAddress, bytes32 name) {
- // Again, the external type of "tokenAddress" is
- // simply "address".
- tokenAddress.changeName(name);
- }
- function isTokenTransferOK(
- address currentOwner,
- address newOwner
- ) returns (bool ok) {
- // Check some arbitrary condition.
- address tokenAddress = msg.sender;
- return (sha3(newOwner) & 0xff) == (bytes20(tokenAddress) & 0xff);
- }
+ {
+ // Create a new Token contract and return its address.
+ // From the JavaScript side, the return type is simply
+ // "address", as this is the closest type available in
+ // the ABI.
+ return new OwnedToken(name);
+ }
+ function changeName(OwnedToken tokenAddress, bytes32 name) {
+ // Again, the external type of "tokenAddress" is
+ // simply "address".
+ tokenAddress.changeName(name);
+ }
+ function isTokenTransferOK(
+ address currentOwner,
+ address newOwner
+ ) returns (bool ok) {
+ // Check some arbitrary condition.
+ address tokenAddress = msg.sender;
+ return (sha3(newOwner) & 0xff) == (bytes20(tokenAddress) & 0xff);
+ }
}
.. index:: ! visibility, external, public, private, internal
@@ -179,9 +179,9 @@ return parameter list for functions.
::
contract c {
- function f(uint a) private returns (uint b) { return a + 1; }
- function setData(uint a) internal { data = a; }
- uint public data;
+ function f(uint a) private returns (uint b) { return a + 1; }
+ function setData(uint a) internal { data = a; }
+ uint public data;
}
Other contracts can call `c.data()` to retrieve the value of
@@ -209,7 +209,7 @@ it is a state variable and if it is accessed externally
::
contract test {
- uint public data = 42;
+ uint public data = 42;
}
The next example is a bit more complex:
@@ -217,16 +217,16 @@ The next example is a bit more complex:
::
contract complex {
- struct Data { uint a; bytes3 b; mapping(uint => uint) map; }
- mapping(uint => mapping(bool => Data[])) public data;
+ struct Data { uint a; bytes3 b; mapping(uint => uint) map; }
+ mapping(uint => mapping(bool => Data[])) public data;
}
It will generate a function of the following form::
function data(uint arg1, bool arg2, uint arg3) returns (uint a, bytes3 b)
{
- a = data[arg1][arg2][arg3].a;
- b = data[arg1][arg2][arg3].b;
+ a = data[arg1][arg2][arg3].a;
+ b = data[arg1][arg2][arg3].b;
}
Note that the mapping in the struct is omitted because there
@@ -247,41 +247,41 @@ inheritable properties of contracts and may be overridden by derived contracts.
::
contract owned {
- function owned() { owner = msg.sender; }
- address owner;
-
- // This contract only defines a modifier but does not use
- // it - it will be used in derived contracts.
- // The function body is inserted where the special symbol
- // "_" in the definition of a modifier appears.
- // This means that if the owner calls this function, the
- // function is executed and otherwise, an exception is
- // thrown.
- modifier onlyowner { if (msg.sender != owner) throw; _ }
+ function owned() { owner = msg.sender; }
+ address owner;
+
+ // This contract only defines a modifier but does not use
+ // it - it will be used in derived contracts.
+ // The function body is inserted where the special symbol
+ // "_" in the definition of a modifier appears.
+ // This means that if the owner calls this function, the
+ // function is executed and otherwise, an exception is
+ // thrown.
+ modifier onlyowner { if (msg.sender != owner) throw; _ }
}
contract mortal is owned {
- // This contract inherits the "onlyowner"-modifier from
- // "owned" and applies it to the "close"-function, which
- // causes that calls to "close" only have an effect if
- // they are made by the stored owner.
- function close() onlyowner {
- selfdestruct(owner);
- }
+ // This contract inherits the "onlyowner"-modifier from
+ // "owned" and applies it to the "close"-function, which
+ // causes that calls to "close" only have an effect if
+ // they are made by the stored owner.
+ function close() onlyowner {
+ selfdestruct(owner);
+ }
}
contract priced {
- // Modifiers can receive arguments:
- modifier costs(uint price) { if (msg.value >= price) _ }
+ // Modifiers can receive arguments:
+ modifier costs(uint price) { if (msg.value >= price) _ }
}
contract Register is priced, owned {
- mapping (address => bool) registeredAddresses;
- uint price;
- function Register(uint initialPrice) { price = initialPrice; }
- function register() costs(price) {
- registeredAddresses[msg.sender] = true;
- }
- function changePrice(uint _price) onlyowner {
- price = _price;
- }
+ mapping (address => bool) registeredAddresses;
+ uint price;
+ function Register(uint initialPrice) { price = initialPrice; }
+ function register() costs(price) {
+ registeredAddresses[msg.sender] = true;
+ }
+ function changePrice(uint _price) onlyowner {
+ price = _price;
+ }
}
Multiple modifiers can be applied to a function by specifying them in a
@@ -305,8 +305,8 @@ for array and struct types and not possible for mapping types).
::
contract C {
- uint constant x = 32**22 + 8;
- string constant text = "abc";
+ uint constant x = 32**22 + 8;
+ string constant text = "abc";
}
This has the effect that the compiler does not reserve a storage slot
@@ -336,24 +336,24 @@ possible.
::
contract Test {
- function() { x = 1; }
- uint x;
+ function() { x = 1; }
+ uint x;
}
// This contract rejects any Ether sent to it. It is good
// practise to include such a function for every contract
// in order not to loose Ether.
contract Rejector {
- function() { throw; }
+ function() { throw; }
}
contract Caller {
function callTest(address testAddress) {
- Test(testAddress).call(0xabcdef01); // hash does not exist
- // results in Test(testAddress).x becoming == 1.
- Rejector r = Rejector(0x123);
- r.send(2 ether);
- // results in r.balance == 0
+ Test(testAddress).call(0xabcdef01); // hash does not exist
+ // results in Test(testAddress).x becoming == 1.
+ Rejector r = Rejector(0x123);
+ r.send(2 ether);
+ // results in r.balance == 0
}
}
@@ -400,17 +400,17 @@ All non-indexed arguments will be stored in the data part of the log.
::
contract ClientReceipt {
- event Deposit(
- address indexed _from,
- bytes32 indexed _id,
- uint _value
- );
- function deposit(bytes32 _id) {
- // Any call to this function (even deeply nested) can
- // be detected from the JavaScript API by filtering
- // for `Deposit` to be called.
- Deposit(msg.sender, _id, msg.value);
- }
+ event Deposit(
+ address indexed _from,
+ bytes32 indexed _id,
+ uint _value
+ );
+ function deposit(bytes32 _id) {
+ // Any call to this function (even deeply nested) can
+ // be detected from the JavaScript API by filtering
+ // for `Deposit` to be called.
+ Deposit(msg.sender, _id, msg.value);
+ }
}
The use in the JavaScript API would be as follows:
@@ -425,17 +425,17 @@ The use in the JavaScript API would be as follows:
// watch for changes
event.watch(function(error, result){
- // result will contain various information
- // including the argumets given to the Deposit
- // call.
- if (!error)
- console.log(result);
+ // result will contain various information
+ // including the argumets given to the Deposit
+ // call.
+ if (!error)
+ console.log(result);
});
// Or pass a callback to start watching immediately
var event = clientReceipt.Deposit(function(error, result) {
- if (!error)
- console.log(result);
+ if (!error)
+ console.log(result);
});
.. index:: ! log
@@ -452,10 +452,10 @@ as topics. The event call above can be performed in the same way as
::
log3(
- msg.value,
- 0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20,
- msg.sender,
- _id
+ msg.value,
+ 0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20,
+ msg.sender,
+ _id
);
where the long hexadecimal number is equal to
@@ -502,7 +502,7 @@ Details are given in the following example.
// accessed externally via `this`, though.
contract mortal is owned {
function kill() {
- if (msg.sender == owner) selfdestruct(owner);
+ if (msg.sender == owner) selfdestruct(owner);
}
}
@@ -611,12 +611,12 @@ Derived contracts need to provide all arguments needed for
the base constructors. This can be done at two places::
contract Base {
- uint x;
- function Base(uint _x) { x = _x; }
+ uint x;
+ function Base(uint _x) { x = _x; }
}
contract Derived is Base(7) {
- function Derived(uint _y) Base(_y * _y) {
- }
+ function Derived(uint _y) Base(_y * _y) {
+ }
}
Either directly in the inheritance list (`is Base(7)`) or in
@@ -667,13 +667,13 @@ Abstract Contracts
Contract functions can lack an implementation as in the following example (note that the function declaration header is terminated by `;`)::
contract feline {
- function utterance() returns (bytes32);
+ function utterance() returns (bytes32);
}
Such contracts cannot be compiled (even if they contain implemented functions alongside non-implemented functions), but they can be used as base contracts::
contract Cat is feline {
- function utterance() returns (bytes32) { return "miaow"; }
+ function utterance() returns (bytes32) { return "miaow"; }
}
If a contract inherits from an abstract contract and does not implement all non-implemented functions by overriding, it will itself be abstract.
@@ -716,35 +716,35 @@ more advanced example to implement a set).
function insert(Data storage self, uint value)
returns (bool)
{
- if (self.flags[value])
- return false; // already there
- self.flags[value] = true;
- return true;
+ if (self.flags[value])
+ return false; // already there
+ self.flags[value] = true;
+ return true;
}
function remove(Data storage self, uint value)
- returns (bool)
+ returns (bool)
{
- if (!self.flags[value])
- return false; // not there
- self.flags[value] = false;
- return true;
+ if (!self.flags[value])
+ return false; // not there
+ self.flags[value] = false;
+ return true;
}
function contains(Data storage self, uint value)
- returns (bool)
+ returns (bool)
{
- return self.flags[value];
+ return self.flags[value];
}
}
contract C {
- Set.Data knownValues;
- function register(uint value) {
- // The library functions can be called without a
- // specific instance of the library, since the
- // "instance" will be the current contract.
- if (!Set.insert(knownValues, value))
- throw;
- }
- // In this contract, we can also directly access knownValues.flags, if we want.
+ Set.Data knownValues;
+ function register(uint value) {
+ // The library functions can be called without a
+ // specific instance of the library, since the
+ // "instance" will be the current contract.
+ if (!Set.insert(knownValues, value))
+ throw;
+ }
+ // In this contract, we can also directly access knownValues.flags, if we want.
}
Of course, you do not have to follow this way to use
@@ -774,8 +774,8 @@ encoding of the address of the library contract.
Restrictions for libraries in comparison to contracts:
- - no state variables
- - cannot inherit nor be inherited
+- no state variables
+- cannot inherit nor be inherited
(these might be lifted at a later point)
@@ -845,63 +845,63 @@ Let us rewrite the set example from the
function insert(Data storage self, uint value)
returns (bool)
{
- if (self.flags[value])
- return false; // already there
- self.flags[value] = true;
- return true;
+ if (self.flags[value])
+ return false; // already there
+ self.flags[value] = true;
+ return true;
}
function remove(Data storage self, uint value)
- returns (bool)
+ returns (bool)
{
- if (!self.flags[value])
- return false; // not there
- self.flags[value] = false;
- return true;
+ if (!self.flags[value])
+ return false; // not there
+ self.flags[value] = false;
+ return true;
}
function contains(Data storage self, uint value)
- returns (bool)
+ returns (bool)
{
- return self.flags[value];
+ return self.flags[value];
}
}
contract C {
- using Set for Set.Data; // this is the crucial change
- Set.Data knownValues;
- function register(uint value) {
- // Here, all variables of type Set.Data have
- // corresponding member functions.
- // The following function call is identical to
- // Set.insert(knownValues, value)
- if (!knownValues.insert(value))
- throw;
- }
+ using Set for Set.Data; // this is the crucial change
+ Set.Data knownValues;
+ function register(uint value) {
+ // Here, all variables of type Set.Data have
+ // corresponding member functions.
+ // The following function call is identical to
+ // Set.insert(knownValues, value)
+ if (!knownValues.insert(value))
+ throw;
+ }
}
It is also possible to extend elementary types in that way::
library Search {
- function indexOf(uint[] storage self, uint value) {
- for (uint i = 0; i < self.length; i++)
- if (self[i] == value) return i;
- return uint(-1);
- }
+ function indexOf(uint[] storage self, uint value) {
+ for (uint i = 0; i < self.length; i++)
+ if (self[i] == value) return i;
+ return uint(-1);
+ }
}
contract C {
- using Search for uint[];
- uint[] data;
- function append(uint value) {
- data.push(value);
- }
- function replace(uint _old, uint _new) {
- // This performs the library function call
- uint index = data.find(_old);
- if (index == -1)
- data.push(_new);
- else
- data[index] = _new;
- }
+ using Search for uint[];
+ uint[] data;
+ function append(uint value) {
+ data.push(value);
+ }
+ function replace(uint _old, uint _new) {
+ // This performs the library function call
+ uint index = data.find(_old);
+ if (index == -1)
+ data.push(_new);
+ else
+ data[index] = _new;
+ }
}
Note that all library calls are actual EVM function calls. This means that
diff --git a/docs/control-structures.rst b/docs/control-structures.rst
index 4f8d3b93..c833fbfc 100644
--- a/docs/control-structures.rst
+++ b/docs/control-structures.rst
@@ -16,7 +16,7 @@ Parentheses can *not* be omitted for conditionals, but curly brances can be omit
around single-statement bodies.
Note that there is no type conversion from non-boolean to boolean types as
-there is in C and JavaScript, so `if (1) { ... }` is _not_ valid Solidity.
+there is in C and JavaScript, so `if (1) { ... }` is *not* valid Solidity.
.. index:: ! function;call, function;internal, function;external
diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst
index b0f1896a..711e7082 100644
--- a/docs/introduction-to-smart-contracts.rst
+++ b/docs/introduction-to-smart-contracts.rst
@@ -100,7 +100,7 @@ registering with username and password - all you need is an Ethereum keypair.
}
}
-This contract introduces some new concepts, let us go through them one by one
+This contract introduces some new concepts, let us go through them one by one.
The line `address public minter;` declares a state variable of type address
that is publicly accessible. The `address` type is a 160 bit value
diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp
index 92347bfc..96ffdd6e 100644
--- a/libsolidity/analysis/NameAndTypeResolver.cpp
+++ b/libsolidity/analysis/NameAndTypeResolver.cpp
@@ -264,7 +264,7 @@ void NameAndTypeResolver::linearizeBaseContracts(ContractDefinition& _contract)
list<list<ContractDefinition const*>> input(1, {});
for (ASTPointer<InheritanceSpecifier> const& baseSpecifier: _contract.baseContracts())
{
- Identifier const& baseName = baseSpecifier->name();
+ UserDefinedTypeName const& baseName = baseSpecifier->name();
auto base = dynamic_cast<ContractDefinition const*>(baseName.annotation().referencedDeclaration);
if (!base)
reportFatalTypeError(baseName.createTypeError("Contract expected."));
diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h
index 84e9e706..604a12a0 100644
--- a/libsolidity/ast/AST.h
+++ b/libsolidity/ast/AST.h
@@ -340,7 +340,7 @@ class InheritanceSpecifier: public ASTNode
public:
InheritanceSpecifier(
SourceLocation const& _location,
- ASTPointer<Identifier> const& _baseName,
+ ASTPointer<UserDefinedTypeName> const& _baseName,
std::vector<ASTPointer<Expression>> _arguments
):
ASTNode(_location), m_baseName(_baseName), m_arguments(_arguments) {}
@@ -348,11 +348,11 @@ public:
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
- Identifier const& name() const { return *m_baseName; }
+ UserDefinedTypeName const& name() const { return *m_baseName; }
std::vector<ASTPointer<Expression>> const& arguments() const { return m_arguments; }
private:
- ASTPointer<Identifier> m_baseName;
+ ASTPointer<UserDefinedTypeName> m_baseName;
std::vector<ASTPointer<Expression>> m_arguments;
};
@@ -366,7 +366,7 @@ class UsingForDirective: public ASTNode
public:
UsingForDirective(
SourceLocation const& _location,
- ASTPointer<Identifier> const& _libraryName,
+ ASTPointer<UserDefinedTypeName> const& _libraryName,
ASTPointer<TypeName> const& _typeName
):
ASTNode(_location), m_libraryName(_libraryName), m_typeName(_typeName) {}
@@ -374,12 +374,12 @@ public:
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
- Identifier const& libraryName() const { return *m_libraryName; }
+ UserDefinedTypeName const& libraryName() const { return *m_libraryName; }
/// @returns the type name the library is attached to, null for `*`.
TypeName const* typeName() const { return m_typeName.get(); }
private:
- ASTPointer<Identifier> m_libraryName;
+ ASTPointer<UserDefinedTypeName> m_libraryName;
ASTPointer<TypeName> m_typeName;
};
diff --git a/libsolidity/ast/ASTPrinter.cpp b/libsolidity/ast/ASTPrinter.cpp
index b2ce1c26..d4f13e47 100644
--- a/libsolidity/ast/ASTPrinter.cpp
+++ b/libsolidity/ast/ASTPrinter.cpp
@@ -63,7 +63,7 @@ bool ASTPrinter::visit(ContractDefinition const& _node)
bool ASTPrinter::visit(InheritanceSpecifier const& _node)
{
- writeLine("InheritanceSpecifier \"" + _node.name().name() + "\"");
+ writeLine("InheritanceSpecifier");
printSourcePart(_node);
return goDeeper();
}
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index d53f825f..7dd3564d 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -238,7 +238,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition(bool _isLibrary)
ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier()
{
ASTNodeFactory nodeFactory(*this);
- ASTPointer<Identifier> name(parseIdentifier());
+ ASTPointer<UserDefinedTypeName> name(parseUserDefinedTypeName());
vector<ASTPointer<Expression>> arguments;
if (m_scanner->currentToken() == Token::LParen)
{
@@ -533,8 +533,7 @@ ASTPointer<UsingForDirective> Parser::parseUsingDirective()
ASTNodeFactory nodeFactory(*this);
expectToken(Token::Using);
- //@todo this should actually parse a full path.
- ASTPointer<Identifier> library(parseIdentifier());
+ ASTPointer<UserDefinedTypeName> library(parseUserDefinedTypeName());
ASTPointer<TypeName> typeName;
expectToken(Token::For);
if (m_scanner->currentToken() == Token::Mul)
@@ -570,6 +569,20 @@ ASTPointer<Identifier> Parser::parseIdentifier()
return nodeFactory.createNode<Identifier>(expectIdentifierToken());
}
+ASTPointer<UserDefinedTypeName> Parser::parseUserDefinedTypeName()
+{
+ ASTNodeFactory nodeFactory(*this);
+ nodeFactory.markEndPosition();
+ vector<ASTString> identifierPath{*expectIdentifierToken()};
+ while (m_scanner->currentToken() == Token::Period)
+ {
+ m_scanner->next();
+ nodeFactory.markEndPosition();
+ identifierPath.push_back(*expectIdentifierToken());
+ }
+ return nodeFactory.createNode<UserDefinedTypeName>(identifierPath);
+}
+
ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
{
ASTNodeFactory nodeFactory(*this);
@@ -589,18 +602,7 @@ ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
else if (token == Token::Mapping)
type = parseMapping();
else if (token == Token::Identifier)
- {
- ASTNodeFactory nodeFactory(*this);
- nodeFactory.markEndPosition();
- vector<ASTString> identifierPath{*expectIdentifierToken()};
- while (m_scanner->currentToken() == Token::Period)
- {
- m_scanner->next();
- nodeFactory.markEndPosition();
- identifierPath.push_back(*expectIdentifierToken());
- }
- type = nodeFactory.createNode<UserDefinedTypeName>(identifierPath);
- }
+ type = parseUserDefinedTypeName();
else
fatalParserError(string("Expected type name"));
diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h
index 5ff46242..eb1aa587 100644
--- a/libsolidity/parsing/Parser.h
+++ b/libsolidity/parsing/Parser.h
@@ -77,6 +77,7 @@ private:
ASTPointer<UsingForDirective> parseUsingDirective();
ASTPointer<ModifierInvocation> parseModifierInvocation();
ASTPointer<Identifier> parseIdentifier();
+ ASTPointer<UserDefinedTypeName> parseUserDefinedTypeName();
ASTPointer<TypeName> parseTypeName(bool _allowVar);
ASTPointer<Mapping> parseMapping();
ASTPointer<ParameterList> parseParameterList(
diff --git a/test/libsolidity/Imports.cpp b/test/libsolidity/Imports.cpp
index 57239cb9..f0f67785 100644
--- a/test/libsolidity/Imports.cpp
+++ b/test/libsolidity/Imports.cpp
@@ -97,7 +97,7 @@ BOOST_AUTO_TEST_CASE(simple_alias)
{
CompilerStack c;
c.addSource("a", "contract A {}");
- c.addSource("dir/a/b/c", "import \"../../.././a\" as x; contract B { function() { x.A r = x.A(20); } }");
+ c.addSource("dir/a/b/c", "import \"../../.././a\" as x; contract B is x.A { function() { x.A r = x.A(20); } }");
BOOST_CHECK(c.compile());
}