added warning for noninitialized references in storage.

This commit is contained in:
LianaHus 2015-09-29 18:22:02 +02:00
parent 6712437e6b
commit fe2b9a3b3c
4 changed files with 49 additions and 15 deletions

View File

@ -31,13 +31,13 @@ namespace dev
{
namespace solidity
{
struct Error: virtual Exception {};
struct ParserError: virtual Error {};
struct TypeError: virtual Error {};
struct DeclarationError: virtual Error {};
struct DocstringParsingError: virtual Error {};
struct Warning: virtual Error {};
struct CompilerError: virtual Exception {};
struct InternalCompilerError: virtual Exception {};
@ -53,7 +53,6 @@ public:
infos.push_back(std::make_pair(_errMsg, _sourceLocation));
return *this;
}
std::vector<errorSourceLocationInfo> infos;
};

View File

@ -43,8 +43,14 @@ bool TypeChecker::checkTypeRequirements(const ContractDefinition& _contract)
if (m_errors.empty())
throw; // Something is weird here, rather throw again.
}
return m_errors.empty();
bool success = m_errors.empty();
for (auto const& it: m_errors)
if (!dynamic_cast<Warning const*>(it.get()))
{
success = false;
break;
}
return success;
}
TypePointer const& TypeChecker::type(Expression const& _expression) const
@ -443,6 +449,18 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
{
if (_variable.value())
expectType(*_variable.value(), *varType);
else
{
if (auto ref = dynamic_cast<ReferenceType const *>(varType.get()))
if (ref->dataStoredIn(DataLocation::Storage) && _variable.isLocalVariable() && !_variable.isCallableParameter())
{
auto err = make_shared<Warning>();
*err <<
errinfo_sourceLocation(_variable.location()) <<
errinfo_comment("Uninitialized storage pointer. Did you mean '" + varType->toString(true) + " memory'?");
m_errors.push_back(err);
}
}
}
else
{

View File

@ -43,10 +43,10 @@ class TypeChecker: private ASTConstVisitor
{
public:
/// Performs type checking on the given contract and all of its sub-nodes.
/// @returns true iff all checks passed.
/// @returns true iff all checks passed. Note even if all checks passed, errors() can still contain warnings
bool checkTypeRequirements(ContractDefinition const& _contract);
/// @returns the list of errors found during type checking.
/// @returns the list of errors and warnings found during type checking.
std::vector<std::shared_ptr<Error const>> const& errors() const { return m_errors; }
/// @returns the type of an expression and asserts that it is present.
@ -57,6 +57,9 @@ public:
/// Adds a new error to the list of errors.
void typeError(ASTNode const& _node, std::string const& _description);
/// Adds a new warning to the list of errors.
void typeWarning(ASTNode const& _node, std::string const& _description);
/// Adds a new error to the list of errors and throws to abort type checking.
void fatalTypeError(ASTNode const& _node, std::string const& _description);

View File

@ -45,7 +45,7 @@ namespace
{
pair<ASTPointer<SourceUnit>, shared_ptr<Exception const>>
parseAnalyseAndReturnError(string const& _source)
parseAnalyseAndReturnError(string const& _source, bool _warning = false)
{
Parser parser;
ASTPointer<SourceUnit> sourceUnit;
@ -74,7 +74,19 @@ parseAnalyseAndReturnError(string const& _source)
TypeChecker typeChecker;
if (!typeChecker.checkTypeRequirements(*contract))
{
err = typeChecker.errors().front();
for (auto const& firstError: typeChecker.errors())
{
if (!dynamic_pointer_cast<Warning const>(firstError))
{
err = firstError;
break;
}
else if (_warning)
{
err = firstError;
break;
}
}
break;
}
}
@ -101,9 +113,9 @@ ASTPointer<SourceUnit> parseAndAnalyse(string const& _source)
return sourceAndError.first;
}
shared_ptr<Exception const> parseAndAnalyseReturnError(std::string const& _source)
shared_ptr<Exception const> parseAndAnalyseReturnError(std::string const& _source, bool _warning = false)
{
auto sourceAndError = parseAnalyseAndReturnError(_source);
auto sourceAndError = parseAnalyseAndReturnError(_source, _warning);
BOOST_REQUIRE(!!sourceAndError.second);
return sourceAndError.second;
}
@ -119,8 +131,10 @@ static ContractDefinition const* retrieveContract(ASTPointer<SourceUnit> _source
return nullptr;
}
static FunctionTypePointer const& retrieveFunctionBySignature(ContractDefinition const* _contract,
std::string const& _signature)
static FunctionTypePointer const& retrieveFunctionBySignature(
ContractDefinition const* _contract,
std::string const& _signature
)
{
FixedHash<4> hash(dev::sha3(_signature));
return _contract->interfaceFunctions()[hash];
@ -155,8 +169,8 @@ BOOST_AUTO_TEST_CASE(double_stateVariable_declaration)
BOOST_AUTO_TEST_CASE(double_function_declaration)
{
char const* text = "contract test {\n"
" function fun() { var x; }\n"
" function fun() { var x; }\n"
" function fun() { uint x; }\n"
" function fun() { uint x; }\n"
"}\n";
SOLIDITY_CHECK_ERROR_TYPE(parseAndAnalyseReturnError(text), DeclarationError);
}
@ -2333,7 +2347,7 @@ BOOST_AUTO_TEST_CASE(non_initialized_references)
}
}
)";
SOLIDITY_CHECK_ERROR_TYPE(parseAndAnalyseReturnError(text), TypeError);
SOLIDITY_CHECK_ERROR_TYPE(parseAndAnalyseReturnError(text, true), Warning);
}
BOOST_AUTO_TEST_SUITE_END()