Coverage Report

Created: 2026-06-15 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmDiagnostics.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
#include "cmDiagnostics.h"
4
5
#include <cassert>
6
#include <map>
7
#include <string>
8
#include <utility>
9
10
#include <cmext/string_view>
11
12
#include "cmStringAlgorithms.h"
13
14
namespace {
15
16
#if __cplusplus >= 201703L
17
constexpr unsigned validateDiagnosticsSubtree(unsigned parent, unsigned index)
18
0
{
19
0
  // Ensure that all diagnostics, starting from the specified index, have the
20
0
  // specified parent as an ancestor. Return the first index that violates
21
0
  // this condition.
22
0
  while (index < cmDiagnostics::CategoryCount &&
23
0
         cmDiagnostics::CategoryInfo[index].Parent == parent) {
24
0
    unsigned const child = index;
25
0
    // For each diagnostic, 'consume' its children (if any).
26
0
    index = validateDiagnosticsSubtree(child, ++index);
27
0
  }
28
0
  return index;
29
0
}
30
31
static_assert(validateDiagnosticsSubtree(cmDiagnostics::CMD_NONE, 1) ==
32
                cmDiagnostics::CategoryCount,
33
              "Diagnostics are not properly ordered"
34
              " (hint: LHS is the index of the first misordered diagnostic)");
35
#endif
36
37
cm::optional<cmDiagnosticCategory> stringToCategory(cm::string_view input)
38
0
{
39
0
  using Map = std::map<cm::string_view, cmDiagnosticCategory>;
40
0
  static Map const mapping = {
41
0
#define CATEGORY_MAP(C) { #C ""_s, cmDiagnostics::C },
42
0
    CM_FOR_EACH_DIAGNOSTIC_CATEGORY(CATEGORY_MAP)
43
0
#undef CATEGORY_MAP
44
0
  };
45
46
0
  assert(!input.empty());
47
0
  if (input.size() >= 4 && cmHasLiteralPrefix(input, "CMD_")) {
48
0
    auto const i = mapping.find(input);
49
0
    if (i != mapping.end()) {
50
0
      return i->second;
51
0
    }
52
0
  }
53
54
0
  return cm::nullopt;
55
0
}
56
}
57
58
#if __cplusplus < 201703L
59
// Prior to C++17, the compiler is unhappy if this member doesn't have explicit
60
// storage... and clang-tidy is unhappy if it does.
61
// NOLINTNEXTLINE(*-redundant-declaration)
62
constexpr cmDiagnostics::DiagnosticCategoryInformation
63
  cmDiagnostics::CategoryInfo[cmDiagnostics::CategoryCount];
64
#endif
65
66
cm::string_view cmDiagnostics::GetActionString(DiagnosticAction action)
67
0
{
68
0
  switch (action) {
69
0
    case Ignore:
70
0
      return "IGNORE"_s;
71
0
    case Warn:
72
0
      return "WARN"_s;
73
0
    case SendError:
74
0
      return "SEND_ERROR"_s;
75
0
    case FatalError:
76
0
      return "FATAL_ERROR"_s;
77
0
    default:
78
0
      return {};
79
0
  }
80
0
}
81
82
cm::string_view cmDiagnostics::GetCategoryString(DiagnosticCategory category)
83
28
{
84
28
  static cm::string_view const names[CategoryCount] = {
85
28
    {}, // CMD_NONE
86
588
#define CATEGORY_NAME(C) #C ""_s,
87
196
    CM_FOR_EACH_DIAGNOSTIC_CATEGORY(CATEGORY_NAME)
88
28
#undef CATEGORY_MAP
89
28
  };
90
91
28
  if (category < CategoryCount) {
92
28
    return names[category];
93
28
  }
94
0
  return {};
95
28
}
96
97
cm::optional<cmDiagnosticAction> cmDiagnostics::GetDiagnosticAction(
98
  cm::string_view name)
99
0
{
100
0
  if (name == "IGNORE"_s) {
101
0
    return DiagnosticAction::Ignore;
102
0
  }
103
0
  if (name == "WARN"_s) {
104
0
    return DiagnosticAction::Warn;
105
0
  }
106
0
  if (name == "SEND_ERROR"_s) {
107
0
    return DiagnosticAction::SendError;
108
0
  }
109
0
  if (name == "FATAL_ERROR"_s) {
110
0
    return DiagnosticAction::FatalError;
111
0
  }
112
113
0
  return cm::nullopt;
114
0
}
115
116
cm::optional<cmDiagnosticCategory> cmDiagnostics::GetDiagnosticCategory(
117
  cm::string_view name)
118
0
{
119
0
  return stringToCategory(name);
120
0
}