• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tudasc / TypeART / 12904858633

22 Jan 2025 09:11AM UTC coverage: 90.735% (+0.005%) from 90.73%
12904858633

Pull #149

github

web-flow
Merge f0a5eda87 into 37d7f8cb1
Pull Request #149: Replace llvm::Optional with std::optional

88 of 102 new or added lines in 23 files covered. (86.27%)

1 existing line in 1 file now uncovered.

3829 of 4220 relevant lines covered (90.73%)

117945.73 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.64
/lib/support/FileConfiguration.cpp
1
// TypeART library
2
//
3
// Copyright (c) 2017-2025 TypeART Authors
4
// Distributed under the BSD 3-Clause license.
5
// (See accompanying file LICENSE.txt or copy at
6
// https://opensource.org/licenses/BSD-3-Clause)
7
//
8
// Project home: https://github.com/tudasc/TypeART
9
//
10
// SPDX-License-Identifier: BSD-3-Clause
11
//
12

13
#include "FileConfiguration.h"
14

15
#include "support/Configuration.h"
16

17
#include "llvm/ADT/StringMap.h"
18
#include "llvm/ADT/StringRef.h"
19
#include "llvm/Support/FileSystem.h"
20
#include "llvm/Support/MemoryBuffer.h"
21
#include "llvm/Support/YAMLTraits.h"
22

23
#include <optional>
24

25
using namespace llvm;
26

27
namespace typeart::config::file {
28

29
using typeart::config::ConfigStdArgValues;
30

31
struct ConfigurationOptions {
36✔
32
  std::string types{ConfigStdArgValues::types};
72✔
33
  bool heap{ConfigStdArgValues::heap};
36✔
34
  bool stack{ConfigStdArgValues::stack};
36✔
35
  bool global{ConfigStdArgValues::global};
36✔
36
  bool statistics{ConfigStdArgValues::stats};
36✔
37
  bool stack_lifetime{ConfigStdArgValues::stack_lifetime};
36✔
38
  std::string typegen{ConfigStdArgValues::typegen};
72✔
39
  bool filter{true};
36✔
40
  struct CallFilter {
41
    std::string implementation{ConfigStdArgValues::filter_impl};
72✔
42
    std::string glob{ConfigStdArgValues::filter_glob};
72✔
43
    std::string glob_deep{ConfigStdArgValues::filter_glob_deep};
72✔
44
    std::string cg_file{ConfigStdArgValues::filter_cg_file};
72✔
45
  };
46
  CallFilter call_filter_configuration{};
288✔
47
  struct Analysis {
48
    bool filter_global{ConfigStdArgValues::analysis_filter_global};
49
    bool filter_heap_alloc{ConfigStdArgValues::analysis_filter_heap_alloc};
50
    bool filter_pointer_alloc{ConfigStdArgValues::analysis_filter_pointer_alloc};
51
    bool filter_alloca_non_array{ConfigStdArgValues::analysis_filter_alloca_non_array};
52
  };
53
  Analysis analysis_configuration{};
72✔
54
  int version{1};
36✔
55
};
56

57
namespace helper {
58

59
ConfigurationOptions map2config(const FileOptionsMap& mapping) {
36✔
60
  const auto make_entry = [&mapping](std::string_view entry, auto& ref) {
612✔
61
    auto key = llvm::StringRef(entry.data());
576✔
62
    ref      = static_cast<typename std::remove_reference<decltype(ref)>::type>(mapping.lookup(key));
576✔
63
  };
576✔
64

65
  ConfigurationOptions conf_file;
36✔
66
  make_entry(ConfigStdArgs::types, conf_file.types);
36✔
67
  make_entry(ConfigStdArgs::stats, conf_file.statistics);
36✔
68
  make_entry(ConfigStdArgs::heap, conf_file.heap);
36✔
69
  make_entry(ConfigStdArgs::global, conf_file.global);
36✔
70
  make_entry(ConfigStdArgs::stack, conf_file.stack);
36✔
71
  make_entry(ConfigStdArgs::stack_lifetime, conf_file.stack_lifetime);
36✔
72
  make_entry(ConfigStdArgs::filter, conf_file.filter);
36✔
73
  make_entry(ConfigStdArgs::filter_impl, conf_file.call_filter_configuration.implementation);
36✔
74
  make_entry(ConfigStdArgs::filter_glob, conf_file.call_filter_configuration.glob);
36✔
75
  make_entry(ConfigStdArgs::filter_glob_deep, conf_file.call_filter_configuration.glob_deep);
36✔
76
  make_entry(ConfigStdArgs::filter_cg_file, conf_file.call_filter_configuration.cg_file);
36✔
77
  make_entry(ConfigStdArgs::analysis_filter_global, conf_file.analysis_configuration.filter_global);
36✔
78
  make_entry(ConfigStdArgs::analysis_filter_heap_alloc, conf_file.analysis_configuration.filter_heap_alloc);
36✔
79
  make_entry(ConfigStdArgs::analysis_filter_pointer_alloc, conf_file.analysis_configuration.filter_pointer_alloc);
36✔
80
  make_entry(ConfigStdArgs::analysis_filter_alloca_non_array, conf_file.analysis_configuration.filter_alloca_non_array);
36✔
81
  make_entry(ConfigStdArgs::typegen, conf_file.typegen);
36✔
82
  return conf_file;
36✔
83
}
36✔
84

85
FileOptionsMap config2map(const ConfigurationOptions& conf_file) {
36✔
86
  using namespace detail;
87

88
  const auto make_entry = [](std::string&& key,
576✔
89
                             const auto& field_value) -> std::pair<StringRef, typename FileOptionsMap ::mapped_type> {
90
    LOG_DEBUG(key << "->" << field_value)
91
    return {key, config::OptionValue{field_value}};
576✔
92
  };
93
  FileOptionsMap mapping_ = {
612✔
94
      make_entry(ConfigStdArgs::types, conf_file.types),
36✔
95
      make_entry(ConfigStdArgs::stats, conf_file.statistics),
36✔
96
      make_entry(ConfigStdArgs::heap, conf_file.heap),
36✔
97
      make_entry(ConfigStdArgs::global, conf_file.global),
36✔
98
      make_entry(ConfigStdArgs::stack, conf_file.stack),
36✔
99
      make_entry(ConfigStdArgs::stack_lifetime, conf_file.stack_lifetime),
36✔
100
      make_entry(ConfigStdArgs::typegen, conf_file.typegen),
36✔
101
      make_entry(ConfigStdArgs::filter, conf_file.filter),
36✔
102
      make_entry(ConfigStdArgs::filter_impl, conf_file.call_filter_configuration.implementation),
36✔
103
      make_entry(ConfigStdArgs::filter_glob, conf_file.call_filter_configuration.glob),
36✔
104
      make_entry(ConfigStdArgs::filter_glob_deep, conf_file.call_filter_configuration.glob_deep),
36✔
105
      make_entry(ConfigStdArgs::filter_cg_file, conf_file.call_filter_configuration.cg_file),
36✔
106
      make_entry(ConfigStdArgs::analysis_filter_global, conf_file.analysis_configuration.filter_global),
36✔
107
      make_entry(ConfigStdArgs::analysis_filter_heap_alloc, conf_file.analysis_configuration.filter_heap_alloc),
36✔
108
      make_entry(ConfigStdArgs::analysis_filter_pointer_alloc, conf_file.analysis_configuration.filter_pointer_alloc),
36✔
109
      make_entry(ConfigStdArgs::analysis_filter_alloca_non_array,
72✔
110
                 conf_file.analysis_configuration.filter_alloca_non_array),
36✔
111
  };
112
  return mapping_;
36✔
113
}
36✔
114

115
}  // namespace helper
116

117
std::string write_file_configuration_as_text(const FileOptions& file_options);
118

119
class YamlFileConfiguration final : public FileOptions {
120
 private:
121
  FileOptionsMap mapping_;
122

123
 public:
124
  explicit YamlFileConfiguration(const ConfigurationOptions& conf_file);
125

126
  [[nodiscard]] std::optional<config::OptionValue> getValue(std::string_view opt_path) const override;
127

128
  [[nodiscard]] FileOptionsMap getConfiguration() const override;
129

130
  [[nodiscard]] std::string getConfigurationAsString() const override;
131

132
  ~YamlFileConfiguration() override = default;
60✔
133
};
134

135
YamlFileConfiguration::YamlFileConfiguration(const ConfigurationOptions& conf_file)
72✔
136
    : mapping_(helper::config2map(conf_file)) {
72✔
137
}
36✔
138

139
std::optional<typeart::config::OptionValue> YamlFileConfiguration::getValue(std::string_view opt_path) const {
480✔
140
  auto key = llvm::StringRef(opt_path.data());
480✔
141
  if (mapping_.count(key) != 0U) {
480✔
142
    return mapping_.lookup(key);
480✔
143
  }
NEW
144
  return {};
×
145
}
480✔
146

147
FileOptionsMap YamlFileConfiguration::getConfiguration() const {
72✔
148
  return this->mapping_;
72✔
149
}
150

151
std::string YamlFileConfiguration::getConfigurationAsString() const {
36✔
152
  return write_file_configuration_as_text(*this);
36✔
153
}
154

155
namespace yaml {
156
ConfigurationOptions yaml_read_file(llvm::yaml::Input& input);
157
void yaml_output_file(llvm::yaml::Output& output, ConfigurationOptions& config);
158
}  // namespace yaml
159

160
namespace compat {
161
auto open_flag() {
×
162
#if LLVM_VERSION_MAJOR < 13
163
  return llvm::sys::fs::OpenFlags::F_Text;
164
#else
165
  return llvm::sys::fs::OpenFlags::OF_Text;
×
166
#endif
167
}
168
}  // namespace compat
169

170
[[maybe_unused]] llvm::ErrorOr<std::unique_ptr<FileOptions>> make_file_configuration(std::string_view file_path) {
36✔
171
  using namespace llvm;
172

173
  ErrorOr<std::unique_ptr<MemoryBuffer>> memBuffer = MemoryBuffer::getFile(file_path.data());
36✔
174

175
  if (std::error_code error = memBuffer.getError(); error) {
36✔
176
    LOG_WARNING("Warning while loading configuration file \'" << file_path.data() << "\'. Reason: " << error.message());
6✔
177
    return error;
6✔
178
  }
179

180
  llvm::yaml::Input input_yaml(memBuffer.get()->getMemBufferRef());
30✔
181
  const auto file_content = typeart::config::file::yaml::yaml_read_file(input_yaml);
30✔
182

183
  return std::make_unique<YamlFileConfiguration>(file_content);
30✔
184
}
36✔
185

186
llvm::ErrorOr<std::unique_ptr<FileOptions>> make_default_file_configuration() {
6✔
187
  ConfigurationOptions options{};
30✔
188
  return std::make_unique<YamlFileConfiguration>(options);
6✔
189
}
6✔
190

191
llvm::ErrorOr<bool> write_file_configuration(llvm::raw_ostream& oss, const FileOptions& options) {
36✔
192
  using namespace llvm;
193

194
  llvm::yaml::Output out(oss);
36✔
195

196
  auto data = options.getConfiguration();
36✔
197

198
  auto conf_file = helper::map2config(options.getConfiguration());
36✔
199
  yaml::yaml_output_file(out, conf_file);
36✔
200

201
  return true;
36✔
202
}
36✔
203

204
std::string write_file_configuration_as_text(const FileOptions& file_options) {
36✔
205
  std::string config_text;
36✔
206
  llvm::raw_string_ostream sstream(config_text);
36✔
207
  if (!write_file_configuration(sstream, file_options)) {
36✔
208
    LOG_WARNING("Could not write config file to string stream.")
×
209
  }
×
210
  return sstream.str();
36✔
211
}
36✔
212

213
}  // namespace typeart::config::file
214

215
using namespace llvm::yaml;
216
using namespace typeart::config::file;
217

218
template <>
219
struct llvm::yaml::MappingTraits<typeart::config::file::ConfigurationOptions::Analysis> {
220
  static void mapping(IO& yml_io, typeart::config::file::ConfigurationOptions::Analysis& info) {
66✔
221
    using typeart::config::ConfigStdArgs;
222
    const auto drop_prefix = [](const std::string& path, std::string_view prefix = "analysis-") {
264✔
223
      llvm::StringRef prefix_less{path};
264✔
224
      prefix_less.consume_front(prefix.data());
264✔
225
      return prefix_less;
264✔
226
    };
227
    yml_io.mapOptional(drop_prefix(ConfigStdArgs::analysis_filter_global).data(), info.filter_global);
66✔
228
    yml_io.mapOptional(drop_prefix(ConfigStdArgs::analysis_filter_heap_alloc).data(), info.filter_heap_alloc);
66✔
229
    yml_io.mapOptional(drop_prefix(ConfigStdArgs::analysis_filter_pointer_alloc).data(), info.filter_pointer_alloc);
66✔
230
    yml_io.mapOptional(drop_prefix(ConfigStdArgs::analysis_filter_alloca_non_array).data(),
132✔
231
                       info.filter_alloca_non_array);
66✔
232
  }
66✔
233
};
234

235
template <>
236
struct llvm::yaml::MappingTraits<typeart::config::file::ConfigurationOptions::CallFilter> {
237
  static void mapping(IO& yml_io, typeart::config::file::ConfigurationOptions::CallFilter& info) {
66✔
238
    using typeart::config::ConfigStdArgs;
239
    const auto drop_prefix = [](const std::string& path, std::string_view prefix = "filter-") {
264✔
240
      llvm::StringRef prefix_less{path};
264✔
241
      prefix_less.consume_front(prefix.data());
264✔
242
      return prefix_less;
264✔
243
    };
244
    yml_io.mapOptional(drop_prefix(ConfigStdArgs::filter_impl).data(), info.implementation);
66✔
245
    yml_io.mapOptional(drop_prefix(ConfigStdArgs::filter_glob).data(), info.glob);
66✔
246
    yml_io.mapOptional(drop_prefix(ConfigStdArgs::filter_glob_deep).data(), info.glob_deep);
66✔
247
    yml_io.mapOptional(drop_prefix(ConfigStdArgs::filter_cg_file).data(), info.cg_file);
66✔
248
  }
66✔
249
};
250

251
template <>
252
struct llvm::yaml::MappingTraits<typeart::config::file::ConfigurationOptions> {
253
  static void mapping(IO& yml_io, typeart::config::file::ConfigurationOptions& info) {
66✔
254
    using typeart::config::ConfigStdArgs;
255
    yml_io.mapRequired(ConfigStdArgs::types, info.types);
66✔
256
    yml_io.mapRequired(ConfigStdArgs::heap, info.heap);
66✔
257
    yml_io.mapRequired(ConfigStdArgs::stack, info.stack);
66✔
258
    yml_io.mapOptional(ConfigStdArgs::global, info.global);
66✔
259
    yml_io.mapOptional(ConfigStdArgs::stats, info.statistics);
66✔
260
    yml_io.mapOptional(ConfigStdArgs::stack_lifetime, info.stack_lifetime);
66✔
261
    yml_io.mapRequired(ConfigStdArgs::typegen, info.typegen);
66✔
262
    yml_io.mapRequired(ConfigStdArgs::filter, info.filter);
66✔
263
    yml_io.mapOptional("call-filter", info.call_filter_configuration);
66✔
264
    yml_io.mapOptional("analysis", info.analysis_configuration);
66✔
265
    yml_io.mapOptional("file-format", info.version);
66✔
266
  }
66✔
267
};
268

269
namespace typeart::config::file::yaml {
270

271
ConfigurationOptions yaml_read_file(llvm::yaml::Input& input) {
30✔
272
  ConfigurationOptions file_content{};
150✔
273
  input >> file_content;
30✔
274

275
  return file_content;
30✔
276
}
30✔
277

278
void yaml_output_file(llvm::yaml::Output& output, ConfigurationOptions& config) {
36✔
279
  output << config;
36✔
280
}
36✔
281

282
}  // namespace typeart::config::file::yaml
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc