summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Basic/Diagnostic.cpp22
-rw-r--r--clang/lib/Basic/DiagnosticIDs.cpp62
-rw-r--r--clang/lib/Basic/Warnings.cpp71
-rw-r--r--clang/lib/Driver/Tools.cpp10
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp33
-rw-r--r--clang/lib/Frontend/FrontendActions.cpp7
-rw-r--r--clang/lib/Lex/PPMacroExpansion.cpp5
-rw-r--r--clang/lib/Lex/Pragma.cpp8
-rw-r--r--clang/lib/Serialization/ASTReader.cpp5
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp3
10 files changed, 145 insertions, 81 deletions
diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp
index f784fe7c321..4567e326713 100644
--- a/clang/lib/Basic/Diagnostic.cpp
+++ b/clang/lib/Basic/Diagnostic.cpp
@@ -228,11 +228,12 @@ void DiagnosticsEngine::setSeverity(diag::kind Diag, diag::Severity Map,
FullSourceLoc(Loc, *SourceMgr)));
}
-bool DiagnosticsEngine::setSeverityForGroup(StringRef Group, diag::Severity Map,
+bool DiagnosticsEngine::setSeverityForGroup(diag::Flavor Flavor,
+ StringRef Group, diag::Severity Map,
SourceLocation Loc) {
// Get the diagnostics in this group.
SmallVector<diag::kind, 8> GroupDiags;
- if (Diags->getDiagnosticsInGroup(Group, GroupDiags))
+ if (Diags->getDiagnosticsInGroup(Flavor, Group, GroupDiags))
return true;
// Set the mapping.
@@ -247,14 +248,16 @@ bool DiagnosticsEngine::setDiagnosticGroupWarningAsError(StringRef Group,
// If we are enabling this feature, just set the diagnostic mappings to map to
// errors.
if (Enabled)
- return setSeverityForGroup(Group, diag::Severity::Error);
+ return setSeverityForGroup(diag::Flavor::WarningOrError, Group,
+ diag::Severity::Error);
// Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and
// potentially downgrade anything already mapped to be a warning.
// Get the diagnostics in this group.
SmallVector<diag::kind, 8> GroupDiags;
- if (Diags->getDiagnosticsInGroup(Group, GroupDiags))
+ if (Diags->getDiagnosticsInGroup(diag::Flavor::WarningOrError, Group,
+ GroupDiags))
return true;
// Perform the mapping change.
@@ -276,14 +279,16 @@ bool DiagnosticsEngine::setDiagnosticGroupErrorAsFatal(StringRef Group,
// If we are enabling this feature, just set the diagnostic mappings to map to
// fatal errors.
if (Enabled)
- return setSeverityForGroup(Group, diag::Severity::Fatal);
+ return setSeverityForGroup(diag::Flavor::WarningOrError, Group,
+ diag::Severity::Fatal);
// Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and
// potentially downgrade anything already mapped to be an error.
// Get the diagnostics in this group.
SmallVector<diag::kind, 8> GroupDiags;
- if (Diags->getDiagnosticsInGroup(Group, GroupDiags))
+ if (Diags->getDiagnosticsInGroup(diag::Flavor::WarningOrError, Group,
+ GroupDiags))
return true;
// Perform the mapping change.
@@ -299,11 +304,12 @@ bool DiagnosticsEngine::setDiagnosticGroupErrorAsFatal(StringRef Group,
return false;
}
-void DiagnosticsEngine::setSeverityForAll(diag::Severity Map,
+void DiagnosticsEngine::setSeverityForAll(diag::Flavor Flavor,
+ diag::Severity Map,
SourceLocation Loc) {
// Get all the diagnostics.
SmallVector<diag::kind, 64> AllDiags;
- Diags->getAllDiagnostics(AllDiags);
+ Diags->getAllDiagnostics(Flavor, AllDiags);
// Set the mapping.
for (unsigned i = 0, e = AllDiags.size(); i != e; ++i)
diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp
index 3c0216a1320..ec244ccda3c 100644
--- a/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/clang/lib/Basic/DiagnosticIDs.cpp
@@ -58,6 +58,11 @@ struct StaticDiagInfoRec {
return StringRef(DescriptionStr, DescriptionLen);
}
+ diag::Flavor getFlavor() const {
+ return Class == CLASS_REMARK ? diag::Flavor::Remark
+ : diag::Flavor::WarningOrError;
+ }
+
bool operator<(const StaticDiagInfoRec &RHS) const {
return DiagID < RHS.DiagID;
}
@@ -522,40 +527,57 @@ StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
return StringRef();
}
-static void getDiagnosticsInGroup(const WarningOption *Group,
+/// Return \c true if any diagnostics were found in this group, even if they
+/// were filtered out due to having the wrong flavor.
+static bool getDiagnosticsInGroup(diag::Flavor Flavor,
+ const WarningOption *Group,
SmallVectorImpl<diag::kind> &Diags) {
+ // An empty group is considered to be a warning group: we have empty groups
+ // for GCC compatibility, and GCC does not have remarks.
+ if (!Group->Members && !Group->SubGroups)
+ return Flavor == diag::Flavor::Remark ? true : false;
+
+ bool NotFound = true;
+
// Add the members of the option diagnostic set.
const int16_t *Member = DiagArrays + Group->Members;
- for (; *Member != -1; ++Member)
- Diags.push_back(*Member);
+ for (; *Member != -1; ++Member) {
+ if (GetDiagInfo(*Member)->getFlavor() == Flavor) {
+ NotFound = false;
+ Diags.push_back(*Member);
+ }
+ }
// Add the members of the subgroups.
const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
for (; *SubGroups != (int16_t)-1; ++SubGroups)
- getDiagnosticsInGroup(&OptionTable[(short)*SubGroups], Diags);
+ NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups],
+ Diags);
+
+ return NotFound;
}
-bool DiagnosticIDs::getDiagnosticsInGroup(
- StringRef Group,
- SmallVectorImpl<diag::kind> &Diags) const {
- const WarningOption *Found =
- std::lower_bound(OptionTable, OptionTable + OptionTableSize, Group,
- WarningOptionCompare);
+bool
+DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group,
+ SmallVectorImpl<diag::kind> &Diags) const {
+ const WarningOption *Found = std::lower_bound(
+ OptionTable, OptionTable + OptionTableSize, Group, WarningOptionCompare);
if (Found == OptionTable + OptionTableSize ||
Found->getName() != Group)
return true; // Option not found.
- ::getDiagnosticsInGroup(Found, Diags);
- return false;
+ return ::getDiagnosticsInGroup(Flavor, Found, Diags);
}
-void DiagnosticIDs::getAllDiagnostics(
- SmallVectorImpl<diag::kind> &Diags) const {
+void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor,
+ SmallVectorImpl<diag::kind> &Diags) const {
for (unsigned i = 0; i != StaticDiagInfoSize; ++i)
- Diags.push_back(StaticDiagInfo[i].DiagID);
+ if (StaticDiagInfo[i].getFlavor() == Flavor)
+ Diags.push_back(StaticDiagInfo[i].DiagID);
}
-StringRef DiagnosticIDs::getNearestWarningOption(StringRef Group) {
+StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor,
+ StringRef Group) {
StringRef Best;
unsigned BestDistance = Group.size() + 1; // Sanity threshold.
for (const WarningOption *i = OptionTable, *e = OptionTable + OptionTableSize;
@@ -565,6 +587,14 @@ StringRef DiagnosticIDs::getNearestWarningOption(StringRef Group) {
continue;
unsigned Distance = i->getName().edit_distance(Group, true, BestDistance);
+ if (Distance > BestDistance)
+ continue;
+
+ // Don't suggest groups that are not of this kind.
+ llvm::SmallVector<diag::kind, 8> Diags;
+ if (::getDiagnosticsInGroup(Flavor, i, Diags) || Diags.empty())
+ continue;
+
if (Distance == BestDistance) {
// Two matches with the same distance, don't prefer one over the other.
Best = "";
diff --git a/clang/lib/Basic/Warnings.cpp b/clang/lib/Basic/Warnings.cpp
index 196a215463a..6306ceabc63 100644
--- a/clang/lib/Basic/Warnings.cpp
+++ b/clang/lib/Basic/Warnings.cpp
@@ -20,6 +20,8 @@
// Given a warning option 'foo', the following are valid:
// -Wfoo, -Wno-foo, -Werror=foo, -Wfatal-errors=foo
//
+// Remark options are also handled here, analogously, except that they are much
+// simpler because a remark can't be promoted to an error.
#include "clang/Basic/AllDiagnostics.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
@@ -31,17 +33,12 @@ using namespace clang;
// EmitUnknownDiagWarning - Emit a warning and typo hint for unknown warning
// opts
static void EmitUnknownDiagWarning(DiagnosticsEngine &Diags,
- StringRef Prefix, StringRef Opt,
- bool isPositive) {
- StringRef Suggestion = DiagnosticIDs::getNearestWarningOption(Opt);
- if (!Suggestion.empty())
- Diags.Report(isPositive? diag::warn_unknown_warning_option_suggest :
- diag::warn_unknown_negative_warning_option_suggest)
- << (Prefix.str() += Opt) << (Prefix.str() += Suggestion);
- else
- Diags.Report(isPositive? diag::warn_unknown_warning_option :
- diag::warn_unknown_negative_warning_option)
- << (Prefix.str() += Opt);
+ diag::Flavor Flavor, StringRef Prefix,
+ StringRef Opt) {
+ StringRef Suggestion = DiagnosticIDs::getNearestOption(Flavor, Opt);
+ Diags.Report(diag::warn_unknown_diag_option)
+ << (Flavor == diag::Flavor::WarningOrError ? 0 : 1) << (Prefix.str() += Opt)
+ << !Suggestion.empty() << (Prefix.str() += Suggestion);
}
void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
@@ -89,6 +86,7 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
break;
for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i) {
+ const auto Flavor = diag::Flavor::WarningOrError;
StringRef Opt = Opts.Warnings[i];
StringRef OrigOpt = Opts.Warnings[i];
@@ -125,7 +123,7 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
Diags.setEnableAllWarnings(true);
} else {
Diags.setEnableAllWarnings(false);
- Diags.setSeverityForAll(diag::Severity::Ignored);
+ Diags.setSeverityForAll(Flavor, diag::Severity::Ignored);
}
}
continue;
@@ -154,8 +152,8 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
if (SetDiagnostic) {
// Set the warning as error flag for this specifier.
Diags.setDiagnosticGroupWarningAsError(Specifier, isPositive);
- } else if (DiagIDs->getDiagnosticsInGroup(Specifier, _Diags)) {
- EmitUnknownDiagWarning(Diags, "-Werror=", Specifier, isPositive);
+ } else if (DiagIDs->getDiagnosticsInGroup(Flavor, Specifier, _Diags)) {
+ EmitUnknownDiagWarning(Diags, Flavor, "-Werror=", Specifier);
}
continue;
}
@@ -182,19 +180,50 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
if (SetDiagnostic) {
// Set the error as fatal flag for this specifier.
Diags.setDiagnosticGroupErrorAsFatal(Specifier, isPositive);
- } else if (DiagIDs->getDiagnosticsInGroup(Specifier, _Diags)) {
- EmitUnknownDiagWarning(Diags, "-Wfatal-errors=", Specifier,
- isPositive);
+ } else if (DiagIDs->getDiagnosticsInGroup(Flavor, Specifier, _Diags)) {
+ EmitUnknownDiagWarning(Diags, Flavor, "-Wfatal-errors=", Specifier);
}
continue;
}
if (Report) {
- if (DiagIDs->getDiagnosticsInGroup(Opt, _Diags))
- EmitUnknownDiagWarning(Diags, isPositive ? "-W" : "-Wno-", Opt,
- isPositive);
+ if (DiagIDs->getDiagnosticsInGroup(Flavor, Opt, _Diags))
+ EmitUnknownDiagWarning(Diags, Flavor, isPositive ? "-W" : "-Wno-",
+ Opt);
+ } else {
+ Diags.setSeverityForGroup(Flavor, Opt, Mapping);
+ }
+ }
+
+ for (unsigned i = 0, e = Opts.Remarks.size(); i != e; ++i) {
+ StringRef Opt = Opts.Remarks[i];
+ const auto Flavor = diag::Flavor::Remark;
+
+ // Check to see if this warning starts with "no-", if so, this is a
+ // negative form of the option.
+ bool IsPositive = !Opt.startswith("no-");
+ if (!IsPositive) Opt = Opt.substr(3);
+
+ auto Severity = IsPositive ? diag::Severity::Remark
+ : diag::Severity::Ignored;
+
+ // -Reverything sets the state of all remarks. Note that all remarks are
+ // in remark groups, so we don't need a separate 'all remarks enabled'
+ // flag.
+ if (Opt == "everything") {
+ if (SetDiagnostic)
+ Diags.setSeverityForAll(Flavor, Severity);
+ continue;
+ }
+
+ if (Report) {
+ if (DiagIDs->getDiagnosticsInGroup(Flavor, Opt, _Diags))
+ EmitUnknownDiagWarning(Diags, Flavor, IsPositive ? "-R" : "-Rno-",
+ Opt);
} else {
- Diags.setSeverityForGroup(Opt, Mapping);
+ Diags.setSeverityForGroup(Flavor, Opt,
+ IsPositive ? diag::Severity::Remark
+ : diag::Severity::Ignored);
}
}
}
diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp
index 93a1d914a0c..c28283fddea 100644
--- a/clang/lib/Driver/Tools.cpp
+++ b/clang/lib/Driver/Tools.cpp
@@ -3374,6 +3374,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// precompiling.
Args.ClaimAllArgs(options::OPT_flto);
+ Args.AddAllArgs(CmdArgs, options::OPT_R_Group);
Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false))
CmdArgs.push_back("-pedantic");
@@ -3735,15 +3736,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->render(Args, CmdArgs);
}
- if (Arg *A = Args.getLastArg(options::OPT_Rpass_EQ))
- A->render(Args, CmdArgs);
-
- if (Arg *A = Args.getLastArg(options::OPT_Rpass_missed_EQ))
- A->render(Args, CmdArgs);
-
- if (Arg *A = Args.getLastArg(options::OPT_Rpass_analysis_EQ))
- A->render(Args, CmdArgs);
-
if (Args.hasArg(options::OPT_mkernel)) {
if (!Args.hasArg(options::OPT_fapple_kext) && types::isCXX(InputType))
CmdArgs.push_back("-fapple-kext");
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index e4be487d7d6..1a67e1376e1 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -111,25 +111,21 @@ static unsigned getOptimizationLevelSize(ArgList &Args) {
return 0;
}
-static void addWarningArgs(ArgList &Args, std::vector<std::string> &Warnings) {
- for (arg_iterator I = Args.filtered_begin(OPT_W_Group),
- E = Args.filtered_end(); I != E; ++I) {
- Arg *A = *I;
- // If the argument is a pure flag, add its name (minus the "W" at the beginning)
- // to the warning list. Else, add its value (for the OPT_W case).
+static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,
+ OptSpecifier GroupWithValue,
+ std::vector<std::string> &Diagnostics) {
+ for (Arg *A : Args.filtered(Group)) {
if (A->getOption().getKind() == Option::FlagClass) {
- Warnings.push_back(A->getOption().getName().substr(1));
+ // The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add
+ // its name (minus the "W" or "R" at the beginning) to the warning list.
+ Diagnostics.push_back(A->getOption().getName().drop_front(1));
+ } else if (A->getOption().matches(GroupWithValue)) {
+ // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic group.
+ Diagnostics.push_back(A->getOption().getName().drop_front(1).rtrim("=-"));
} else {
- for (unsigned Idx = 0, End = A->getNumValues();
- Idx < End; ++Idx) {
- StringRef V = A->getValue(Idx);
- // "-Wl," and such are not warning options.
- // FIXME: Should be handled by putting these in separate flags.
- if (V.startswith("l,") || V.startswith("a,") || V.startswith("p,"))
- continue;
-
- Warnings.push_back(V);
- }
+ // Otherwise, add its value (for OPT_W_Joined and similar).
+ for (const char *Arg : A->getValues())
+ Diagnostics.push_back(Arg);
}
}
}
@@ -700,7 +696,8 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
<< Opts.TabStop << DiagnosticOptions::DefaultTabStop;
}
Opts.MessageLength = getLastArgIntValue(Args, OPT_fmessage_length, 0, Diags);
- addWarningArgs(Args, Opts.Warnings);
+ addDiagnosticArgs(Args, OPT_W_Group, OPT_W_value_Group, Opts.Warnings);
+ addDiagnosticArgs(Args, OPT_R_Group, OPT_R_value_Group, Opts.Remarks);
return Success;
}
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index ef6bfec0f1b..6dcaf382c3c 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -470,10 +470,11 @@ namespace {
Out.indent(4) << #Name << ": " << DiagOpts->Name << "\n";
#include "clang/Basic/DiagnosticOptions.def"
- Out.indent(4) << "Warning options:\n";
- for (const std::string &Warning : DiagOpts->Warnings) {
+ Out.indent(4) << "Diagnostic flags:\n";
+ for (const std::string &Warning : DiagOpts->Warnings)
Out.indent(6) << "-W" << Warning << "\n";
- }
+ for (const std::string &Remark : DiagOpts->Remarks)
+ Out.indent(6) << "-R" << Remark << "\n";
return false;
}
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp
index 26b99fa21fb..2d7c6d4b522 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -1446,6 +1446,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
break;
}
+ // FIXME: Should we accept "-R..." flags here, or should that be handled
+ // by a separate __has_remark?
if (WarningName.size() < 3 || WarningName[0] != '-' ||
WarningName[1] != 'W') {
Diag(StrStartLoc, diag::warn_has_warning_invalid_option);
@@ -1458,7 +1460,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
// worth special casing.
SmallVector<diag::kind, 10> Diags;
Value = !getDiagnostics().getDiagnosticIDs()->
- getDiagnosticsInGroup(WarningName.substr(2), Diags);
+ getDiagnosticsInGroup(diag::Flavor::WarningOrError,
+ WarningName.substr(2), Diags);
} while (false);
OS << (int)Value;
diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp
index 6a8b0a6bd31..356ab2bc9b3 100644
--- a/clang/lib/Lex/Pragma.cpp
+++ b/clang/lib/Lex/Pragma.cpp
@@ -993,13 +993,15 @@ public:
}
if (WarningName.size() < 3 || WarningName[0] != '-' ||
- WarningName[1] != 'W') {
+ (WarningName[1] != 'W' && WarningName[1] != 'R')) {
PP.Diag(StringLoc, diag::warn_pragma_diagnostic_invalid_option);
return;
}
- if (PP.getDiagnostics().setSeverityForGroup(WarningName.substr(2), SV,
- DiagLoc))
+ if (PP.getDiagnostics().setSeverityForGroup(
+ WarningName[1] == 'W' ? diag::Flavor::WarningOrError
+ : diag::Flavor::Remark,
+ WarningName.substr(2), SV, DiagLoc))
PP.Diag(StringLoc, diag::warn_pragma_diagnostic_unknown_warning)
<< WarningName;
else if (Callbacks)
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 24237851576..4847678d25f 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -4639,9 +4639,10 @@ bool ASTReader::ParseDiagnosticOptions(const RecordData &Record, bool Complain,
DiagOpts->set##Name(static_cast<Type>(Record[Idx++]));
#include "clang/Basic/DiagnosticOptions.def"
- for (unsigned N = Record[Idx++]; N; --N) {
+ for (unsigned N = Record[Idx++]; N; --N)
DiagOpts->Warnings.push_back(ReadString(Record, Idx));
- }
+ for (unsigned N = Record[Idx++]; N; --N)
+ DiagOpts->Remarks.push_back(ReadString(Record, Idx));
return Listener.ReadDiagnosticOptions(DiagOpts, Complain);
}
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index ba74a88d6a4..8de1fca05f4 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -1226,6 +1226,9 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
Record.push_back(DiagOpts.Warnings.size());
for (unsigned I = 0, N = DiagOpts.Warnings.size(); I != N; ++I)
AddString(DiagOpts.Warnings[I], Record);
+ Record.push_back(DiagOpts.Remarks.size());
+ for (unsigned I = 0, N = DiagOpts.Remarks.size(); I != N; ++I)
+ AddString(DiagOpts.Remarks[I], Record);
// Note: we don't serialize the log or serialization file names, because they
// are generally transient files and will almost always be overridden.
Stream.EmitRecord(DIAGNOSTIC_OPTIONS, Record);
OpenPOWER on IntegriCloud