@@ -82,25 +82,34 @@ bool has_lazy_field(const t_structured& node) {
8282}
8383
8484// Reports an existing name was redefined within the given parent node.
85- void report_redef_error (
85+ void report_redef_diag (
8686 diagnostics_engine& diags,
87+ const diagnostic_level& level,
8788 const char * kind,
8889 std::string_view name,
8990 const t_named& parent,
9091 const t_node& child,
9192 const t_node& /* existing*/ ) {
9293 // TODO(afuller): Use `existing` to provide more detail in the
9394 // diagnostic.
94- diags.error (
95- child, " {} `{}` is already defined for `{}`." , kind, name, parent.name ());
95+ diags.report (
96+ child,
97+ level,
98+ " {} `{}` is already defined for `{}`." ,
99+ kind,
100+ name,
101+ parent.name ());
96102}
97103
98104// Helper for checking for the redefinition of a name in the context of a node.
99105class redef_checker {
100106 public:
101107 redef_checker (
102- diagnostics_engine& diags, const char * kind, const t_named& parent)
103- : diags_(diags), kind_(kind), parent_(parent) {}
108+ diagnostics_engine& diags,
109+ const char * kind,
110+ const t_named& parent,
111+ const diagnostic_level& level = diagnostic_level::error)
112+ : diags_(diags), kind_(kind), parent_(parent), level_(level) {}
104113
105114 // Checks if the given `name`, derived from `node` via `child`, has already
106115 // been defined.
@@ -116,10 +125,11 @@ class redef_checker {
116125 }
117126 if (&node == &parent_ && existing == &parent_) {
118127 // The degenerate case where parent_ is conflicting with itself.
119- report_redef_error (diags_, kind_, name, parent_, child, *existing);
128+ report_redef_diag (diags_, level_ , kind_, name, parent_, child, *existing);
120129 } else {
121- diags_.error (
130+ diags_.report (
122131 child,
132+ level_,
123133 " {} `{}.{}` and `{}.{}` can not have same name in `{}`." ,
124134 kind_,
125135 node.name (),
@@ -136,8 +146,8 @@ class redef_checker {
136146 // For example, all functions in an interface.
137147 void check (const t_named& child) {
138148 if (const t_named* existing = insert (child.name (), child)) {
139- report_redef_error (
140- diags_, kind_, child.name (), parent_, child, *existing);
149+ report_redef_diag (
150+ diags_, level_, kind_, child.name (), parent_, child, *existing);
141151 }
142152 }
143153
@@ -162,6 +172,7 @@ class redef_checker {
162172 diagnostics_engine& diags_;
163173 const char * kind_;
164174 const t_named& parent_;
175+ const diagnostic_level level_;
165176
166177 std::unordered_map<std::string_view, const t_named*> seen_;
167178};
@@ -800,8 +811,9 @@ void validate_structured_annotation(sema_context& ctx, const t_named& node) {
800811 for (const t_const& annot : node.structured_annotations ()) {
801812 auto [it, inserted] = seen.emplace (annot.type (), &annot);
802813 if (!inserted) {
803- report_redef_error (
814+ report_redef_diag (
804815 ctx,
816+ diagnostic_level::error,
805817 " Structured annotation" ,
806818 it->first ->name (),
807819 node,
@@ -823,8 +835,14 @@ void validate_uri_uniqueness(sema_context& ctx, const t_program& prog) {
823835 }
824836 auto result = uri_to_node.emplace (uri, &node);
825837 if (!result.second ) {
826- report_redef_error (
827- ctx, " Thrift URI" , uri, node, node, *result.first ->second );
838+ report_redef_diag (
839+ ctx,
840+ diagnostic_level::error,
841+ " Thrift URI" ,
842+ uri,
843+ node,
844+ node,
845+ *result.first ->second );
828846 }
829847 });
830848 for (const auto * p : prog.get_included_programs ()) {
@@ -999,6 +1017,14 @@ void validate_function_priority_annotation(
9991017 }
10001018}
10011019
1020+ void validate_function_exception_field_name_uniqueness (
1021+ sema_context& ctx, const t_function& node) {
1022+ if (node.exceptions () != nullptr ) {
1023+ redef_checker (ctx, " Exception field" , node, diagnostic_level::warning)
1024+ .check_all (node.exceptions ()->fields ());
1025+ }
1026+ }
1027+
10021028void validate_exception_message_annotation (
10031029 sema_context& ctx, const t_exception& node) {
10041030 // Check that value of "message" annotation is
@@ -1679,6 +1705,8 @@ ast_validator standard_validator() {
16791705 validator.add_function_visitor (&validate_function_priority_annotation);
16801706 validator.add_function_visitor (ValidateAnnotationPositions{});
16811707 validator.add_function_visitor (&detail::validate_annotation_scopes<>);
1708+ validator.add_function_visitor (
1709+ &validate_function_exception_field_name_uniqueness);
16821710
16831711 validator.add_structured_definition_visitor (&validate_field_names_uniqueness);
16841712 validator.add_structured_definition_visitor (
0 commit comments