[clang] [flang] [flang] Add options -W[no-]unused-dummy-argument and -W[no-]unused-variable (PR #127214)
Jean-Didier PAILLEUX via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 7 01:42:08 PST 2025
https://github.com/JDPailleux updated https://github.com/llvm/llvm-project/pull/127214
>From 86e34cf5a7b652b0ce0158b9687543691cba7ab7 Mon Sep 17 00:00:00 2001
From: Jean-Didier Pailleux <jean-didier.pailleux at sipearl.com>
Date: Fri, 7 Mar 2025 08:31:46 +0100
Subject: [PATCH] [flang] Add options -W[no-]unused-dummy-argument and
-W[no-]unused-variable
Addition of two new warning options and a diagnostic system for Flang
based on the Clang's diagnostics.
---
clang/include/clang/Basic/Diagnostic.td | 5 +-
.../clang/Basic/DiagnosticCategories.h | 3 +-
clang/include/clang/Basic/DiagnosticGroups.td | 5 +-
clang/include/clang/Basic/DiagnosticIDs.h | 5 +
.../clang/Basic/DiagnosticSemaKinds.td | 6 ++
clang/lib/Basic/DiagnosticIDs.cpp | 14 ++-
clang/lib/Basic/Warnings.cpp | 9 ++
clang/test/TableGen/DiagnosticBase.inc | 4 +-
clang/tools/diagtool/DiagnosticNames.cpp | 3 +-
.../TableGen/ClangDiagnosticsEmitter.cpp | 4 +
.../flang/Frontend/CompilerInvocation.h | 10 +-
flang/include/flang/Semantics/semantics.h | 5 +-
flang/include/flang/Semantics/symbol.h | 3 +
flang/lib/Frontend/CMakeLists.txt | 1 +
flang/lib/Frontend/CompilerInstance.cpp | 3 +-
flang/lib/Frontend/CompilerInvocation.cpp | 50 +++++----
flang/lib/Frontend/Warnings.cpp | 102 ++++++++++++++++++
flang/lib/Semantics/CMakeLists.txt | 4 +
flang/lib/Semantics/check-warning.cpp | 89 +++++++++++++++
flang/lib/Semantics/check-warning.h | 36 +++++++
flang/lib/Semantics/expression.cpp | 7 ++
flang/lib/Semantics/resolve-names.cpp | 5 +
flang/lib/Semantics/semantics.cpp | 7 +-
flang/test/Driver/w-arg-unknown.f90 | 7 ++
flang/test/Driver/werror-wrong.f90 | 6 --
flang/test/Driver/wextra-ok.f90 | 4 +-
.../test/Semantics/wunused-dummy-argument.f90 | 54 ++++++++++
flang/test/Semantics/wunused-variable.f90 | 72 +++++++++++++
flang/tools/bbc/CMakeLists.txt | 5 +
flang/tools/bbc/bbc.cpp | 14 ++-
flang/tools/flang-driver/driver.cpp | 10 +-
flang/tools/flang-driver/fc1_main.cpp | 19 ++--
32 files changed, 518 insertions(+), 53 deletions(-)
create mode 100644 flang/lib/Frontend/Warnings.cpp
create mode 100644 flang/lib/Semantics/check-warning.cpp
create mode 100644 flang/lib/Semantics/check-warning.h
create mode 100644 flang/test/Driver/w-arg-unknown.f90
delete mode 100644 flang/test/Driver/werror-wrong.f90
create mode 100644 flang/test/Semantics/wunused-dummy-argument.f90
create mode 100644 flang/test/Semantics/wunused-variable.f90
diff --git a/clang/include/clang/Basic/Diagnostic.td b/clang/include/clang/Basic/Diagnostic.td
index 0b8b3af939ba0..b3a2e76ddc453 100644
--- a/clang/include/clang/Basic/Diagnostic.td
+++ b/clang/include/clang/Basic/Diagnostic.td
@@ -55,11 +55,14 @@ class DiagCategory<string Name> {
}
// Diagnostic Groups.
-class DiagGroup<string Name, list<DiagGroup> subgroups = [], code docs = [{}]> {
+class DiagGroup<string Name, list<DiagGroup> subgroups = [], code docs = [{}],
+ bit clangDiag = 1, bit flangDiag = 0> {
string GroupName = Name;
list<DiagGroup> SubGroups = subgroups;
string CategoryName = "";
code Documentation = docs;
+ bit IsClangDiag = clangDiag;
+ bit IsFlangDiag = flangDiag;
}
class InGroup<DiagGroup G> { DiagGroup Group = G; }
//class IsGroup<string Name> { DiagGroup Group = DiagGroup<Name>; }
diff --git a/clang/include/clang/Basic/DiagnosticCategories.h b/clang/include/clang/Basic/DiagnosticCategories.h
index 839f8dee3ca89..5e44889a2fcd8 100644
--- a/clang/include/clang/Basic/DiagnosticCategories.h
+++ b/clang/include/clang/Basic/DiagnosticCategories.h
@@ -21,7 +21,8 @@ namespace clang {
};
enum class Group {
-#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
+#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs, \
+ IsClang, IsFlang) \
GroupName,
#include "clang/Basic/DiagnosticGroups.inc"
#undef CATEGORY
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 05e39899e6f25..edff8b3ed84cf 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -885,12 +885,13 @@ def UnevaluatedExpression : DiagGroup<"unevaluated-expression",
def UnusedValue : DiagGroup<"unused-value", [UnusedComparison, UnusedResult,
UnevaluatedExpression]>;
def UnusedConstVariable : DiagGroup<"unused-const-variable">;
-def UnusedVariable : DiagGroup<"unused-variable",
- [UnusedConstVariable]>;
+def UnusedVariable
+ : DiagGroup<"unused-variable", [UnusedConstVariable], [{}], 1, 1>;
def UnusedButSetVariable : DiagGroup<"unused-but-set-variable">;
def UnusedLocalTypedef : DiagGroup<"unused-local-typedef">;
def UnusedPropertyIvar : DiagGroup<"unused-property-ivar">;
def UnusedGetterReturnValue : DiagGroup<"unused-getter-return-value">;
+def UnusedDummyArgument : DiagGroup<"unused-dummy-argument", [], [{}], 0, 1>;
def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">;
def UsedSearchPath : DiagGroup<"search-path-usage">;
def UserDefinedLiterals : DiagGroup<"user-defined-literals">;
diff --git a/clang/include/clang/Basic/DiagnosticIDs.h b/clang/include/clang/Basic/DiagnosticIDs.h
index b49185c3335d8..2ae737b1a1031 100644
--- a/clang/include/clang/Basic/DiagnosticIDs.h
+++ b/clang/include/clang/Basic/DiagnosticIDs.h
@@ -365,6 +365,11 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
/// Given a diagnostic group ID, return its documentation.
static StringRef getWarningOptionDocumentation(diag::Group GroupID);
+ /// Given a diagnostic group ID, return true if its a Flang warning.
+ static bool isFlangWarningOption(diag::Group Group);
+ /// Given a diagnostic group ID, return true if its a Clang warning.
+ static bool isClangWarningOption(diag::Group Group);
+
void setGroupSeverity(StringRef Group, diag::Severity);
void setGroupNoWarningsAsError(StringRef Group, bool);
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 2fce5e88ba8a0..4ab94ecbb7e56 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12966,4 +12966,10 @@ def note_acc_atomic_mismatch_compound_operand
// AMDGCN builtins diagnostics
def err_amdgcn_global_load_lds_size_invalid_value : Error<"invalid size value">;
def note_amdgcn_global_load_lds_size_valid_value : Note<"size must be %select{1, 2, or 4|1, 2, 4, 12 or 16}0">;
+
+// Flang diagnostics
+def warn_unused_dummy_argument : Warning<"unused dummy argument %0">,
+ InGroup<UnusedDummyArgument>,
+ DefaultIgnore;
+
} // end of sema component.
diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp
index ca5b8d2da769e..e275f7165b392 100644
--- a/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/clang/lib/Basic/DiagnosticIDs.cpp
@@ -585,6 +585,8 @@ namespace {
uint16_t Members;
uint16_t SubGroups;
StringRef Documentation;
+ bool IsClangDiag;
+ bool IsFlangDiag;
StringRef getName() const { return DiagGroupNames[NameOffset]; }
};
@@ -592,8 +594,9 @@ namespace {
// Second the table of options, sorted by name for fast binary lookup.
static const WarningOption OptionTable[] = {
-#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
- {FlagNameOffset, Members, SubGroups, Docs},
+#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs, \
+ IsClang, IsFlang) \
+ {FlagNameOffset, Members, SubGroups, Docs, IsClang, IsFlang},
#include "clang/Basic/DiagnosticGroups.inc"
#undef DIAG_ENTRY
};
@@ -607,6 +610,13 @@ StringRef DiagnosticIDs::getWarningOptionForGroup(diag::Group Group) {
return OptionTable[static_cast<int>(Group)].getName();
}
+bool DiagnosticIDs::isFlangWarningOption(diag::Group Group) {
+ return OptionTable[static_cast<int>(Group)].IsFlangDiag;
+}
+
+bool DiagnosticIDs::isClangWarningOption(diag::Group Group) {
+ return OptionTable[static_cast<int>(Group)].IsClangDiag;
+}
std::optional<diag::Group>
DiagnosticIDs::getGroupForWarningOption(StringRef Name) {
const auto *Found = llvm::partition_point(
diff --git a/clang/lib/Basic/Warnings.cpp b/clang/lib/Basic/Warnings.cpp
index 5f48e0ec81554..e6c1355650113 100644
--- a/clang/lib/Basic/Warnings.cpp
+++ b/clang/lib/Basic/Warnings.cpp
@@ -106,6 +106,15 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
diag::Severity Mapping =
isPositive ? diag::Severity::Warning : diag::Severity::Ignored;
+ // Check if the warning option is valid for Clang
+ std::optional<diag::Group> Group = DiagIDs->getGroupForWarningOption(Opt);
+ if (Group.has_value() && !DiagIDs->isClangWarningOption(Group.value())) {
+ const unsigned DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "Warning option \"%0\" is valid for Fortran but not for C++.");
+ Diags.Report(DiagID) << Opt;
+ }
+
// -Wsystem-headers is a special case, not driven by the option table. It
// cannot be controlled with -Werror.
if (Opt == "system-headers") {
diff --git a/clang/test/TableGen/DiagnosticBase.inc b/clang/test/TableGen/DiagnosticBase.inc
index 2fc7bb4266edb..359c6d1edd79a 100644
--- a/clang/test/TableGen/DiagnosticBase.inc
+++ b/clang/test/TableGen/DiagnosticBase.inc
@@ -55,11 +55,13 @@ class DiagCategory<string Name> {
}
// Diagnostic Groups.
-class DiagGroup<string Name, list<DiagGroup> subgroups = []> {
+class DiagGroup<string Name, list<DiagGroup> subgroups = [], bit clangDiag = 1, bit flangDiag = 0> {
string GroupName = Name;
list<DiagGroup> SubGroups = subgroups;
string CategoryName = "";
code Documentation = [{}];
+ bit IsClangDiag = clangDiag;
+ bit IsFlangDiag = flangDiag;
}
class InGroup<DiagGroup G> { DiagGroup Group = G; }
//class IsGroup<string Name> { DiagGroup Group = DiagGroup<Name>; }
diff --git a/clang/tools/diagtool/DiagnosticNames.cpp b/clang/tools/diagtool/DiagnosticNames.cpp
index 4ac9825848ef3..95b9da461599b 100644
--- a/clang/tools/diagtool/DiagnosticNames.cpp
+++ b/clang/tools/diagtool/DiagnosticNames.cpp
@@ -62,7 +62,8 @@ const DiagnosticRecord &diagtool::getDiagnosticForID(short DiagID) {
// Second the table of options, sorted by name for fast binary lookup.
static const GroupRecord OptionTable[] = {
-#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
+#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs, \
+ IsClang, IsFlang) \
{FlagNameOffset, Members, SubGroups},
#include "clang/Basic/DiagnosticGroups.inc"
#undef DIAG_ENTRY
diff --git a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
index 8f846a4744bbf..0c0962f6fceaa 100644
--- a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
+++ b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
@@ -1890,6 +1890,10 @@ static void emitDiagTable(DiagsInGroupTy &DiagsInGroup,
OS << "R\"(" << StringRef(Documentation).trim() << ")\"";
+ OS << ", /*IsClangDiag*/ "
+ << bool(GroupInfo.Defs.back()->getValueAsBit("IsClangDiag"));
+ OS << ", /*IsFlangDiag*/ "
+ << bool(GroupInfo.Defs.back()->getValueAsBit("IsFlangDiag"));
OS << ")\n";
}
OS << "#endif // DIAG_ENTRY\n\n";
diff --git a/flang/include/flang/Frontend/CompilerInvocation.h b/flang/include/flang/Frontend/CompilerInvocation.h
index 9e6724be33033..9fdaeac3d999a 100644
--- a/flang/include/flang/Frontend/CompilerInvocation.h
+++ b/flang/include/flang/Frontend/CompilerInvocation.h
@@ -33,12 +33,18 @@ class TargetMachine;
namespace Fortran::frontend {
+/// processWarningOptions - Initialize the diagnostic client and process the
+/// warning options specified on the command line.
+void processWarningOptions(clang::DiagnosticsEngine &Diags,
+ const clang::DiagnosticOptions &Opts);
+
/// Fill out Opts based on the options given in Args.
///
/// When errors are encountered, return false and, if Diags is non-null,
/// report the error(s).
bool parseDiagnosticArgs(clang::DiagnosticOptions &opts,
- llvm::opt::ArgList &args);
+ llvm::opt::ArgList &args,
+ bool defaultDiagColor = true);
class CompilerInvocationBase {
public:
@@ -174,7 +180,7 @@ class CompilerInvocation : public CompilerInvocationBase {
/// Creates and configures semantics context based on the compilation flags.
std::unique_ptr<Fortran::semantics::SemanticsContext>
getSemanticsCtx(Fortran::parser::AllCookedSources &allCookedSources,
- const llvm::TargetMachine &);
+ const llvm::TargetMachine &, clang::DiagnosticsEngine &diag);
std::string &getModuleDir() { return moduleDir; }
const std::string &getModuleDir() const { return moduleDir; }
diff --git a/flang/include/flang/Semantics/semantics.h b/flang/include/flang/Semantics/semantics.h
index 730513dbe3232..72ecd046f4048 100644
--- a/flang/include/flang/Semantics/semantics.h
+++ b/flang/include/flang/Semantics/semantics.h
@@ -19,6 +19,7 @@
#include "flang/Parser/message.h"
#include "flang/Support/Fortran-features.h"
#include "flang/Support/LangOptions.h"
+#include "clang/Basic/Diagnostic.h"
#include <iosfwd>
#include <set>
#include <string>
@@ -68,7 +69,7 @@ class SemanticsContext {
public:
SemanticsContext(const common::IntrinsicTypeDefaultKinds &,
const common::LanguageFeatureControl &, const common::LangOptions &,
- parser::AllCookedSources &);
+ parser::AllCookedSources &, clang::DiagnosticsEngine &);
~SemanticsContext();
const common::IntrinsicTypeDefaultKinds &defaultKinds() const {
@@ -82,6 +83,7 @@ class SemanticsContext {
int doublePrecisionKind() const {
return defaultKinds_.doublePrecisionKind();
}
+ clang::DiagnosticsEngine &getDiagnostics() const { return diags_; }
int quadPrecisionKind() const { return defaultKinds_.quadPrecisionKind(); }
bool IsEnabled(common::LanguageFeature feature) const {
return languageFeatures_.IsEnabled(feature);
@@ -305,6 +307,7 @@ class SemanticsContext {
const common::IntrinsicTypeDefaultKinds &defaultKinds_;
const common::LanguageFeatureControl &languageFeatures_;
const common::LangOptions &langOpts_;
+ clang::DiagnosticsEngine &diags_;
parser::AllCookedSources &allCookedSources_;
std::optional<parser::CharBlock> location_;
std::vector<std::string> searchDirectories_;
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/lib/Frontend/CMakeLists.txt b/flang/lib/Frontend/CMakeLists.txt
index 81eef2d468d8c..ac03f8ab4cce7 100644
--- a/flang/lib/Frontend/CMakeLists.txt
+++ b/flang/lib/Frontend/CMakeLists.txt
@@ -11,6 +11,7 @@ add_flang_library(flangFrontend
TextDiagnosticPrinter.cpp
TextDiagnosticBuffer.cpp
TextDiagnostic.cpp
+ Warnings.cpp
DEPENDS
CUFDialect
diff --git a/flang/lib/Frontend/CompilerInstance.cpp b/flang/lib/Frontend/CompilerInstance.cpp
index b1fa32ecb4cfc..6374a8b0d45bd 100644
--- a/flang/lib/Frontend/CompilerInstance.cpp
+++ b/flang/lib/Frontend/CompilerInstance.cpp
@@ -163,7 +163,8 @@ bool CompilerInstance::executeAction(FrontendAction &act) {
if (!setUpTargetMachine())
return false;
// Create the semantics context
- semaContext = invoc.getSemanticsCtx(*allCookedSources, getTargetMachine());
+ semaContext = invoc.getSemanticsCtx(*allCookedSources, getTargetMachine(),
+ getDiagnostics());
// Set options controlling lowering to FIR.
invoc.setLoweringOptions();
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index f3d9432c62d3b..4a1f73bb76fba 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -32,6 +32,7 @@
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
+#include "llvm/Option/Option.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileUtilities.h"
@@ -118,9 +119,26 @@ static unsigned getOptimizationLevel(llvm::opt::ArgList &args,
}
bool Fortran::frontend::parseDiagnosticArgs(clang::DiagnosticOptions &opts,
- llvm::opt::ArgList &args) {
- opts.ShowColors = parseShowColorsArgs(args);
-
+ llvm::opt::ArgList &args,
+ bool defaultDiagColor) {
+ opts.ShowColors = parseShowColorsArgs(args, defaultDiagColor);
+
+ for (llvm::opt::Arg *A : args.filtered(clang::driver::options::OPT_W_Group)) {
+ if (A->getOption().getKind() == llvm::opt::Option::FlagClass) {
+ // The argument is a pure flag (such as OPT_Wall).
+ opts.Warnings.push_back(
+ std::string(A->getOption().getName().drop_front(1)));
+ } else if (A->getOption().matches(
+ clang::driver::options::OPT_W_value_Group)) {
+ // This is -Wfoo= where foo is the name of the diagnostic group.
+ // Add only the group name to the diagnostics.
+ opts.Warnings.push_back(
+ std::string(A->getOption().getName().drop_front(1).rtrim("=-")));
+ } else {
+ // Otherwise, add its value for OPT_W_Joined.
+ opts.Warnings.push_back(A->getValue());
+ }
+ }
return true;
}
@@ -923,22 +941,11 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
clang::DiagnosticsEngine &diags) {
unsigned numErrorsBefore = diags.getNumErrors();
- // -Werror option
- // TODO: Currently throws a Diagnostic for anything other than -W<error>,
- // this has to change when other -W<opt>'s are supported.
- if (args.hasArg(clang::driver::options::OPT_W_Joined)) {
- const auto &wArgs =
- args.getAllArgValues(clang::driver::options::OPT_W_Joined);
- for (const auto &wArg : wArgs) {
- if (wArg == "error") {
- res.setWarnAsErr(true);
- } else {
- const unsigned diagID =
- diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
- "Only `-Werror` is supported currently.");
- diags.Report(diagID);
- }
- }
+ // Handle warning Diagnostic for the frontend.
+ clang::DiagnosticOptions &diagOpts = res.getDiagnosticOpts();
+ for (const auto &warning : diagOpts.Warnings) {
+ if (warning == "error")
+ res.setWarnAsErr(true);
}
// Default to off for `flang -fc1`.
@@ -1000,6 +1007,7 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
if (args.hasArg(clang::driver::options::OPT_pedantic)) {
res.setEnableConformanceChecks();
res.setEnableUsageChecks();
+ res.getDiagnosticOpts().Pedantic = true;
}
// -w
@@ -1620,12 +1628,12 @@ void CompilerInvocation::setFortranOpts() {
std::unique_ptr<Fortran::semantics::SemanticsContext>
CompilerInvocation::getSemanticsCtx(
Fortran::parser::AllCookedSources &allCookedSources,
- const llvm::TargetMachine &targetMachine) {
+ const llvm::TargetMachine &targetMachine, clang::DiagnosticsEngine &diags) {
auto &fortranOptions = getFortranOpts();
auto semanticsContext = std::make_unique<semantics::SemanticsContext>(
getDefaultKinds(), fortranOptions.features, getLangOpts(),
- allCookedSources);
+ allCookedSources, diags);
semanticsContext->set_moduleDirectory(getModuleDir())
.set_searchDirectories(fortranOptions.searchDirectories)
diff --git a/flang/lib/Frontend/Warnings.cpp b/flang/lib/Frontend/Warnings.cpp
new file mode 100644
index 0000000000000..70e93efdd866d
--- /dev/null
+++ b/flang/lib/Frontend/Warnings.cpp
@@ -0,0 +1,102 @@
+//===--- Warnings.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
+//
+//===----------------------------------------------------------------------===//
+//
+// Command line warning options handler.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is responsible for handling all warning options. This includes
+// a number of -Wfoo options and their variants, which are driven by TableGen-
+// generated data, and the special cases -pedantic, -pedantic-errors, -w,
+// -Werror, ...
+//
+// Each warning option controls any number of actual warnings.
+// Given a warning option 'foo', the following are valid:
+// -Wfoo, -Wno-foo, -Werror=foo
+//
+#include "clang/Basic/AllDiagnostics.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticDriver.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "llvm/ADT/StringRef.h"
+#include <cstring>
+
+namespace Fortran::frontend {
+
+// EmitUnknownDiagWarning - Emit a warning and typo hint for unknown warning
+// opts
+
+static void EmitUnknownDiagWarning(clang::DiagnosticsEngine &diags,
+ clang::diag::Flavor flavor,
+ llvm::StringRef prefix,
+ llvm::StringRef opt) {
+ llvm::StringRef suggestion =
+ clang::DiagnosticIDs::getNearestOption(flavor, opt);
+ diags.Report(clang::diag::warn_unknown_diag_option)
+ << (flavor == clang::diag::Flavor::WarningOrError ? 0 : 1)
+ << (prefix.str() += std::string(opt)) << !suggestion.empty()
+ << (prefix.str() += std::string(suggestion));
+}
+
+void processWarningOptions(clang::DiagnosticsEngine &diags,
+ const clang::DiagnosticOptions &opts) {
+ diags.setIgnoreAllWarnings(opts.IgnoreWarnings);
+ diags.setShowColors(opts.ShowColors);
+
+ // If -pedantic or -pedantic-errors was specified, then we want to map all
+ // extension diagnostics onto WARNING or ERROR.
+ if (opts.PedanticErrors)
+ diags.setExtensionHandlingBehavior(clang::diag::Severity::Error);
+ else if (opts.Pedantic)
+ diags.setExtensionHandlingBehavior(clang::diag::Severity::Warning);
+ else
+ diags.setExtensionHandlingBehavior(clang::diag::Severity::Ignored);
+
+ llvm::SmallVector<clang::diag::kind, 10> _diags;
+ const llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagIDs =
+ diags.getDiagnosticIDs();
+ for (unsigned i = 0, e = opts.Warnings.size(); i != e; ++i) {
+ const auto flavor = clang::diag::Flavor::WarningOrError;
+ llvm::StringRef opt = opts.Warnings[i];
+
+ // Check to see if this warning starts with "no-", if so, this is a
+ // negative form of the option.
+ bool isPositive = !opt.consume_front("no-");
+
+ // Figure out how this option affects the warning. If -Wfoo, map the
+ // diagnostic to a warning, if -Wno-foo, map it to ignore.
+ clang::diag::Severity mapping = isPositive ? clang::diag::Severity::Warning
+ : clang::diag::Severity::Ignored;
+
+ // -Werror/-Wno-error is a special case, not controlled by the option table.
+ // TODO: Adding support of "specifier" form of -Werror=foo.
+ if (opt == "error") {
+ diags.setWarningsAsErrors(isPositive);
+ continue;
+ }
+
+ if (std::optional<clang::diag::Group> group =
+ diagIDs->getGroupForWarningOption(opt)) {
+ if (!diagIDs->isFlangWarningOption(group.value())) {
+ // Warning option not supported by Flang
+ // FIXME : Updating diagnostic error message when all warning options
+ // will be supported
+ const unsigned diagID =
+ diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
+ "Warning option \"%0\" not supported.");
+ diags.Report(diagID) << opt;
+ }
+ } else {
+ // Unkown warning option.
+ EmitUnknownDiagWarning(diags, flavor, isPositive ? "-W" : "-Wno-", opt);
+ }
+ diags.setSeverityForGroup(flavor, opt, mapping);
+ }
+}
+} // namespace Fortran::frontend
diff --git a/flang/lib/Semantics/CMakeLists.txt b/flang/lib/Semantics/CMakeLists.txt
index 00108dde49dbd..7182a23cb7352 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
@@ -62,4 +63,7 @@ add_flang_library(FortranSemantics
FrontendOpenMP
FrontendOpenACC
TargetParser
+
+ CLANG_LIBS
+ clangBasic
)
diff --git a/flang/lib/Semantics/check-warning.cpp b/flang/lib/Semantics/check-warning.cpp
new file mode 100644
index 0000000000000..512b9237ea8d9
--- /dev/null
+++ b/flang/lib/Semantics/check-warning.cpp
@@ -0,0 +1,89 @@
+//===-- 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"
+#include "clang/Basic/AllDiagnostics.h"
+#include "clang/Basic/DiagnosticDriver.h"
+#include "clang/Basic/DiagnosticOptions.h"
+
+namespace Fortran::semantics {
+
+void WarningChecker::Enter(const parser::FunctionStmt &stmt) {
+ clang::DiagnosticsEngine &diags = context_.getDiagnostics();
+ auto opts = diags.getDiagnosticOptions().Warnings;
+ 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()) {
+ diags.Report(clang::diag::warn_unused_dummy_argument)
+ << dummyName.ToString();
+ }
+ }
+ }
+ 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()) {
+ diags.Report(clang::diag::warn_unused_variable)
+ << suffix->resultName->ToString();
+ }
+ }
+ }
+ }
+}
+
+void WarningChecker::Enter(const parser::SubroutineStmt &stmt) {
+ clang::DiagnosticsEngine &diags = context_.getDiagnostics();
+ 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()) {
+ diags.Report(clang::diag::warn_unused_dummy_argument)
+ << dummyName->ToString();
+ }
+ }
+ }
+ }
+ }
+}
+
+void WarningChecker::Enter(const parser::EntityDecl &decl) {
+ clang::DiagnosticsEngine &diags = context_.getDiagnostics();
+ const auto &name{std::get<parser::ObjectName>(decl.t)};
+ if (const auto *symbol = name.symbol) {
+ if (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()) {
+ diags.Report(clang::diag::warn_unused_variable) << 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..33e9187e9c0e4
--- /dev/null
+++ b/flang/lib/Semantics/check-warning.h
@@ -0,0 +1,36 @@
+//===-- 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_;
+};
+} // 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..4b5b31fe606ca 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,7 @@ static bool PerformStatementSemantics(
if (context.languageFeatures().IsEnabled(common::LanguageFeature::CUDA)) {
SemanticsVisitor<CUDAChecker>{context}.Walk(program);
}
+ StatementSemanticsPass3{context}.Walk(program);
if (!context.messages().AnyFatalError()) {
WarnUndefinedFunctionResult(context, context.globalScope());
}
@@ -346,9 +349,9 @@ SemanticsContext::SemanticsContext(
const common::IntrinsicTypeDefaultKinds &defaultKinds,
const common::LanguageFeatureControl &languageFeatures,
const common::LangOptions &langOpts,
- parser::AllCookedSources &allCookedSources)
+ parser::AllCookedSources &allCookedSources, clang::DiagnosticsEngine &diags)
: defaultKinds_{defaultKinds}, languageFeatures_{languageFeatures},
- langOpts_{langOpts}, allCookedSources_{allCookedSources},
+ langOpts_{langOpts}, allCookedSources_{allCookedSources}, diags_{diags},
intrinsics_{evaluate::IntrinsicProcTable::Configure(defaultKinds_)},
globalScope_{*this}, intrinsicModulesScope_{globalScope_.MakeScope(
Scope::Kind::IntrinsicModules, nullptr)},
diff --git a/flang/test/Driver/w-arg-unknown.f90 b/flang/test/Driver/w-arg-unknown.f90
new file mode 100644
index 0000000000000..19b39f6cb3b33
--- /dev/null
+++ b/flang/test/Driver/w-arg-unknown.f90
@@ -0,0 +1,7 @@
+! Ensure that unknown warning options generate a warning message.
+
+! RUN: %flang_fc1 -fsyntax-only -WX %s 2>&1 | FileCheck %s --check-prefix=UNKNOWN1
+! RUN: %flang_fc1 -fsyntax-only -Werror2 %s 2>&1 | FileCheck %s --check-prefix=UNKNOWN2
+
+! UNKNOWN1: unknown warning option '-WX'
+! UNKNOWN2: unknown warning option '-Werror2'
diff --git a/flang/test/Driver/werror-wrong.f90 b/flang/test/Driver/werror-wrong.f90
deleted file mode 100644
index 58adf6f745d5e..0000000000000
--- a/flang/test/Driver/werror-wrong.f90
+++ /dev/null
@@ -1,6 +0,0 @@
-! Ensure that only argument -Werror is supported.
-
-! 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.
diff --git a/flang/test/Driver/wextra-ok.f90 b/flang/test/Driver/wextra-ok.f90
index 441029aa0af27..63c18c3ad2b12 100644
--- a/flang/test/Driver/wextra-ok.f90
+++ b/flang/test/Driver/wextra-ok.f90
@@ -2,10 +2,10 @@
! The first check should be changed if -Wextra is implemented
! RUN: %flang -std=f2018 -Wextra %s -c 2>&1 | FileCheck %s --check-prefix=CHECK-OK
-! RUN: not %flang -std=f2018 -Wblah -Wextra %s -c 2>&1 | FileCheck %s --check-prefix=WRONG
+! RUN: %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: unknown warning option '-Wblah'
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..e09132aec5342
--- /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..28f1b3aacbc3f
--- /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
diff --git a/flang/tools/bbc/CMakeLists.txt b/flang/tools/bbc/CMakeLists.txt
index f950f03920d3f..7c6ac4220ca33 100644
--- a/flang/tools/bbc/CMakeLists.txt
+++ b/flang/tools/bbc/CMakeLists.txt
@@ -31,6 +31,11 @@ target_link_libraries(bbc PRIVATE
FlangOpenMPTransforms
)
+clang_target_link_libraries(bbc PRIVATE
+ PRIVATE
+ clangBasic
+)
+
mlir_target_link_libraries(bbc PRIVATE
${dialect_libs}
${extension_libs}
diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp
index 3b19a1c2a78d9..0a07eee2da839 100644
--- a/flang/tools/bbc/bbc.cpp
+++ b/flang/tools/bbc/bbc.cpp
@@ -15,7 +15,10 @@
//===----------------------------------------------------------------------===//
#include "flang/Frontend/CodeGenOptions.h"
+#include "flang/Frontend/CompilerInstance.h"
+#include "flang/Frontend/CompilerInvocation.h"
#include "flang/Frontend/TargetOptions.h"
+#include "flang/Frontend/TextDiagnosticBuffer.h"
#include "flang/Lower/Bridge.h"
#include "flang/Lower/PFTBuilder.h"
#include "flang/Lower/Support/Verifier.h"
@@ -492,6 +495,15 @@ static llvm::LogicalResult convertFortranSourceToMLIR(
}
int main(int argc, char **argv) {
+ // Creating a SemanticsContext require a DiagnosticsEngine
+ Fortran::frontend::TextDiagnosticBuffer *diagsBuffer =
+ new Fortran::frontend::TextDiagnosticBuffer;
+ llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagID(
+ new clang::DiagnosticIDs());
+ llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> diagOpts =
+ new clang::DiagnosticOptions();
+ clang::DiagnosticsEngine diags(diagID, &*diagOpts, diagsBuffer);
+
[[maybe_unused]] llvm::InitLLVM y(argc, argv);
llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
@@ -573,7 +585,7 @@ int main(int argc, char **argv) {
Fortran::parser::AllSources allSources;
Fortran::parser::AllCookedSources allCookedSources(allSources);
Fortran::semantics::SemanticsContext semanticsContext{
- defaultKinds, options.features, langOpts, allCookedSources};
+ defaultKinds, options.features, langOpts, allCookedSources, diags};
semanticsContext.set_moduleDirectory(moduleDir)
.set_moduleFileSuffix(moduleSuffix)
.set_searchDirectories(includeDirs)
diff --git a/flang/tools/flang-driver/driver.cpp b/flang/tools/flang-driver/driver.cpp
index ed52988feaa59..a6c616289f28a 100644
--- a/flang/tools/flang-driver/driver.cpp
+++ b/flang/tools/flang-driver/driver.cpp
@@ -115,12 +115,20 @@ int main(int argc, const char **argv) {
// Create DiagnosticsEngine for the compiler driver
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> diagOpts =
- createAndPopulateDiagOpts(args);
+ new clang::DiagnosticOptions();
llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagID(
new clang::DiagnosticIDs());
Fortran::frontend::TextDiagnosticPrinter *diagClient =
new Fortran::frontend::TextDiagnosticPrinter(llvm::errs(), &*diagOpts);
+ // Use the DiagnosticsEngine instance of the frontend driver
+ // for parsing the arguments
+ unsigned missingArgIndex, missingArgCount;
+ llvm::opt::InputArgList args2 = clang::driver::getDriverOptTable().ParseArgs(
+ args, missingArgIndex, missingArgCount,
+ llvm::opt::Visibility(clang::driver::options::FlangOption));
+ Fortran::frontend::parseDiagnosticArgs(*diagOpts, args2);
+
diagClient->setPrefix(
std::string(llvm::sys::path::stem(getExecutablePath(args[0]))));
diff --git a/flang/tools/flang-driver/fc1_main.cpp b/flang/tools/flang-driver/fc1_main.cpp
index 561a0dd5524e3..af98d8b0c6993 100644
--- a/flang/tools/flang-driver/fc1_main.cpp
+++ b/flang/tools/flang-driver/fc1_main.cpp
@@ -20,6 +20,7 @@
#include "flang/Frontend/CompilerInvocation.h"
#include "flang/Frontend/TextDiagnosticBuffer.h"
#include "flang/FrontendTool/Utils.h"
+#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Option/Arg.h"
@@ -63,15 +64,17 @@ int fc1_main(llvm::ArrayRef<const char *> argv, const char *argv0) {
// them using a well formed diagnostic object.
TextDiagnosticBuffer *diagsBuffer = new TextDiagnosticBuffer;
- // Create CompilerInvocation - use a dedicated instance of DiagnosticsEngine
+ // Use the DiagnosticsEngine instance of the frontend driver
// for parsing the arguments
- llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagID(
- new clang::DiagnosticIDs());
- llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> diagOpts =
- new clang::DiagnosticOptions();
- clang::DiagnosticsEngine diags(diagID, &*diagOpts, diagsBuffer);
- bool success = CompilerInvocation::createFromArgs(flang->getInvocation(),
- argv, diags, argv0);
+ unsigned missingArgIndex, missingArgCount;
+ llvm::opt::InputArgList args = clang::driver::getDriverOptTable().ParseArgs(
+ argv.slice(0), missingArgIndex, missingArgCount,
+ llvm::opt::Visibility(clang::driver::options::FC1Option));
+ parseDiagnosticArgs(flang->getDiagnosticOpts(), args, false);
+
+ bool success = CompilerInvocation::createFromArgs(
+ flang->getInvocation(), argv, flang->getDiagnostics(), argv0);
+ processWarningOptions(flang->getDiagnostics(), flang->getDiagnosticOpts());
// Initialize targets first, so that --version shows registered targets.
llvm::InitializeAllTargets();
More information about the cfe-commits
mailing list