-
Notifications
You must be signed in to change notification settings - Fork 13.3k
[flang] Add options -W[no-]unused-dummy-argument and -W[no-]unused-variable #127214
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
base: main
Are you sure you want to change the base?
[flang] Add options -W[no-]unused-dummy-argument and -W[no-]unused-variable #127214
Conversation
@llvm/pr-subscribers-clang @llvm/pr-subscribers-flang-semantics Author: Jean-Didier PAILLEUX (JDPailleux) ChangesAdding support of new warning flags
Full diff: https://github.com/llvm/llvm-project/pull/127214.diff 14 Files Affected:
diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h
index 4ae2775c0f849..2c7e9bae5e652 100644
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -293,10 +293,13 @@ class EntityDetails : public WithBindName {
void set_isDummy(bool value = true) { isDummy_ = value; }
bool isFuncResult() const { return isFuncResult_; }
void set_funcResult(bool x) { isFuncResult_ = x; }
+ bool isUsed() const { return isUsed_; }
+ void set_isUsed() { isUsed_ = true; }
private:
bool isDummy_{false};
bool isFuncResult_{false};
+ bool isUsed_{false};
const DeclTypeSpec *type_{nullptr};
friend llvm::raw_ostream &operator<<(
llvm::raw_ostream &, const EntityDetails &);
diff --git a/flang/include/flang/Support/Fortran-features.h b/flang/include/flang/Support/Fortran-features.h
index 44ba6428e6c93..afccf76d5c025 100644
--- a/flang/include/flang/Support/Fortran-features.h
+++ b/flang/include/flang/Support/Fortran-features.h
@@ -54,7 +54,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
PolymorphicActualAllocatableOrPointerToMonomorphicDummy, RelaxedPureDummy,
UndefinableAsynchronousOrVolatileActual, AutomaticInMainProgram, PrintCptr,
SavedLocalInSpecExpr, PrintNamelist, AssumedRankPassedToNonAssumedRank,
- IgnoreIrrelevantAttributes, Unsigned)
+ IgnoreIrrelevantAttributes, Unsigned, UnusedDummyArgument, UnusedVariable)
// Portability and suspicious usage warnings
ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index f3d9432c62d3b..8b5f69d42bbb4 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -932,10 +932,24 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
for (const auto &wArg : wArgs) {
if (wArg == "error") {
res.setWarnAsErr(true);
+ } else if (wArg == "unused-dummy-argument") {
+ res.getFrontendOpts().features.Enable(
+ Fortran::common::LanguageFeature::UnusedDummyArgument);
+ } else if (wArg == "no-unused-dummy-argument") {
+ res.getFrontendOpts().features.Enable(
+ Fortran::common::LanguageFeature::UnusedDummyArgument, false);
+ } else if (wArg == "unused-variable") {
+ res.getFrontendOpts().features.Enable(
+ Fortran::common::LanguageFeature::UnusedVariable);
+ } else if (wArg == "no-unused-variable") {
+ res.getFrontendOpts().features.Enable(
+ Fortran::common::LanguageFeature::UnusedVariable, false);
} else {
- const unsigned diagID =
- diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
- "Only `-Werror` is supported currently.");
+ const unsigned diagID = diags.getCustomDiagID(
+ clang::DiagnosticsEngine::Error,
+ "Only `-Werror`, `-W[no]unused-dummy-argument` "
+ "and `-W[no]unused-variable` are supported "
+ "currently.");
diags.Report(diagID);
}
}
diff --git a/flang/lib/Semantics/CMakeLists.txt b/flang/lib/Semantics/CMakeLists.txt
index 00108dde49dbd..366282361baf9 100644
--- a/flang/lib/Semantics/CMakeLists.txt
+++ b/flang/lib/Semantics/CMakeLists.txt
@@ -26,6 +26,7 @@ add_flang_library(FortranSemantics
check-select-rank.cpp
check-select-type.cpp
check-stop.cpp
+ check-warning.cpp
compute-offsets.cpp
data-to-inits.cpp
definable.cpp
diff --git a/flang/lib/Semantics/check-warning.cpp b/flang/lib/Semantics/check-warning.cpp
new file mode 100644
index 0000000000000..1604e7590429d
--- /dev/null
+++ b/flang/lib/Semantics/check-warning.cpp
@@ -0,0 +1,99 @@
+//===-- lib/Semantics/check-warning.cpp
+//-----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "check-warning.h"
+#include "flang/Semantics/tools.h"
+
+namespace Fortran::semantics {
+
+void WarningChecker::Enter(const parser::FunctionStmt &stmt) {
+ if (Wunused_dummy_argument) {
+ for (const auto &dummyName : std::get<std::list<parser::Name>>(stmt.t)) {
+ if (auto *detail = dummyName.symbol->detailsIf<ObjectEntityDetails>()) {
+ const Symbol *ownerSymbol{dummyName.symbol->owner().symbol()};
+ const auto *ownerSubp{ownerSymbol->detailsIf<SubprogramDetails>()};
+ bool inInterface{ownerSubp && ownerSubp->isInterface()};
+
+ if (!inInterface && !detail->isUsed()) {
+ context_.Say(dummyName.symbol->GetUltimate().name(),
+ "Unused dummy argument '%s' [-Wunused-dummy-argument]"_warn_en_US,
+ dummyName.ToString());
+ }
+ }
+ }
+ }
+ if (Wunused_variable) {
+ if (const auto &suffix{std::get<std::optional<parser::Suffix>>(stmt.t)}) {
+ if (suffix->resultName.has_value()) {
+ if (auto *detail =
+ suffix->resultName->symbol->detailsIf<ObjectEntityDetails>()) {
+ const Symbol *ownerSymbol{
+ suffix->resultName->symbol->owner().symbol()};
+ const auto *ownerSubp{ownerSymbol->detailsIf<SubprogramDetails>()};
+ bool inInterface{ownerSubp && ownerSubp->isInterface()};
+ if (!inInterface && !detail->isUsed()) {
+ context_.Say(suffix->resultName->source,
+ "Unused variable '%s' [-Wunused-variable]"_warn_en_US,
+ suffix->resultName->ToString());
+ }
+ }
+ }
+ }
+ }
+}
+
+void WarningChecker::Enter(const parser::SubroutineStmt &stmt) {
+ if (!Wunused_dummy_argument) {
+ return;
+ }
+ for (const auto &dummyArg : std::get<std::list<parser::DummyArg>>(stmt.t)) {
+ if (const auto *dummyName{std::get_if<parser::Name>(&dummyArg.u)}) {
+ if (const auto *symbol = dummyName->symbol) {
+
+ const Symbol *ownerSymbol{symbol->owner().symbol()};
+ const auto *ownerSubp{ownerSymbol->detailsIf<SubprogramDetails>()};
+ bool inInterface{ownerSubp && ownerSubp->isInterface()};
+
+ if (auto *detail = symbol->detailsIf<ObjectEntityDetails>()) {
+ if (!inInterface && !detail->isUsed()) {
+ context_.Say(symbol->GetUltimate().name(),
+ "Unused dummy argument '%s' [-Wunused-dummy-argument]"_warn_en_US,
+ dummyName->ToString());
+ }
+ }
+ }
+ }
+ }
+}
+
+void WarningChecker::Enter(const parser::EntityDecl &decl) {
+ if (!Wunused_variable) {
+ return;
+ }
+
+ const auto &name{std::get<parser::ObjectName>(decl.t)};
+ if (const auto *symbol = name.symbol) {
+ const Symbol *ownerSymbol{symbol->owner().symbol()};
+ const auto *ownerSubp{ownerSymbol->detailsIf<SubprogramDetails>()};
+ bool inInterface{ownerSubp && ownerSubp->isInterface()};
+ bool inModule{ownerSymbol && ownerSymbol->scope() &&
+ ownerSymbol->scope()->IsModule()};
+
+ if (auto *detail = symbol->detailsIf<ObjectEntityDetails>()) {
+ if (!inInterface && !inModule && !detail->isDummy() &&
+ !detail->isFuncResult() && !detail->isUsed()) {
+ context_.Say(symbol->name(),
+ "Unused variable '%s' [-Wunused-variable]"_warn_en_US,
+ name.ToString());
+ }
+ }
+ }
+}
+
+} // namespace Fortran::semantics
diff --git a/flang/lib/Semantics/check-warning.h b/flang/lib/Semantics/check-warning.h
new file mode 100644
index 0000000000000..f13d159392ab4
--- /dev/null
+++ b/flang/lib/Semantics/check-warning.h
@@ -0,0 +1,40 @@
+//===-- lib/Semantics/check-warning.h ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_SEMANTICS_CHECK_WARNING_H_
+#define FORTRAN_SEMANTICS_CHECK_WARNING_H_
+
+#include "flang/Semantics/semantics.h"
+
+namespace Fortran::parser {
+struct FunctionStmt;
+struct InterfaceBody;
+struct SubroutineStmt;
+struct EntityDecl;
+} // namespace Fortran::parser
+
+namespace Fortran::semantics {
+
+// Perform semantic checks on DummyArg on Function and Subroutine
+// TODO: Add checks for future warning options
+class WarningChecker : public virtual BaseChecker {
+public:
+ explicit WarningChecker(SemanticsContext &context) : context_{context} {}
+ void Enter(const parser::FunctionStmt &);
+ void Enter(const parser::SubroutineStmt &);
+ void Enter(const parser::EntityDecl &);
+
+private:
+ SemanticsContext &context_;
+ const bool Wunused_dummy_argument = context_.languageFeatures().IsEnabled(
+ common::LanguageFeature::UnusedDummyArgument);
+ const bool Wunused_variable = context_.languageFeatures().IsEnabled(
+ common::LanguageFeature::UnusedVariable);
+};
+} // namespace Fortran::semantics
+#endif
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 6949e5693d08f..be077fdceddf4 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -590,6 +590,13 @@ MaybeExpr ExpressionAnalyzer::FixMisparsedSubstring(
}
MaybeExpr ExpressionAnalyzer::Analyze(const parser::Designator &d) {
+ const auto &name = GetFirstName(d);
+ if (name.symbol) {
+ if (auto *detail =
+ name.symbol->detailsIf<Fortran::semantics::ObjectEntityDetails>()) {
+ detail->set_isUsed();
+ }
+ }
auto restorer{GetContextualMessages().SetLocation(d.source)};
if (auto substringInquiry{FixMisparsedSubstring(d)}) {
return substringInquiry;
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index e64abe6b50e78..488b0acfee8ff 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -6693,6 +6693,11 @@ bool DeclarationVisitor::Pre(const parser::CommonBlockObject &) {
void DeclarationVisitor::Post(const parser::CommonBlockObject &x) {
const auto &name{std::get<parser::Name>(x.t)};
DeclareObjectEntity(name);
+ if (name.symbol) {
+ if (auto *detail{name.symbol->detailsIf<ObjectEntityDetails>()}) {
+ detail->set_isUsed();
+ }
+ }
auto pair{specPartState_.commonBlockObjects.insert(name.source)};
if (!pair.second) {
const SourceName &prev{*pair.first};
diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp
index 10a01039ea0ae..d3703b8fc2148 100644
--- a/flang/lib/Semantics/semantics.cpp
+++ b/flang/lib/Semantics/semantics.cpp
@@ -32,6 +32,7 @@
#include "check-select-rank.h"
#include "check-select-type.h"
#include "check-stop.h"
+#include "check-warning.h"
#include "compute-offsets.h"
#include "mod-file.h"
#include "resolve-labels.h"
@@ -202,6 +203,7 @@ using StatementSemanticsPass2 = SemanticsVisitor<AllocateChecker,
MiscChecker, NamelistChecker, NullifyChecker, PurityChecker,
ReturnStmtChecker, SelectRankConstructChecker, SelectTypeChecker,
StopChecker>;
+using StatementSemanticsPass3 = SemanticsVisitor<WarningChecker>;
static bool PerformStatementSemantics(
SemanticsContext &context, parser::Program &program) {
@@ -221,6 +223,12 @@ static bool PerformStatementSemantics(
if (context.languageFeatures().IsEnabled(common::LanguageFeature::CUDA)) {
SemanticsVisitor<CUDAChecker>{context}.Walk(program);
}
+ if (context.languageFeatures().IsEnabled(
+ common::LanguageFeature::UnusedDummyArgument) ||
+ context.languageFeatures().IsEnabled(
+ common::LanguageFeature::UnusedVariable)) {
+ StatementSemanticsPass3{context}.Walk(program);
+ }
if (!context.messages().AnyFatalError()) {
WarnUndefinedFunctionResult(context, context.globalScope());
}
diff --git a/flang/lib/Support/Fortran-features.cpp b/flang/lib/Support/Fortran-features.cpp
index bbeb4b15a0486..056177d714423 100644
--- a/flang/lib/Support/Fortran-features.cpp
+++ b/flang/lib/Support/Fortran-features.cpp
@@ -31,6 +31,8 @@ LanguageFeatureControl::LanguageFeatureControl() {
disable_.set(LanguageFeature::LogicalAbbreviations);
disable_.set(LanguageFeature::XOROperator);
disable_.set(LanguageFeature::OldStyleParameter);
+ disable_.set(LanguageFeature::UnusedDummyArgument);
+ disable_.set(LanguageFeature::UnusedVariable);
// Possibly an accidental "feature" of nvfortran.
disable_.set(LanguageFeature::AssumedRankPassedToNonAssumedRank);
// These warnings are enabled by default, but only because they used
diff --git a/flang/test/Driver/werror-wrong.f90 b/flang/test/Driver/werror-wrong.f90
index 58adf6f745d5e..364be4a0e6e11 100644
--- a/flang/test/Driver/werror-wrong.f90
+++ b/flang/test/Driver/werror-wrong.f90
@@ -3,4 +3,4 @@
! RUN: not %flang_fc1 -fsyntax-only -Wall %s 2>&1 | FileCheck %s --check-prefix=WRONG
! RUN: not %flang_fc1 -fsyntax-only -WX %s 2>&1 | FileCheck %s --check-prefix=WRONG
-! WRONG: Only `-Werror` is supported currently.
+! WRONG: Only `-Werror`, `-W[no]unused-dummy-argument` and `-W[no]unused-variable` are supported currently.
diff --git a/flang/test/Driver/wextra-ok.f90 b/flang/test/Driver/wextra-ok.f90
index 441029aa0af27..9b391d5b91a59 100644
--- a/flang/test/Driver/wextra-ok.f90
+++ b/flang/test/Driver/wextra-ok.f90
@@ -5,7 +5,7 @@
! RUN: not %flang -std=f2018 -Wblah -Wextra %s -c 2>&1 | FileCheck %s --check-prefix=WRONG
! CHECK-OK: the warning option '-Wextra' is not supported
-! WRONG: Only `-Werror` is supported currently.
+! WRONG: Only `-Werror`, `-W[no]unused-dummy-argument` and `-W[no]unused-variable` are supported currently.
program wextra_ok
end program wextra_ok
diff --git a/flang/test/Semantics/wunused-dummy-argument.f90 b/flang/test/Semantics/wunused-dummy-argument.f90
new file mode 100644
index 0000000000000..bad7720f48f2c
--- /dev/null
+++ b/flang/test/Semantics/wunused-dummy-argument.f90
@@ -0,0 +1,54 @@
+! RUN: %flang_fc1 -Wunused-dummy-argument %s 2>&1 | FileCheck %s
+! RUN: not %flang_fc1 -Wunused-dummy-argument -Werror %s
+! RUN: %flang_fc1 -Wno-unused-dummy-argument %s 2>&1 | FileCheck %s --check-prefix=NOWARN
+
+! CHECK: warning: Unused dummy argument 'a4' [-Wunused-dummy-argument]
+! CHECK: warning: Unused dummy argument 'b4' [-Wunused-dummy-argument]
+! CHECK: warning: Unused dummy argument 'a6' [-Wunused-dummy-argument]
+! CHECK: warning: Unused dummy argument 'b6' [-Wunused-dummy-argument]
+
+! NOWARN-NOT: warning: Unused dummy argument 'a4' [-Wunused-dummy-argument]
+! NOWARN-NOT: warning: Unused dummy argument 'b4' [-Wunused-dummy-argument]
+! NOWARN-NOT: warning: Unused dummy argument 'a6' [-Wunused-dummy-argument]
+! NOWARN-NOT: warning: Unused dummy argument 'b6' [-Wunused-dummy-argument]
+
+program main
+ type :: my_type
+ integer :: val
+ end type
+ integer :: not_dummy_arg
+ interface
+ subroutine subroutine_interface(a)
+ integer, intent(in) :: a
+ end subroutine
+
+ function function_interface(a2)
+ integer, intent(in) :: a2
+ end function
+ end interface
+contains
+ subroutine subroutine_all_used(a3, b3)
+ integer, intent(inout) :: a3, b3
+ a3 = a3 + b3
+ end subroutine
+
+ subroutine subroutine_unused_both(a4, b4)
+ integer, intent(inout) :: a4(10)
+ type(my_type) :: b4
+ end subroutine
+
+
+ function function_used_all(a5, b5) result(c1)
+ integer, intent(inout) :: a5(10)
+ type(my_type), intent(in) :: b5
+ integer :: c1
+ a5(1) = b5%val
+ c1 = a5(2)
+ end function
+
+ function function_unused_both(a6, b6) result(c2)
+ integer, intent(inout) :: a6(10)
+ type(my_type) :: b6
+ integer :: c2
+ end function
+end program
diff --git a/flang/test/Semantics/wunused-variable.f90 b/flang/test/Semantics/wunused-variable.f90
new file mode 100644
index 0000000000000..146f943f83a35
--- /dev/null
+++ b/flang/test/Semantics/wunused-variable.f90
@@ -0,0 +1,72 @@
+! RUN: %flang_fc1 -Wunused-variable %s 2>&1 | FileCheck %s
+! RUN: not %flang_fc1 -Wunused-variable -Werror %s
+! RUN: %flang_fc1 -Wno-unused-variable %s 2>&1 | FileCheck %s --check-prefix=NOWARN
+
+! CHECK: warning: Unused variable 'unused_var_in_submod_subroutine' [-Wunused-variable]
+! CHECK: warning: Unused variable 'my_type_var1' [-Wunused-variable]
+! CHECK: warning: Unused variable 'not_dummy_arg' [-Wunused-variable]
+! CHECK: warning: Unused variable 'in_subroutine' [-Wunused-variable]
+! CHECK: warning: Unused variable 'c1' [-Wunused-variable]
+
+! NOWARN-NOT: warning: Unused variable 'unused_var_in_submod_subroutine' [-Wunused-variable]
+! NOWARN-NOT: warning: Unused variable 'my_type_var1' [-Wunused-variable]
+! NOWARN-NOT: warning: Unused variable 'not_dummy_arg' [-Wunused-variable]
+! NOWARN-NOT: warning: Unused variable 'in_subroutine' [-Wunused-variable]
+! NOWARN-NOT: warning: Unused variable 'c1' [-Wunused-variable]
+module test
+ integer :: var_in_module
+ contains
+ subroutine module_subroutine(a)
+ integer :: unused_var_in_submod_subroutine
+ integer :: a
+ end subroutine
+end module test
+
+program main
+ type :: my_type
+ integer :: val
+ integer :: unused_val
+ end type
+ interface
+ subroutine subroutine_in_interface()
+ integer :: w
+ end subroutine
+ function function_in_interface() result(j)
+ integer :: x
+ integer :: j
+ end function
+ end interface
+ type(my_type) :: my_type_var1
+ type(my_type) :: my_type_var2
+ integer :: not_dummy_arg
+
+ integer :: variable_common
+ common variable_common
+
+ my_type_var2%val = 12
+
+
+
+ print *, function_used_all()
+
+ contains
+ subroutine subroutine_all_used(a3)
+ integer, intent(in) :: a3
+ integer :: in_subroutine_used
+ in_subroutine_used = a3
+ end subroutine
+
+ subroutine subroutine_unused(a4)
+ integer, intent(in) :: a4
+ integer :: in_subroutine
+ end subroutine
+
+ function function_used_all() result(c1)
+ integer :: in_function
+ integer :: c1
+ c1 = in_function
+ end function
+
+ function function_unused_all() result(c1)
+ end function
+end program
|
@llvm/pr-subscribers-flang-driver Author: Jean-Didier PAILLEUX (JDPailleux) ChangesAdding support of new warning flags
Full diff: https://github.com/llvm/llvm-project/pull/127214.diff 14 Files Affected:
diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h
index 4ae2775c0f849..2c7e9bae5e652 100644
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -293,10 +293,13 @@ class EntityDetails : public WithBindName {
void set_isDummy(bool value = true) { isDummy_ = value; }
bool isFuncResult() const { return isFuncResult_; }
void set_funcResult(bool x) { isFuncResult_ = x; }
+ bool isUsed() const { return isUsed_; }
+ void set_isUsed() { isUsed_ = true; }
private:
bool isDummy_{false};
bool isFuncResult_{false};
+ bool isUsed_{false};
const DeclTypeSpec *type_{nullptr};
friend llvm::raw_ostream &operator<<(
llvm::raw_ostream &, const EntityDetails &);
diff --git a/flang/include/flang/Support/Fortran-features.h b/flang/include/flang/Support/Fortran-features.h
index 44ba6428e6c93..afccf76d5c025 100644
--- a/flang/include/flang/Support/Fortran-features.h
+++ b/flang/include/flang/Support/Fortran-features.h
@@ -54,7 +54,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
PolymorphicActualAllocatableOrPointerToMonomorphicDummy, RelaxedPureDummy,
UndefinableAsynchronousOrVolatileActual, AutomaticInMainProgram, PrintCptr,
SavedLocalInSpecExpr, PrintNamelist, AssumedRankPassedToNonAssumedRank,
- IgnoreIrrelevantAttributes, Unsigned)
+ IgnoreIrrelevantAttributes, Unsigned, UnusedDummyArgument, UnusedVariable)
// Portability and suspicious usage warnings
ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index f3d9432c62d3b..8b5f69d42bbb4 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -932,10 +932,24 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
for (const auto &wArg : wArgs) {
if (wArg == "error") {
res.setWarnAsErr(true);
+ } else if (wArg == "unused-dummy-argument") {
+ res.getFrontendOpts().features.Enable(
+ Fortran::common::LanguageFeature::UnusedDummyArgument);
+ } else if (wArg == "no-unused-dummy-argument") {
+ res.getFrontendOpts().features.Enable(
+ Fortran::common::LanguageFeature::UnusedDummyArgument, false);
+ } else if (wArg == "unused-variable") {
+ res.getFrontendOpts().features.Enable(
+ Fortran::common::LanguageFeature::UnusedVariable);
+ } else if (wArg == "no-unused-variable") {
+ res.getFrontendOpts().features.Enable(
+ Fortran::common::LanguageFeature::UnusedVariable, false);
} else {
- const unsigned diagID =
- diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
- "Only `-Werror` is supported currently.");
+ const unsigned diagID = diags.getCustomDiagID(
+ clang::DiagnosticsEngine::Error,
+ "Only `-Werror`, `-W[no]unused-dummy-argument` "
+ "and `-W[no]unused-variable` are supported "
+ "currently.");
diags.Report(diagID);
}
}
diff --git a/flang/lib/Semantics/CMakeLists.txt b/flang/lib/Semantics/CMakeLists.txt
index 00108dde49dbd..366282361baf9 100644
--- a/flang/lib/Semantics/CMakeLists.txt
+++ b/flang/lib/Semantics/CMakeLists.txt
@@ -26,6 +26,7 @@ add_flang_library(FortranSemantics
check-select-rank.cpp
check-select-type.cpp
check-stop.cpp
+ check-warning.cpp
compute-offsets.cpp
data-to-inits.cpp
definable.cpp
diff --git a/flang/lib/Semantics/check-warning.cpp b/flang/lib/Semantics/check-warning.cpp
new file mode 100644
index 0000000000000..1604e7590429d
--- /dev/null
+++ b/flang/lib/Semantics/check-warning.cpp
@@ -0,0 +1,99 @@
+//===-- lib/Semantics/check-warning.cpp
+//-----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "check-warning.h"
+#include "flang/Semantics/tools.h"
+
+namespace Fortran::semantics {
+
+void WarningChecker::Enter(const parser::FunctionStmt &stmt) {
+ if (Wunused_dummy_argument) {
+ for (const auto &dummyName : std::get<std::list<parser::Name>>(stmt.t)) {
+ if (auto *detail = dummyName.symbol->detailsIf<ObjectEntityDetails>()) {
+ const Symbol *ownerSymbol{dummyName.symbol->owner().symbol()};
+ const auto *ownerSubp{ownerSymbol->detailsIf<SubprogramDetails>()};
+ bool inInterface{ownerSubp && ownerSubp->isInterface()};
+
+ if (!inInterface && !detail->isUsed()) {
+ context_.Say(dummyName.symbol->GetUltimate().name(),
+ "Unused dummy argument '%s' [-Wunused-dummy-argument]"_warn_en_US,
+ dummyName.ToString());
+ }
+ }
+ }
+ }
+ if (Wunused_variable) {
+ if (const auto &suffix{std::get<std::optional<parser::Suffix>>(stmt.t)}) {
+ if (suffix->resultName.has_value()) {
+ if (auto *detail =
+ suffix->resultName->symbol->detailsIf<ObjectEntityDetails>()) {
+ const Symbol *ownerSymbol{
+ suffix->resultName->symbol->owner().symbol()};
+ const auto *ownerSubp{ownerSymbol->detailsIf<SubprogramDetails>()};
+ bool inInterface{ownerSubp && ownerSubp->isInterface()};
+ if (!inInterface && !detail->isUsed()) {
+ context_.Say(suffix->resultName->source,
+ "Unused variable '%s' [-Wunused-variable]"_warn_en_US,
+ suffix->resultName->ToString());
+ }
+ }
+ }
+ }
+ }
+}
+
+void WarningChecker::Enter(const parser::SubroutineStmt &stmt) {
+ if (!Wunused_dummy_argument) {
+ return;
+ }
+ for (const auto &dummyArg : std::get<std::list<parser::DummyArg>>(stmt.t)) {
+ if (const auto *dummyName{std::get_if<parser::Name>(&dummyArg.u)}) {
+ if (const auto *symbol = dummyName->symbol) {
+
+ const Symbol *ownerSymbol{symbol->owner().symbol()};
+ const auto *ownerSubp{ownerSymbol->detailsIf<SubprogramDetails>()};
+ bool inInterface{ownerSubp && ownerSubp->isInterface()};
+
+ if (auto *detail = symbol->detailsIf<ObjectEntityDetails>()) {
+ if (!inInterface && !detail->isUsed()) {
+ context_.Say(symbol->GetUltimate().name(),
+ "Unused dummy argument '%s' [-Wunused-dummy-argument]"_warn_en_US,
+ dummyName->ToString());
+ }
+ }
+ }
+ }
+ }
+}
+
+void WarningChecker::Enter(const parser::EntityDecl &decl) {
+ if (!Wunused_variable) {
+ return;
+ }
+
+ const auto &name{std::get<parser::ObjectName>(decl.t)};
+ if (const auto *symbol = name.symbol) {
+ const Symbol *ownerSymbol{symbol->owner().symbol()};
+ const auto *ownerSubp{ownerSymbol->detailsIf<SubprogramDetails>()};
+ bool inInterface{ownerSubp && ownerSubp->isInterface()};
+ bool inModule{ownerSymbol && ownerSymbol->scope() &&
+ ownerSymbol->scope()->IsModule()};
+
+ if (auto *detail = symbol->detailsIf<ObjectEntityDetails>()) {
+ if (!inInterface && !inModule && !detail->isDummy() &&
+ !detail->isFuncResult() && !detail->isUsed()) {
+ context_.Say(symbol->name(),
+ "Unused variable '%s' [-Wunused-variable]"_warn_en_US,
+ name.ToString());
+ }
+ }
+ }
+}
+
+} // namespace Fortran::semantics
diff --git a/flang/lib/Semantics/check-warning.h b/flang/lib/Semantics/check-warning.h
new file mode 100644
index 0000000000000..f13d159392ab4
--- /dev/null
+++ b/flang/lib/Semantics/check-warning.h
@@ -0,0 +1,40 @@
+//===-- lib/Semantics/check-warning.h ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_SEMANTICS_CHECK_WARNING_H_
+#define FORTRAN_SEMANTICS_CHECK_WARNING_H_
+
+#include "flang/Semantics/semantics.h"
+
+namespace Fortran::parser {
+struct FunctionStmt;
+struct InterfaceBody;
+struct SubroutineStmt;
+struct EntityDecl;
+} // namespace Fortran::parser
+
+namespace Fortran::semantics {
+
+// Perform semantic checks on DummyArg on Function and Subroutine
+// TODO: Add checks for future warning options
+class WarningChecker : public virtual BaseChecker {
+public:
+ explicit WarningChecker(SemanticsContext &context) : context_{context} {}
+ void Enter(const parser::FunctionStmt &);
+ void Enter(const parser::SubroutineStmt &);
+ void Enter(const parser::EntityDecl &);
+
+private:
+ SemanticsContext &context_;
+ const bool Wunused_dummy_argument = context_.languageFeatures().IsEnabled(
+ common::LanguageFeature::UnusedDummyArgument);
+ const bool Wunused_variable = context_.languageFeatures().IsEnabled(
+ common::LanguageFeature::UnusedVariable);
+};
+} // namespace Fortran::semantics
+#endif
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 6949e5693d08f..be077fdceddf4 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -590,6 +590,13 @@ MaybeExpr ExpressionAnalyzer::FixMisparsedSubstring(
}
MaybeExpr ExpressionAnalyzer::Analyze(const parser::Designator &d) {
+ const auto &name = GetFirstName(d);
+ if (name.symbol) {
+ if (auto *detail =
+ name.symbol->detailsIf<Fortran::semantics::ObjectEntityDetails>()) {
+ detail->set_isUsed();
+ }
+ }
auto restorer{GetContextualMessages().SetLocation(d.source)};
if (auto substringInquiry{FixMisparsedSubstring(d)}) {
return substringInquiry;
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index e64abe6b50e78..488b0acfee8ff 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -6693,6 +6693,11 @@ bool DeclarationVisitor::Pre(const parser::CommonBlockObject &) {
void DeclarationVisitor::Post(const parser::CommonBlockObject &x) {
const auto &name{std::get<parser::Name>(x.t)};
DeclareObjectEntity(name);
+ if (name.symbol) {
+ if (auto *detail{name.symbol->detailsIf<ObjectEntityDetails>()}) {
+ detail->set_isUsed();
+ }
+ }
auto pair{specPartState_.commonBlockObjects.insert(name.source)};
if (!pair.second) {
const SourceName &prev{*pair.first};
diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp
index 10a01039ea0ae..d3703b8fc2148 100644
--- a/flang/lib/Semantics/semantics.cpp
+++ b/flang/lib/Semantics/semantics.cpp
@@ -32,6 +32,7 @@
#include "check-select-rank.h"
#include "check-select-type.h"
#include "check-stop.h"
+#include "check-warning.h"
#include "compute-offsets.h"
#include "mod-file.h"
#include "resolve-labels.h"
@@ -202,6 +203,7 @@ using StatementSemanticsPass2 = SemanticsVisitor<AllocateChecker,
MiscChecker, NamelistChecker, NullifyChecker, PurityChecker,
ReturnStmtChecker, SelectRankConstructChecker, SelectTypeChecker,
StopChecker>;
+using StatementSemanticsPass3 = SemanticsVisitor<WarningChecker>;
static bool PerformStatementSemantics(
SemanticsContext &context, parser::Program &program) {
@@ -221,6 +223,12 @@ static bool PerformStatementSemantics(
if (context.languageFeatures().IsEnabled(common::LanguageFeature::CUDA)) {
SemanticsVisitor<CUDAChecker>{context}.Walk(program);
}
+ if (context.languageFeatures().IsEnabled(
+ common::LanguageFeature::UnusedDummyArgument) ||
+ context.languageFeatures().IsEnabled(
+ common::LanguageFeature::UnusedVariable)) {
+ StatementSemanticsPass3{context}.Walk(program);
+ }
if (!context.messages().AnyFatalError()) {
WarnUndefinedFunctionResult(context, context.globalScope());
}
diff --git a/flang/lib/Support/Fortran-features.cpp b/flang/lib/Support/Fortran-features.cpp
index bbeb4b15a0486..056177d714423 100644
--- a/flang/lib/Support/Fortran-features.cpp
+++ b/flang/lib/Support/Fortran-features.cpp
@@ -31,6 +31,8 @@ LanguageFeatureControl::LanguageFeatureControl() {
disable_.set(LanguageFeature::LogicalAbbreviations);
disable_.set(LanguageFeature::XOROperator);
disable_.set(LanguageFeature::OldStyleParameter);
+ disable_.set(LanguageFeature::UnusedDummyArgument);
+ disable_.set(LanguageFeature::UnusedVariable);
// Possibly an accidental "feature" of nvfortran.
disable_.set(LanguageFeature::AssumedRankPassedToNonAssumedRank);
// These warnings are enabled by default, but only because they used
diff --git a/flang/test/Driver/werror-wrong.f90 b/flang/test/Driver/werror-wrong.f90
index 58adf6f745d5e..364be4a0e6e11 100644
--- a/flang/test/Driver/werror-wrong.f90
+++ b/flang/test/Driver/werror-wrong.f90
@@ -3,4 +3,4 @@
! RUN: not %flang_fc1 -fsyntax-only -Wall %s 2>&1 | FileCheck %s --check-prefix=WRONG
! RUN: not %flang_fc1 -fsyntax-only -WX %s 2>&1 | FileCheck %s --check-prefix=WRONG
-! WRONG: Only `-Werror` is supported currently.
+! WRONG: Only `-Werror`, `-W[no]unused-dummy-argument` and `-W[no]unused-variable` are supported currently.
diff --git a/flang/test/Driver/wextra-ok.f90 b/flang/test/Driver/wextra-ok.f90
index 441029aa0af27..9b391d5b91a59 100644
--- a/flang/test/Driver/wextra-ok.f90
+++ b/flang/test/Driver/wextra-ok.f90
@@ -5,7 +5,7 @@
! RUN: not %flang -std=f2018 -Wblah -Wextra %s -c 2>&1 | FileCheck %s --check-prefix=WRONG
! CHECK-OK: the warning option '-Wextra' is not supported
-! WRONG: Only `-Werror` is supported currently.
+! WRONG: Only `-Werror`, `-W[no]unused-dummy-argument` and `-W[no]unused-variable` are supported currently.
program wextra_ok
end program wextra_ok
diff --git a/flang/test/Semantics/wunused-dummy-argument.f90 b/flang/test/Semantics/wunused-dummy-argument.f90
new file mode 100644
index 0000000000000..bad7720f48f2c
--- /dev/null
+++ b/flang/test/Semantics/wunused-dummy-argument.f90
@@ -0,0 +1,54 @@
+! RUN: %flang_fc1 -Wunused-dummy-argument %s 2>&1 | FileCheck %s
+! RUN: not %flang_fc1 -Wunused-dummy-argument -Werror %s
+! RUN: %flang_fc1 -Wno-unused-dummy-argument %s 2>&1 | FileCheck %s --check-prefix=NOWARN
+
+! CHECK: warning: Unused dummy argument 'a4' [-Wunused-dummy-argument]
+! CHECK: warning: Unused dummy argument 'b4' [-Wunused-dummy-argument]
+! CHECK: warning: Unused dummy argument 'a6' [-Wunused-dummy-argument]
+! CHECK: warning: Unused dummy argument 'b6' [-Wunused-dummy-argument]
+
+! NOWARN-NOT: warning: Unused dummy argument 'a4' [-Wunused-dummy-argument]
+! NOWARN-NOT: warning: Unused dummy argument 'b4' [-Wunused-dummy-argument]
+! NOWARN-NOT: warning: Unused dummy argument 'a6' [-Wunused-dummy-argument]
+! NOWARN-NOT: warning: Unused dummy argument 'b6' [-Wunused-dummy-argument]
+
+program main
+ type :: my_type
+ integer :: val
+ end type
+ integer :: not_dummy_arg
+ interface
+ subroutine subroutine_interface(a)
+ integer, intent(in) :: a
+ end subroutine
+
+ function function_interface(a2)
+ integer, intent(in) :: a2
+ end function
+ end interface
+contains
+ subroutine subroutine_all_used(a3, b3)
+ integer, intent(inout) :: a3, b3
+ a3 = a3 + b3
+ end subroutine
+
+ subroutine subroutine_unused_both(a4, b4)
+ integer, intent(inout) :: a4(10)
+ type(my_type) :: b4
+ end subroutine
+
+
+ function function_used_all(a5, b5) result(c1)
+ integer, intent(inout) :: a5(10)
+ type(my_type), intent(in) :: b5
+ integer :: c1
+ a5(1) = b5%val
+ c1 = a5(2)
+ end function
+
+ function function_unused_both(a6, b6) result(c2)
+ integer, intent(inout) :: a6(10)
+ type(my_type) :: b6
+ integer :: c2
+ end function
+end program
diff --git a/flang/test/Semantics/wunused-variable.f90 b/flang/test/Semantics/wunused-variable.f90
new file mode 100644
index 0000000000000..146f943f83a35
--- /dev/null
+++ b/flang/test/Semantics/wunused-variable.f90
@@ -0,0 +1,72 @@
+! RUN: %flang_fc1 -Wunused-variable %s 2>&1 | FileCheck %s
+! RUN: not %flang_fc1 -Wunused-variable -Werror %s
+! RUN: %flang_fc1 -Wno-unused-variable %s 2>&1 | FileCheck %s --check-prefix=NOWARN
+
+! CHECK: warning: Unused variable 'unused_var_in_submod_subroutine' [-Wunused-variable]
+! CHECK: warning: Unused variable 'my_type_var1' [-Wunused-variable]
+! CHECK: warning: Unused variable 'not_dummy_arg' [-Wunused-variable]
+! CHECK: warning: Unused variable 'in_subroutine' [-Wunused-variable]
+! CHECK: warning: Unused variable 'c1' [-Wunused-variable]
+
+! NOWARN-NOT: warning: Unused variable 'unused_var_in_submod_subroutine' [-Wunused-variable]
+! NOWARN-NOT: warning: Unused variable 'my_type_var1' [-Wunused-variable]
+! NOWARN-NOT: warning: Unused variable 'not_dummy_arg' [-Wunused-variable]
+! NOWARN-NOT: warning: Unused variable 'in_subroutine' [-Wunused-variable]
+! NOWARN-NOT: warning: Unused variable 'c1' [-Wunused-variable]
+module test
+ integer :: var_in_module
+ contains
+ subroutine module_subroutine(a)
+ integer :: unused_var_in_submod_subroutine
+ integer :: a
+ end subroutine
+end module test
+
+program main
+ type :: my_type
+ integer :: val
+ integer :: unused_val
+ end type
+ interface
+ subroutine subroutine_in_interface()
+ integer :: w
+ end subroutine
+ function function_in_interface() result(j)
+ integer :: x
+ integer :: j
+ end function
+ end interface
+ type(my_type) :: my_type_var1
+ type(my_type) :: my_type_var2
+ integer :: not_dummy_arg
+
+ integer :: variable_common
+ common variable_common
+
+ my_type_var2%val = 12
+
+
+
+ print *, function_used_all()
+
+ contains
+ subroutine subroutine_all_used(a3)
+ integer, intent(in) :: a3
+ integer :: in_subroutine_used
+ in_subroutine_used = a3
+ end subroutine
+
+ subroutine subroutine_unused(a4)
+ integer, intent(in) :: a4
+ integer :: in_subroutine
+ end subroutine
+
+ function function_used_all() result(c1)
+ integer :: in_function
+ integer :: c1
+ c1 = in_function
+ end function
+
+ function function_unused_all() result(c1)
+ end function
+end program
|
Does support for these options need to be added in the main driver? |
There's no need to add these options warning in the main driver, as |
} else if (wArg == "unused-dummy-argument") { | ||
res.getFrontendOpts().features.Enable( | ||
Fortran::common::LanguageFeature::UnusedDummyArgument); | ||
} else if (wArg == "no-unused-dummy-argument") { | ||
res.getFrontendOpts().features.Enable( | ||
Fortran::common::LanguageFeature::UnusedDummyArgument, false); | ||
} else if (wArg == "unused-variable") { | ||
res.getFrontendOpts().features.Enable( | ||
Fortran::common::LanguageFeature::UnusedVariable); | ||
} else if (wArg == "no-unused-variable") { | ||
res.getFrontendOpts().features.Enable( | ||
Fortran::common::LanguageFeature::UnusedVariable, false); | ||
} else { | ||
const unsigned diagID = | ||
diags.getCustomDiagID(clang::DiagnosticsEngine::Error, | ||
"Only `-Werror` is supported currently."); | ||
const unsigned diagID = diags.getCustomDiagID( | ||
clang::DiagnosticsEngine::Error, | ||
"Only `-Werror`, `-W[no]unused-dummy-argument` " | ||
"and `-W[no]unused-variable` are supported " | ||
"currently."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't look like it is scalable. For every warning option that is added, we would have to add a check and change the diagnostic line. Besides, the comment above suggests that this was intended to be a temporary measure. This code predates my involvement with this project. Perhaps those who have been around longer have some insight on how the warning classes were intended to be handled: @banach-space @kiranchandramohan @jeanPerier
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When we implemented this part, Flang had no mechanism to control diagnostics or warnings, which is why this logic is so basic. I see that this is slowly changing.
This doesn't look like it is scalable.
Agreed - this is not a sustainable long-term approach. One way forward could be to take inspiration from Clang, for example: clang/include/clang/Basic/DiagnosticGroups.td#L863.
My perspective on changes like this is that we shouldn't block them unless we can propose a concrete alternative. In practice, that means someone needs to design and implement a better approach.
@JDPailleux, are we expecting more patches like this in the near future? It would be helpful to understand the urgency of updating this logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@banach-space Yes, probably, because in the near future we'd like to add more in order to support -Wall
in Flang. And I agree that in the long term, adding all the warning flags should be improved.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, basically, it would be better to add an entry for each warning flag in the main driver? And therefore remove/rework the use of OPT_W_Joined
in a future PR? I'll modify this PR to do that ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've just realised that the link that I shared was wrong, I meant this:
def UnusedArgument : DiagGroup<"unused-argument">; |
it would be better to add an entry for each warning flag in the main driver?
Adding things in the main driver makes sense if it's going to be re-used by Clang. Is it? IIRC, Clang ties these "warning" flags to various diagnostic groups (hence the link above), as opposed to using https://github.com/llvm/llvm-project/blob/main/clang/include/clang/Driver/Options.td.
But please keep in mind that I've not touched this in ~3yrs and these are just bits from my memory. In practice, we should re-visit the logic in Clang and see whether there's scope for re-use.
- If yes, great, just do it!
- If not, then Flang needs something bespoke.
As I no longer actively work in this area, I am unable to make a specific suggestion. But hopefully this provides a good starting point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the tip, I'll look into it!
Do these warning flags appear in |
Yes here : |
If a user doesn't know of the existence of these warning flags, how would they find it? Having said that, it seems that one can't do that with |
That's likely linked to
|
From
@JDPailleux, will you be looking into a different way of structuring the warning flags as part of this patch? I have requested reviews from others for the non-driver parts of this PR. |
@tarunprabhu Yes, it's planned to restructure the warnings flags in this patch by using the Clang Diagnostics or a similar mechanism. |
Ok, thanks 👍🏾 Feel free to open a different PR for those changes if that feels more appropriate. |
900b32a
to
46f8e51
Compare
✅ With the latest revision this PR passed the C/C++ code formatter. |
46f8e51
to
ab53339
Compare
…riable Addition of two new warning options and a diagnostic system for Flang based on the Clang's diagnostics.
ab53339
to
86e34cf
Compare
Thanks for working on this @JDPailleux. This looks like a substantial change including to parts of clang. Is it possible to split this into two. One PR for just the "infrastructure" and another for the flang-specifc warnings. This would make it easier to focus the discussion on the design. Could you also provide a high-level description of the approach that you have taken? Thanks. |
Yes of course, I'll split this in 2 PRs. |
Hi, A PR has been created to support a diagnostic system for Flang here: #130593. |
Adding support of new warning flags
-W[no-]unused-dummy-argument
and-W[no-]unused-variable
.Used in ECRAD, but not a mandatory flags for the project (https://github.com/ecmwf-ifs/ecrad).
I think it could be usefull to develop various Fortran projects and avoiding unused dummy arguments / variables.
-Wunused-dummy-argument
: Warn about unused dummy arguments.-Wunused-variable
: Warn whenever a local variable or non-constant static variable is unused aside from its declaration.