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
