Skip to content

Commit 86e34cf

Browse files
committed
[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.
1 parent 2077d40 commit 86e34cf

32 files changed

+518
-53
lines changed

clang/include/clang/Basic/Diagnostic.td

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,14 @@ class DiagCategory<string Name> {
5555
}
5656

5757
// Diagnostic Groups.
58-
class DiagGroup<string Name, list<DiagGroup> subgroups = [], code docs = [{}]> {
58+
class DiagGroup<string Name, list<DiagGroup> subgroups = [], code docs = [{}],
59+
bit clangDiag = 1, bit flangDiag = 0> {
5960
string GroupName = Name;
6061
list<DiagGroup> SubGroups = subgroups;
6162
string CategoryName = "";
6263
code Documentation = docs;
64+
bit IsClangDiag = clangDiag;
65+
bit IsFlangDiag = flangDiag;
6366
}
6467
class InGroup<DiagGroup G> { DiagGroup Group = G; }
6568
//class IsGroup<string Name> { DiagGroup Group = DiagGroup<Name>; }

clang/include/clang/Basic/DiagnosticCategories.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ namespace clang {
2121
};
2222

2323
enum class Group {
24-
#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
24+
#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs, \
25+
IsClang, IsFlang) \
2526
GroupName,
2627
#include "clang/Basic/DiagnosticGroups.inc"
2728
#undef CATEGORY

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -885,12 +885,13 @@ def UnevaluatedExpression : DiagGroup<"unevaluated-expression",
885885
def UnusedValue : DiagGroup<"unused-value", [UnusedComparison, UnusedResult,
886886
UnevaluatedExpression]>;
887887
def UnusedConstVariable : DiagGroup<"unused-const-variable">;
888-
def UnusedVariable : DiagGroup<"unused-variable",
889-
[UnusedConstVariable]>;
888+
def UnusedVariable
889+
: DiagGroup<"unused-variable", [UnusedConstVariable], [{}], 1, 1>;
890890
def UnusedButSetVariable : DiagGroup<"unused-but-set-variable">;
891891
def UnusedLocalTypedef : DiagGroup<"unused-local-typedef">;
892892
def UnusedPropertyIvar : DiagGroup<"unused-property-ivar">;
893893
def UnusedGetterReturnValue : DiagGroup<"unused-getter-return-value">;
894+
def UnusedDummyArgument : DiagGroup<"unused-dummy-argument", [], [{}], 0, 1>;
894895
def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">;
895896
def UsedSearchPath : DiagGroup<"search-path-usage">;
896897
def UserDefinedLiterals : DiagGroup<"user-defined-literals">;

clang/include/clang/Basic/DiagnosticIDs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,11 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
365365
/// Given a diagnostic group ID, return its documentation.
366366
static StringRef getWarningOptionDocumentation(diag::Group GroupID);
367367

368+
/// Given a diagnostic group ID, return true if its a Flang warning.
369+
static bool isFlangWarningOption(diag::Group Group);
370+
/// Given a diagnostic group ID, return true if its a Clang warning.
371+
static bool isClangWarningOption(diag::Group Group);
372+
368373
void setGroupSeverity(StringRef Group, diag::Severity);
369374
void setGroupNoWarningsAsError(StringRef Group, bool);
370375

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12966,4 +12966,10 @@ def note_acc_atomic_mismatch_compound_operand
1296612966
// AMDGCN builtins diagnostics
1296712967
def err_amdgcn_global_load_lds_size_invalid_value : Error<"invalid size value">;
1296812968
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">;
12969+
12970+
// Flang diagnostics
12971+
def warn_unused_dummy_argument : Warning<"unused dummy argument %0">,
12972+
InGroup<UnusedDummyArgument>,
12973+
DefaultIgnore;
12974+
1296912975
} // end of sema component.

clang/lib/Basic/DiagnosticIDs.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -585,15 +585,18 @@ namespace {
585585
uint16_t Members;
586586
uint16_t SubGroups;
587587
StringRef Documentation;
588+
bool IsClangDiag;
589+
bool IsFlangDiag;
588590

589591
StringRef getName() const { return DiagGroupNames[NameOffset]; }
590592
};
591593
}
592594

593595
// Second the table of options, sorted by name for fast binary lookup.
594596
static const WarningOption OptionTable[] = {
595-
#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
596-
{FlagNameOffset, Members, SubGroups, Docs},
597+
#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs, \
598+
IsClang, IsFlang) \
599+
{FlagNameOffset, Members, SubGroups, Docs, IsClang, IsFlang},
597600
#include "clang/Basic/DiagnosticGroups.inc"
598601
#undef DIAG_ENTRY
599602
};
@@ -607,6 +610,13 @@ StringRef DiagnosticIDs::getWarningOptionForGroup(diag::Group Group) {
607610
return OptionTable[static_cast<int>(Group)].getName();
608611
}
609612

613+
bool DiagnosticIDs::isFlangWarningOption(diag::Group Group) {
614+
return OptionTable[static_cast<int>(Group)].IsFlangDiag;
615+
}
616+
617+
bool DiagnosticIDs::isClangWarningOption(diag::Group Group) {
618+
return OptionTable[static_cast<int>(Group)].IsClangDiag;
619+
}
610620
std::optional<diag::Group>
611621
DiagnosticIDs::getGroupForWarningOption(StringRef Name) {
612622
const auto *Found = llvm::partition_point(

clang/lib/Basic/Warnings.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,15 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
106106
diag::Severity Mapping =
107107
isPositive ? diag::Severity::Warning : diag::Severity::Ignored;
108108

109+
// Check if the warning option is valid for Clang
110+
std::optional<diag::Group> Group = DiagIDs->getGroupForWarningOption(Opt);
111+
if (Group.has_value() && !DiagIDs->isClangWarningOption(Group.value())) {
112+
const unsigned DiagID = Diags.getCustomDiagID(
113+
DiagnosticsEngine::Error,
114+
"Warning option \"%0\" is valid for Fortran but not for C++.");
115+
Diags.Report(DiagID) << Opt;
116+
}
117+
109118
// -Wsystem-headers is a special case, not driven by the option table. It
110119
// cannot be controlled with -Werror.
111120
if (Opt == "system-headers") {

clang/test/TableGen/DiagnosticBase.inc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,13 @@ class DiagCategory<string Name> {
5555
}
5656

5757
// Diagnostic Groups.
58-
class DiagGroup<string Name, list<DiagGroup> subgroups = []> {
58+
class DiagGroup<string Name, list<DiagGroup> subgroups = [], bit clangDiag = 1, bit flangDiag = 0> {
5959
string GroupName = Name;
6060
list<DiagGroup> SubGroups = subgroups;
6161
string CategoryName = "";
6262
code Documentation = [{}];
63+
bit IsClangDiag = clangDiag;
64+
bit IsFlangDiag = flangDiag;
6365
}
6466
class InGroup<DiagGroup G> { DiagGroup Group = G; }
6567
//class IsGroup<string Name> { DiagGroup Group = DiagGroup<Name>; }

clang/tools/diagtool/DiagnosticNames.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ const DiagnosticRecord &diagtool::getDiagnosticForID(short DiagID) {
6262

6363
// Second the table of options, sorted by name for fast binary lookup.
6464
static const GroupRecord OptionTable[] = {
65-
#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
65+
#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs, \
66+
IsClang, IsFlang) \
6667
{FlagNameOffset, Members, SubGroups},
6768
#include "clang/Basic/DiagnosticGroups.inc"
6869
#undef DIAG_ENTRY

clang/utils/TableGen/ClangDiagnosticsEmitter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1890,6 +1890,10 @@ static void emitDiagTable(DiagsInGroupTy &DiagsInGroup,
18901890

18911891
OS << "R\"(" << StringRef(Documentation).trim() << ")\"";
18921892

1893+
OS << ", /*IsClangDiag*/ "
1894+
<< bool(GroupInfo.Defs.back()->getValueAsBit("IsClangDiag"));
1895+
OS << ", /*IsFlangDiag*/ "
1896+
<< bool(GroupInfo.Defs.back()->getValueAsBit("IsFlangDiag"));
18931897
OS << ")\n";
18941898
}
18951899
OS << "#endif // DIAG_ENTRY\n\n";

flang/include/flang/Frontend/CompilerInvocation.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,18 @@ class TargetMachine;
3333

3434
namespace Fortran::frontend {
3535

36+
/// processWarningOptions - Initialize the diagnostic client and process the
37+
/// warning options specified on the command line.
38+
void processWarningOptions(clang::DiagnosticsEngine &Diags,
39+
const clang::DiagnosticOptions &Opts);
40+
3641
/// Fill out Opts based on the options given in Args.
3742
///
3843
/// When errors are encountered, return false and, if Diags is non-null,
3944
/// report the error(s).
4045
bool parseDiagnosticArgs(clang::DiagnosticOptions &opts,
41-
llvm::opt::ArgList &args);
46+
llvm::opt::ArgList &args,
47+
bool defaultDiagColor = true);
4248

4349
class CompilerInvocationBase {
4450
public:
@@ -174,7 +180,7 @@ class CompilerInvocation : public CompilerInvocationBase {
174180
/// Creates and configures semantics context based on the compilation flags.
175181
std::unique_ptr<Fortran::semantics::SemanticsContext>
176182
getSemanticsCtx(Fortran::parser::AllCookedSources &allCookedSources,
177-
const llvm::TargetMachine &);
183+
const llvm::TargetMachine &, clang::DiagnosticsEngine &diag);
178184

179185
std::string &getModuleDir() { return moduleDir; }
180186
const std::string &getModuleDir() const { return moduleDir; }

flang/include/flang/Semantics/semantics.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "flang/Parser/message.h"
2020
#include "flang/Support/Fortran-features.h"
2121
#include "flang/Support/LangOptions.h"
22+
#include "clang/Basic/Diagnostic.h"
2223
#include <iosfwd>
2324
#include <set>
2425
#include <string>
@@ -68,7 +69,7 @@ class SemanticsContext {
6869
public:
6970
SemanticsContext(const common::IntrinsicTypeDefaultKinds &,
7071
const common::LanguageFeatureControl &, const common::LangOptions &,
71-
parser::AllCookedSources &);
72+
parser::AllCookedSources &, clang::DiagnosticsEngine &);
7273
~SemanticsContext();
7374

7475
const common::IntrinsicTypeDefaultKinds &defaultKinds() const {
@@ -82,6 +83,7 @@ class SemanticsContext {
8283
int doublePrecisionKind() const {
8384
return defaultKinds_.doublePrecisionKind();
8485
}
86+
clang::DiagnosticsEngine &getDiagnostics() const { return diags_; }
8587
int quadPrecisionKind() const { return defaultKinds_.quadPrecisionKind(); }
8688
bool IsEnabled(common::LanguageFeature feature) const {
8789
return languageFeatures_.IsEnabled(feature);
@@ -305,6 +307,7 @@ class SemanticsContext {
305307
const common::IntrinsicTypeDefaultKinds &defaultKinds_;
306308
const common::LanguageFeatureControl &languageFeatures_;
307309
const common::LangOptions &langOpts_;
310+
clang::DiagnosticsEngine &diags_;
308311
parser::AllCookedSources &allCookedSources_;
309312
std::optional<parser::CharBlock> location_;
310313
std::vector<std::string> searchDirectories_;

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/lib/Frontend/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ add_flang_library(flangFrontend
1111
TextDiagnosticPrinter.cpp
1212
TextDiagnosticBuffer.cpp
1313
TextDiagnostic.cpp
14+
Warnings.cpp
1415

1516
DEPENDS
1617
CUFDialect

flang/lib/Frontend/CompilerInstance.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ bool CompilerInstance::executeAction(FrontendAction &act) {
163163
if (!setUpTargetMachine())
164164
return false;
165165
// Create the semantics context
166-
semaContext = invoc.getSemanticsCtx(*allCookedSources, getTargetMachine());
166+
semaContext = invoc.getSemanticsCtx(*allCookedSources, getTargetMachine(),
167+
getDiagnostics());
167168
// Set options controlling lowering to FIR.
168169
invoc.setLoweringOptions();
169170

flang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "llvm/Option/Arg.h"
3333
#include "llvm/Option/ArgList.h"
3434
#include "llvm/Option/OptTable.h"
35+
#include "llvm/Option/Option.h"
3536
#include "llvm/Support/CodeGen.h"
3637
#include "llvm/Support/FileSystem.h"
3738
#include "llvm/Support/FileUtilities.h"
@@ -118,9 +119,26 @@ static unsigned getOptimizationLevel(llvm::opt::ArgList &args,
118119
}
119120

120121
bool Fortran::frontend::parseDiagnosticArgs(clang::DiagnosticOptions &opts,
121-
llvm::opt::ArgList &args) {
122-
opts.ShowColors = parseShowColorsArgs(args);
123-
122+
llvm::opt::ArgList &args,
123+
bool defaultDiagColor) {
124+
opts.ShowColors = parseShowColorsArgs(args, defaultDiagColor);
125+
126+
for (llvm::opt::Arg *A : args.filtered(clang::driver::options::OPT_W_Group)) {
127+
if (A->getOption().getKind() == llvm::opt::Option::FlagClass) {
128+
// The argument is a pure flag (such as OPT_Wall).
129+
opts.Warnings.push_back(
130+
std::string(A->getOption().getName().drop_front(1)));
131+
} else if (A->getOption().matches(
132+
clang::driver::options::OPT_W_value_Group)) {
133+
// This is -Wfoo= where foo is the name of the diagnostic group.
134+
// Add only the group name to the diagnostics.
135+
opts.Warnings.push_back(
136+
std::string(A->getOption().getName().drop_front(1).rtrim("=-")));
137+
} else {
138+
// Otherwise, add its value for OPT_W_Joined.
139+
opts.Warnings.push_back(A->getValue());
140+
}
141+
}
124142
return true;
125143
}
126144

@@ -923,22 +941,11 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
923941
clang::DiagnosticsEngine &diags) {
924942
unsigned numErrorsBefore = diags.getNumErrors();
925943

926-
// -Werror option
927-
// TODO: Currently throws a Diagnostic for anything other than -W<error>,
928-
// this has to change when other -W<opt>'s are supported.
929-
if (args.hasArg(clang::driver::options::OPT_W_Joined)) {
930-
const auto &wArgs =
931-
args.getAllArgValues(clang::driver::options::OPT_W_Joined);
932-
for (const auto &wArg : wArgs) {
933-
if (wArg == "error") {
934-
res.setWarnAsErr(true);
935-
} else {
936-
const unsigned diagID =
937-
diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
938-
"Only `-Werror` is supported currently.");
939-
diags.Report(diagID);
940-
}
941-
}
944+
// Handle warning Diagnostic for the frontend.
945+
clang::DiagnosticOptions &diagOpts = res.getDiagnosticOpts();
946+
for (const auto &warning : diagOpts.Warnings) {
947+
if (warning == "error")
948+
res.setWarnAsErr(true);
942949
}
943950

944951
// Default to off for `flang -fc1`.
@@ -1000,6 +1007,7 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
10001007
if (args.hasArg(clang::driver::options::OPT_pedantic)) {
10011008
res.setEnableConformanceChecks();
10021009
res.setEnableUsageChecks();
1010+
res.getDiagnosticOpts().Pedantic = true;
10031011
}
10041012

10051013
// -w
@@ -1620,12 +1628,12 @@ void CompilerInvocation::setFortranOpts() {
16201628
std::unique_ptr<Fortran::semantics::SemanticsContext>
16211629
CompilerInvocation::getSemanticsCtx(
16221630
Fortran::parser::AllCookedSources &allCookedSources,
1623-
const llvm::TargetMachine &targetMachine) {
1631+
const llvm::TargetMachine &targetMachine, clang::DiagnosticsEngine &diags) {
16241632
auto &fortranOptions = getFortranOpts();
16251633

16261634
auto semanticsContext = std::make_unique<semantics::SemanticsContext>(
16271635
getDefaultKinds(), fortranOptions.features, getLangOpts(),
1628-
allCookedSources);
1636+
allCookedSources, diags);
16291637

16301638
semanticsContext->set_moduleDirectory(getModuleDir())
16311639
.set_searchDirectories(fortranOptions.searchDirectories)

0 commit comments

Comments
 (0)