[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:33:33 PDT 2012
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