aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/contributing.rst2
-rw-r--r--docs/miscellaneous.rst6
-rw-r--r--docs/using-the-compiler.rst24
-rw-r--r--libdevcore/IndentedWriter.cpp2
-rw-r--r--libdevcore/StringUtils.cpp2
-rw-r--r--libevmasm/Assembly.cpp16
-rw-r--r--libevmasm/BlockDeduplicator.cpp14
-rw-r--r--libevmasm/ControlFlowGraph.cpp2
-rw-r--r--libevmasm/SimplificationRules.cpp2
-rw-r--r--liblangutil/Exceptions.h2
-rw-r--r--liblll/CodeFragment.cpp6
-rw-r--r--liblll/Compiler.cpp20
-rw-r--r--libsolidity/analysis/ContractLevelChecker.cpp10
-rw-r--r--libsolidity/analysis/TypeChecker.cpp76
-rw-r--r--libsolidity/ast/AST.cpp2
-rw-r--r--libsolidity/ast/ASTJsonConverter.cpp12
-rw-r--r--libsolidity/ast/Types.cpp107
-rw-r--r--libsolidity/codegen/ABIFunctions.cpp4
-rw-r--r--libsolidity/codegen/ContractCompiler.cpp12
-rw-r--r--libsolidity/parsing/Parser.cpp4
-rw-r--r--test/InteractiveTests.h63
-rw-r--r--test/boostTest.cpp58
-rw-r--r--test/libsolidity/syntaxTests/nameAndTypeResolution/313_fixed_type_size_capabilities.sol3
-rw-r--r--test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol15
-rw-r--r--test/libsolidity/syntaxTests/types/too_small_negative_numbers.sol1
-rw-r--r--test/tools/isoltest.cpp62
26 files changed, 277 insertions, 250 deletions
diff --git a/docs/contributing.rst b/docs/contributing.rst
index 43b2fd38..12dea7d1 100644
--- a/docs/contributing.rst
+++ b/docs/contributing.rst
@@ -61,7 +61,7 @@ New features and bugfixes should be added to the ``Changelog.md`` file: please
follow the style of previous entries, when applicable.
Finally, please make sure you respect the `coding style
-<https://raw.githubusercontent.com/ethereum/solidity/develop/CODING_STYLE.md>`_
+<https://github.com/ethereum/solidity/blob/develop/CODING_STYLE.md>`_
for this project. Also, even though we do CI testing, please test your code and
ensure that it builds locally before submitting a pull request.
diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst
index 017d5b81..5a6f3875 100644
--- a/docs/miscellaneous.rst
+++ b/docs/miscellaneous.rst
@@ -224,9 +224,9 @@ for displaying the current position in the source code inside a debugger
or for breakpoint handling.
Both kinds of source mappings use integer identifiers to refer to source files.
-These are regular array indices into a list of source files usually called
-``"sourceList"``, which is part of the combined-json and the output of
-the json / npm compiler.
+The identifier of a source file is stored in
+``output['sources'][sourceName]['id']`` where ``output`` is the output of the
+standard-json compiler interface parsed as JSON.
.. note ::
In the case of instructions that are not associated with any particular source file,
diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst
index 9ba6caa5..4749ef1f 100644
--- a/docs/using-the-compiler.rst
+++ b/docs/using-the-compiler.rst
@@ -200,15 +200,27 @@ Input Description
"MyLib": "0x123123..."
}
}
- // The following can be used to select desired outputs.
- // If this field is omitted, then the compiler loads and does type checking, but will not generate any outputs apart from errors.
- // The first level key is the file name and the second is the contract name, where empty contract name refers to the file itself,
- // while the star refers to all of the contracts.
+ // The following can be used to select desired outputs based
+ // on file and contract names.
+ // If this field is omitted, then the compiler loads and does type checking,
+ // but will not generate any outputs apart from errors.
+ // The first level key is the file name and the second level key is the contract name.
+ // An empty contract name is used for outputs that are not tied to a contract
+ // but to the whole source file like the AST.
+ // A star as contract name refers to all contracts in the file.
+ // Similarly, a star as a file name matches all files.
+ // To select all outputs the compiler can possibly generate, use
+ // "outputSelection: { "*": { "*": [ "*" ], "": [ "*" ] } }"
+ // but note that this might slow down the compilation process needlessly.
//
// The available output types are as follows:
- // abi - ABI
+ //
+ // File level (needs empty string as contract name):
// ast - AST of all source files
// legacyAST - legacy AST of all source files
+ //
+ // Contract level (needs the contract name or "*"):
+ // abi - ABI
// devdoc - Developer documentation (natspec)
// userdoc - User documentation (natspec)
// metadata - Metadata
@@ -281,7 +293,7 @@ Output Description
// This contains the file-level outputs. In can be limited/filtered by the outputSelection settings.
sources: {
"sourceFile.sol": {
- // Identifier (used in source maps)
+ // Identifier of the source (used in source maps)
id: 1,
// The AST object
ast: {},
diff --git a/libdevcore/IndentedWriter.cpp b/libdevcore/IndentedWriter.cpp
index 96aaf0fa..1a85957b 100644
--- a/libdevcore/IndentedWriter.cpp
+++ b/libdevcore/IndentedWriter.cpp
@@ -36,7 +36,7 @@ string IndentedWriter::format() const
void IndentedWriter::newLine()
{
if (!m_lines.back().contents.empty())
- m_lines.push_back({ string(), m_lines.back().indentation });
+ m_lines.emplace_back(Line{string(), m_lines.back().indentation});
}
void IndentedWriter::indent()
diff --git a/libdevcore/StringUtils.cpp b/libdevcore/StringUtils.cpp
index 50bf7cce..196ac8f7 100644
--- a/libdevcore/StringUtils.cpp
+++ b/libdevcore/StringUtils.cpp
@@ -91,7 +91,7 @@ string dev::quotedAlternativesList(vector<string> const& suggestions)
vector<string> quotedSuggestions;
for (auto& suggestion: suggestions)
- quotedSuggestions.push_back("\"" + suggestion + "\"");
+ quotedSuggestions.emplace_back("\"" + suggestion + "\"");
return joinHumanReadable(quotedSuggestions, ", ", " or ");
}
diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp
index 29d9846d..231eed93 100644
--- a/libevmasm/Assembly.cpp
+++ b/libevmasm/Assembly.cpp
@@ -83,7 +83,7 @@ AssemblyItem const& Assembly::append(AssemblyItem const& _i)
{
assertThrow(m_deposit >= 0, AssemblyException, "Stack underflow.");
m_deposit += _i.deposit();
- m_items.push_back(_i);
+ m_items.emplace_back(_i);
if (m_items.back().location().isEmpty() && !m_currentSourceLocation.isEmpty())
m_items.back().setLocation(m_currentSourceLocation);
return back();
@@ -353,14 +353,14 @@ AssemblyItem Assembly::namedTag(string const& _name)
assertThrow(!_name.empty(), AssemblyException, "Empty named tag.");
if (!m_namedTags.count(_name))
m_namedTags[_name] = size_t(newTag().data());
- return AssemblyItem(Tag, m_namedTags.at(_name));
+ return AssemblyItem{Tag, m_namedTags.at(_name)};
}
AssemblyItem Assembly::newPushLibraryAddress(string const& _identifier)
{
h256 h(dev::keccak256(_identifier));
m_libraries[h] = _identifier;
- return AssemblyItem(PushLibraryAddress, h);
+ return AssemblyItem{PushLibraryAddress, h};
}
Assembly& Assembly::optimise(bool _enable, EVMVersion _evmVersion, bool _isCreation, size_t _runs)
@@ -415,14 +415,14 @@ map<u256, u256> Assembly::optimiseInternal(
if (_settings.runJumpdestRemover)
{
- JumpdestRemover jumpdestOpt(m_items);
+ JumpdestRemover jumpdestOpt{m_items};
if (jumpdestOpt.optimise(_tagsReferencedFromOutside))
count++;
}
if (_settings.runPeephole)
{
- PeepholeOptimiser peepOpt(m_items);
+ PeepholeOptimiser peepOpt{m_items};
while (peepOpt.optimise())
{
count++;
@@ -433,7 +433,7 @@ map<u256, u256> Assembly::optimiseInternal(
// This only modifies PushTags, we have to run again to actually remove code.
if (_settings.runDeduplicate)
{
- BlockDeduplicator dedup(m_items);
+ BlockDeduplicator dedup{m_items};
if (dedup.deduplicate())
{
tagReplacements.insert(dedup.replacedTags().begin(), dedup.replacedTags().end());
@@ -448,13 +448,13 @@ map<u256, u256> Assembly::optimiseInternal(
// function types that can be stored in storage.
AssemblyItems optimisedItems;
- bool usesMSize = (find(m_items.begin(), m_items.end(), AssemblyItem(Instruction::MSIZE)) != m_items.end());
+ bool usesMSize = (find(m_items.begin(), m_items.end(), AssemblyItem{Instruction::MSIZE}) != m_items.end());
auto iter = m_items.begin();
while (iter != m_items.end())
{
KnownState emptyState;
- CommonSubexpressionEliminator eliminator(emptyState);
+ CommonSubexpressionEliminator eliminator{emptyState};
auto orig = iter;
iter = eliminator.feedItems(iter, m_items.end(), usesMSize);
bool shouldReplace = false;
diff --git a/libevmasm/BlockDeduplicator.cpp b/libevmasm/BlockDeduplicator.cpp
index b7c69531..ca439925 100644
--- a/libevmasm/BlockDeduplicator.cpp
+++ b/libevmasm/BlockDeduplicator.cpp
@@ -41,7 +41,7 @@ bool BlockDeduplicator::deduplicate()
// Virtual tag that signifies "the current block" and which is used to optimise loops.
// We abort if this virtual tag actually exists.
- AssemblyItem pushSelf(PushTag, u256(-4));
+ AssemblyItem pushSelf{PushTag, u256(-4)};
if (
std::count(m_items.cbegin(), m_items.cend(), pushSelf.tag()) ||
std::count(m_items.cbegin(), m_items.cend(), pushSelf.pushTag())
@@ -55,17 +55,17 @@ bool BlockDeduplicator::deduplicate()
// To compare recursive loops, we have to already unify PushTag opcodes of the
// block's own tag.
- AssemblyItem pushFirstTag(pushSelf);
- AssemblyItem pushSecondTag(pushSelf);
+ AssemblyItem pushFirstTag{pushSelf};
+ AssemblyItem pushSecondTag{pushSelf};
if (_i < m_items.size() && m_items.at(_i).type() == Tag)
pushFirstTag = m_items.at(_i).pushTag();
if (_j < m_items.size() && m_items.at(_j).type() == Tag)
pushSecondTag = m_items.at(_j).pushTag();
- BlockIterator first(m_items.begin() + _i, m_items.end(), &pushFirstTag, &pushSelf);
- BlockIterator second(m_items.begin() + _j, m_items.end(), &pushSecondTag, &pushSelf);
- BlockIterator end(m_items.end(), m_items.end());
+ BlockIterator first{m_items.begin() + _i, m_items.end(), &pushFirstTag, &pushSelf};
+ BlockIterator second{m_items.begin() + _j, m_items.end(), &pushSecondTag, &pushSelf};
+ BlockIterator end{m_items.end(), m_items.end()};
if (first != end && (*first).type() == Tag)
++first;
@@ -126,7 +126,7 @@ BlockDeduplicator::BlockIterator& BlockDeduplicator::BlockIterator::operator++()
{
if (it == end)
return *this;
- if (SemanticInformation::altersControlFlow(*it) && *it != AssemblyItem(Instruction::JUMPI))
+ if (SemanticInformation::altersControlFlow(*it) && *it != AssemblyItem{Instruction::JUMPI})
it = end;
else
{
diff --git a/libevmasm/ControlFlowGraph.cpp b/libevmasm/ControlFlowGraph.cpp
index d62f5436..e82c2903 100644
--- a/libevmasm/ControlFlowGraph.cpp
+++ b/libevmasm/ControlFlowGraph.cpp
@@ -87,7 +87,7 @@ void ControlFlowGraph::splitBlocks()
m_blocks[id].begin = index;
}
if (item.type() == PushTag)
- m_blocks[id].pushedTags.push_back(BlockId(item.data()));
+ m_blocks[id].pushedTags.emplace_back(item.data());
if (SemanticInformation::altersControlFlow(item))
{
m_blocks[id].end = index + 1;
diff --git a/libevmasm/SimplificationRules.cpp b/libevmasm/SimplificationRules.cpp
index 1dce5f1e..b812cecc 100644
--- a/libevmasm/SimplificationRules.cpp
+++ b/libevmasm/SimplificationRules.cpp
@@ -209,7 +209,7 @@ ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern, SourceLocation c
item = _pattern.toAssemblyItem(_location);
}
for (auto const& arg: _pattern.arguments())
- arguments.push_back(ExpressionTemplate(arg, _location));
+ arguments.emplace_back(arg, _location);
}
string ExpressionTemplate::toString() const
diff --git a/liblangutil/Exceptions.h b/liblangutil/Exceptions.h
index 5ad31ab2..22deb058 100644
--- a/liblangutil/Exceptions.h
+++ b/liblangutil/Exceptions.h
@@ -105,7 +105,7 @@ class SecondarySourceLocation
public:
SecondarySourceLocation& append(std::string const& _errMsg, SourceLocation const& _sourceLocation)
{
- infos.push_back(std::make_pair(_errMsg, _sourceLocation));
+ infos.emplace_back(_errMsg, _sourceLocation);
return *this;
}
diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp
index b32f14e9..63d8da3d 100644
--- a/liblll/CodeFragment.cpp
+++ b/liblll/CodeFragment.cpp
@@ -353,7 +353,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
if (j.tag() || j.which() != sp::utree_type::symbol_type)
error<InvalidMacroArgs>();
auto sr = j.get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::symbol_type>>();
- args.push_back(string(sr.begin(), sr.end()));
+ args.emplace_back(sr.begin(), sr.end());
}
else if (ii == 3)
{
@@ -464,9 +464,9 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
if (c++)
{
if (us == "LLL" && c == 1)
- code.push_back(CodeFragment(i, ns, m_readFile));
+ code.emplace_back(i, ns, m_readFile);
else
- code.push_back(CodeFragment(i, _s, m_readFile));
+ code.emplace_back(i, _s, m_readFile);
}
auto requireSize = [&](unsigned s) { if (code.size() != s) error<IncorrectParameterCount>(us); };
auto requireMinSize = [&](unsigned s) { if (code.size() < s) error<IncorrectParameterCount>(us); };
diff --git a/liblll/Compiler.cpp b/liblll/Compiler.cpp
index f944adbd..6296cbcf 100644
--- a/liblll/Compiler.cpp
+++ b/liblll/Compiler.cpp
@@ -46,22 +46,22 @@ bytes dev::lll::compileLLL(string const& _src, dev::solidity::EVMVersion _evmVer
{
if (_errors)
{
- _errors->push_back("Parse error.");
- _errors->push_back(boost::diagnostic_information(_e));
+ _errors->emplace_back("Parse error.");
+ _errors->emplace_back(boost::diagnostic_information(_e));
}
}
catch (std::exception const& _e)
{
if (_errors)
{
- _errors->push_back("Parse exception.");
- _errors->push_back(boost::diagnostic_information(_e));
+ _errors->emplace_back("Parse exception.");
+ _errors->emplace_back(boost::diagnostic_information(_e));
}
}
catch (...)
{
if (_errors)
- _errors->push_back("Internal compiler exception.");
+ _errors->emplace_back("Internal compiler exception.");
}
return bytes();
}
@@ -84,22 +84,22 @@ std::string dev::lll::compileLLLToAsm(std::string const& _src, EVMVersion _evmVe
{
if (_errors)
{
- _errors->push_back("Parse error.");
- _errors->push_back(boost::diagnostic_information(_e));
+ _errors->emplace_back("Parse error.");
+ _errors->emplace_back(boost::diagnostic_information(_e));
}
}
catch (std::exception const& _e)
{
if (_errors)
{
- _errors->push_back("Parse exception.");
- _errors->push_back(boost::diagnostic_information(_e));
+ _errors->emplace_back("Parse exception.");
+ _errors->emplace_back(boost::diagnostic_information(_e));
}
}
catch (...)
{
if (_errors)
- _errors->push_back("Internal compiler exception.");
+ _errors->emplace_back("Internal compiler exception.");
}
return string();
}
diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp
index 6dc564de..526caff9 100644
--- a/libsolidity/analysis/ContractLevelChecker.cpp
+++ b/libsolidity/analysis/ContractLevelChecker.cpp
@@ -227,7 +227,7 @@ void ContractLevelChecker::checkAbstractFunctions(ContractDefinition const& _con
return _type->hasEqualParameterTypes(*_funAndFlag.first);
});
if (it == overloads.end())
- overloads.push_back(make_pair(_type, _implemented));
+ overloads.emplace_back(_type, _implemented);
else if (it->second)
{
if (!_implemented)
@@ -409,8 +409,8 @@ void ContractLevelChecker::checkExternalTypeClashes(ContractDefinition const& _c
auto functionType = make_shared<FunctionType>(*f);
// under non error circumstances this should be true
if (functionType->interfaceFunctionType())
- externalDeclarations[functionType->externalSignature()].push_back(
- make_pair(f, functionType->asCallableFunction(false))
+ externalDeclarations[functionType->externalSignature()].emplace_back(
+ f, functionType->asCallableFunction(false)
);
}
for (VariableDeclaration const* v: contract->stateVariables())
@@ -419,8 +419,8 @@ void ContractLevelChecker::checkExternalTypeClashes(ContractDefinition const& _c
auto functionType = make_shared<FunctionType>(*v);
// under non error circumstances this should be true
if (functionType->interfaceFunctionType())
- externalDeclarations[functionType->externalSignature()].push_back(
- make_pair(v, functionType->asCallableFunction(false))
+ externalDeclarations[functionType->externalSignature()].emplace_back(
+ v, functionType->asCallableFunction(false)
);
}
}
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 1c9f1956..d41415c0 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -935,30 +935,32 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
var.accept(*this);
if (!valueComponentType->isImplicitlyConvertibleTo(*var.annotation().type))
{
+ auto errorMsg = "Type " +
+ valueComponentType->toString() +
+ " is not implicitly convertible to expected type " +
+ var.annotation().type->toString();
if (
valueComponentType->category() == Type::Category::RationalNumber &&
dynamic_cast<RationalNumberType const&>(*valueComponentType).isFractional() &&
valueComponentType->mobileType()
)
- m_errorReporter.typeError(
- _statement.location(),
- "Type " +
- valueComponentType->toString() +
- " is not implicitly convertible to expected type " +
- var.annotation().type->toString() +
- ". Try converting to type " +
- valueComponentType->mobileType()->toString() +
- " or use an explicit conversion."
- );
+ {
+ if (var.annotation().type->operator==(*valueComponentType->mobileType()))
+ m_errorReporter.typeError(
+ _statement.location(),
+ errorMsg + ", but it can be explicitly converted."
+ );
+ else
+ m_errorReporter.typeError(
+ _statement.location(),
+ errorMsg +
+ ". Try converting to type " +
+ valueComponentType->mobileType()->toString() +
+ " or use an explicit conversion."
+ );
+ }
else
- m_errorReporter.typeError(
- _statement.location(),
- "Type " +
- valueComponentType->toString() +
- " is not implicitly convertible to expected type " +
- var.annotation().type->toString() +
- "."
- );
+ m_errorReporter.typeError(_statement.location(), errorMsg + ".");
}
}
}
@@ -2331,30 +2333,32 @@ bool TypeChecker::expectType(Expression const& _expression, Type const& _expecte
_expression.accept(*this);
if (!type(_expression)->isImplicitlyConvertibleTo(_expectedType))
{
+ auto errorMsg = "Type " +
+ type(_expression)->toString() +
+ " is not implicitly convertible to expected type " +
+ _expectedType.toString();
if (
type(_expression)->category() == Type::Category::RationalNumber &&
dynamic_pointer_cast<RationalNumberType const>(type(_expression))->isFractional() &&
type(_expression)->mobileType()
)
- m_errorReporter.typeError(
- _expression.location(),
- "Type " +
- type(_expression)->toString() +
- " is not implicitly convertible to expected type " +
- _expectedType.toString() +
- ". Try converting to type " +
- type(_expression)->mobileType()->toString() +
- " or use an explicit conversion."
- );
+ {
+ if (_expectedType.operator==(*type(_expression)->mobileType()))
+ m_errorReporter.typeError(
+ _expression.location(),
+ errorMsg + ", but it can be explicitly converted."
+ );
+ else
+ m_errorReporter.typeError(
+ _expression.location(),
+ errorMsg +
+ ". Try converting to type " +
+ type(_expression)->mobileType()->toString() +
+ " or use an explicit conversion."
+ );
+ }
else
- m_errorReporter.typeError(
- _expression.location(),
- "Type " +
- type(_expression)->toString() +
- " is not implicitly convertible to expected type " +
- _expectedType.toString() +
- "."
- );
+ m_errorReporter.typeError(_expression.location(), errorMsg + ".");
return false;
}
return true;
diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp
index 3ae6bd6d..5779e4ad 100644
--- a/libsolidity/ast/AST.cpp
+++ b/libsolidity/ast/AST.cpp
@@ -198,7 +198,7 @@ vector<pair<FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::inter
{
signaturesSeen.insert(functionSignature);
FixedHash<4> hash(dev::keccak256(functionSignature));
- m_interfaceFunctionList->push_back(make_pair(hash, fun));
+ m_interfaceFunctionList->emplace_back(hash, fun);
}
}
}
diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp
index e92134a8..1a2b3345 100644
--- a/libsolidity/ast/ASTJsonConverter.cpp
+++ b/libsolidity/ast/ASTJsonConverter.cpp
@@ -234,7 +234,7 @@ bool ASTJsonConverter::visit(ImportDirective const& _node)
make_pair(m_legacy ? "SourceUnit" : "sourceUnit", nodeId(*_node.annotation().sourceUnit)),
make_pair("scope", idOrNull(_node.scope()))
};
- attributes.push_back(make_pair("unitAlias", _node.name()));
+ attributes.emplace_back("unitAlias", _node.name());
Json::Value symbolAliases(Json::arrayValue);
for (auto const& symbolAlias: _node.symbolAliases())
{
@@ -244,7 +244,7 @@ bool ASTJsonConverter::visit(ImportDirective const& _node)
tuple["local"] = symbolAlias.second ? Json::Value(*symbolAlias.second) : Json::nullValue;
symbolAliases.append(tuple);
}
- attributes.push_back(make_pair("symbolAliases", std::move(symbolAliases)));
+ attributes.emplace_back("symbolAliases", std::move(symbolAliases));
setJsonNode(_node, "ImportDirective", std::move(attributes));
return false;
}
@@ -357,7 +357,7 @@ bool ASTJsonConverter::visit(VariableDeclaration const& _node)
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
};
if (m_inEvent)
- attributes.push_back(make_pair("indexed", _node.isIndexed()));
+ attributes.emplace_back("indexed", _node.isIndexed());
setJsonNode(_node, "VariableDeclaration", std::move(attributes));
return false;
}
@@ -647,11 +647,11 @@ bool ASTJsonConverter::visit(FunctionCall const& _node)
};
if (m_legacy)
{
- attributes.push_back(make_pair("isStructConstructorCall", _node.annotation().kind == FunctionCallKind::StructConstructorCall));
- attributes.push_back(make_pair("type_conversion", _node.annotation().kind == FunctionCallKind::TypeConversion));
+ attributes.emplace_back("isStructConstructorCall", _node.annotation().kind == FunctionCallKind::StructConstructorCall);
+ attributes.emplace_back("type_conversion", _node.annotation().kind == FunctionCallKind::TypeConversion);
}
else
- attributes.push_back(make_pair("kind", functionCallKind(_node.annotation().kind)));
+ attributes.emplace_back("kind", functionCallKind(_node.annotation().kind));
appendExpressionAttributes(attributes, _node.annotation());
setJsonNode(_node, "FunctionCall", std::move(attributes));
return false;
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index f5a38747..c35dde3c 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -125,6 +125,22 @@ bool fitsPrecisionBase2(bigint const& _mantissa, uint32_t _expBase2)
return fitsPrecisionBaseX(_mantissa, 1.0, _expBase2);
}
+/// Checks whether _value fits into IntegerType _type.
+bool fitsIntegerType(bigint const& _value, IntegerType const& _type)
+{
+ return (_type.minValue() <= _value) && (_value <= _type.maxValue());
+}
+
+/// Checks whether _value fits into _bits bits when having 1 bit as the sign bit
+/// if _signed is true.
+bool fitsIntoBits(bigint const& _value, unsigned _bits, bool _signed)
+{
+ return fitsIntegerType(_value, IntegerType(
+ _bits,
+ _signed ? IntegerType::Modifier::Signed : IntegerType::Modifier::Unsigned
+ ));
+}
+
}
void StorageOffsets::computeOffsets(TypePointers const& _types)
@@ -446,7 +462,7 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ContractDefinition
continue;
FunctionTypePointer fun = FunctionType(*function, false).asCallableFunction(true, true);
if (_type.isImplicitlyConvertibleTo(*fun->selfType()))
- members.push_back(MemberList::Member(function->name(), fun, function));
+ members.emplace_back(function->name(), fun, function);
}
}
return members;
@@ -963,27 +979,21 @@ BoolResult RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo)
if (isFractional())
return false;
IntegerType const& targetType = dynamic_cast<IntegerType const&>(_convertTo);
- if (m_value == rational(0))
- return true;
- unsigned forSignBit = (targetType.isSigned() ? 1 : 0);
- if (m_value > rational(0))
- {
- if (m_value.numerator() <= (u256(-1) >> (256 - targetType.numBits() + forSignBit)))
- return true;
- return false;
- }
- if (targetType.isSigned())
- {
- if (-m_value.numerator() <= (u256(1) << (targetType.numBits() - forSignBit)))
- return true;
- }
- return false;
+ return fitsIntegerType(m_value.numerator(), targetType);
}
case Category::FixedPoint:
{
- if (auto fixed = fixedPointType())
- return fixed->isImplicitlyConvertibleTo(_convertTo);
- return false;
+ FixedPointType const& targetType = dynamic_cast<FixedPointType const&>(_convertTo);
+ // Store a negative number into an unsigned.
+ if (isNegative() && !targetType.isSigned())
+ return false;
+ if (!isFractional())
+ return (targetType.minIntegerValue() <= m_value) && (m_value <= targetType.maxIntegerValue());
+ rational value = m_value * pow(bigint(10), targetType.fractionalDigits());
+ // Need explicit conversion since truncation will occur.
+ if (value.denominator() != 1)
+ return false;
+ return fitsIntoBits(value.numerator(), targetType.numBits(), targetType.isSigned());
}
case Category::FixedBytes:
return (m_value == rational(0)) || (m_compatibleBytesType && *m_compatibleBytesType == _convertTo);
@@ -1811,23 +1821,23 @@ MemberList::MemberMap ArrayType::nativeMembers(ContractDefinition const*) const
MemberList::MemberMap members;
if (!isString())
{
- members.push_back({"length", make_shared<IntegerType>(256)});
+ members.emplace_back("length", make_shared<IntegerType>(256));
if (isDynamicallySized() && location() == DataLocation::Storage)
{
- members.push_back({"push", make_shared<FunctionType>(
+ members.emplace_back("push", make_shared<FunctionType>(
TypePointers{baseType()},
TypePointers{make_shared<IntegerType>(256)},
strings{string()},
strings{string()},
isByteArray() ? FunctionType::Kind::ByteArrayPush : FunctionType::Kind::ArrayPush
- )});
- members.push_back({"pop", make_shared<FunctionType>(
+ ));
+ members.emplace_back("pop", make_shared<FunctionType>(
TypePointers{},
TypePointers{},
strings{string()},
strings{string()},
FunctionType::Kind::ArrayPop
- )});
+ ));
}
}
return members;
@@ -1956,21 +1966,17 @@ MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const* _con
break;
}
if (!functionWithEqualArgumentsFound)
- members.push_back(MemberList::Member(
- function->name(),
- functionType,
- function
- ));
+ members.emplace_back(function->name(), functionType, function);
}
}
else if (!m_contract.isLibrary())
{
for (auto const& it: m_contract.interfaceFunctions())
- members.push_back(MemberList::Member(
+ members.emplace_back(
it.second->declaration().name(),
it.second->asCallableFunction(m_contract.isLibrary()),
&it.second->declaration()
- ));
+ );
}
return members;
}
@@ -1998,7 +2004,7 @@ vector<tuple<VariableDeclaration const*, u256, unsigned>> ContractType::stateVar
vector<tuple<VariableDeclaration const*, u256, unsigned>> variablesAndOffsets;
for (size_t index = 0; index < variables.size(); ++index)
if (auto const* offset = offsets.offset(index))
- variablesAndOffsets.push_back(make_tuple(variables[index], offset->first, offset->second));
+ variablesAndOffsets.emplace_back(variables[index], offset->first, offset->second);
return variablesAndOffsets;
}
@@ -2088,10 +2094,10 @@ MemberList::MemberMap StructType::nativeMembers(ContractDefinition const*) const
// Skip all mapping members if we are not in storage.
if (location() != DataLocation::Storage && !type->canLiveOutsideStorage())
continue;
- members.push_back(MemberList::Member(
+ members.emplace_back(
variable->name(),
copyForLocationIfReference(type),
- variable.get())
+ variable.get()
);
}
return members;
@@ -2428,7 +2434,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
if (auto mappingType = dynamic_cast<MappingType const*>(returnType.get()))
{
m_parameterTypes.push_back(mappingType->keyType());
- m_parameterNames.push_back("");
+ m_parameterNames.emplace_back("");
returnType = mappingType->valueType();
}
else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType.get()))
@@ -2437,7 +2443,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
// Return byte arrays as whole.
break;
returnType = arrayType->baseType();
- m_parameterNames.push_back("");
+ m_parameterNames.emplace_back("");
m_parameterTypes.push_back(make_shared<IntegerType>(256));
}
else
@@ -2468,7 +2474,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
DataLocation::Memory,
returnType
));
- m_returnParameterNames.push_back("");
+ m_returnParameterNames.emplace_back("");
}
}
@@ -2837,14 +2843,11 @@ MemberList::MemberMap FunctionType::nativeMembers(ContractDefinition const*) con
{
MemberList::MemberMap members;
if (m_kind == Kind::External)
- members.push_back(MemberList::Member(
- "selector",
- make_shared<FixedBytesType>(4)
- ));
+ members.emplace_back("selector", make_shared<FixedBytesType>(4));
if (m_kind != Kind::BareDelegateCall)
{
if (isPayable())
- members.push_back(MemberList::Member(
+ members.emplace_back(
"value",
make_shared<FunctionType>(
parseElementaryTypeVector({"uint"}),
@@ -2858,10 +2861,10 @@ MemberList::MemberMap FunctionType::nativeMembers(ContractDefinition const*) con
m_gasSet,
m_valueSet
)
- ));
+ );
}
if (m_kind != Kind::Creation)
- members.push_back(MemberList::Member(
+ members.emplace_back(
"gas",
make_shared<FunctionType>(
parseElementaryTypeVector({"uint"}),
@@ -2875,7 +2878,7 @@ MemberList::MemberMap FunctionType::nativeMembers(ContractDefinition const*) con
m_gasSet,
m_valueSet
)
- ));
+ );
return members;
}
default:
@@ -3203,24 +3206,24 @@ MemberList::MemberMap TypeType::nativeMembers(ContractDefinition const* _current
if (contract.isLibrary())
for (FunctionDefinition const* function: contract.definedFunctions())
if (function->isVisibleAsLibraryMember())
- members.push_back(MemberList::Member(
+ members.emplace_back(
function->name(),
FunctionType(*function).asCallableFunction(true),
function
- ));
+ );
if (isBase)
{
// We are accessing the type of a base contract, so add all public and protected
// members. Note that this does not add inherited functions on purpose.
for (Declaration const* decl: contract.inheritableMembers())
- members.push_back(MemberList::Member(decl->name(), decl->type(), decl));
+ members.emplace_back(decl->name(), decl->type(), decl);
}
else
{
for (auto const& stru: contract.definedStructs())
- members.push_back(MemberList::Member(stru->name(), stru->type(), stru));
+ members.emplace_back(stru->name(), stru->type(), stru);
for (auto const& enu: contract.definedEnums())
- members.push_back(MemberList::Member(enu->name(), enu->type(), enu));
+ members.emplace_back(enu->name(), enu->type(), enu);
}
}
else if (m_actualType->category() == Category::Enum)
@@ -3228,7 +3231,7 @@ MemberList::MemberMap TypeType::nativeMembers(ContractDefinition const* _current
EnumDefinition const& enumDef = dynamic_cast<EnumType const&>(*m_actualType).enumDefinition();
auto enumType = make_shared<EnumType>(enumDef);
for (ASTPointer<EnumValue> const& enumValue: enumDef.members())
- members.push_back(MemberList::Member(enumValue->name(), enumType));
+ members.emplace_back(enumValue->name(), enumType);
}
return members;
}
@@ -3293,7 +3296,7 @@ MemberList::MemberMap ModuleType::nativeMembers(ContractDefinition const*) const
MemberList::MemberMap symbols;
for (auto const& symbolName: m_sourceUnit.annotation().exportedSymbols)
for (Declaration const* symbol: symbolName.second)
- symbols.push_back(MemberList::Member(symbolName.first, symbol->type(), symbol));
+ symbols.emplace_back(symbolName.first, symbol->type(), symbol);
return symbols;
}
diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp
index b02623de..5000131c 100644
--- a/libsolidity/codegen/ABIFunctions.cpp
+++ b/libsolidity/codegen/ABIFunctions.cpp
@@ -141,8 +141,8 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
vector<string> valueNamesLocal;
for (size_t j = 0; j < sizeOnStack; j++)
{
- valueNamesLocal.push_back("value" + to_string(stackPos));
- valueReturnParams.push_back("value" + to_string(stackPos));
+ valueNamesLocal.emplace_back("value" + to_string(stackPos));
+ valueReturnParams.emplace_back("value" + to_string(stackPos));
stackPos++;
}
bool dynamic = decodingTypes[i]->isDynamicallyEncoded();
diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp
index 79c53a1c..67876721 100644
--- a/libsolidity/codegen/ContractCompiler.cpp
+++ b/libsolidity/codegen/ContractCompiler.cpp
@@ -721,14 +721,14 @@ bool ContractCompiler::visit(WhileStatement const& _whileStatement)
eth::AssemblyItem loopStart = m_context.newTag();
eth::AssemblyItem loopEnd = m_context.newTag();
- m_breakTags.push_back({loopEnd, m_context.stackHeight()});
+ m_breakTags.emplace_back(loopEnd, m_context.stackHeight());
m_context << loopStart;
if (_whileStatement.isDoWhile())
{
eth::AssemblyItem condition = m_context.newTag();
- m_continueTags.push_back({condition, m_context.stackHeight()});
+ m_continueTags.emplace_back(condition, m_context.stackHeight());
_whileStatement.body().accept(*this);
@@ -739,7 +739,7 @@ bool ContractCompiler::visit(WhileStatement const& _whileStatement)
}
else
{
- m_continueTags.push_back({loopStart, m_context.stackHeight()});
+ m_continueTags.emplace_back(loopStart, m_context.stackHeight());
compileExpression(_whileStatement.condition());
m_context << Instruction::ISZERO;
m_context.appendConditionalJumpTo(loopEnd);
@@ -770,8 +770,8 @@ bool ContractCompiler::visit(ForStatement const& _forStatement)
if (_forStatement.initializationExpression())
_forStatement.initializationExpression()->accept(*this);
- m_breakTags.push_back({loopEnd, m_context.stackHeight()});
- m_continueTags.push_back({loopNext, m_context.stackHeight()});
+ m_breakTags.emplace_back(loopEnd, m_context.stackHeight());
+ m_continueTags.emplace_back(loopNext, m_context.stackHeight());
m_context << loopStart;
// if there is no terminating condition in for, default is to always be true
@@ -997,7 +997,7 @@ void ContractCompiler::appendModifierOrFunctionCode()
if (codeBlock)
{
- m_returnTags.push_back({m_context.newTag(), m_context.stackHeight()});
+ m_returnTags.emplace_back(m_context.newTag(), m_context.stackHeight());
codeBlock->accept(*this);
solAssert(!m_returnTags.empty(), "");
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index 6cab7be3..0b4eca7d 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -170,7 +170,7 @@ ASTPointer<ImportDirective> Parser::parseImportDirective()
expectToken(Token::As);
alias = expectIdentifierToken();
}
- symbolAliases.push_back(make_pair(move(id), move(alias)));
+ symbolAliases.emplace_back(move(id), move(alias));
if (m_scanner->currentToken() != Token::Comma)
break;
m_scanner->next();
@@ -1690,7 +1690,7 @@ Parser::IndexAccessedPath Parser::parseIndexAccessedPath()
index = parseExpression();
SourceLocation indexLocation = iap.path.front()->location();
indexLocation.end = endPosition();
- iap.indices.push_back(make_pair(index, indexLocation));
+ iap.indices.emplace_back(index, indexLocation);
expectToken(Token::RBrack);
}
diff --git a/test/InteractiveTests.h b/test/InteractiveTests.h
new file mode 100644
index 00000000..be076059
--- /dev/null
+++ b/test/InteractiveTests.h
@@ -0,0 +1,63 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include <test/TestCase.h>
+#include <test/libsolidity/ASTJSONTest.h>
+#include <test/libsolidity/SyntaxTest.h>
+#include <test/libsolidity/SMTCheckerJSONTest.h>
+#include <test/libyul/YulOptimizerTest.h>
+#include <test/libyul/ObjectCompilerTest.h>
+
+#include <boost/filesystem.hpp>
+
+namespace dev
+{
+namespace solidity
+{
+namespace test
+{
+
+/** Container for all information regarding a testsuite */
+struct Testsuite
+{
+ char const* title;
+ boost::filesystem::path const path;
+ boost::filesystem::path const subpath;
+ bool smt;
+ bool ipc;
+ TestCase::TestCaseCreator testCaseCreator;
+};
+
+
+/// Array of testsuits that can be run interactively as well as automatically
+Testsuite const g_interactiveTestsuites[] = {
+/*
+ Title Path Subpath SMT IPC Creator function */
+ {"Yul Optimizer", "libyul", "yulOptimizerTests", false, false, &yul::test::YulOptimizerTest::create},
+ {"Yul Object Compiler", "libyul", "objectCompiler", false, false, &yul::test::ObjectCompilerTest::create},
+ {"Syntax", "libsolidity", "syntaxTests", false, false, &SyntaxTest::create},
+ {"JSON AST", "libsolidity", "ASTJSON", false, false, &ASTJSONTest::create},
+ {"SMT Checker", "libsolidity", "smtCheckerTests", true, false, &SyntaxTest::create},
+ {"SMT Checker JSON", "libsolidity", "smtCheckerTestsJSON", true, false, &SMTCheckerTest::create}
+};
+
+}
+}
+}
+
diff --git a/test/boostTest.cpp b/test/boostTest.cpp
index cff0f5c0..d6e75cb9 100644
--- a/test/boostTest.cpp
+++ b/test/boostTest.cpp
@@ -35,16 +35,13 @@
#pragma GCC diagnostic pop
+#include <test/InteractiveTests.h>
#include <test/Options.h>
-#include <test/libsolidity/ASTJSONTest.h>
-#include <test/libsolidity/SyntaxTest.h>
-#include <test/libsolidity/SMTCheckerJSONTest.h>
-#include <test/libyul/YulOptimizerTest.h>
-#include <test/libyul/ObjectCompilerTest.h>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem.hpp>
+#include <string>
using namespace boost::unit_test;
using namespace dev::solidity::test;
@@ -129,46 +126,26 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] )
master_test_suite_t& master = framework::master_test_suite();
master.p_name.value = "SolidityTests";
dev::test::Options::get().validate();
- solAssert(registerTests(
- master,
- dev::test::Options::get().testPath / "libsolidity",
- "syntaxTests",
- SyntaxTest::create
- ) > 0, "no syntax tests found");
- solAssert(registerTests(
- master,
- dev::test::Options::get().testPath / "libsolidity",
- "ASTJSON",
- ASTJSONTest::create
- ) > 0, "no JSON AST tests found");
- solAssert(registerTests(
- master,
- dev::test::Options::get().testPath / "libyul",
- "yulOptimizerTests",
- yul::test::YulOptimizerTest::create
- ) > 0, "no Yul Optimizer tests found");
- solAssert(registerTests(
- master,
- dev::test::Options::get().testPath / "libyul",
- "objectCompiler",
- yul::test::ObjectCompilerTest::create
- ) > 0, "no Yul Object compiler tests found");
- if (!dev::test::Options::get().disableSMT)
+
+ // Include the interactive tests in the automatic tests as well
+ for (auto const& ts: g_interactiveTestsuites)
{
- solAssert(registerTests(
- master,
- dev::test::Options::get().testPath / "libsolidity",
- "smtCheckerTests",
- SyntaxTest::create
- ) > 0, "no SMT checker tests found");
+ auto const& options = dev::test::Options::get();
+
+ if (ts.smt && options.disableSMT)
+ continue;
+
+ if (ts.ipc && options.disableIPC)
+ continue;
solAssert(registerTests(
master,
- dev::test::Options::get().testPath / "libsolidity",
- "smtCheckerTestsJSON",
- SMTCheckerTest::create
- ) > 0, "no SMT checker JSON tests found");
+ options.testPath / ts.path,
+ ts.subpath,
+ ts.testCaseCreator
+ ) > 0, std::string("no ") + ts.title + " tests found");
}
+
if (dev::test::Options::get().disableIPC)
{
for (auto suite: {
@@ -189,6 +166,7 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] )
})
removeTestSuite(suite);
}
+
if (dev::test::Options::get().disableSMT)
removeTestSuite("SMTChecker");
diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/313_fixed_type_size_capabilities.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/313_fixed_type_size_capabilities.sol
index 441cf81e..295cf4ea 100644
--- a/test/libsolidity/syntaxTests/nameAndTypeResolution/313_fixed_type_size_capabilities.sol
+++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/313_fixed_type_size_capabilities.sol
@@ -10,4 +10,5 @@ contract test {
}
}
// ----
-// Warning: (20-707): Function state mutability can be restricted to pure
+// TypeError: (153-250): Type rational_const 9208...(70 digits omitted)...7637 / 1000...(71 digits omitted)...0000 is not implicitly convertible to expected type ufixed256x77, but it can be explicitly converted.
+// TypeError: (470-566): Type rational_const -933...(70 digits omitted)...0123 / 1000...(70 digits omitted)...0000 is not implicitly convertible to expected type fixed256x76, but it can be explicitly converted.
diff --git a/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol b/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol
new file mode 100644
index 00000000..ca50e03b
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol
@@ -0,0 +1,15 @@
+contract C {
+ function literalToUFixed() public pure {
+ ufixed8x2 a = 0.10;
+ ufixed8x2 b = 0.00;
+ ufixed8x2 c = 2.55;
+ a; b; c;
+ }
+ function literalToFixed() public pure {
+ fixed8x1 a = 0.1;
+ fixed8x1 b = 12.7;
+ fixed8x1 c = -12.8;
+ a; b; c;
+ }
+}
+// ----
diff --git a/test/libsolidity/syntaxTests/types/too_small_negative_numbers.sol b/test/libsolidity/syntaxTests/types/too_small_negative_numbers.sol
index 66bd9a8e..f86ffcdd 100644
--- a/test/libsolidity/syntaxTests/types/too_small_negative_numbers.sol
+++ b/test/libsolidity/syntaxTests/types/too_small_negative_numbers.sol
@@ -2,3 +2,4 @@ contract C {
fixed8x80 a = -1e-100;
}
// ----
+// TypeError: (29-36): Type rational_const -1 / 1000...(93 digits omitted)...0000 is not implicitly convertible to expected type fixed8x80, but it can be explicitly converted.
diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp
index 13585887..e5578045 100644
--- a/test/tools/isoltest.cpp
+++ b/test/tools/isoltest.cpp
@@ -19,11 +19,7 @@
#include <test/Common.h>
#include <test/libsolidity/AnalysisFramework.h>
-#include <test/libsolidity/SyntaxTest.h>
-#include <test/libsolidity/ASTJSONTest.h>
-#include <test/libsolidity/SMTCheckerJSONTest.h>
-#include <test/libyul/YulOptimizerTest.h>
-#include <test/libyul/ObjectCompilerTest.h>
+#include <test/InteractiveTests.h>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/replace.hpp>
@@ -380,59 +376,13 @@ Allowed options)",
TestStats global_stats{0, 0};
// Actually run the tests.
- // If you add new tests here, you also have to add them in boostTest.cpp
- if (auto stats = runTestSuite("Syntax", testPath / "libsolidity", "syntaxTests", SyntaxTest::create, formatted))
- global_stats += *stats;
- else
- return 1;
-
- if (auto stats = runTestSuite("JSON AST", testPath / "libsolidity", "ASTJSON", ASTJSONTest::create, formatted))
- global_stats += *stats;
- else
- return 1;
-
- if (auto stats = runTestSuite(
- "Yul Optimizer",
- testPath / "libyul",
- "yulOptimizerTests",
- yul::test::YulOptimizerTest::create,
- formatted
- ))
- global_stats += *stats;
- else
- return 1;
-
- if (auto stats = runTestSuite(
- "Yul Object Compiler",
- testPath / "libyul",
- "objectCompiler",
- yul::test::ObjectCompilerTest::create,
- formatted
- ))
- global_stats += *stats;
- else
- return 1;
-
- if (!disableSMT)
+ // Interactive tests are added in InteractiveTests.h
+ for (auto const& ts: g_interactiveTestsuites)
{
- if (auto stats = runTestSuite(
- "SMT Checker",
- testPath / "libsolidity",
- "smtCheckerTests",
- SyntaxTest::create,
- formatted
- ))
- global_stats += *stats;
- else
- return 1;
+ if (ts.smt && disableSMT)
+ continue;
- if (auto stats = runTestSuite(
- "SMT Checker JSON",
- testPath / "libsolidity",
- "smtCheckerTestsJSON",
- SMTCheckerTest::create,
- formatted
- ))
+ if (auto stats = runTestSuite(ts.title, testPath / ts.path, ts.subpath, ts.testCaseCreator, formatted))
global_stats += *stats;
else
return 1;