diff options
Diffstat (limited to 'libsolidity/analysis')
-rw-r--r-- | libsolidity/analysis/PostTypeChecker.cpp | 3 | ||||
-rw-r--r-- | libsolidity/analysis/StaticAnalyzer.cpp | 45 | ||||
-rw-r--r-- | libsolidity/analysis/StaticAnalyzer.h | 9 | ||||
-rw-r--r-- | libsolidity/analysis/SyntaxChecker.cpp | 17 | ||||
-rw-r--r-- | libsolidity/analysis/SyntaxChecker.h | 4 |
5 files changed, 77 insertions, 1 deletions
diff --git a/libsolidity/analysis/PostTypeChecker.cpp b/libsolidity/analysis/PostTypeChecker.cpp index cae77c74..e8da3ca4 100644 --- a/libsolidity/analysis/PostTypeChecker.cpp +++ b/libsolidity/analysis/PostTypeChecker.cpp @@ -58,6 +58,9 @@ void PostTypeChecker::endVisit(ContractDefinition const&) for (auto declaration: m_constVariables) if (auto identifier = findCycle(declaration)) typeError(declaration->location(), "The value of the constant " + declaration->name() + " has a cyclic dependency via " + identifier->name() + "."); + + m_constVariables.clear(); + m_constVariableDependencies.clear(); } bool PostTypeChecker::visit(VariableDeclaration const& _variable) diff --git a/libsolidity/analysis/StaticAnalyzer.cpp b/libsolidity/analysis/StaticAnalyzer.cpp index 190d2420..369376fa 100644 --- a/libsolidity/analysis/StaticAnalyzer.cpp +++ b/libsolidity/analysis/StaticAnalyzer.cpp @@ -48,13 +48,58 @@ void StaticAnalyzer::endVisit(ContractDefinition const&) bool StaticAnalyzer::visit(FunctionDefinition const& _function) { + if (_function.isImplemented()) + m_currentFunction = &_function; + else + solAssert(!m_currentFunction, ""); + solAssert(m_localVarUseCount.empty(), ""); m_nonPayablePublic = _function.isPublic() && !_function.isPayable(); return true; } void StaticAnalyzer::endVisit(FunctionDefinition const&) { + m_currentFunction = nullptr; m_nonPayablePublic = false; + for (auto const& var: m_localVarUseCount) + if (var.second == 0) + warning(var.first->location(), "Unused local variable"); + m_localVarUseCount.clear(); +} + +bool StaticAnalyzer::visit(Identifier const& _identifier) +{ + if (m_currentFunction) + if (auto var = dynamic_cast<VariableDeclaration const*>(_identifier.annotation().referencedDeclaration)) + { + solAssert(!var->name().empty(), ""); + if (var->isLocalVariable()) + m_localVarUseCount[var] += 1; + } + return true; +} + +bool StaticAnalyzer::visit(VariableDeclaration const& _variable) +{ + if (m_currentFunction) + { + solAssert(_variable.isLocalVariable(), ""); + if (_variable.name() != "") + // This is not a no-op, the entry might pre-exist. + m_localVarUseCount[&_variable] += 0; + } + return true; +} + +bool StaticAnalyzer::visit(Return const& _return) +{ + // If the return has an expression, it counts as + // a "use" of the return parameters. + if (m_currentFunction && _return.expression()) + for (auto const& var: m_currentFunction->returnParameters()) + if (!var->name().empty()) + m_localVarUseCount[var.get()] += 1; + return true; } bool StaticAnalyzer::visit(ExpressionStatement const& _statement) diff --git a/libsolidity/analysis/StaticAnalyzer.h b/libsolidity/analysis/StaticAnalyzer.h index 84342322..ab72e7d9 100644 --- a/libsolidity/analysis/StaticAnalyzer.h +++ b/libsolidity/analysis/StaticAnalyzer.h @@ -61,7 +61,9 @@ private: virtual void endVisit(FunctionDefinition const& _function) override; virtual bool visit(ExpressionStatement const& _statement) override; - + virtual bool visit(VariableDeclaration const& _variable) override; + virtual bool visit(Identifier const& _identifier) override; + virtual bool visit(Return const& _return) override; virtual bool visit(MemberAccess const& _memberAccess) override; ErrorList& m_errors; @@ -71,6 +73,11 @@ private: /// Flag that indicates whether a public function does not contain the "payable" modifier. bool m_nonPayablePublic = false; + + /// Number of uses of each (named) local variable in a function, counter is initialized with zero. + std::map<VariableDeclaration const*, int> m_localVarUseCount; + + FunctionDefinition const* m_currentFunction = nullptr; }; } diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index 89014133..94e82a87 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -32,6 +32,16 @@ bool SyntaxChecker::checkSyntax(ASTNode const& _astRoot) return Error::containsOnlyWarnings(m_errors); } +void SyntaxChecker::warning(SourceLocation const& _location, string const& _description) +{ + auto err = make_shared<Error>(Error::Type::Warning); + *err << + errinfo_sourceLocation(_location) << + errinfo_comment(_description); + + m_errors.push_back(err); +} + void SyntaxChecker::syntaxError(SourceLocation const& _location, std::string const& _description) { auto err = make_shared<Error>(Error::Type::SyntaxError); @@ -148,6 +158,13 @@ bool SyntaxChecker::visit(Break const& _breakStatement) return true; } +bool SyntaxChecker::visit(UnaryOperation const& _operation) +{ + if (_operation.getOperator() == Token::Add) + warning(_operation.location(), "Use of unary + is deprecated."); + return true; +} + bool SyntaxChecker::visit(PlaceholderStatement const&) { m_placeholderFound = true; diff --git a/libsolidity/analysis/SyntaxChecker.h b/libsolidity/analysis/SyntaxChecker.h index 308e128b..8d7dcdd3 100644 --- a/libsolidity/analysis/SyntaxChecker.h +++ b/libsolidity/analysis/SyntaxChecker.h @@ -32,6 +32,7 @@ namespace solidity * The module that performs syntax analysis on the AST: * - whether continue/break is in a for/while loop. * - whether a modifier contains at least one '_' + * - issues deprecation warnings for unary '+' */ class SyntaxChecker: private ASTConstVisitor { @@ -43,6 +44,7 @@ public: private: /// Adds a new error to the list of errors. + void warning(SourceLocation const& _location, std::string const& _description); void syntaxError(SourceLocation const& _location, std::string const& _description); virtual bool visit(SourceUnit const& _sourceUnit) override; @@ -60,6 +62,8 @@ private: virtual bool visit(Continue const& _continueStatement) override; virtual bool visit(Break const& _breakStatement) override; + virtual bool visit(UnaryOperation const& _operation) override; + virtual bool visit(PlaceholderStatement const& _placeholderStatement) override; ErrorList& m_errors; |