Skip to content

Commit 900b32a

Browse files
committed
[flang] Add options -W[no-]unused-dummy-argument and -W[no-]unused-variable
1 parent 2077d40 commit 900b32a

File tree

14 files changed

+311
-6
lines changed

14 files changed

+311
-6
lines changed

flang/include/flang/Semantics/symbol.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,10 +293,13 @@ class EntityDetails : public WithBindName {
293293
void set_isDummy(bool value = true) { isDummy_ = value; }
294294
bool isFuncResult() const { return isFuncResult_; }
295295
void set_funcResult(bool x) { isFuncResult_ = x; }
296+
bool isUsed() const { return isUsed_; }
297+
void set_isUsed() { isUsed_ = true; }
296298

297299
private:
298300
bool isDummy_{false};
299301
bool isFuncResult_{false};
302+
bool isUsed_{false};
300303
const DeclTypeSpec *type_{nullptr};
301304
friend llvm::raw_ostream &operator<<(
302305
llvm::raw_ostream &, const EntityDetails &);

flang/include/flang/Support/Fortran-features.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
5454
PolymorphicActualAllocatableOrPointerToMonomorphicDummy, RelaxedPureDummy,
5555
UndefinableAsynchronousOrVolatileActual, AutomaticInMainProgram, PrintCptr,
5656
SavedLocalInSpecExpr, PrintNamelist, AssumedRankPassedToNonAssumedRank,
57-
IgnoreIrrelevantAttributes, Unsigned)
57+
IgnoreIrrelevantAttributes, Unsigned, UnusedDummyArgument, UnusedVariable)
5858

5959
// Portability and suspicious usage warnings
6060
ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,

flang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -932,10 +932,24 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
932932
for (const auto &wArg : wArgs) {
933933
if (wArg == "error") {
934934
res.setWarnAsErr(true);
935+
} else if (wArg == "unused-dummy-argument") {
936+
res.getFrontendOpts().features.Enable(
937+
Fortran::common::LanguageFeature::UnusedDummyArgument);
938+
} else if (wArg == "no-unused-dummy-argument") {
939+
res.getFrontendOpts().features.Enable(
940+
Fortran::common::LanguageFeature::UnusedDummyArgument, false);
941+
} else if (wArg == "unused-variable") {
942+
res.getFrontendOpts().features.Enable(
943+
Fortran::common::LanguageFeature::UnusedVariable);
944+
} else if (wArg == "no-unused-variable") {
945+
res.getFrontendOpts().features.Enable(
946+
Fortran::common::LanguageFeature::UnusedVariable, false);
935947
} else {
936-
const unsigned diagID =
937-
diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
938-
"Only `-Werror` is supported currently.");
948+
const unsigned diagID = diags.getCustomDiagID(
949+
clang::DiagnosticsEngine::Error,
950+
"Only `-Werror`, `-W[no]unused-dummy-argument` "
951+
"and `-W[no]unused-variable` are supported "
952+
"currently.");
939953
diags.Report(diagID);
940954
}
941955
}

flang/lib/Semantics/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ add_flang_library(FortranSemantics
2626
check-select-rank.cpp
2727
check-select-type.cpp
2828
check-stop.cpp
29+
check-warning.cpp
2930
compute-offsets.cpp
3031
data-to-inits.cpp
3132
definable.cpp

flang/lib/Semantics/check-warning.cpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//===-- lib/Semantics/check-warning.cpp
2+
//-----------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#include "check-warning.h"
11+
#include "flang/Semantics/tools.h"
12+
13+
namespace Fortran::semantics {
14+
15+
void WarningChecker::Enter(const parser::FunctionStmt &stmt) {
16+
if (Wunused_dummy_argument) {
17+
for (const auto &dummyName : std::get<std::list<parser::Name>>(stmt.t)) {
18+
if (auto *detail = dummyName.symbol->detailsIf<ObjectEntityDetails>()) {
19+
const Symbol *ownerSymbol{dummyName.symbol->owner().symbol()};
20+
const auto *ownerSubp{ownerSymbol->detailsIf<SubprogramDetails>()};
21+
bool inInterface{ownerSubp && ownerSubp->isInterface()};
22+
23+
if (!inInterface && !detail->isUsed()) {
24+
context_.Say(dummyName.symbol->GetUltimate().name(),
25+
"Unused dummy argument '%s' [-Wunused-dummy-argument]"_warn_en_US,
26+
dummyName.ToString());
27+
}
28+
}
29+
}
30+
}
31+
if (Wunused_variable) {
32+
if (const auto &suffix{std::get<std::optional<parser::Suffix>>(stmt.t)}) {
33+
if (suffix->resultName.has_value()) {
34+
if (auto *detail =
35+
suffix->resultName->symbol->detailsIf<ObjectEntityDetails>()) {
36+
const Symbol *ownerSymbol{
37+
suffix->resultName->symbol->owner().symbol()};
38+
const auto *ownerSubp{ownerSymbol->detailsIf<SubprogramDetails>()};
39+
bool inInterface{ownerSubp && ownerSubp->isInterface()};
40+
if (!inInterface && !detail->isUsed()) {
41+
context_.Say(suffix->resultName->source,
42+
"Unused variable '%s' [-Wunused-variable]"_warn_en_US,
43+
suffix->resultName->ToString());
44+
}
45+
}
46+
}
47+
}
48+
}
49+
}
50+
51+
void WarningChecker::Enter(const parser::SubroutineStmt &stmt) {
52+
if (!Wunused_dummy_argument) {
53+
return;
54+
}
55+
for (const auto &dummyArg : std::get<std::list<parser::DummyArg>>(stmt.t)) {
56+
if (const auto *dummyName{std::get_if<parser::Name>(&dummyArg.u)}) {
57+
if (const auto *symbol = dummyName->symbol) {
58+
59+
const Symbol *ownerSymbol{symbol->owner().symbol()};
60+
const auto *ownerSubp{ownerSymbol->detailsIf<SubprogramDetails>()};
61+
bool inInterface{ownerSubp && ownerSubp->isInterface()};
62+
63+
if (auto *detail = symbol->detailsIf<ObjectEntityDetails>()) {
64+
if (!inInterface && !detail->isUsed()) {
65+
context_.Say(symbol->GetUltimate().name(),
66+
"Unused dummy argument '%s' [-Wunused-dummy-argument]"_warn_en_US,
67+
dummyName->ToString());
68+
}
69+
}
70+
}
71+
}
72+
}
73+
}
74+
75+
void WarningChecker::Enter(const parser::EntityDecl &decl) {
76+
if (!Wunused_variable) {
77+
return;
78+
}
79+
80+
const auto &name{std::get<parser::ObjectName>(decl.t)};
81+
if (const auto *symbol = name.symbol) {
82+
const Symbol *ownerSymbol{symbol->owner().symbol()};
83+
const auto *ownerSubp{ownerSymbol->detailsIf<SubprogramDetails>()};
84+
bool inInterface{ownerSubp && ownerSubp->isInterface()};
85+
bool inModule{ownerSymbol && ownerSymbol->scope() &&
86+
ownerSymbol->scope()->IsModule()};
87+
88+
if (auto *detail = symbol->detailsIf<ObjectEntityDetails>()) {
89+
if (!inInterface && !inModule && !detail->isDummy() &&
90+
!detail->isFuncResult() && !detail->isUsed()) {
91+
context_.Say(symbol->name(),
92+
"Unused variable '%s' [-Wunused-variable]"_warn_en_US,
93+
name.ToString());
94+
}
95+
}
96+
}
97+
}
98+
99+
} // namespace Fortran::semantics

flang/lib/Semantics/check-warning.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===-- lib/Semantics/check-warning.h ---------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef FORTRAN_SEMANTICS_CHECK_WARNING_H_
10+
#define FORTRAN_SEMANTICS_CHECK_WARNING_H_
11+
12+
#include "flang/Semantics/semantics.h"
13+
14+
namespace Fortran::parser {
15+
struct FunctionStmt;
16+
struct InterfaceBody;
17+
struct SubroutineStmt;
18+
struct EntityDecl;
19+
} // namespace Fortran::parser
20+
21+
namespace Fortran::semantics {
22+
23+
// Perform semantic checks on DummyArg on Function and Subroutine
24+
// TODO: Add checks for future warning options
25+
class WarningChecker : public virtual BaseChecker {
26+
public:
27+
explicit WarningChecker(SemanticsContext &context) : context_{context} {}
28+
void Enter(const parser::FunctionStmt &);
29+
void Enter(const parser::SubroutineStmt &);
30+
void Enter(const parser::EntityDecl &);
31+
32+
private:
33+
SemanticsContext &context_;
34+
const bool Wunused_dummy_argument = context_.languageFeatures().IsEnabled(
35+
common::LanguageFeature::UnusedDummyArgument);
36+
const bool Wunused_variable = context_.languageFeatures().IsEnabled(
37+
common::LanguageFeature::UnusedVariable);
38+
};
39+
} // namespace Fortran::semantics
40+
#endif

flang/lib/Semantics/expression.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,13 @@ MaybeExpr ExpressionAnalyzer::FixMisparsedSubstring(
590590
}
591591

592592
MaybeExpr ExpressionAnalyzer::Analyze(const parser::Designator &d) {
593+
const auto &name = GetFirstName(d);
594+
if (name.symbol) {
595+
if (auto *detail =
596+
name.symbol->detailsIf<Fortran::semantics::ObjectEntityDetails>()) {
597+
detail->set_isUsed();
598+
}
599+
}
593600
auto restorer{GetContextualMessages().SetLocation(d.source)};
594601
if (auto substringInquiry{FixMisparsedSubstring(d)}) {
595602
return substringInquiry;

flang/lib/Semantics/resolve-names.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6693,6 +6693,11 @@ bool DeclarationVisitor::Pre(const parser::CommonBlockObject &) {
66936693
void DeclarationVisitor::Post(const parser::CommonBlockObject &x) {
66946694
const auto &name{std::get<parser::Name>(x.t)};
66956695
DeclareObjectEntity(name);
6696+
if (name.symbol) {
6697+
if (auto *detail{name.symbol->detailsIf<ObjectEntityDetails>()}) {
6698+
detail->set_isUsed();
6699+
}
6700+
}
66966701
auto pair{specPartState_.commonBlockObjects.insert(name.source)};
66976702
if (!pair.second) {
66986703
const SourceName &prev{*pair.first};

flang/lib/Semantics/semantics.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "check-select-rank.h"
3333
#include "check-select-type.h"
3434
#include "check-stop.h"
35+
#include "check-warning.h"
3536
#include "compute-offsets.h"
3637
#include "mod-file.h"
3738
#include "resolve-labels.h"
@@ -202,6 +203,7 @@ using StatementSemanticsPass2 = SemanticsVisitor<AllocateChecker,
202203
MiscChecker, NamelistChecker, NullifyChecker, PurityChecker,
203204
ReturnStmtChecker, SelectRankConstructChecker, SelectTypeChecker,
204205
StopChecker>;
206+
using StatementSemanticsPass3 = SemanticsVisitor<WarningChecker>;
205207

206208
static bool PerformStatementSemantics(
207209
SemanticsContext &context, parser::Program &program) {
@@ -221,6 +223,12 @@ static bool PerformStatementSemantics(
221223
if (context.languageFeatures().IsEnabled(common::LanguageFeature::CUDA)) {
222224
SemanticsVisitor<CUDAChecker>{context}.Walk(program);
223225
}
226+
if (context.languageFeatures().IsEnabled(
227+
common::LanguageFeature::UnusedDummyArgument) ||
228+
context.languageFeatures().IsEnabled(
229+
common::LanguageFeature::UnusedVariable)) {
230+
StatementSemanticsPass3{context}.Walk(program);
231+
}
224232
if (!context.messages().AnyFatalError()) {
225233
WarnUndefinedFunctionResult(context, context.globalScope());
226234
}

flang/lib/Support/Fortran-features.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ LanguageFeatureControl::LanguageFeatureControl() {
3131
disable_.set(LanguageFeature::LogicalAbbreviations);
3232
disable_.set(LanguageFeature::XOROperator);
3333
disable_.set(LanguageFeature::OldStyleParameter);
34+
disable_.set(LanguageFeature::UnusedDummyArgument);
35+
disable_.set(LanguageFeature::UnusedVariable);
3436
// Possibly an accidental "feature" of nvfortran.
3537
disable_.set(LanguageFeature::AssumedRankPassedToNonAssumedRank);
3638
// These warnings are enabled by default, but only because they used

0 commit comments

Comments
 (0)