Skip to content

Commit e31899c

Browse files
committed
Reland "[clang-cl] Accept #pragma warning(disable : N) for some N"
This reverts commit 0cd9d8a and adds the changes described in https://reviews.llvm.org/D110668#3034461.
1 parent b989211 commit e31899c

File tree

18 files changed

+176
-28
lines changed

18 files changed

+176
-28
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===--- CLWarnings.h - Maps some cl.exe warning ids -----------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_BASIC_CLWARNINGS_H
10+
#define LLVM_CLANG_BASIC_CLWARNINGS_H
11+
12+
#include "llvm/ADT/Optional.h"
13+
14+
namespace clang {
15+
16+
namespace diag {
17+
enum class Group;
18+
}
19+
20+
/// For cl.exe warning IDs that cleany map to clang diagnostic groups,
21+
/// returns the corresponding group. Else, returns an empty Optional.
22+
llvm::Optional<diag::Group> diagGroupFromCLWarningID(unsigned);
23+
24+
} // end namespace clang
25+
26+
#endif // LLVM_CLANG_BASIC_CLWARNINGS_H

clang/include/clang/Basic/Diagnostic.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,9 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
807807
bool setSeverityForGroup(diag::Flavor Flavor, StringRef Group,
808808
diag::Severity Map,
809809
SourceLocation Loc = SourceLocation());
810+
bool setSeverityForGroup(diag::Flavor Flavor, diag::Group Group,
811+
diag::Severity Map,
812+
SourceLocation Loc = SourceLocation());
810813

811814
/// Set the warning-as-error flag for the given diagnostic group.
812815
///

clang/include/clang/Basic/DiagnosticCategories.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ namespace clang {
1919
#undef GET_CATEGORY_TABLE
2020
DiagCat_NUM_CATEGORIES
2121
};
22+
23+
enum class Group {
24+
#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups) GroupName,
25+
#include "clang/Basic/DiagnosticGroups.inc"
26+
#undef CATEGORY
27+
#undef DIAG_ENTRY
28+
};
2229
} // end namespace diag
2330
} // end namespace clang
2431

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ def Dangling : DiagGroup<"dangling", [DanglingField,
396396
DanglingGsl,
397397
ReturnStackAddress]>;
398398
def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;
399+
def DllexportExplicitInstantiationDecl : DiagGroup<"dllexport-explicit-instantiation-decl">;
399400
def ExcessInitializers : DiagGroup<"excess-initializers">;
400401
def ExpansionToDefined : DiagGroup<"expansion-to-defined">;
401402
def FlagEnum : DiagGroup<"flag-enum">;

clang/include/clang/Basic/DiagnosticIDs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ namespace clang {
2525

2626
// Import the diagnostic enums themselves.
2727
namespace diag {
28+
enum class Group;
29+
2830
// Size of each of the diagnostic categories.
2931
enum {
3032
DIAG_SIZE_COMMON = 300,
@@ -224,6 +226,10 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
224226
///
225227
static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault);
226228

229+
/// Given a group ID, returns the flag that toggles the group.
230+
/// For example, for Group::DeprecatedDeclarations, returns
231+
/// "deprecated-declarations".
232+
static StringRef getWarningOptionForGroup(diag::Group);
227233

228234
/// Return the lowest-level warning option that enables the specified
229235
/// diagnostic.

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3396,7 +3396,7 @@ def warn_attribute_dllimport_static_field_definition : Warning<
33963396
InGroup<DiagGroup<"dllimport-static-field-def">>;
33973397
def warn_attribute_dllexport_explicit_instantiation_decl : Warning<
33983398
"explicit instantiation declaration should not be 'dllexport'">,
3399-
InGroup<DiagGroup<"dllexport-explicit-instantiation-decl">>;
3399+
InGroup<DllexportExplicitInstantiationDecl>;
34003400
def warn_attribute_dllexport_explicit_instantiation_def : Warning<
34013401
"'dllexport' attribute ignored on explicit instantiation definition">,
34023402
InGroup<IgnoredAttributes>;

clang/include/clang/Driver/Options.td

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6106,16 +6106,7 @@ def _SLASH_WX_ : CLFlag<"WX-">,
61066106
HelpText<"Do not treat warnings as errors (default)">,
61076107
Alias<W_Joined>, AliasArgs<["no-error"]>;
61086108
def _SLASH_w_flag : CLFlag<"w">, HelpText<"Disable all warnings">, Alias<w>;
6109-
def _SLASH_wd4005 : CLFlag<"wd4005">, Alias<W_Joined>,
6110-
AliasArgs<["no-macro-redefined"]>;
6111-
def _SLASH_wd4018 : CLFlag<"wd4018">, Alias<W_Joined>,
6112-
AliasArgs<["no-sign-compare"]>;
6113-
def _SLASH_wd4100 : CLFlag<"wd4100">, Alias<W_Joined>,
6114-
AliasArgs<["no-unused-parameter"]>;
6115-
def _SLASH_wd4910 : CLFlag<"wd4910">, Alias<W_Joined>,
6116-
AliasArgs<["no-dllexport-explicit-instantiation-decl"]>;
6117-
def _SLASH_wd4996 : CLFlag<"wd4996">, Alias<W_Joined>,
6118-
AliasArgs<["no-deprecated-declarations"]>;
6109+
def _SLASH_wd : CLCompileJoined<"wd">;
61196110
def _SLASH_vd : CLJoined<"vd">, HelpText<"Control vtordisp placement">,
61206111
Alias<vtordisp_mode_EQ>;
61216112
def _SLASH_X : CLFlag<"X">,

clang/lib/Basic/CLWarnings.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//===--- CLWarnings.h - Maps some cl.exe warning ids -----------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file implements the Diagnostic-related interfaces.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "clang/Basic/CLWarnings.h"
14+
#include "clang/Basic/DiagnosticCategories.h"
15+
16+
using namespace clang;
17+
18+
llvm::Optional<diag::Group>
19+
clang::diagGroupFromCLWarningID(unsigned CLWarningID) {
20+
switch (CLWarningID) {
21+
case 4005: return diag::Group::MacroRedefined;
22+
case 4018: return diag::Group::SignCompare;
23+
case 4100: return diag::Group::UnusedParameter;
24+
case 4910: return diag::Group::DllexportExplicitInstantiationDecl;
25+
case 4996: return diag::Group::DeprecatedDeclarations;
26+
}
27+
return {};
28+
}

clang/lib/Basic/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ endif()
3939
add_clang_library(clangBasic
4040
Attributes.cpp
4141
Builtins.cpp
42+
CLWarnings.cpp
4243
CharInfo.cpp
4344
CodeGenOptions.cpp
4445
Cuda.cpp

clang/lib/Basic/Diagnostic.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,14 @@ bool DiagnosticsEngine::setSeverityForGroup(diag::Flavor Flavor,
408408
return false;
409409
}
410410

411+
bool DiagnosticsEngine::setSeverityForGroup(diag::Flavor Flavor,
412+
diag::Group Group,
413+
diag::Severity Map,
414+
SourceLocation Loc) {
415+
return setSeverityForGroup(Flavor, Diags->getWarningOptionForGroup(Group),
416+
Map, Loc);
417+
}
418+
411419
bool DiagnosticsEngine::setDiagnosticGroupWarningAsError(StringRef Group,
412420
bool Enabled) {
413421
// If we are enabling this feature, just set the diagnostic mappings to map to

clang/lib/Basic/DiagnosticIDs.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -609,17 +609,23 @@ namespace {
609609

610610
// Second the table of options, sorted by name for fast binary lookup.
611611
static const WarningOption OptionTable[] = {
612-
#define GET_DIAG_TABLE
612+
#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups) \
613+
{FlagNameOffset, Members, SubGroups},
613614
#include "clang/Basic/DiagnosticGroups.inc"
614-
#undef GET_DIAG_TABLE
615+
#undef DIAG_ENTRY
615616
};
616617

618+
StringRef DiagnosticIDs::getWarningOptionForGroup(diag::Group Group) {
619+
return OptionTable[static_cast<int>(Group)].getName();
620+
}
621+
617622
/// getWarningOptionForDiag - Return the lowest-level warning option that
618623
/// enables the specified diagnostic. If there is no -Wfoo flag that controls
619624
/// the diagnostic, this returns null.
620625
StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
621626
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
622-
return OptionTable[Info->getOptionGroupIndex()].getName();
627+
return getWarningOptionForGroup(
628+
static_cast<diag::Group>(Info->getOptionGroupIndex()));
623629
return StringRef();
624630
}
625631

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "Hexagon.h"
2323
#include "MSP430.h"
2424
#include "PS4CPU.h"
25+
#include "clang/Basic/CLWarnings.h"
2526
#include "clang/Basic/CharInfo.h"
2627
#include "clang/Basic/CodeGenOptions.h"
2728
#include "clang/Basic/LangOptions.h"
@@ -5438,7 +5439,26 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
54385439

54395440
Args.AddAllArgs(CmdArgs, options::OPT_R_Group);
54405441

5441-
Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
5442+
for (const Arg *A :
5443+
Args.filtered(options::OPT_W_Group, options::OPT__SLASH_wd)) {
5444+
A->claim();
5445+
if (A->getOption().getID() == options::OPT__SLASH_wd) {
5446+
unsigned WarningNumber;
5447+
if (StringRef(A->getValue()).getAsInteger(10, WarningNumber)) {
5448+
D.Diag(diag::err_drv_invalid_int_value)
5449+
<< A->getAsString(Args) << A->getValue();
5450+
continue;
5451+
}
5452+
5453+
if (auto Group = diagGroupFromCLWarningID(WarningNumber)) {
5454+
CmdArgs.push_back(Args.MakeArgString(
5455+
"-Wno-" + DiagnosticIDs::getWarningOptionForGroup(*Group)));
5456+
}
5457+
continue;
5458+
}
5459+
A->render(Args, CmdArgs);
5460+
}
5461+
54425462
if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false))
54435463
CmdArgs.push_back("-pedantic");
54445464
Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors);

clang/lib/Lex/Pragma.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
#include "clang/Lex/Pragma.h"
15+
#include "clang/Basic/CLWarnings.h"
1516
#include "clang/Basic/Diagnostic.h"
1617
#include "clang/Basic/DiagnosticLex.h"
1718
#include "clang/Basic/FileManager.h"
@@ -1413,12 +1414,15 @@ struct PragmaWarningHandler : public PragmaHandler {
14131414
return;
14141415
}
14151416
}
1417+
PP.getDiagnostics().pushMappings(DiagLoc);
14161418
if (Callbacks)
14171419
Callbacks->PragmaWarningPush(DiagLoc, Level);
14181420
} else if (II && II->isStr("pop")) {
14191421
// #pragma warning( pop )
14201422
PP.Lex(Tok);
1421-
if (Callbacks)
1423+
if (!PP.getDiagnostics().popMappings(DiagLoc))
1424+
PP.Diag(Tok, diag::warn_pragma_diagnostic_cannot_pop);
1425+
else if (Callbacks)
14221426
Callbacks->PragmaWarningPop(DiagLoc);
14231427
} else {
14241428
// #pragma warning( warning-specifier : warning-number-list
@@ -1482,6 +1486,22 @@ struct PragmaWarningHandler : public PragmaHandler {
14821486
}
14831487
Ids.push_back(int(Value));
14841488
}
1489+
1490+
// Only act on disable for now.
1491+
diag::Severity SV = diag::Severity();
1492+
if (Specifier == PPCallbacks::PWS_Disable)
1493+
SV = diag::Severity::Ignored;
1494+
if (SV != diag::Severity())
1495+
for (int Id : Ids) {
1496+
if (auto Group = diagGroupFromCLWarningID(Id)) {
1497+
bool unknownDiag = PP.getDiagnostics().setSeverityForGroup(
1498+
diag::Flavor::WarningOrError, *Group, SV, DiagLoc);
1499+
assert(!unknownDiag &&
1500+
"wd table should only contain known diags");
1501+
(void)unknownDiag;
1502+
}
1503+
}
1504+
14851505
if (Callbacks)
14861506
Callbacks->PragmaWarning(DiagLoc, Specifier, Ids);
14871507

clang/test/Driver/cl-options.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,12 +353,13 @@
353353
// CHECK-C11: -std=c11
354354

355355
// For some warning ids, we can map from MSVC warning to Clang warning.
356-
// RUN: %clang_cl -wd4005 -wd4100 -wd4910 -wd4996 -### -- %s 2>&1 | FileCheck -check-prefix=Wno %s
356+
// RUN: %clang_cl -wd4005 -wd4100 -wd4910 -wd4996 -wd12345678 -### -- %s 2>&1 | FileCheck -check-prefix=Wno %s
357357
// Wno: "-cc1"
358358
// Wno: "-Wno-macro-redefined"
359359
// Wno: "-Wno-unused-parameter"
360360
// Wno: "-Wno-dllexport-explicit-instantiation-decl"
361361
// Wno: "-Wno-deprecated-declarations"
362+
// Wno-NOT: "-wd
362363

363364
// Ignored options. Check that we don't get "unused during compilation" errors.
364365
// RUN: %clang_cl /c \

clang/test/Sema/pragma-warning.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fms-extensions -fsyntax-only -verify %s
2+
3+
[[deprecated]] void f() {} // expected-note 2 {{marked deprecated here}}
4+
5+
#define From__pragma() \
6+
__pragma(warning(push)) \
7+
__pragma(warning(disable:4996)) \
8+
f(); \
9+
__pragma(warning(pop))
10+
11+
void g() {
12+
f(); // expected-warning {{deprecated}}
13+
14+
#pragma warning(push)
15+
#pragma warning(disable: 4996)
16+
f(); // no diag
17+
18+
#pragma warning(disable: 49960000)
19+
#pragma warning(pop)
20+
21+
f(); // expected-warning {{deprecated}}
22+
23+
From__pragma(); // no diag
24+
}

clang/tools/diagtool/DiagnosticNames.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,10 @@ const DiagnosticRecord &diagtool::getDiagnosticForID(short DiagID) {
6666

6767
// Second the table of options, sorted by name for fast binary lookup.
6868
static const GroupRecord OptionTable[] = {
69-
#define GET_DIAG_TABLE
69+
#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups) \
70+
{FlagNameOffset, Members, SubGroups},
7071
#include "clang/Basic/DiagnosticGroups.inc"
71-
#undef GET_DIAG_TABLE
72+
#undef DIAG_ENTRY
7273
};
7374

7475
llvm::StringRef GroupRecord::getName() const {

clang/utils/TableGen/ClangDiagnosticsEmitter.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ namespace {
129129
};
130130

131131
struct GroupInfo {
132+
llvm::StringRef GroupName;
132133
std::vector<const Record*> DiagsInGroup;
133134
std::vector<std::string> SubGroups;
134135
unsigned IDNo;
@@ -174,6 +175,7 @@ static void groupDiagnostics(const std::vector<Record*> &Diags,
174175
Record *Group = DiagGroups[i];
175176
GroupInfo &GI =
176177
DiagsInGroup[std::string(Group->getValueAsString("GroupName"))];
178+
GI.GroupName = Group->getName();
177179
GI.Defs.push_back(Group);
178180

179181
std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups");
@@ -1279,8 +1281,8 @@ void clang::EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
12791281
OS << ", \"";
12801282
OS.write_escaped(DiagTextBuilder.buildForDefinition(&R)) << '"';
12811283

1282-
// Warning associated with the diagnostic. This is stored as an index into
1283-
// the alphabetically sorted warning table.
1284+
// Warning group associated with the diagnostic. This is stored as an index
1285+
// into the alphabetically sorted warning group table.
12841286
if (DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
12851287
std::map<std::string, GroupInfo>::iterator I = DiagsInGroup.find(
12861288
std::string(DI->getDef()->getValueAsString("GroupName")));
@@ -1487,18 +1489,20 @@ static void emitDiagTable(std::map<std::string, GroupInfo> &DiagsInGroup,
14871489
for (auto const &I: DiagsInGroup)
14881490
MaxLen = std::max(MaxLen, (unsigned)I.first.size());
14891491

1490-
OS << "\n#ifdef GET_DIAG_TABLE\n";
1492+
OS << "\n#ifdef DIAG_ENTRY\n";
14911493
unsigned SubGroupIndex = 1, DiagArrayIndex = 1;
14921494
for (auto const &I: DiagsInGroup) {
14931495
// Group option string.
1494-
OS << " { /* ";
1496+
OS << "DIAG_ENTRY(";
1497+
OS << I.second.GroupName << " /* ";
1498+
14951499
if (I.first.find_first_not_of("abcdefghijklmnopqrstuvwxyz"
14961500
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
14971501
"0123456789!@#$%^*-+=:?") !=
14981502
std::string::npos)
14991503
PrintFatalError("Invalid character in diagnostic group '" + I.first +
15001504
"'");
1501-
OS << I.first << " */ " << std::string(MaxLen - I.first.size(), ' ');
1505+
OS << I.first << " */, ";
15021506
// Store a pascal-style length byte at the beginning of the string.
15031507
std::string Name = char(I.first.size()) + I.first;
15041508
OS << GroupNames.GetOrAddStringOffset(Name, false) << ", ";
@@ -1517,7 +1521,7 @@ static void emitDiagTable(std::map<std::string, GroupInfo> &DiagsInGroup,
15171521
DiagArrayIndex += DiagsInPedantic.size();
15181522
DiagArrayIndex += V.size() + 1;
15191523
} else {
1520-
OS << "/* Empty */ 0, ";
1524+
OS << "0, ";
15211525
}
15221526

15231527
// Subgroups.
@@ -1530,12 +1534,12 @@ static void emitDiagTable(std::map<std::string, GroupInfo> &DiagsInGroup,
15301534
SubGroupIndex += GroupsInPedantic.size();
15311535
SubGroupIndex += SubGroups.size() + 1;
15321536
} else {
1533-
OS << "/* Empty */ 0";
1537+
OS << "0";
15341538
}
15351539

1536-
OS << " },\n";
1540+
OS << ")\n";
15371541
}
1538-
OS << "#endif // GET_DIAG_TABLE\n\n";
1542+
OS << "#endif // DIAG_ENTRY\n\n";
15391543
}
15401544

15411545
/// Emit the table of diagnostic categories.

0 commit comments

Comments
 (0)