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?). I'd be concerned that ignoring unexpected diagnostics could hide warnings/errors in libc++? > > 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
