Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add "forbid-implicit-declarations" lint rule #244

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions verilog/analysis/checkers/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ cc_library(
":explicit_task_lifetime_rule",
":forbid_consecutive_null_statements_rule",
":forbid_defparam_rule",
":forbid_implicit_declarations_rule",
":forbidden_anonymous_enums_rule",
":forbidden_anonymous_structs_unions_rule",
":forbidden_macro_rule",
Expand Down Expand Up @@ -357,6 +358,47 @@ cc_test(
],
)

cc_library(
name = "forbid_implicit_declarations_rule",
srcs = ["forbid_implicit_declarations_rule.cc"],
hdrs = ["forbid_implicit_declarations_rule.h"],
deps = [
"//common/analysis:citation",
"//common/analysis:lint_rule_status",
"//common/analysis:text_structure_lint_rule",
"//common/analysis/matcher",
"//common/analysis/matcher:bound_symbol_manager",
"//common/analysis/matcher:core_matchers",
"//common/analysis/matcher:matcher_builders",
"//common/text:symbol",
"//common/text:tree_context_visitor",
"//common/util:auto_pop_stack",
"//verilog/CST:identifier",
"//verilog/CST:verilog_matchers",
"//verilog/analysis:descriptions",
"//verilog/analysis:lint_rule_registry",
"//verilog/analysis:symbol_table",
"//verilog/analysis:verilog_project",
"@com_google_absl//absl/strings",
],
alwayslink = 1,
)

cc_test(
name = "forbid_implicit_declarations_rule_test",
srcs = ["forbid_implicit_declarations_rule_test.cc"],
deps = [
":forbid_implicit_declarations_rule",
"//common/analysis:linter_test_utils",
"//common/analysis:text_structure_linter_test_utils",
"//common/text:symbol",
"//verilog/CST:verilog_nonterminals",
"//verilog/CST:verilog_treebuilder_utils",
"//verilog/analysis:verilog_analyzer",
"@com_google_googletest//:gtest_main",
],
)

cc_library(
name = "mismatched_labels_rule",
srcs = ["mismatched_labels_rule.cc"],
Expand Down
123 changes: 123 additions & 0 deletions verilog/analysis/checkers/forbid_implicit_declarations_rule.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Copyright 2017-2020 The Verible Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "verilog/analysis/checkers/forbid_implicit_declarations_rule.h"

#include <set>
#include <string>

#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "common/analysis/citation.h"
#include "common/analysis/lint_rule_status.h"
#include "common/analysis/matcher/bound_symbol_manager.h"
#include "common/text/symbol.h"
#include "common/text/syntax_tree_context.h"
#include "common/text/tree_context_visitor.h"
#include "verilog/CST/identifier.h"
#include "verilog/analysis/descriptions.h"
#include "verilog/analysis/lint_rule_registry.h"
#include "verilog/analysis/symbol_table.h"

namespace verilog {
namespace analysis {

using verible::GetStyleGuideCitation;
using verible::LintRuleStatus;
using verible::LintViolation;
using verible::SyntaxTreeContext;

// Register ForbidImplicitDeclarationsRule
VERILOG_REGISTER_LINT_RULE(ForbidImplicitDeclarationsRule);

// forbid-implicit-net-declarations?
absl::string_view ForbidImplicitDeclarationsRule::Name() {
return "forbid-implicit-declarations";
}
const char ForbidImplicitDeclarationsRule::kTopic[] = "implicit-declarations";
const char ForbidImplicitDeclarationsRule::kMessage[] =
"Nets must be declared explicitly.";

std::string ForbidImplicitDeclarationsRule::GetDescription(
DescriptionType description_type) {
return absl::StrCat(
"Checks that there are no occurrences of "
"implicitly declared nets.");
}

void ForbidImplicitDeclarationsRule::Lint(
const verible::TextStructureView& text_structure,
absl::string_view filename) {
SymbolTable symbol_table(nullptr);

ParsedVerilogSourceFile* src =
new ParsedVerilogSourceFile("internal", &text_structure);
// Already parsed, calling to ensure that VerilogSourceFile internals are in
// correct state
const auto status = src->Parse();
CHECK_EQ(status.ok(), true);

auto diagnostics = BuildSymbolTable(*src, &symbol_table);
for (const auto& itr : diagnostics) {
CHECK_EQ(itr.ok(), true);
}
// Skipping resolving stage as implicit declarations are pre-resolved
// during symbol table building stage

auto& violations = this->violations_;
symbol_table.Root().ApplyPreOrder([&violations, &text_structure](
const SymbolTableNode& node) {
for (const auto& itr : node.Value().local_references_to_bind) {
ABSL_DIE_IF_NULL(itr.LastLeaf())
->ApplyPreOrder([&violations,
&text_structure](const ReferenceComponent& node) {
// Skip unresolved symbols (implicit declarations are pre-resolved)
if (node.resolved_symbol == nullptr) {
return;
}

const auto& resolved_symbol_node =
*ABSL_DIE_IF_NULL(node.resolved_symbol);
const auto& resolved_symbol = resolved_symbol_node.Value();
const auto& resolved_symbol_identifier =
*ABSL_DIE_IF_NULL(resolved_symbol_node.Key());

// Skip pre-resolved symbols that have explicit declarations
if (resolved_symbol.declared_type.implicit == false) {
return;
}

// Only report reference that caused implicit declarations
if (node.identifier.begin() == resolved_symbol_identifier.begin()) {
const auto offset = std::distance(
text_structure.Contents().begin(), node.identifier.begin());
CHECK_GE(offset, 0);
auto range =
text_structure.TokenRangeSpanningOffsets(offset, offset);
auto token = range.begin();
CHECK(token != text_structure.TokenStream().end());
const auto& token_info = *token;
violations.insert(LintViolation(token_info, kMessage));
}
});
}
});
}

LintRuleStatus ForbidImplicitDeclarationsRule::Report() const {
return LintRuleStatus(violations_, Name(), GetStyleGuideCitation(kTopic));
}

} // namespace analysis
} // namespace verilog
70 changes: 70 additions & 0 deletions verilog/analysis/checkers/forbid_implicit_declarations_rule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2017-2020 The Verible Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef VERIBLE_VERILOG_ANALYSIS_CHECKERS_FORBID_IMPLICIT_DECLARATIONS_RULE_H_
#define VERIBLE_VERILOG_ANALYSIS_CHECKERS_FORBID_IMPLICIT_DECLARATIONS_RULE_H_

#include <set>
#include <string>

#include "common/analysis/lint_rule_status.h"
#include "common/analysis/matcher/core_matchers.h"
#include "common/analysis/matcher/matcher.h"
#include "common/analysis/matcher/matcher_builders.h"
#include "common/analysis/text_structure_lint_rule.h"
#include "common/text/symbol.h"
#include "common/text/syntax_tree_context.h"
#include "common/text/tree_context_visitor.h"
#include "common/util/auto_pop_stack.h"
#include "verilog/CST/verilog_matchers.h" // IWYU pragma: keep
#include "verilog/analysis/descriptions.h"
#include "verilog/analysis/symbol_table.h"
#include "verilog/analysis/verilog_project.h"

namespace verilog {
namespace analysis {

// ForbidImplicitDeclarationsRule detect implicitly declared nets
class ForbidImplicitDeclarationsRule : public verible::TextStructureLintRule {
//public ScopeTreeVisitor {
public:
using rule_type = verible::TextStructureLintRule;
static absl::string_view Name();

// Returns the description of the rule implemented formatted for either the
// helper flag or markdown depending on the parameter type.
static std::string GetDescription(DescriptionType);

// Analyze text structure for violations.
void Lint(const verible::TextStructureView& text_structure,
absl::string_view filename) override;

verible::LintRuleStatus Report() const override;

private:

private:
// Link to style guide rule.
static const char kTopic[];

// Diagnostic message.
static const char kMessage[];

std::set<verible::LintViolation> violations_;
};

} // namespace analysis
} // namespace verilog

#endif // VERIBLE_VERILOG_ANALYSIS_CHECKERS_FORBID_IMPLICIT_DECLARATIONS_RULE_H_
Loading