зеркало из https://github.com/microsoft/clang-1.git
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159875 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
48088ed56f
Коммит
25570a94ca
|
@ -380,6 +380,9 @@ def ThreadSafety : DiagGroup<"thread-safety",
|
|||
// 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
|
||||
|
|
|
@ -868,6 +868,7 @@ def no_canonical_prefixes : Flag<"-no-canonical-prefixes">, Flags<[HelpHidden]>,
|
|||
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_EQ : Joined<"--machine=">, Alias<m_Joined>;
|
|||
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]>;
|
||||
|
|
|
@ -2093,7 +2093,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -79,16 +79,6 @@ static void printDiagnosticOptions(raw_ostream &OS,
|
|||
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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -23,5 +23,5 @@ void test(int x, int y) {
|
|||
// 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]
|
||||
}
|
||||
|
|
|
@ -17,66 +17,7 @@ This test serves two purposes:
|
|||
|
||||
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_too_large
|
|||
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_file_asm_volatile
|
|||
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_ns_attribute_wrong_return_type
|
|||
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_of_va_start_not_last_named_argument
|
|||
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_unknown_method_family
|
|||
CHECK-NEXT: warn_use_out_of_scope_declaration
|
||||
CHECK-NEXT: warn_weak_identifier_undeclared
|
||||
CHECK-NEXT: warn_weak_import
|
||||
|
||||
|
|
|
@ -66,13 +66,8 @@ CXString CXStoredDiagnostic::getDiagnosticOption(CXString *Disable) const {
|
|||
*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 {
|
||||
|
|
|
@ -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 @@ static std::string getDiagnosticCategory(const Record *R,
|
|||
DiagGroupParents);
|
||||
if (!CatName.empty()) return CatName;
|
||||
}
|
||||
|
||||
|
||||
// If the diagnostic itself has a category, get it.
|
||||
return R->getValueAsString("CategoryName");
|
||||
}
|
||||
|
@ -159,6 +161,179 @@ static void groupDiagnostics(const std::vector<Record*> &Diags,
|
|||
I->second.IDNo = IDNo;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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 @@ void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
|
|||
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 @@ void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
|
|||
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 @@ static std::string getDiagCategoryEnum(llvm::StringRef name) {
|
|||
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 @@ void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) {
|
|||
|
||||
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 @@ void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) {
|
|||
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 @@ void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) {
|
|||
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 @@ void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) {
|
|||
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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче