[cfe-commits] r159875 - in /cfe/trunk: include/clang/Basic/DiagnosticGroups.td include/clang/Driver/Options.td lib/Driver/Tools.cpp lib/Frontend/TextDiagnosticPrinter.cpp test/Driver/warning-options.cpp test/Misc/show-diag-options.c test/Misc/war

Ted Kremenek kremenek at apple.com
Fri Jul 6 21:38:34 PDT 2012


Ah, now I see a builtbot failure.  I'll take a look.  Looks like it failed on Darwin as well.

On Jul 6, 2012, at 9:33 PM, Ted Kremenek <kremenek at apple.com> wrote:

> Hi Takumi,
> 
> Interesting.  I didn't see any failures on the lab.llvm.org buildbots, nor the internal ones at Apple.  Couple comments inline.
> 
> On Jul 6, 2012, at 7:51 PM, NAKAMURA Takumi <geek4civic at gmail.com> wrote:
> 
>> Ted, excuse me, I have reverted it in r159886.
>> 
>> I suspect -Wpedantic would not work as you expected.
> 
> Can you elaborate a bit on this?  I don't actually know how to interpret that comment.
> 
>> 
>> I would be happier if you consider in the next commit, thank you;
>> 
>> - Split PEDANTIC tests to other test.
>> - Mark it as XFAIL: cygwin,mingw32 . They still use gcc-as driver.
> 
> I'd be happy to do this, but I really would like see the failure you saw to understand why.  As I said, I didn't see any failures on the buildbots, so it makes me nervous that you said that several builds were breaking.
> 
> Thanks,
> Ted
> 
> 
>> 
>> ...Takumi
>> 
>> 
>> 2012/7/7 Ted Kremenek <kremenek at apple.com>:
>>> Author: kremenek
>>> Date: Fri Jul  6 18:07:31 2012
>>> New Revision: 159875
>>> 
>>> URL: http://llvm.org/viewvc/llvm-project?rev=159875&view=rev
>>> Log:
>>> Implement -Wpedantic and --no-pedantic to complement -Weverything.
>>> 
>>> This patch introduces some magic in tablegen to create a "Pedantic" diagnostic
>>> group which automagically includes all warnings that are extensions.  This
>>> allows a user to suppress specific warnings traditionally under -pedantic used
>>> an ordinary warning flag.  This also allows users to use #pragma to silence
>>> specific -pedantic warnings, or promote them to errors, within blocks of text
>>> (just like any other warning).
>>> 
>>> -Wpedantic is NOT an alias for -pedantic.  Instead, it provides another way
>>> to (a) activate -pedantic warnings and (b) disable them.  Where they differ
>>> is that -pedantic changes the behavior of the preprocessor slightly, whereas
>>> -Wpedantic does not (it just turns on the warnings).
>>> 
>>> The magic in the tablegen diagnostic emitter has to do with computing the minimal
>>> set of diagnostic groups and diagnostics that should go into -Wpedantic, as those
>>> diagnostics that already members of groups that themselves are (transitively) members
>>> of -Wpedantic do not need to be included in the Pedantic group directly.  I went
>>> back and forth on whether or not to magically generate this group, and the invariant
>>> was that we always wanted extension warnings to be included in -Wpedantic "some how",
>>> but the bookkeeping would be very onerous to manage by hand.
>>> 
>>> -no-pedantic (and --no-pedantic) is included for completeness, and matches many of the
>>> same kind of flags the compiler already supports.  It does what it says: cancels out
>>> -pedantic.  One discrepancy is that if one specifies --no-pedantic and -Weverything or
>>> -Wpedantic the pedantic warnings are still enabled (essentially the -W flags win).  We
>>> can debate the correct behavior here.
>>> 
>>> Along the way, this patch nukes some code in TextDiagnosticPrinter.cpp and CXStoredDiagnostic.cpp
>>> that determine whether to include the "-pedantic" flag in the warning output.  This is
>>> no longer needed, as all extensions now have a -W flag.
>>> 
>>> This patch also significantly reduces the number of warnings not under flags from 229
>>> to 158 (all extension warnings).  That's a 31% reduction.
>>> 
>>> Modified:
>>>   cfe/trunk/include/clang/Basic/DiagnosticGroups.td
>>>   cfe/trunk/include/clang/Driver/Options.td
>>>   cfe/trunk/lib/Driver/Tools.cpp
>>>   cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp
>>>   cfe/trunk/test/Driver/warning-options.cpp
>>>   cfe/trunk/test/Misc/show-diag-options.c
>>>   cfe/trunk/test/Misc/warning-flags.c
>>>   cfe/trunk/tools/libclang/CXStoredDiagnostic.cpp
>>>   cfe/trunk/utils/TableGen/ClangDiagnosticsEmitter.cpp
>>> 
>>> Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=159875&r1=159874&r2=159875&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
>>> +++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Fri Jul  6 18:07:31 2012
>>> @@ -380,6 +380,9 @@
>>> // DefaultIgnore in addition to putting it here.
>>> def : DiagGroup<"all", [Most, Parentheses, Switch]>;
>>> 
>>> +// Warnings enabled by -pedantic.  This is magically filled in by TableGen.
>>> +def Pedantic : DiagGroup<"pedantic">;
>>> +
>>> // Aliases.
>>> def : DiagGroup<"", [Extra]>;                   // -W = -Wextra
>>> def : DiagGroup<"endif-labels", [ExtraTokens]>; // -Wendif-labels=-Wendif-tokens
>>> 
>>> Modified: cfe/trunk/include/clang/Driver/Options.td
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=159875&r1=159874&r2=159875&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/Driver/Options.td (original)
>>> +++ cfe/trunk/include/clang/Driver/Options.td Fri Jul  6 18:07:31 2012
>>> @@ -868,6 +868,7 @@
>>> def no_cpp_precomp : Flag<"-no-cpp-precomp">, Group<clang_ignored_f_Group>;
>>> def no_integrated_as : Flag<"-no-integrated-as">, Flags<[DriverOption]>;
>>> def no_integrated_cpp : Flag<"-no-integrated-cpp">, Flags<[DriverOption]>;
>>> +def no_pedantic : Flag<"-no-pedantic">, Group<pedantic_Group>;
>>> def no__dead__strip__inits__and__terms : Flag<"-no_dead_strip_inits_and_terms">;
>>> def nobuiltininc : Flag<"-nobuiltininc">, Flags<[CC1Option]>,
>>>  HelpText<"Disable builtin #include directories">;
>>> @@ -1070,6 +1071,7 @@
>>> def _machine : Separate<"--machine">, Alias<m_Joined>;
>>> def _no_integrated_cpp : Flag<"--no-integrated-cpp">, Alias<no_integrated_cpp>;
>>> def _no_line_commands : Flag<"--no-line-commands">, Alias<P>;
>>> +def _no_pedantic : Flag<"--no-pedantic">, Alias<no_pedantic>;
>>> def _no_standard_includes : Flag<"--no-standard-includes">, Alias<nostdinc>;
>>> def _no_standard_libraries : Flag<"--no-standard-libraries">, Alias<nostdlib>;
>>> def _no_undefined : Flag<"--no-undefined">, Flags<[LinkerInput]>;
>>> 
>>> Modified: cfe/trunk/lib/Driver/Tools.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=159875&r1=159874&r2=159875&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/lib/Driver/Tools.cpp (original)
>>> +++ cfe/trunk/lib/Driver/Tools.cpp Fri Jul  6 18:07:31 2012
>>> @@ -2093,7 +2093,8 @@
>>>  }
>>> 
>>>  Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
>>> -  Args.AddLastArg(CmdArgs, options::OPT_pedantic);
>>> +  if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false))
>>> +    CmdArgs.push_back("-pedantic");
>>>  Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors);
>>>  Args.AddLastArg(CmdArgs, options::OPT_w);
>>> 
>>> 
>>> Modified: cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp?rev=159875&r1=159874&r2=159875&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp (original)
>>> +++ cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp Fri Jul  6 18:07:31 2012
>>> @@ -79,16 +79,6 @@
>>>      Started = true;
>>>    }
>>> 
>>> -    // If the diagnostic is an extension diagnostic and not enabled by default
>>> -    // then it must have been turned on with -pedantic.
>>> -    bool EnabledByDefault;
>>> -    if (DiagnosticIDs::isBuiltinExtensionDiag(Info.getID(),
>>> -                                              EnabledByDefault) &&
>>> -        !EnabledByDefault) {
>>> -      OS << (Started ? "," : " [") << "-pedantic";
>>> -      Started = true;
>>> -    }
>>> -
>>>    StringRef Opt = DiagnosticIDs::getWarningOptionForDiag(Info.getID());
>>>    if (!Opt.empty()) {
>>>      OS << (Started ? "," : " [") << "-W" << Opt;
>>> 
>>> Modified: cfe/trunk/test/Driver/warning-options.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/warning-options.cpp?rev=159875&r1=159874&r2=159875&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/test/Driver/warning-options.cpp (original)
>>> +++ cfe/trunk/test/Driver/warning-options.cpp Fri Jul  6 18:07:31 2012
>>> @@ -8,3 +8,11 @@
>>> // CHECK: unknown warning option '-Wmonkey'
>>> // CHECK: unknown warning option '-Wno-monkey'
>>> // CHECK: unknown warning option '-Wno-unused-command-line-arguments'; did you mean '-Wno-unused-command-line-argument'?
>>> +
>>> +// RUN: %clang -### -pedantic -no-pedantic %s 2>&1 | FileCheck -check-prefix=NO_PEDANTIC %s
>>> +// RUN: %clang -### -pedantic -Wno-pedantic %s 2>&1 | FileCheck -check-prefix=PEDANTIC %s
>>> +// NO_PEDANTIC-NOT: -pedantic
>>> +// RUN: %clang -### -pedantic -pedantic -no-pedantic -pedantic %s 2>&1 | FileCheck -check-prefix=PEDANTIC %s
>>> +// RUN: %clang -### -pedantic -pedantic -no-pedantic -Wpedantic %s 2>&1 | FileCheck -check-prefix=PEDANTIC %s
>>> +// PEDANTIC: -pedantic
>>> +
>>> 
>>> Modified: cfe/trunk/test/Misc/show-diag-options.c
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/show-diag-options.c?rev=159875&r1=159874&r2=159875&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/test/Misc/show-diag-options.c (original)
>>> +++ cfe/trunk/test/Misc/show-diag-options.c Fri Jul  6 18:07:31 2012
>>> @@ -23,5 +23,5 @@
>>>  // OPTION_ERROR_CATEGORY: {{.*}}: error: {{[a-z ]+}} [-Werror,-Wparentheses,Semantic Issue]
>>> 
>>>  // Leverage the fact that all these '//'s get warned about in C89 pedantic.
>>> -  // OPTION_PEDANTIC: {{.*}}: warning: {{[/a-z ]+}} [-pedantic,-Wcomment]
>>> +  // OPTION_PEDANTIC: {{.*}}: warning: {{[/a-z ]+}} [-Wcomment]
>>> }
>>> 
>>> Modified: cfe/trunk/test/Misc/warning-flags.c
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/warning-flags.c?rev=159875&r1=159874&r2=159875&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/test/Misc/warning-flags.c (original)
>>> +++ cfe/trunk/test/Misc/warning-flags.c Fri Jul  6 18:07:31 2012
>>> @@ -17,66 +17,7 @@
>>> 
>>> The list of warnings below should NEVER grow.  It should gradually shrink to 0.
>>> 
>>> -CHECK: Warnings without flags (229):
>>> -CHECK-NEXT:   ext_anonymous_struct_union_qualified
>>> -CHECK-NEXT:   ext_binary_literal
>>> -CHECK-NEXT:   ext_cast_fn_obj
>>> -CHECK-NEXT:   ext_delete_void_ptr_operand
>>> -CHECK-NEXT:   ext_designated_init
>>> -CHECK-NEXT:   ext_duplicate_declspec
>>> -CHECK-NEXT:   ext_ellipsis_exception_spec
>>> -CHECK-NEXT:   ext_enum_friend
>>> -CHECK-NEXT:   ext_enum_value_not_int
>>> -CHECK-NEXT:   ext_enumerator_list_comma
>>> -CHECK-NEXT:   ext_expected_semi_decl_list
>>> -CHECK-NEXT:   ext_explicit_instantiation_without_qualified_id
>>> -CHECK-NEXT:   ext_explicit_specialization_storage_class
>>> -CHECK-NEXT:   ext_forward_ref_enum
>>> -CHECK-NEXT:   ext_freestanding_complex
>>> -CHECK-NEXT:   ext_hexconstant_invalid
>>> -CHECK-NEXT:   ext_ident_list_in_param
>>> -CHECK-NEXT:   ext_imaginary_constant
>>> -CHECK-NEXT:   ext_implicit_lib_function_decl
>>> -CHECK-NEXT:   ext_in_class_initializer_non_constant
>>> -CHECK-NEXT:   ext_integer_complement_complex
>>> -CHECK-NEXT:   ext_integer_complex
>>> -CHECK-NEXT:   ext_integer_increment_complex
>>> -CHECK-NEXT:   ext_invalid_sign_spec
>>> -CHECK-NEXT:   ext_missing_declspec
>>> -CHECK-NEXT:   ext_missing_whitespace_after_macro_name
>>> -CHECK-NEXT:   ext_new_paren_array_nonconst
>>> -CHECK-NEXT:   ext_nonstandard_escape
>>> -CHECK-NEXT:   ext_param_not_declared
>>> -CHECK-NEXT:   ext_plain_complex
>>> -CHECK-NEXT:   ext_pp_bad_vaargs_use
>>> -CHECK-NEXT:   ext_pp_comma_expr
>>> -CHECK-NEXT:   ext_pp_ident_directive
>>> -CHECK-NEXT:   ext_pp_include_next_directive
>>> -CHECK-NEXT:   ext_pp_line_too_big
>>> -CHECK-NEXT:   ext_pp_macro_redef
>>> -CHECK-NEXT:   ext_pp_warning_directive
>>> -CHECK-NEXT:   ext_return_has_void_expr
>>> -CHECK-NEXT:   ext_subscript_non_lvalue
>>> -CHECK-NEXT:   ext_template_arg_extra_parens
>>> -CHECK-NEXT:   ext_thread_before
>>> -CHECK-NEXT:   ext_typecheck_addrof_void
>>> -CHECK-NEXT:   ext_typecheck_cast_nonscalar
>>> -CHECK-NEXT:   ext_typecheck_cast_to_union
>>> -CHECK-NEXT:   ext_typecheck_comparison_of_distinct_pointers
>>> -CHECK-NEXT:   ext_typecheck_comparison_of_distinct_pointers_nonstandard
>>> -CHECK-NEXT:   ext_typecheck_comparison_of_fptr_to_void
>>> -CHECK-NEXT:   ext_typecheck_comparison_of_pointer_integer
>>> -CHECK-NEXT:   ext_typecheck_cond_incompatible_operands
>>> -CHECK-NEXT:   ext_typecheck_cond_incompatible_operands_nonstandard
>>> -CHECK-NEXT:   ext_typecheck_cond_one_void
>>> -CHECK-NEXT:   ext_typecheck_convert_pointer_void_func
>>> -CHECK-NEXT:   ext_typecheck_ordered_comparison_of_function_pointers
>>> -CHECK-NEXT:   ext_typecheck_ordered_comparison_of_pointer_and_zero
>>> -CHECK-NEXT:   ext_typecheck_ordered_comparison_of_pointer_integer
>>> -CHECK-NEXT:   ext_typecheck_zero_array_size
>>> -CHECK-NEXT:   ext_unknown_escape
>>> -CHECK-NEXT:   ext_using_undefined_std
>>> -CHECK-NEXT:   ext_vla_folded_to_constant
>>> +CHECK: Warnings without flags (158):
>>> CHECK-NEXT:   pp_include_next_absolute_path
>>> CHECK-NEXT:   pp_include_next_in_primary
>>> CHECK-NEXT:   pp_invalid_string_literal
>>> @@ -138,9 +79,6 @@
>>> CHECK-NEXT:   warn_enum_value_overflow
>>> CHECK-NEXT:   warn_enumerator_too_large
>>> CHECK-NEXT:   warn_exception_caught_by_earlier_handler
>>> -CHECK-NEXT:   warn_excess_initializers
>>> -CHECK-NEXT:   warn_excess_initializers_in_char_array_initializer
>>> -CHECK-NEXT:   warn_expected_qualified_after_typename
>>> CHECK-NEXT:   warn_extraneous_char_constant
>>> CHECK-NEXT:   warn_fe_cc_log_diagnostics_failure
>>> CHECK-NEXT:   warn_fe_cc_print_header_failure
>>> @@ -149,23 +87,17 @@
>>> CHECK-NEXT:   warn_function_attribute_wrong_type
>>> CHECK-NEXT:   warn_gc_attribute_weak_on_local
>>> CHECK-NEXT:   warn_gnu_inline_attribute_requires_inline
>>> -CHECK-NEXT:   warn_hex_escape_too_large
>>> CHECK-NEXT:   warn_ignoring_ftabstop_value
>>> -CHECK-NEXT:   warn_illegal_constant_array_size
>>> CHECK-NEXT:   warn_implements_nscopying
>>> CHECK-NEXT:   warn_incompatible_qualified_id
>>> -CHECK-NEXT:   warn_initializer_string_for_char_array_too_long
>>> CHECK-NEXT:   warn_inline_namespace_reopened_noninline
>>> CHECK-NEXT:   warn_integer_too_large
>>> CHECK-NEXT:   warn_integer_too_large_for_signed
>>> CHECK-NEXT:   warn_invalid_asm_cast_lvalue
>>> -CHECK-NEXT:   warn_many_braces_around_scalar_init
>>> CHECK-NEXT:   warn_maynot_respond
>>> CHECK-NEXT:   warn_member_extra_qualification
>>> CHECK-NEXT:   warn_method_param_redefinition
>>> -CHECK-NEXT:   warn_mismatched_exception_spec
>>> CHECK-NEXT:   warn_missing_case_for_condition
>>> -CHECK-NEXT:   warn_missing_dependent_template_keyword
>>> CHECK-NEXT:   warn_missing_exception_specification
>>> CHECK-NEXT:   warn_missing_whitespace_after_macro_name
>>> CHECK-NEXT:   warn_multiple_method_decl
>>> @@ -177,10 +109,8 @@
>>> CHECK-NEXT:   warn_objc_object_attribute_wrong_type
>>> CHECK-NEXT:   warn_objc_property_copy_missing_on_block
>>> CHECK-NEXT:   warn_objc_protocol_qualifier_missing_id
>>> -CHECK-NEXT:   warn_octal_escape_too_large
>>> CHECK-NEXT:   warn_odr_tag_type_inconsistent
>>> CHECK-NEXT:   warn_on_superclass_use
>>> -CHECK-NEXT:   warn_param_default_argument_redefinition
>>> CHECK-NEXT:   warn_partial_specs_not_deducible
>>> CHECK-NEXT:   warn_pointer_attribute_wrong_type
>>> CHECK-NEXT:   warn_pp_convert_lhs_to_positive
>>> @@ -228,7 +158,6 @@
>>> CHECK-NEXT:   warn_second_parameter_to_va_arg_never_compatible
>>> CHECK-NEXT:   warn_standalone_specifier
>>> CHECK-NEXT:   warn_static_inline_explicit_inst_ignored
>>> -CHECK-NEXT:   warn_static_non_static
>>> CHECK-NEXT:   warn_template_export_unsupported
>>> CHECK-NEXT:   warn_template_spec_extra_headers
>>> CHECK-NEXT:   warn_tentative_incomplete_array
>>> @@ -247,3 +176,4 @@
>>> CHECK-NEXT:   warn_use_out_of_scope_declaration
>>> CHECK-NEXT:   warn_weak_identifier_undeclared
>>> CHECK-NEXT:   warn_weak_import
>>> +
>>> 
>>> Modified: cfe/trunk/tools/libclang/CXStoredDiagnostic.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXStoredDiagnostic.cpp?rev=159875&r1=159874&r2=159875&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/tools/libclang/CXStoredDiagnostic.cpp (original)
>>> +++ cfe/trunk/tools/libclang/CXStoredDiagnostic.cpp Fri Jul  6 18:07:31 2012
>>> @@ -66,13 +66,8 @@
>>>      *Disable = createCXString("-ferror-limit=0");
>>>    return createCXString("-ferror-limit=");
>>>  }
>>> -
>>> -  bool EnabledByDefault;
>>> -  if (DiagnosticIDs::isBuiltinExtensionDiag(ID, EnabledByDefault) &&
>>> -      !EnabledByDefault)
>>> -    return createCXString("-pedantic");
>>> 
>>> -  return createCXString("");
>>> +  return createCXString("");
>>> }
>>> 
>>> unsigned CXStoredDiagnostic::getCategory() const {
>>> 
>>> Modified: cfe/trunk/utils/TableGen/ClangDiagnosticsEmitter.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangDiagnosticsEmitter.cpp?rev=159875&r1=159874&r2=159875&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/utils/TableGen/ClangDiagnosticsEmitter.cpp (original)
>>> +++ cfe/trunk/utils/TableGen/ClangDiagnosticsEmitter.cpp Fri Jul  6 18:07:31 2012
>>> @@ -11,9 +11,11 @@
>>> //
>>> //===----------------------------------------------------------------------===//
>>> 
>>> +#include "llvm/ADT/PointerUnion.h"
>>> #include "llvm/ADT/DenseSet.h"
>>> #include "llvm/ADT/SmallString.h"
>>> #include "llvm/ADT/StringMap.h"
>>> +#include "llvm/ADT/Optional.h"
>>> #include "llvm/Support/Compiler.h"
>>> #include "llvm/Support/Debug.h"
>>> #include "llvm/TableGen/Record.h"
>>> @@ -78,7 +80,7 @@
>>>                                                   DiagGroupParents);
>>>    if (!CatName.empty()) return CatName;
>>>  }
>>> -
>>> +
>>>  // If the diagnostic itself has a category, get it.
>>>  return R->getValueAsString("CategoryName");
>>> }
>>> @@ -160,6 +162,179 @@
>>> }
>>> 
>>> //===----------------------------------------------------------------------===//
>>> +// Infer members of -Wpedantic.
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +typedef std::vector<const Record *> RecordVec;
>>> +typedef llvm::DenseSet<const Record *> RecordSet;
>>> +typedef llvm::PointerUnion<RecordVec*, RecordSet*> VecOrSet;
>>> +
>>> +namespace {
>>> +class InferPedantic {
>>> +  typedef llvm::DenseMap<const Record*,
>>> +                         std::pair<unsigned, llvm::Optional<unsigned> > > GMap;
>>> +
>>> +  DiagGroupParentMap &DiagGroupParents;
>>> +  const std::vector<Record*> &Diags;
>>> +  const std::vector<Record*> DiagGroups;
>>> +  std::map<std::string, GroupInfo> &DiagsInGroup;
>>> +  llvm::DenseSet<const Record*> DiagsSet;
>>> +  GMap GroupCount;
>>> +public:
>>> +  InferPedantic(DiagGroupParentMap &DiagGroupParents,
>>> +                const std::vector<Record*> &Diags,
>>> +                const std::vector<Record*> &DiagGroups,
>>> +                std::map<std::string, GroupInfo> &DiagsInGroup)
>>> +  : DiagGroupParents(DiagGroupParents),
>>> +  Diags(Diags),
>>> +  DiagGroups(DiagGroups),
>>> +  DiagsInGroup(DiagsInGroup) {}
>>> +
>>> +  /// Compute the set of diagnostics and groups that are immediately
>>> +  /// in -Wpedantic.
>>> +  void compute(VecOrSet DiagsInPedantic,
>>> +               VecOrSet GroupsInPedantic);
>>> +
>>> +private:
>>> +  /// Determine whether a group is a subgroup of another group.
>>> +  bool isSubGroupOfGroup(const Record *Group,
>>> +                         llvm::StringRef RootGroupName);
>>> +
>>> +  /// Determine if the diagnostic is an extension.
>>> +  bool isExtension(const Record *Diag);
>>> +
>>> +  /// Increment the count for a group, and transitively marked
>>> +  /// parent groups when appropriate.
>>> +  void markGroup(const Record *Group);
>>> +
>>> +  /// Return true if the diagnostic is in a pedantic group.
>>> +  bool groupInPedantic(const Record *Group, bool increment = false);
>>> +};
>>> +} // end anonymous namespace
>>> +
>>> +bool InferPedantic::isSubGroupOfGroup(const Record *Group,
>>> +                                      llvm::StringRef GName) {
>>> +
>>> +  const std::string &GroupName = Group->getValueAsString("GroupName");
>>> +  if (GName == GroupName)
>>> +    return true;
>>> +
>>> +  const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
>>> +  for (unsigned i = 0, e = Parents.size(); i != e; ++i)
>>> +    if (isSubGroupOfGroup(Parents[i], GName))
>>> +      return true;
>>> +
>>> +  return false;
>>> +}
>>> +
>>> +/// Determine if the diagnostic is an extension.
>>> +bool InferPedantic::isExtension(const Record *Diag) {
>>> +  const std::string &ClsName = Diag->getValueAsDef("Class")->getName();
>>> +  return ClsName == "CLASS_EXTENSION";
>>> +}
>>> +
>>> +bool InferPedantic::groupInPedantic(const Record *Group, bool increment) {
>>> +  GMap::mapped_type &V = GroupCount[Group];
>>> +  // Lazily compute the threshold value for the group count.
>>> +  if (!V.second.hasValue()) {
>>> +    const GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
>>> +    V.second = GI.SubGroups.size() + GI.DiagsInGroup.size();
>>> +  }
>>> +
>>> +  if (increment)
>>> +    ++V.first;
>>> +
>>> +  // Consider a group in -Wpendatic IFF if has at least one diagnostic
>>> +  // or subgroup AND all of those diagnostics and subgroups are covered
>>> +  // by -Wpedantic via our computation.
>>> +  return V.first != 0 && V.first == V.second.getValue();
>>> +}
>>> +
>>> +void InferPedantic::markGroup(const Record *Group) {
>>> +  // If all the diagnostics and subgroups have been marked as being
>>> +  // covered by -Wpedantic, increment the count of parent groups.  Once the
>>> +  // group's count is equal to the number of subgroups and diagnostics in
>>> +  // that group, we can safely add this group to -Wpedantic.
>>> +  if (groupInPedantic(Group, /* increment */ true)) {
>>> +    const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
>>> +    for (unsigned i = 0, e = Parents.size(); i != e; ++i)
>>> +      markGroup(Parents[i]);
>>> +  }
>>> +}
>>> +
>>> +void InferPedantic::compute(VecOrSet DiagsInPedantic,
>>> +                            VecOrSet GroupsInPedantic) {
>>> +  // All extensions are implicitly in the "pedantic" group.  For those that
>>> +  // aren't explicitly included in -Wpedantic, mark them for consideration
>>> +  // to be included in -Wpedantic directly.
>>> +  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
>>> +    Record *R = Diags[i];
>>> +    if (isExtension(R))
>>> +      DiagsSet.insert(R);
>>> +    if (DefInit *Group = dynamic_cast<DefInit*>(R->getValueInit("Group"))) {
>>> +      const Record *GroupRec = Group->getDef();
>>> +      if (!isSubGroupOfGroup(GroupRec, "pedantic")) {
>>> +        markGroup(GroupRec);
>>> +      }
>>> +    }
>>> +  }
>>> +
>>> +  // Compute the set of diagnostics that are directly in -Wpedantic.  We
>>> +  // march through Diags a second time to ensure the results are emitted
>>> +  // in deterministic order.
>>> +  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
>>> +    Record *R = Diags[i];
>>> +    if (!DiagsSet.count(R))
>>> +      continue;
>>> +    // Check if the group is implicitly in -Wpedantic.  If so,
>>> +    // the diagnostic should not be directly included in the -Wpedantic
>>> +    // diagnostic group.
>>> +    if (DefInit *Group = dynamic_cast<DefInit*>(R->getValueInit("Group")))
>>> +      if (groupInPedantic(Group->getDef()))
>>> +        continue;
>>> +
>>> +    // The diagnostic is not included in a group that is (transitively) in
>>> +    // -Wpedantic.  Include it in -Wpedantic directly.
>>> +    if (RecordVec *V = DiagsInPedantic.dyn_cast<RecordVec*>())
>>> +      V->push_back(R);
>>> +    else {
>>> +      DiagsInPedantic.get<RecordSet*>()->insert(R);
>>> +    }
>>> +  }
>>> +
>>> +  if (!GroupsInPedantic)
>>> +    return;
>>> +
>>> +  // Compute the set of groups that are directly in -Wpedantic.  We
>>> +  // march through the groups to ensure the results are emitted
>>> +  /// in a deterministc order.
>>> +  for (unsigned i = 0, ei = DiagGroups.size(); i != ei; ++i) {
>>> +    Record *Group = DiagGroups[i];
>>> +    if (!groupInPedantic(Group))
>>> +      continue;
>>> +
>>> +    unsigned ParentsInPedantic = 0;
>>> +    const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
>>> +    for (unsigned j = 0, ej = Parents.size(); j != ej; ++j) {
>>> +      if (groupInPedantic(Parents[j]))
>>> +        ++ParentsInPedantic;
>>> +    }
>>> +    // If all the parents are in -Wpedantic, this means that this diagnostic
>>> +    // group will be indirectly included by -Wpedantic already.  In that
>>> +    // case, do not add it directly to -Wpedantic.  If the group has no
>>> +    // parents, obviously it should go into -Wpedantic.
>>> +    if (Parents.size() > 0 && ParentsInPedantic == Parents.size())
>>> +      continue;
>>> +
>>> +    if (RecordVec *V = GroupsInPedantic.dyn_cast<RecordVec*>())
>>> +      V->push_back(Group);
>>> +    else {
>>> +      GroupsInPedantic.get<RecordSet*>()->insert(Group);
>>> +    }
>>> +  }
>>> +}
>>> +
>>> +//===----------------------------------------------------------------------===//
>>> // Warning Tables (.inc file) generation.
>>> //===----------------------------------------------------------------------===//
>>> 
>>> @@ -190,6 +365,11 @@
>>>  DiagCategoryIDMap CategoryIDs(Records);
>>>  DiagGroupParentMap DGParentMap(Records);
>>> 
>>> +  // Compute the set of diagnostics that are in -Wpedantic.
>>> +  RecordSet DiagsInPedantic;
>>> +  InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
>>> +  inferPedantic.compute(&DiagsInPedantic, (RecordVec*)0);
>>> +
>>>  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
>>>    const Record &R = *Diags[i];
>>>    // Filter by component.
>>> @@ -211,6 +391,11 @@
>>>          DiagsInGroup.find(DI->getDef()->getValueAsString("GroupName"));
>>>      assert(I != DiagsInGroup.end());
>>>      OS << ", " << I->second.IDNo;
>>> +    } else if (DiagsInPedantic.count(&R)) {
>>> +      std::map<std::string, GroupInfo>::iterator I =
>>> +        DiagsInGroup.find("pedantic");
>>> +      assert(I != DiagsInGroup.end() && "pedantic group not defined");
>>> +      OS << ", " << I->second.IDNo;
>>>    } else {
>>>      OS << ", 0";
>>>    }
>>> @@ -262,12 +447,12 @@
>>>    enumName += isalnum(*I) ? *I : '_';
>>>  return enumName.str();
>>> }
>>> -
>>> +
>>> namespace clang {
>>> void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) {
>>>  // Compute a mapping from a DiagGroup to all of its parents.
>>>  DiagGroupParentMap DGParentMap(Records);
>>> -
>>> +
>>>  std::vector<Record*> Diags =
>>>    Records.getAllDerivedDefinitions("Diagnostic");
>>> 
>>> @@ -276,7 +461,15 @@
>>> 
>>>  std::map<std::string, GroupInfo> DiagsInGroup;
>>>  groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
>>> -
>>> +
>>> +  // All extensions are implicitly in the "pedantic" group.  Record the
>>> +  // implicit set of groups in the "pedantic" group, and use this information
>>> +  // later when emitting the group information for Pedantic.
>>> +  RecordVec DiagsInPedantic;
>>> +  RecordVec GroupsInPedantic;
>>> +  InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
>>> +  inferPedantic.compute(&DiagsInPedantic, &GroupsInPedantic);
>>> +
>>>  // Walk through the groups emitting an array for each diagnostic of the diags
>>>  // that are mapped to.
>>>  OS << "\n#ifdef GET_DIAG_ARRAYS\n";
>>> @@ -284,17 +477,23 @@
>>>  for (std::map<std::string, GroupInfo>::iterator
>>>       I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) {
>>>    MaxLen = std::max(MaxLen, (unsigned)I->first.size());
>>> -
>>> +    const bool IsPedantic = I->first == "pedantic";
>>> +
>>>    std::vector<const Record*> &V = I->second.DiagsInGroup;
>>> -    if (!V.empty()) {
>>> +    if (!V.empty() || (IsPedantic && !DiagsInPedantic.empty())) {
>>>      OS << "static const short DiagArray" << I->second.IDNo << "[] = { ";
>>>      for (unsigned i = 0, e = V.size(); i != e; ++i)
>>>        OS << "diag::" << V[i]->getName() << ", ";
>>> +      // Emit the diagnostics implicitly in "pedantic".
>>> +      if (IsPedantic) {
>>> +        for (unsigned i = 0, e = DiagsInPedantic.size(); i != e; ++i)
>>> +          OS << "diag::" << DiagsInPedantic[i]->getName() << ", ";
>>> +      }
>>>      OS << "-1 };\n";
>>>    }
>>> 
>>>    const std::vector<std::string> &SubGroups = I->second.SubGroups;
>>> -    if (!SubGroups.empty()) {
>>> +    if (!SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty())) {
>>>      OS << "static const short DiagSubGroup" << I->second.IDNo << "[] = { ";
>>>      for (unsigned i = 0, e = SubGroups.size(); i != e; ++i) {
>>>        std::map<std::string, GroupInfo>::iterator RI =
>>> @@ -302,6 +501,18 @@
>>>        assert(RI != DiagsInGroup.end() && "Referenced without existing?");
>>>        OS << RI->second.IDNo << ", ";
>>>      }
>>> +      // Emit the groups implicitly in "pedantic".
>>> +      if (IsPedantic) {
>>> +        for (unsigned i = 0, e = GroupsInPedantic.size(); i != e; ++i) {
>>> +          const std::string &GroupName =
>>> +            GroupsInPedantic[i]->getValueAsString("GroupName");
>>> +          std::map<std::string, GroupInfo>::iterator RI =
>>> +            DiagsInGroup.find(GroupName);
>>> +          assert(RI != DiagsInGroup.end() && "Referenced without existing?");
>>> +          OS << RI->second.IDNo << ", ";
>>> +        }
>>> +      }
>>> +
>>>      OS << "-1 };\n";
>>>    }
>>>  }
>>> @@ -321,15 +532,22 @@
>>>      throw "Invalid character in diagnostic group '" + I->first + "'";
>>>    OS.write_escaped(I->first) << "\","
>>>                               << std::string(MaxLen-I->first.size()+1, ' ');
>>> -
>>> +
>>> +    // Special handling for 'pedantic'.
>>> +    const bool IsPedantic = I->first == "pedantic";
>>> +
>>>    // Diagnostics in the group.
>>> -    if (I->second.DiagsInGroup.empty())
>>> +    const bool hasDiags = !I->second.DiagsInGroup.empty() ||
>>> +                          (IsPedantic && !DiagsInPedantic.empty());
>>> +    if (!hasDiags)
>>>      OS << "0, ";
>>>    else
>>>      OS << "DiagArray" << I->second.IDNo << ", ";
>>> 
>>>    // Subgroups.
>>> -    if (I->second.SubGroups.empty())
>>> +    const bool hasSubGroups = !I->second.SubGroups.empty() ||
>>> +                              (IsPedantic && !GroupsInPedantic.empty());
>>> +    if (!hasSubGroups)
>>>      OS << 0;
>>>    else
>>>      OS << "DiagSubGroup" << I->second.IDNo;
>>> 
>>> 
>>> _______________________________________________
>>> cfe-commits mailing list
>>> cfe-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
> 




More information about the cfe-commits mailing list