On Sat, Jun 13, 2015 at 12:16 PM, David Blaikie <[email protected]> wrote: > > > On Sat, Jun 13, 2015 at 12:11 AM, Eric Fiselier <[email protected]> wrote: >> >> Author: ericwf >> Date: Sat Jun 13 02:11:40 2015 >> New Revision: 239665 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=239665&view=rev >> Log: >> Add `-verify-ignore-unexpected` option to ignore unexpected diagnostics in >> VerifyDiagnosticsConsumer >> >> Summary: >> The goal of this patch is to make `-verify` easier to use when testing >> libc++. The `notes` attached to compile error diagnostics are numerous and >> relatively unstable when they reference libc++ header internals. This patch >> allows libc++ to write stable compilation failure tests by allowing >> unexpected diagnostic messages to be ignored where they are not relevant. > > > Would it be better to have a flag that only ignores notes (or do we have a > flag that disables notes? That might be generically useful?).
-verify-ignore-unexpected=note will only ignore notes. > I'd be concerned that ignoring unexpected diagnostics could hide > warnings/errors in libc++? I agree with your concerns. Within libc++ I was only planning on ignoring notes, and possibly warnings in some contexts (C++11 extensions warnings for example). However I felt that providing '-verify-ignore-unexpected' and '-verify-ignore-unexpected=<Levels>' was a better, more generic, solution than just providing something like '-verify-ignore-unexpected-notes'. /Eric > >> >> >> This patch adds a new CC1 flag called `-verify-ignore-unexpected`. >> `-verify-ignore-unexpected` tells `VerifyDiagnosticsConsumer` to ignore >> *all* unexpected diagnostic messages. >> `-verify-ignore-unexpected=<LevelList>` can be used to only ignore certain >> diagnostic levels. `<LevelList>` is a comma separated list of diagnostic >> levels to ignore. The supported levels are `note`, `remark`, `warning` and >> `error`. >> >> >> >> Reviewers: bogner, grosser, EricWF >> >> Reviewed By: EricWF >> >> Subscribers: cfe-commits >> >> Differential Revision: http://reviews.llvm.org/D10138 >> >> Added: >> cfe/trunk/lib/Basic/DiagnosticOptions.cpp >> cfe/trunk/test/Frontend/verify-ignore-unexpected.c >> Modified: >> cfe/trunk/include/clang/Basic/DiagnosticOptions.def >> cfe/trunk/include/clang/Basic/DiagnosticOptions.h >> cfe/trunk/include/clang/Driver/CC1Options.td >> cfe/trunk/lib/Basic/CMakeLists.txt >> cfe/trunk/lib/Frontend/CompilerInvocation.cpp >> cfe/trunk/lib/Frontend/VerifyDiagnosticConsumer.cpp >> >> Modified: cfe/trunk/include/clang/Basic/DiagnosticOptions.def >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticOptions.def?rev=239665&r1=239664&r2=239665&view=diff >> >> ============================================================================== >> --- cfe/trunk/include/clang/Basic/DiagnosticOptions.def (original) >> +++ cfe/trunk/include/clang/Basic/DiagnosticOptions.def Sat Jun 13 >> 02:11:40 2015 >> @@ -69,7 +69,10 @@ ENUM_DIAGOPT(ShowOverloads, OverloadsSho >> DIAGOPT(VerifyDiagnostics, 1, 0) /// Check that diagnostics match the >> expected >> /// diagnostics, indicated by markers in >> the >> /// input source file. >> - >> +ENUM_DIAGOPT(VerifyIgnoreUnexpected, DiagnosticLevelMask, 4, >> + DiagnosticLevelMask::None) /// Ignore unexpected diagnostics >> of >> + /// the specified levels when >> using >> + /// -verify. >> DIAGOPT(ElideType, 1, 0) /// Elide identical types in template >> diffing >> DIAGOPT(ShowTemplateTree, 1, 0) /// Print a template tree when diffing >> DIAGOPT(CLFallbackMode, 1, 0) /// Format for clang-cl fallback mode >> >> Modified: cfe/trunk/include/clang/Basic/DiagnosticOptions.h >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticOptions.h?rev=239665&r1=239664&r2=239665&view=diff >> >> ============================================================================== >> --- cfe/trunk/include/clang/Basic/DiagnosticOptions.h (original) >> +++ cfe/trunk/include/clang/Basic/DiagnosticOptions.h Sat Jun 13 02:11:40 >> 2015 >> @@ -13,6 +13,7 @@ >> #include "clang/Basic/LLVM.h" >> #include "llvm/ADT/IntrusiveRefCntPtr.h" >> #include <string> >> +#include <type_traits> >> #include <vector> >> >> namespace clang { >> @@ -24,6 +25,38 @@ enum OverloadsShown : unsigned { >> Ovl_Best ///< Show just the "best" overload candidates. >> }; >> >> +/// \brief A bitmask representing the diagnostic levels used by >> +/// VerifyDiagnosticConsumer. >> +enum class DiagnosticLevelMask : unsigned { >> + None = 0, >> + Note = 1 << 0, >> + Remark = 1 << 1, >> + Warning = 1 << 2, >> + Error = 1 << 3, >> + All = Note | Remark | Warning | Error >> +}; >> + >> +inline DiagnosticLevelMask operator~(DiagnosticLevelMask M) { >> + using UT = std::underlying_type<DiagnosticLevelMask>::type; >> + return static_cast<DiagnosticLevelMask>(~static_cast<UT>(M)); >> +} >> + >> +inline DiagnosticLevelMask operator|(DiagnosticLevelMask LHS, >> + DiagnosticLevelMask RHS) { >> + using UT = std::underlying_type<DiagnosticLevelMask>::type; >> + return static_cast<DiagnosticLevelMask>( >> + static_cast<UT>(LHS) | static_cast<UT>(RHS)); >> +} >> + >> +inline DiagnosticLevelMask operator&(DiagnosticLevelMask LHS, >> + DiagnosticLevelMask RHS) { >> + using UT = std::underlying_type<DiagnosticLevelMask>::type; >> + return static_cast<DiagnosticLevelMask>( >> + static_cast<UT>(LHS) & static_cast<UT>(RHS)); >> +} >> + >> +raw_ostream& operator<<(raw_ostream& Out, DiagnosticLevelMask M); >> + >> /// \brief Options for controlling the compiler diagnostics engine. >> class DiagnosticOptions : public RefCountedBase<DiagnosticOptions>{ >> public: >> >> Modified: cfe/trunk/include/clang/Driver/CC1Options.td >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=239665&r1=239664&r2=239665&view=diff >> >> ============================================================================== >> --- cfe/trunk/include/clang/Driver/CC1Options.td (original) >> +++ cfe/trunk/include/clang/Driver/CC1Options.td Sat Jun 13 02:11:40 2015 >> @@ -301,6 +301,10 @@ def fmessage_length : Separate<["-"], "f >> HelpText<"Format message diagnostics so that they fit within N columns >> or fewer, when possible.">; >> def verify : Flag<["-"], "verify">, >> HelpText<"Verify diagnostic output using comment directives">; >> +def verify_ignore_unexpected : Flag<["-"], "verify-ignore-unexpected">, >> + HelpText<"Ignore unexpected diagnostic messages">; >> +def verify_ignore_unexpected_EQ : CommaJoined<["-"], >> "verify-ignore-unexpected=">, >> + HelpText<"Ignore unexpected diagnostic messages">; >> def Wno_rewrite_macros : Flag<["-"], "Wno-rewrite-macros">, >> HelpText<"Silence ObjC rewriting warnings">; >> >> >> Modified: cfe/trunk/lib/Basic/CMakeLists.txt >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/CMakeLists.txt?rev=239665&r1=239664&r2=239665&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/Basic/CMakeLists.txt (original) >> +++ cfe/trunk/lib/Basic/CMakeLists.txt Sat Jun 13 02:11:40 2015 >> @@ -61,6 +61,7 @@ add_clang_library(clangBasic >> CharInfo.cpp >> Diagnostic.cpp >> DiagnosticIDs.cpp >> + DiagnosticOptions.cpp >> FileManager.cpp >> FileSystemStatCache.cpp >> IdentifierTable.cpp >> >> Added: cfe/trunk/lib/Basic/DiagnosticOptions.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/DiagnosticOptions.cpp?rev=239665&view=auto >> >> ============================================================================== >> --- cfe/trunk/lib/Basic/DiagnosticOptions.cpp (added) >> +++ cfe/trunk/lib/Basic/DiagnosticOptions.cpp Sat Jun 13 02:11:40 2015 >> @@ -0,0 +1,24 @@ >> +//===--- DiagnosticOptions.cpp - C Language Family Diagnostic Handling >> ----===// >> +// >> +// The LLVM Compiler Infrastructure >> +// >> +// This file is distributed under the University of Illinois Open Source >> +// License. See LICENSE.TXT for details. >> +// >> >> +//===----------------------------------------------------------------------===// >> +// >> +// This file implements the DiagnosticOptions related interfaces. >> +// >> >> +//===----------------------------------------------------------------------===// >> + >> +#include "clang/Basic/DiagnosticOptions.h" >> +#include "llvm/Support/raw_ostream.h" >> + >> +namespace clang { >> + >> +raw_ostream& operator<<(raw_ostream& Out, DiagnosticLevelMask M) { >> + using UT = std::underlying_type<DiagnosticLevelMask>::type; >> + return Out << static_cast<UT>(M); >> +} >> + >> +} // end namespace clang >> >> Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=239665&r1=239664&r2=239665&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original) >> +++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Sat Jun 13 02:11:40 2015 >> @@ -321,6 +321,29 @@ GenerateOptimizationRemarkRegex(Diagnost >> return Pattern; >> } >> >> +static bool parseDiagnosticLevelMask(StringRef FlagName, >> + const std::vector<std::string> >> &Levels, >> + DiagnosticsEngine *Diags, >> + DiagnosticLevelMask &M) { >> + bool Success = true; >> + for (const auto &Level : Levels) { >> + DiagnosticLevelMask const PM = >> + llvm::StringSwitch<DiagnosticLevelMask>(Level) >> + .Case("note", DiagnosticLevelMask::Note) >> + .Case("remark", DiagnosticLevelMask::Remark) >> + .Case("warning", DiagnosticLevelMask::Warning) >> + .Case("error", DiagnosticLevelMask::Error) >> + .Default(DiagnosticLevelMask::None); >> + if (PM == DiagnosticLevelMask::None) { >> + Success = false; >> + if (Diags) >> + Diags->Report(diag::err_drv_invalid_value) << FlagName << Level; >> + } >> + M = M | PM; >> + } >> + return Success; >> +} >> + >> static void parseSanitizerKinds(StringRef FlagName, >> const std::vector<std::string> >> &Sanitizers, >> DiagnosticsEngine &Diags, SanitizerSet >> &S) { >> @@ -748,11 +771,18 @@ bool clang::ParseDiagnosticArgs(Diagnost >> << Args.getLastArg(OPT_fdiagnostics_format)->getAsString(Args) >> << Format; >> } >> - >> + >> Opts.ShowSourceRanges = >> Args.hasArg(OPT_fdiagnostics_print_source_range_info); >> Opts.ShowParseableFixits = >> Args.hasArg(OPT_fdiagnostics_parseable_fixits); >> Opts.ShowPresumedLoc = >> !Args.hasArg(OPT_fno_diagnostics_use_presumed_location); >> Opts.VerifyDiagnostics = Args.hasArg(OPT_verify); >> + DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None; >> + Success &= parseDiagnosticLevelMask("-verify-ignore-unexpected=", >> + Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ), >> + Diags, DiagMask); >> + if (Args.hasArg(OPT_verify_ignore_unexpected)) >> + DiagMask = DiagnosticLevelMask::All; >> + Opts.setVerifyIgnoreUnexpected(DiagMask); >> Opts.ElideType = !Args.hasArg(OPT_fno_elide_type); >> Opts.ShowTemplateTree = >> Args.hasArg(OPT_fdiagnostics_show_template_tree); >> Opts.ErrorLimit = getLastArgIntValue(Args, OPT_ferror_limit, 0, Diags); >> >> Modified: cfe/trunk/lib/Frontend/VerifyDiagnosticConsumer.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/VerifyDiagnosticConsumer.cpp?rev=239665&r1=239664&r2=239665&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/Frontend/VerifyDiagnosticConsumer.cpp (original) >> +++ cfe/trunk/lib/Frontend/VerifyDiagnosticConsumer.cpp Sat Jun 13 >> 02:11:40 2015 >> @@ -691,7 +691,8 @@ static unsigned CheckLists(DiagnosticsEn >> const char *Label, >> DirectiveList &Left, >> const_diag_iterator d2_begin, >> - const_diag_iterator d2_end) { >> + const_diag_iterator d2_end, >> + bool IgnoreUnexpected) { >> std::vector<Directive *> LeftOnly; >> DiagList Right(d2_begin, d2_end); >> >> @@ -727,7 +728,8 @@ static unsigned CheckLists(DiagnosticsEn >> } >> // Now all that's left in Right are those that were not matched. >> unsigned num = PrintExpected(Diags, SourceMgr, LeftOnly, Label); >> - num += PrintUnexpected(Diags, &SourceMgr, Right.begin(), Right.end(), >> Label); >> + if (!IgnoreUnexpected) >> + num += PrintUnexpected(Diags, &SourceMgr, Right.begin(), Right.end(), >> Label); >> return num; >> } >> >> @@ -745,21 +747,28 @@ static unsigned CheckResults(Diagnostics >> // Seen \ Expected - set seen but not expected >> unsigned NumProblems = 0; >> >> + const DiagnosticLevelMask DiagMask = >> + Diags.getDiagnosticOptions().getVerifyIgnoreUnexpected(); >> + >> // See if there are error mismatches. >> NumProblems += CheckLists(Diags, SourceMgr, "error", ED.Errors, >> - Buffer.err_begin(), Buffer.err_end()); >> + Buffer.err_begin(), Buffer.err_end(), >> + bool(DiagnosticLevelMask::Error & DiagMask)); >> >> // See if there are warning mismatches. >> NumProblems += CheckLists(Diags, SourceMgr, "warning", ED.Warnings, >> - Buffer.warn_begin(), Buffer.warn_end()); >> + Buffer.warn_begin(), Buffer.warn_end(), >> + bool(DiagnosticLevelMask::Warning & >> DiagMask)); >> >> // See if there are remark mismatches. >> NumProblems += CheckLists(Diags, SourceMgr, "remark", ED.Remarks, >> - Buffer.remark_begin(), Buffer.remark_end()); >> + Buffer.remark_begin(), Buffer.remark_end(), >> + bool(DiagnosticLevelMask::Remark & >> DiagMask)); >> >> // See if there are note mismatches. >> NumProblems += CheckLists(Diags, SourceMgr, "note", ED.Notes, >> - Buffer.note_begin(), Buffer.note_end()); >> + Buffer.note_begin(), Buffer.note_end(), >> + bool(DiagnosticLevelMask::Note & DiagMask)); >> >> return NumProblems; >> } >> @@ -854,12 +863,20 @@ void VerifyDiagnosticConsumer::CheckDiag >> // Check that the expected diagnostics occurred. >> NumErrors += CheckResults(Diags, *SrcManager, *Buffer, ED); >> } else { >> - NumErrors += (PrintUnexpected(Diags, nullptr, Buffer->err_begin(), >> - Buffer->err_end(), "error") + >> - PrintUnexpected(Diags, nullptr, Buffer->warn_begin(), >> - Buffer->warn_end(), "warn") + >> - PrintUnexpected(Diags, nullptr, Buffer->note_begin(), >> - Buffer->note_end(), "note")); >> + const DiagnosticLevelMask DiagMask = >> + ~Diags.getDiagnosticOptions().getVerifyIgnoreUnexpected(); >> + if (bool(DiagnosticLevelMask::Error & DiagMask)) >> + NumErrors += PrintUnexpected(Diags, nullptr, Buffer->err_begin(), >> + Buffer->err_end(), "error"); >> + if (bool(DiagnosticLevelMask::Warning & DiagMask)) >> + NumErrors += PrintUnexpected(Diags, nullptr, Buffer->warn_begin(), >> + Buffer->warn_end(), "warn"); >> + if (bool(DiagnosticLevelMask::Remark & DiagMask)) >> + NumErrors += PrintUnexpected(Diags, nullptr, >> Buffer->remark_begin(), >> + Buffer->remark_end(), "remark"); >> + if (bool(DiagnosticLevelMask::Note & DiagMask)) >> + NumErrors += PrintUnexpected(Diags, nullptr, Buffer->note_begin(), >> + Buffer->note_end(), "note"); >> } >> >> Diags.setClient(CurClient, Owner.release() != nullptr); >> >> Added: cfe/trunk/test/Frontend/verify-ignore-unexpected.c >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Frontend/verify-ignore-unexpected.c?rev=239665&view=auto >> >> ============================================================================== >> --- cfe/trunk/test/Frontend/verify-ignore-unexpected.c (added) >> +++ cfe/trunk/test/Frontend/verify-ignore-unexpected.c Sat Jun 13 02:11:40 >> 2015 >> @@ -0,0 +1,81 @@ >> +// RUN: not %clang_cc1 -DTEST_SWITCH >> -verify-ignore-unexpected=remark,aoeu,note -verify %s 2>&1 \ >> +// RUN: | FileCheck -check-prefix=CHECK-BAD-SWITCH %s >> +#ifdef TEST_SWITCH >> +// expected-no-diagnostics >> +#endif >> +// CHECK-BAD-SWITCH: error: 'error' diagnostics seen but not expected: >> +// CHECK-BAD-SWITCH-NEXT: (frontend): invalid value 'aoeu' in >> '-verify-ignore-unexpected=' >> + >> +// RUN: %clang_cc1 -DTEST1 -verify %s >> +// RUN: %clang_cc1 -DTEST1 -verify -verify-ignore-unexpected %s >> +#ifdef TEST1 >> +#warning MyWarning1 >> + // expected-warning@-1 {{MyWarning1}} >> +int x; // expected-note {{previous definition is here}} >> +float x; // expected-error {{redefinition of 'x'}} >> +#endif >> + >> +// RUN: not %clang_cc1 -DTEST2 -verify %s 2>&1 \ >> +// RUN: | FileCheck -check-prefix=CHECK-UNEXP %s >> +// RUN: not %clang_cc1 -DTEST2 -verify -verify-ignore-unexpected= %s 2>&1 >> \ >> +// RUN: | FileCheck -check-prefix=CHECK-UNEXP %s >> +// RUN: not %clang_cc1 -DTEST2 -verify -verify-ignore-unexpected=note %s >> 2>&1 \ >> +// RUN: | FileCheck -check-prefix=CHECK-NOTE %s >> +// RUN: not %clang_cc1 -DTEST2 -verify -verify-ignore-unexpected=warning >> %s 2>&1 \ >> +// RUN: | FileCheck -check-prefix=CHECK-WARN %s >> +// RUN: not %clang_cc1 -DTEST2 -verify -verify-ignore-unexpected=error %s >> 2>&1 \ >> +// RUN: | FileCheck -check-prefix=CHECK-ERR %s >> +#ifdef TEST2 >> +#warning MyWarning2 >> +int x; >> +float x; >> +#endif >> +// CHECK-UNEXP: no expected directives found >> +// CHECK-UNEXP-NEXT: 'error' diagnostics seen but not expected >> +// CHECK-UNEXP-NEXT: Line {{[0-9]+}}: redefinition of 'x' >> +// CHECK-UNEXP-NEXT: 'warning' diagnostics seen but not expected >> +// CHECK-UNEXP-NEXT: Line {{[0-9]+}}: MyWarning2 >> +// CHECK-UNEXP-NEXT: 'note' diagnostics seen but not expected >> +// CHECK-UNEXP-NEXT: Line {{[0-9]+}}: previous definition is here >> +// CHECK-UNEXP-NEXT: 4 errors generated. >> + >> +// CHECK-NOTE: no expected directives found >> +// CHECK-NOTE-NEXT: 'error' diagnostics seen but not expected >> +// CHECK-NOTE-NEXT: Line {{[0-9]+}}: redefinition of 'x' >> +// CHECK-NOTE-NEXT: 'warning' diagnostics seen but not expected >> +// CHECK-NOTE-NEXT: Line {{[0-9]+}}: MyWarning2 >> +// CHECK-NOTE-NEXT: 3 errors generated. >> + >> +// CHECK-WARN: no expected directives found >> +// CHECK-WARN-NEXT: 'error' diagnostics seen but not expected >> +// CHECK-WARN-NEXT: Line {{[0-9]+}}: redefinition of 'x' >> +// CHECK-WARN-NEXT: 'note' diagnostics seen but not expected >> +// CHECK-WARN-NEXT: Line {{[0-9]+}}: previous definition is here >> +// CHECK-WARN-NEXT: 3 errors generated. >> + >> +// CHECK-ERR: no expected directives found >> +// CHECK-ERR-NEXT: 'warning' diagnostics seen but not expected >> +// CHECK-ERR-NEXT: Line {{[0-9]+}}: MyWarning2 >> +// CHECK-ERR-NEXT: 'note' diagnostics seen but not expected >> +// CHECK-ERR-NEXT: Line {{[0-9]+}}: previous definition is here >> +// CHECK-ERR-NEXT: 3 errors generated. >> + >> +// RUN: not %clang_cc1 -DTEST3 -verify -verify-ignore-unexpected %s 2>&1 >> \ >> +// RUN: | FileCheck -check-prefix=CHECK-EXP %s >> +#ifdef TEST3 >> +// expected-error {{test3}} >> +#endif >> +// CHECK-EXP: 'error' diagnostics expected but not seen >> +// CHECK-EXP-NEXT: Line {{[0-9]+}}: test3 >> + >> +// RUN: not %clang_cc1 -DTEST4 -verify -verify-ignore-unexpected %s 2>&1 >> \ >> +// RUN: | FileCheck -check-prefix=CHECK-NOEXP %s >> +// RUN: not %clang_cc1 -DTEST4 -verify >> -verify-ignore-unexpected=warning,error,note %s 2>&1 \ >> +// RUN: | FileCheck -check-prefix=CHECK-NOEXP %s >> +#ifdef TEST4 >> +#warning MyWarning4 >> +int x; >> +float x; >> +#endif >> +// CHECK-NOEXP: error: no expected directives found >> +// CHECK-NOEXP-NEXT: 1 error generated >> >> >> _______________________________________________ >> cfe-commits mailing list >> [email protected] >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > > _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
