diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Basic/Diagnostic.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Basic/DiagnosticIDs.cpp | 62 | ||||
-rw-r--r-- | clang/lib/Basic/Warnings.cpp | 71 | ||||
-rw-r--r-- | clang/lib/Driver/Tools.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 33 | ||||
-rw-r--r-- | clang/lib/Frontend/FrontendActions.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Lex/PPMacroExpansion.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Lex/Pragma.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 3 |
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); |