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 <[email protected]> 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 <[email protected]> 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 <[email protected]>: >>> 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 >>> [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
