[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 22:56:41 PDT 2012


I've re-applied in 159892, with one critical fix.  Errors were accidentally being included in -Wpedantic, which was due to a last second formatting change that wasn't caught because of stale test results on my machine.  I'll be monitoring the bots to see if these go through.  Thanks for your patience and attention!

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.
> 
> 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.
> 
> ...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