bool                    header;
        bool                    header_only;
        bool                    nonany_branch_mode;
+       bool                    group_set;
        int                     max_stack;
        struct perf_read_values show_threads_values;
        const char              *pretty_printing_style;
        return err;
 }
 
+/*
+ * Events in data file are not collect in groups, but we still want
+ * the group display. Set the artificial group and set the leader's
+ * forced_leader flag to notify the display code.
+ */
+static void setup_forced_leader(struct report *report,
+                               struct perf_evlist *evlist)
+{
+       if (report->group_set && !evlist->nr_groups) {
+               struct perf_evsel *leader = perf_evlist__first(evlist);
+
+               perf_evlist__set_leader(evlist);
+               leader->forced_leader = true;
+       }
+}
+
+static int process_feature_event(struct perf_tool *tool,
+                                union perf_event *event,
+                                struct perf_session *session __maybe_unused)
+{
+       struct report *rep = container_of(tool, struct report, tool);
+
+       if (event->feat.feat_id < HEADER_LAST_FEATURE)
+               return perf_event__process_feature(tool, event, session);
+
+       if (event->feat.feat_id != HEADER_LAST_FEATURE) {
+               pr_err("failed: wrong feature ID: %" PRIu64 "\n",
+                      event->feat.feat_id);
+               return -1;
+       }
+
+       /*
+        * All features are received, we can force the
+        * group if needed.
+        */
+       setup_forced_leader(rep, session->evlist);
+       return 0;
+}
+
 static int process_sample_event(struct perf_tool *tool,
                                union perf_event *event,
                                struct perf_sample *sample,
                "perf report [<options>]",
                NULL
        };
-       bool group_set = false;
        struct report report = {
                .tool = {
                        .sample          = process_sample_event,
                        .id_index        = perf_event__process_id_index,
                        .auxtrace_info   = perf_event__process_auxtrace_info,
                        .auxtrace        = perf_event__process_auxtrace,
-                       .feature         = perf_event__process_feature,
+                       .feature         = process_feature_event,
                        .ordered_events  = true,
                        .ordering_requires_timestamps = true,
                },
                   "Specify disassembler style (e.g. -M intel for intel syntax)"),
        OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
                    "Show a column with the sum of periods"),
-       OPT_BOOLEAN_SET(0, "group", &symbol_conf.event_group, &group_set,
+       OPT_BOOLEAN_SET(0, "group", &symbol_conf.event_group, &report.group_set,
                    "Show event group information together"),
        OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "",
                    "use branch records for per branch histogram filling",
        has_br_stack = perf_header__has_feat(&session->header,
                                             HEADER_BRANCH_STACK);
 
-       /*
-        * Events in data file are not collect in groups, but we still want
-        * the group display. Set the artificial group and set the leader's
-        * forced_leader flag to notify the display code.
-        */
-       if (group_set && !session->evlist->nr_groups) {
-               struct perf_evsel *leader = perf_evlist__first(session->evlist);
-
-               perf_evlist__set_leader(session->evlist);
-               leader->forced_leader = true;
-       }
+       setup_forced_leader(&report, session->evlist);
 
        if (itrace_synth_opts.last_branch)
                has_br_stack = true;