mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge branch 'origin/develop' into develop_060
This commit is contained in:
commit
f884373142
@ -115,6 +115,17 @@ defaults:
|
||||
- store_test_results: *store_test_results
|
||||
- store_artifacts: *artifacts_test_results
|
||||
|
||||
- test_ubuntu1904_clang: &test_ubuntu1904_clang
|
||||
docker:
|
||||
- image: ethereum/solidity-buildpack-deps:ubuntu1904-clang
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: build
|
||||
- run: *run_soltest
|
||||
- store_test_results: *store_test_results
|
||||
- store_artifacts: *artifacts_test_results
|
||||
|
||||
- test_ubuntu1904_all: &test_ubuntu1904
|
||||
docker:
|
||||
- image: ethereum/solidity-buildpack-deps:ubuntu1904
|
||||
@ -151,6 +162,11 @@ defaults:
|
||||
requires:
|
||||
- b_ubu
|
||||
|
||||
- workflow_ubuntu1904_clang: &workflow_ubuntu1904_clang
|
||||
<<: *workflow_trigger_on_tags
|
||||
requires:
|
||||
- b_ubu_clang
|
||||
|
||||
- workflow_ubuntu1904_release: &workflow_ubuntu1904_release
|
||||
<<: *workflow_trigger_on_tags
|
||||
requires:
|
||||
@ -280,6 +296,18 @@ jobs:
|
||||
pip install --user z3-solver
|
||||
- run: *run_proofs
|
||||
|
||||
b_ubu_clang: &build_ubuntu1904_clang
|
||||
docker:
|
||||
- image: ethereum/solidity-buildpack-deps:ubuntu1904-clang
|
||||
environment:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
steps:
|
||||
- checkout
|
||||
- run: *run_build
|
||||
- store_artifacts: *artifacts_solc
|
||||
- persist_to_workspace: *artifacts_executables
|
||||
|
||||
b_ubu: &build_ubuntu1904
|
||||
docker:
|
||||
- image: ethereum/solidity-buildpack-deps:ubuntu1904
|
||||
@ -349,11 +377,11 @@ jobs:
|
||||
- run: *run_build
|
||||
|
||||
b_ubu_ossfuzz:
|
||||
<<: *build_ubuntu1904
|
||||
<<: *build_ubuntu1904_clang
|
||||
environment:
|
||||
TERM: xterm
|
||||
CC: /usr/bin/clang-8
|
||||
CXX: /usr/bin/clang++-8
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
CMAKE_OPTIONS: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/libfuzzer.cmake
|
||||
steps:
|
||||
- checkout
|
||||
@ -362,7 +390,7 @@ jobs:
|
||||
- persist_to_workspace: *artifacts_executables_ossfuzz
|
||||
|
||||
t_ubu_ossfuzz: &t_ubu_ossfuzz
|
||||
<<: *test_ubuntu1904
|
||||
<<: *test_ubuntu1904_clang
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
@ -495,6 +523,12 @@ jobs:
|
||||
t_ubu_soltest: &t_ubu_soltest
|
||||
<<: *test_ubuntu1904
|
||||
|
||||
t_ubu_clang_soltest: &t_ubu_clang_soltest
|
||||
<<: *test_ubuntu1904_clang
|
||||
environment:
|
||||
EVM: constantinople
|
||||
OPTIMIZE: 0
|
||||
|
||||
t_ubu_release_soltest: &t_ubu_release_soltest
|
||||
<<: *t_ubu_soltest
|
||||
|
||||
@ -632,6 +666,8 @@ workflows:
|
||||
- b_ubu18: *workflow_trigger_on_tags
|
||||
- t_ubu_cli: *workflow_ubuntu1904
|
||||
- t_ubu_soltest: *workflow_ubuntu1904
|
||||
- b_ubu_clang: *workflow_trigger_on_tags
|
||||
- t_ubu_clang_soltest: *workflow_ubuntu1904_clang
|
||||
|
||||
# Ubuntu fake release build and tests
|
||||
- b_ubu_release: *workflow_trigger_on_tags
|
||||
|
@ -28,7 +28,9 @@ Compiler Features:
|
||||
Bugfixes:
|
||||
|
||||
|
||||
### 0.5.12 (unreleased)
|
||||
### 0.5.13 (unreleased)
|
||||
|
||||
### 0.5.12 (2019-10-01)
|
||||
|
||||
Language Features:
|
||||
* Type Checker: Allow assignment to external function arguments except for reference types.
|
||||
@ -43,7 +45,10 @@ Compiler Features:
|
||||
|
||||
|
||||
Bugfixes:
|
||||
* Fix internal error when popping a dynamic storage array of mappings.
|
||||
* Code Generator: Fix internal error when popping a dynamic storage array of mappings.
|
||||
* Name Resolver: Fix wrong source location when warning on shadowed aliases in import declarations.
|
||||
* Scanner: Fix multi-line natspec comment parsing with triple slashes when file is encoded with CRLF instead of LF.
|
||||
* Type System: Fix arrays of recursive structs.
|
||||
* Yul Optimizer: Fix reordering bug in connection with shifted one and mul/div-instructions in for loop conditions.
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Inherit default options
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/default.cmake")
|
||||
# Disable Z3 and CVC4 since none of the existing fuzzers need them
|
||||
set(USE_Z3 OFF CACHE BOOL "Disable Z3" FORCE)
|
||||
# Enable Z3, disable CVC4
|
||||
set(USE_Z3 ON CACHE BOOL "Enable Z3" FORCE)
|
||||
set(USE_CVC4 OFF CACHE BOOL "Disable CVC4" FORCE)
|
||||
# Build fuzzing binaries
|
||||
set(OSSFUZZ ON CACHE BOOL "Enable fuzzer build" FORCE)
|
||||
|
@ -444,16 +444,16 @@ JSON
|
||||
The JSON format for a contract's interface is given by an array of function and/or event descriptions.
|
||||
A function description is a JSON object with the fields:
|
||||
|
||||
- ``type``: ``"function"``, ``"constructor"``, or ``"fallback"`` (the :ref:`unnamed "default" function <fallback-function>`);
|
||||
- ``name``: the name of the function;
|
||||
- ``type``: ``"function"``, ``"constructor"``, or ``"fallback"`` (the :ref:`unnamed "default" function <fallback-function>`).
|
||||
- ``name``: the name of the function.
|
||||
- ``inputs``: an array of objects, each of which contains:
|
||||
|
||||
* ``name``: the name of the parameter;
|
||||
* ``name``: the name of the parameter.
|
||||
* ``type``: the canonical type of the parameter (more below).
|
||||
* ``components``: used for tuple types (more below).
|
||||
|
||||
- ``outputs``: an array of objects similar to ``inputs``, can be omitted if function doesn't return anything;
|
||||
- ``stateMutability``: a string with one of the following values: ``pure`` (:ref:`specified to not read blockchain state <pure-functions>`), ``view`` (:ref:`specified to not modify the blockchain state <view-functions>`), ``nonpayable`` (function does not accept Ether) and ``payable`` (function accepts Ether);
|
||||
- ``outputs``: an array of objects similar to ``inputs``.
|
||||
- ``stateMutability``: a string with one of the following values: ``pure`` (:ref:`specified to not read blockchain state <pure-functions>`), ``view`` (:ref:`specified to not modify the blockchain state <view-functions>`), ``nonpayable`` (function does not accept Ether) and ``payable`` (function accepts Ether).
|
||||
|
||||
Constructor and fallback function never have ``name`` or ``outputs``. Fallback function doesn't have ``inputs`` either.
|
||||
|
||||
@ -463,10 +463,10 @@ Constructor and fallback function never have ``name`` or ``outputs``. Fallback f
|
||||
An event description is a JSON object with fairly similar fields:
|
||||
|
||||
- ``type``: always ``"event"``
|
||||
- ``name``: the name of the event;
|
||||
- ``name``: the name of the event.
|
||||
- ``inputs``: an array of objects, each of which contains:
|
||||
|
||||
* ``name``: the name of the parameter;
|
||||
* ``name``: the name of the parameter.
|
||||
* ``type``: the canonical type of the parameter (more below).
|
||||
* ``components``: used for tuple types (more below).
|
||||
* ``indexed``: ``true`` if the field is part of the log's topics, ``false`` if it one of the log's data segment.
|
||||
|
@ -750,6 +750,10 @@
|
||||
"bugs": [],
|
||||
"released": "2019-08-12"
|
||||
},
|
||||
"0.5.12": {
|
||||
"bugs": [],
|
||||
"released": "2019-10-01"
|
||||
},
|
||||
"0.5.2": {
|
||||
"bugs": [
|
||||
"SignedArrayStorageCopy",
|
||||
|
@ -37,3 +37,7 @@ add_library(devcore ${sources})
|
||||
target_link_libraries(devcore PUBLIC jsoncpp Boost::boost Boost::filesystem Boost::regex Boost::system)
|
||||
target_include_directories(devcore PUBLIC "${CMAKE_SOURCE_DIR}")
|
||||
add_dependencies(devcore solidity_BuildInfo.h)
|
||||
|
||||
if(SOLC_LINK_STATIC)
|
||||
target_link_libraries(devcore PUBLIC Threads::Threads)
|
||||
endif()
|
||||
|
@ -30,11 +30,6 @@ inline bool isHexDigit(char c)
|
||||
('A' <= c && c <= 'F');
|
||||
}
|
||||
|
||||
inline bool isLineTerminator(char c)
|
||||
{
|
||||
return c == '\n';
|
||||
}
|
||||
|
||||
inline bool isWhiteSpace(char c)
|
||||
{
|
||||
return c == ' ' || c == '\n' || c == '\t' || c == '\r';
|
||||
|
@ -280,6 +280,29 @@ Token Scanner::skipSingleLineComment()
|
||||
return Token::Whitespace;
|
||||
}
|
||||
|
||||
bool Scanner::atEndOfLine() const
|
||||
{
|
||||
return m_char == '\n' || m_char == '\r';
|
||||
}
|
||||
|
||||
bool Scanner::tryScanEndOfLine()
|
||||
{
|
||||
if (m_char == '\n')
|
||||
{
|
||||
advance();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_char == '\r')
|
||||
{
|
||||
if (advance() && m_char == '\n')
|
||||
advance();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Token Scanner::scanSingleLineDocComment()
|
||||
{
|
||||
LiteralScope literal(this, LITERAL_TYPE_COMMENT);
|
||||
@ -289,7 +312,7 @@ Token Scanner::scanSingleLineDocComment()
|
||||
|
||||
while (!isSourcePastEndOfInput())
|
||||
{
|
||||
if (isLineTerminator(m_char))
|
||||
if (tryScanEndOfLine())
|
||||
{
|
||||
// check if next line is also a documentation comment
|
||||
skipWhitespace();
|
||||
@ -303,7 +326,6 @@ Token Scanner::scanSingleLineDocComment()
|
||||
}
|
||||
else
|
||||
break; // next line is not a documentation comment, we are done
|
||||
|
||||
}
|
||||
else if (isUnicodeLinebreak())
|
||||
// Any line terminator that is not '\n' is considered to end the
|
||||
@ -343,13 +365,13 @@ Token Scanner::scanMultiLineDocComment()
|
||||
bool endFound = false;
|
||||
bool charsAdded = false;
|
||||
|
||||
while (isWhiteSpace(m_char) && !isLineTerminator(m_char))
|
||||
while (isWhiteSpace(m_char) && !atEndOfLine())
|
||||
advance();
|
||||
|
||||
while (!isSourcePastEndOfInput())
|
||||
{
|
||||
//handle newlines in multline comments
|
||||
if (isLineTerminator(m_char))
|
||||
if (atEndOfLine())
|
||||
{
|
||||
skipWhitespace();
|
||||
if (!m_source->isPastEndOfInput(1) && m_source->get(0) == '*' && m_source->get(1) == '*')
|
||||
@ -664,10 +686,12 @@ void Scanner::scanToken()
|
||||
bool Scanner::scanEscape()
|
||||
{
|
||||
char c = m_char;
|
||||
advance();
|
||||
|
||||
// Skip escaped newlines.
|
||||
if (isLineTerminator(c))
|
||||
if (tryScanEndOfLine())
|
||||
return true;
|
||||
advance();
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\'': // fall through
|
||||
|
@ -219,6 +219,12 @@ private:
|
||||
Token skipSingleLineComment();
|
||||
Token skipMultiLineComment();
|
||||
|
||||
/// Tests if current source position is CR, LF or CRLF.
|
||||
bool atEndOfLine() const;
|
||||
|
||||
/// Tries to consume CR, LF or CRLF line terminators and returns success or failure.
|
||||
bool tryScanEndOfLine();
|
||||
|
||||
void scanDecimalDigits();
|
||||
Token scanNumber(char _charSeen = 0);
|
||||
std::tuple<Token, unsigned, unsigned> scanIdentifierOrKeyword();
|
||||
|
@ -91,13 +91,13 @@ bool NameAndTypeResolver::performImports(SourceUnit& _sourceUnit, map<string, So
|
||||
if (!imp->symbolAliases().empty())
|
||||
for (auto const& alias: imp->symbolAliases())
|
||||
{
|
||||
auto declarations = scope->second->resolveName(alias.first->name(), false);
|
||||
auto declarations = scope->second->resolveName(alias.symbol->name(), false);
|
||||
if (declarations.empty())
|
||||
{
|
||||
m_errorReporter.declarationError(
|
||||
imp->location(),
|
||||
"Declaration \"" +
|
||||
alias.first->name() +
|
||||
alias.symbol->name() +
|
||||
"\" not found in \"" +
|
||||
path +
|
||||
"\" (referenced as \"" +
|
||||
@ -109,7 +109,7 @@ bool NameAndTypeResolver::performImports(SourceUnit& _sourceUnit, map<string, So
|
||||
else
|
||||
for (Declaration const* declaration: declarations)
|
||||
if (!DeclarationRegistrationHelper::registerDeclaration(
|
||||
target, *declaration, alias.second.get(), &imp->location(), true, false, m_errorReporter
|
||||
target, *declaration, alias.alias.get(), &alias.location, true, false, m_errorReporter
|
||||
))
|
||||
error = true;
|
||||
}
|
||||
@ -523,7 +523,7 @@ bool DeclarationRegistrationHelper::registerDeclaration(
|
||||
{
|
||||
if (dynamic_cast<MagicVariableDeclaration const*>(shadowedDeclaration))
|
||||
_errorReporter.warning(
|
||||
_declaration.location(),
|
||||
*_errorLocation,
|
||||
"This declaration shadows a builtin symbol."
|
||||
);
|
||||
else
|
||||
|
@ -280,22 +280,31 @@ private:
|
||||
class ImportDirective: public Declaration
|
||||
{
|
||||
public:
|
||||
struct SymbolAlias
|
||||
{
|
||||
ASTPointer<Identifier> symbol;
|
||||
ASTPointer<ASTString> alias;
|
||||
SourceLocation location;
|
||||
};
|
||||
|
||||
using SymbolAliasList = std::vector<SymbolAlias>;
|
||||
|
||||
ImportDirective(
|
||||
SourceLocation const& _location,
|
||||
ASTPointer<ASTString> const& _path,
|
||||
ASTPointer<ASTString> const& _unitAlias,
|
||||
std::vector<std::pair<ASTPointer<Identifier>, ASTPointer<ASTString>>>&& _symbolAliases
|
||||
SymbolAliasList _symbolAliases
|
||||
):
|
||||
Declaration(_location, _unitAlias),
|
||||
m_path(_path),
|
||||
m_symbolAliases(_symbolAliases)
|
||||
m_symbolAliases(move(_symbolAliases))
|
||||
{ }
|
||||
|
||||
void accept(ASTVisitor& _visitor) override;
|
||||
void accept(ASTConstVisitor& _visitor) const override;
|
||||
|
||||
ASTString const& path() const { return *m_path; }
|
||||
std::vector<std::pair<ASTPointer<Identifier>, ASTPointer<ASTString>>> const& symbolAliases() const
|
||||
SymbolAliasList const& symbolAliases() const
|
||||
{
|
||||
return m_symbolAliases;
|
||||
}
|
||||
@ -306,9 +315,9 @@ public:
|
||||
private:
|
||||
ASTPointer<ASTString> m_path;
|
||||
/// The aliases for the specific symbols to import. If non-empty import the specific symbols.
|
||||
/// If the second component is empty, import the identifier unchanged.
|
||||
/// If the `alias` component is empty, import the identifier unchanged.
|
||||
/// If both m_unitAlias and m_symbolAlias are empty, import all symbols into the current scope.
|
||||
std::vector<std::pair<ASTPointer<Identifier>, ASTPointer<ASTString>>> m_symbolAliases;
|
||||
SymbolAliasList m_symbolAliases;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -243,9 +243,9 @@ bool ASTJsonConverter::visit(ImportDirective const& _node)
|
||||
for (auto const& symbolAlias: _node.symbolAliases())
|
||||
{
|
||||
Json::Value tuple(Json::objectValue);
|
||||
solAssert(symbolAlias.first, "");
|
||||
tuple["foreign"] = nodeId(*symbolAlias.first);
|
||||
tuple["local"] = symbolAlias.second ? Json::Value(*symbolAlias.second) : Json::nullValue;
|
||||
solAssert(symbolAlias.symbol, "");
|
||||
tuple["foreign"] = nodeId(*symbolAlias.symbol);
|
||||
tuple["local"] = symbolAlias.alias ? Json::Value(*symbolAlias.alias) : Json::nullValue;
|
||||
symbolAliases.append(tuple);
|
||||
}
|
||||
attributes.emplace_back("symbolAliases", std::move(symbolAliases));
|
||||
|
@ -2086,6 +2086,8 @@ unsigned StructType::calldataOffsetOfMember(std::string const& _member) const
|
||||
|
||||
bool StructType::isDynamicallyEncoded() const
|
||||
{
|
||||
if (recursive())
|
||||
return true;
|
||||
solAssert(interfaceType(false).get(), "");
|
||||
for (auto t: memoryMemberTypes())
|
||||
{
|
||||
|
@ -186,7 +186,7 @@ ASTPointer<ImportDirective> Parser::parseImportDirective()
|
||||
expectToken(Token::Import);
|
||||
ASTPointer<ASTString> path;
|
||||
ASTPointer<ASTString> unitAlias = make_shared<string>();
|
||||
vector<pair<ASTPointer<Identifier>, ASTPointer<ASTString>>> symbolAliases;
|
||||
ImportDirective::SymbolAliasList symbolAliases;
|
||||
|
||||
if (m_scanner->currentToken() == Token::StringLiteral)
|
||||
{
|
||||
@ -204,14 +204,16 @@ ASTPointer<ImportDirective> Parser::parseImportDirective()
|
||||
m_scanner->next();
|
||||
while (true)
|
||||
{
|
||||
ASTPointer<Identifier> id = parseIdentifier();
|
||||
ASTPointer<ASTString> alias;
|
||||
SourceLocation aliasLocation = SourceLocation{position(), endPosition(), source()};
|
||||
ASTPointer<Identifier> id = parseIdentifier();
|
||||
if (m_scanner->currentToken() == Token::As)
|
||||
{
|
||||
expectToken(Token::As);
|
||||
aliasLocation = SourceLocation{position(), endPosition(), source()};
|
||||
alias = expectIdentifierToken();
|
||||
}
|
||||
symbolAliases.emplace_back(move(id), move(alias));
|
||||
symbolAliases.emplace_back(ImportDirective::SymbolAlias{move(id), move(alias), aliasLocation});
|
||||
if (m_scanner->currentToken() != Token::Comma)
|
||||
break;
|
||||
m_scanner->next();
|
||||
|
@ -568,7 +568,7 @@ BOOST_AUTO_TEST_CASE(multiline_comment_at_eos)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(regular_line_break_in_single_line_comment)
|
||||
{
|
||||
for (auto const& nl: {"\r", "\n"})
|
||||
for (auto const& nl: {"\r", "\n", "\r\n"})
|
||||
{
|
||||
Scanner scanner(CharStream("// abc " + string(nl) + " def ", ""));
|
||||
BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), "");
|
||||
@ -595,7 +595,7 @@ BOOST_AUTO_TEST_CASE(irregular_line_breaks_in_single_line_comment)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(regular_line_breaks_in_single_line_doc_comment)
|
||||
{
|
||||
for (auto const& nl: {"\r", "\n"})
|
||||
for (auto const& nl: {"\r", "\n", "\r\n"})
|
||||
{
|
||||
Scanner scanner(CharStream("/// abc " + string(nl) + " def ", ""));
|
||||
BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), "abc ");
|
||||
@ -605,6 +605,22 @@ BOOST_AUTO_TEST_CASE(regular_line_breaks_in_single_line_doc_comment)
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(regular_line_breaks_in_multiline_doc_comment)
|
||||
{
|
||||
// Test CR, LF, CRLF as line valid terminators for code comments.
|
||||
// Any accepted non-LF is being canonicalized to LF.
|
||||
for (auto const& nl : {"\r"s, "\n"s, "\r\n"s})
|
||||
{
|
||||
Scanner scanner{CharStream{"/// Hello" + nl + "/// World" + nl + "ident", ""}};
|
||||
auto const& lit = scanner.currentCommentLiteral();
|
||||
BOOST_CHECK_EQUAL(lit, "Hello\n World");
|
||||
BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), "Hello\n World");
|
||||
BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier);
|
||||
BOOST_CHECK_EQUAL(scanner.currentLiteral(), "ident");
|
||||
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(irregular_line_breaks_in_single_line_doc_comment)
|
||||
{
|
||||
for (auto const& nl: {"\v", "\f", "\xE2\x80\xA8", "\xE2\x80\xA9"})
|
||||
@ -622,9 +638,9 @@ BOOST_AUTO_TEST_CASE(irregular_line_breaks_in_single_line_doc_comment)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(regular_line_breaks_in_strings)
|
||||
{
|
||||
for (auto const& nl: {"\n", "\r"})
|
||||
for (auto const& nl: {"\r"s, "\n"s, "\r\n"s})
|
||||
{
|
||||
Scanner scanner(CharStream("\"abc " + string(nl) + " def\"", ""));
|
||||
Scanner scanner(CharStream("\"abc " + nl + " def\"", ""));
|
||||
BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal);
|
||||
BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
|
||||
BOOST_CHECK_EQUAL(scanner.currentLiteral(), "def");
|
||||
|
@ -0,0 +1,12 @@
|
||||
contract Test {
|
||||
struct RecursiveStruct {
|
||||
RecursiveStruct[] vals;
|
||||
}
|
||||
|
||||
function func() public pure {
|
||||
RecursiveStruct[1] memory val = [ RecursiveStruct(new RecursiveStruct[](42)) ];
|
||||
assert(val[0].vals.length == 42);
|
||||
}
|
||||
}
|
||||
// -----
|
||||
// func() ->
|
@ -5,4 +5,4 @@ library A {}
|
||||
==== Source: c ====
|
||||
import {A} from "./a"; import {A} from "./b";
|
||||
// ----
|
||||
// DeclarationError: (c:23-45): Identifier already declared.
|
||||
// DeclarationError: (c:31-32): Identifier already declared.
|
||||
|
@ -3,4 +3,4 @@ contract C {}
|
||||
==== Source: b ====
|
||||
import {C as msg} from "B.sol";
|
||||
// ----
|
||||
// Warning: (B.sol:0-13): This declaration shadows a builtin symbol.
|
||||
// Warning: (b:13-16): This declaration shadows a builtin symbol.
|
||||
|
@ -7,5 +7,5 @@ contract C {
|
||||
// ----
|
||||
// Warning: (B.sol:0-15): This declaration shadows a builtin symbol.
|
||||
// Warning: (B.sol:16-32): This declaration shadows a builtin symbol.
|
||||
// Warning: (B.sol:0-15): This declaration shadows a builtin symbol.
|
||||
// Warning: (B.sol:16-32): This declaration shadows a builtin symbol.
|
||||
// Warning: (b:8-11): This declaration shadows a builtin symbol.
|
||||
// Warning: (b:13-18): This declaration shadows a builtin symbol.
|
||||
|
@ -5,4 +5,4 @@ library A {}
|
||||
==== Source: c ====
|
||||
import {A} from "./a"; import {A} from "./b";
|
||||
// ----
|
||||
// DeclarationError: (c:23-45): Identifier already declared.
|
||||
// DeclarationError: (c:31-32): Identifier already declared.
|
||||
|
@ -0,0 +1,10 @@
|
||||
contract Test {
|
||||
struct RecursiveStruct {
|
||||
RecursiveStruct[] vals;
|
||||
}
|
||||
|
||||
function func() private pure {
|
||||
RecursiveStruct[1] memory val;
|
||||
val;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user