Skip to content

Commit d7ca1e2

Browse files
committed
Merge branch 'standard-ifdefs' into ast-matcher
2 parents 64f51ef + c283d9a commit d7ca1e2

14 files changed

Lines changed: 96 additions & 84 deletions

File tree

‎CMakeLists.txt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ set(rules_index_parts_dir ${CMAKE_BINARY_DIR}/rules_index/parts)
231231
set(RULES_IR_DIR "${CMAKE_BINARY_DIR}/rules")
232232
set(rust_rules_ir_outputs)
233233
foreach(_rule_dir IN LISTS rule_subdirs)
234-
file(GLOB _cpp_srcs ${_rule_dir}/src.c ${_rule_dir}/src.cpp)
234+
file(GLOB _cpp_srcs ${_rule_dir}/src.c ${_rule_dir}/src.cpp ${_rule_dir}/src_cxx*.cpp)
235235
if(NOT _cpp_srcs)
236236
continue()
237237
endif()

‎cpp2rust/converter/rules/rules_loader.cpp‎

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#include <clang/AST/ASTContext.h>
77
#include <clang/AST/RecursiveASTVisitor.h>
88
#include <clang/Basic/LangOptions.h>
9-
#include <clang/Basic/LangStandard.h>
109
#include <clang/Lex/Lexer.h>
1110
#include <clang/Lex/Preprocessor.h>
1211
#include <clang/Sema/Sema.h>
@@ -280,23 +279,22 @@ std::string WrapRule(const llvm::json::Object &rule, bool is_cxx) {
280279
}
281280

282281
unsigned CxxStandard(const clang::LangOptions &opts) {
283-
switch (opts.LangStd) {
284-
case clang::LangStandard::lang_cxx23:
285-
case clang::LangStandard::lang_gnucxx23:
282+
if (opts.CPlusPlus26) {
283+
return 26;
284+
}
285+
if (opts.CPlusPlus23) {
286286
return 23;
287-
case clang::LangStandard::lang_cxx20:
288-
case clang::LangStandard::lang_gnucxx20:
287+
}
288+
if (opts.CPlusPlus20) {
289289
return 20;
290-
case clang::LangStandard::lang_cxx17:
291-
case clang::LangStandard::lang_gnucxx17:
290+
}
291+
if (opts.CPlusPlus17) {
292292
return 17;
293-
case clang::LangStandard::lang_cxx11:
294-
case clang::LangStandard::lang_gnucxx11:
295-
return 11;
296-
default:
297-
assert(0 && "rules are indexed for C++11, C++17, C++20 and C++23 only");
298-
return 0;
299293
}
294+
if (opts.CPlusPlus14) {
295+
return 14;
296+
}
297+
return 11;
300298
}
301299

302300
std::string BuildRulesEpilogue(const std::unordered_set<std::string> &keys,
@@ -317,11 +315,7 @@ std::string BuildRulesEpilogue(const std::unordered_set<std::string> &keys,
317315
}
318316
for (const auto &entry : *entries) {
319317
auto rule = entry.getAsObject();
320-
if (auto standards = rule->getArray("standards");
321-
standards &&
322-
llvm::none_of(*standards, [&](const llvm::json::Value &v) {
323-
return v.getAsInteger() == standard;
324-
})) {
318+
if (auto since = rule->getInteger("since"); since && *since > standard) {
325319
continue;
326320
}
327321
if (auto required = rule->getArray("requires");

‎cpp2rust/rule_preprocessing/cpp_rule_indexer.cpp‎

Lines changed: 32 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -139,27 +139,49 @@ llvm::json::Object ReadJson(const fs::path &path) {
139139
return std::move(*parsed->getAsObject());
140140
}
141141

142-
void MergeRules(llvm::json::Object &into, llvm::json::Object &&from);
142+
unsigned SinceStandard(const fs::path &src_path) {
143+
auto stem_string = src_path.stem().string();
144+
llvm::StringRef stem = stem_string;
145+
unsigned standard = 11;
146+
if (stem.consume_front("src_cxx") && stem.getAsInteger(10, standard)) {
147+
llvm::errs() << "ERROR: unexpected rule file " << src_path.string() << '\n';
148+
std::exit(EXIT_FAILURE);
149+
}
150+
return standard;
151+
}
152+
153+
void MergeRules(llvm::json::Object &into, llvm::json::Object &&from) {
154+
for (auto &[key, entries] : from) {
155+
for (auto &entry : *entries.getAsArray()) {
156+
AddRule(into, key.str(), std::move(entry));
157+
}
158+
}
159+
}
143160

144161
void IndexDir(const fs::path &rule_dir, const fs::path &out) {
145162
auto dir_name = rule_dir.filename().string();
146163
llvm::json::Object c_rules;
147164
if (fs::exists(rule_dir / "src.c")) {
148165
Index(rule_dir / "src.c", /*is_c=*/true, dir_name, {}, c_rules);
149166
}
167+
std::vector<fs::path> cxx_srcs;
168+
for (const auto &entry : fs::directory_iterator(rule_dir)) {
169+
auto name = entry.path().filename().string();
170+
if (name == "src.c" || name == "src.cpp" ||
171+
(name.starts_with("src_cxx") && name.ends_with(".cpp"))) {
172+
cxx_srcs.push_back(entry.path());
173+
}
174+
}
175+
std::ranges::sort(cxx_srcs);
150176
llvm::json::Object cxx_rules;
151-
for (unsigned standard : {11u, 17u, 20u, 23u}) {
177+
for (const auto &src_path : cxx_srcs) {
178+
auto standard = SinceStandard(src_path);
152179
llvm::json::Object rules;
153-
std::vector<std::string> flags{std::format("-std=c++{}", standard)};
154-
for (const char *name : {"src.c", "src.cpp"}) {
155-
auto src_path = rule_dir / name;
156-
if (fs::exists(src_path)) {
157-
Index(src_path, /*is_c=*/false, dir_name, flags, rules);
158-
}
159-
}
180+
Index(src_path, /*is_c=*/false, dir_name,
181+
{std::format("-std=c++{}", standard)}, rules);
160182
for (auto &[key, entries] : rules) {
161183
for (auto &entry : *entries.getAsArray()) {
162-
(*entry.getAsObject())["standards"] = llvm::json::Array{standard};
184+
(*entry.getAsObject())["since"] = standard;
163185
}
164186
}
165187
MergeRules(cxx_rules, std::move(rules));
@@ -168,33 +190,6 @@ void IndexDir(const fs::path &rule_dir, const fs::path &out) {
168190
{"cpp", std::move(cxx_rules)}});
169191
}
170192

171-
void MergeRules(llvm::json::Object &into, llvm::json::Object &&from) {
172-
for (auto &[key, entries] : from) {
173-
auto &slot = into[key];
174-
if (!slot.getAsArray()) {
175-
slot = llvm::json::Array();
176-
}
177-
auto merged = slot.getAsArray();
178-
for (auto &entry : *entries.getAsArray()) {
179-
auto rule = entry.getAsObject();
180-
auto standards = rule->getArray("standards");
181-
auto same = llvm::find_if(*merged, [&](const llvm::json::Value &value) {
182-
auto other = value.getAsObject();
183-
return standards &&
184-
*other->getString("dir") == *rule->getString("dir") &&
185-
*other->getString("text") == *rule->getString("text");
186-
});
187-
if (same == merged->end()) {
188-
merged->push_back(std::move(*rule));
189-
continue;
190-
}
191-
auto into_standards = same->getAsObject()->getArray("standards");
192-
into_standards->insert(into_standards->end(), standards->begin(),
193-
standards->end());
194-
}
195-
}
196-
}
197-
198193
void MergeIndexes(const std::vector<std::string> &parts,
199194
const std::vector<std::string> &common_headers,
200195
const fs::path &index_dir) {

‎docs/src/rules/format.md‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ library it covers (`rules/unistd`, `rules/vector`, `rules/string`, ...). It
55
contains:
66

77
- `src.cpp` and/or `src.c`: the C++ (or C) side of each rule.
8+
- `src_cxxNN.cpp` (optional): C++ rules that exist from C++NN on, for example
9+
`src_cxx17.cpp`; see below.
810
- `tgt_unsafe.rs`: the Rust targets for the unsafe model.
911
- `tgt_refcount.rs`: the Rust targets for the reference counting model
1012
(optional, see below).
@@ -141,6 +143,21 @@ for the C++ `__builtin_mul_overflow` (returning `bool`) while `src.c` defines
141143
`f12`/`f13` for the C version (returning `int`); their Rust bodies are
142144
identical.
143145

146+
## Standard versions
147+
148+
`src.cpp` is parsed as C++11 and its rules are available to every C++
149+
translation unit. A rule that needs a later standard goes into `src_cxxNN.cpp`,
150+
which is parsed as C++NN and whose rules are only loaded into translation units
151+
compiled as C++NN or later:
152+
153+
```cpp
154+
// rules/new/src_cxx17.cpp
155+
template <typename T1> T1 *f5(T1 *a0) { return std::launder(a0); }
156+
```
157+
158+
Rule names are shared across all the files of a module. Platform `#if`s are
159+
fine in any file; `#if __cplusplus` is not needed.
160+
144161
## The `rules` crate
145162
146163
The whole `rules/` tree is a single Rust crate. `rules/build.rs` walks the tree,

‎rules/builtin_types/src.cpp‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66
typedef decltype(nullptr) t0;
77

88
typedef bool t10;
9-
#if __cplusplus >= 202002L
10-
typedef char8_t t50;
11-
#endif
129
typedef char16_t t80;
1310
typedef wchar_t t110;
1411
typedef char32_t t120;

‎rules/builtin_types/src_cxx20.cpp‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Copyright (c) 2022-present INESC-ID.
2+
// Distributed under the MIT license that can be found in the LICENSE file.
3+
4+
typedef char8_t t50;
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
#include <compare>
55

6-
#if __cplusplus >= 202002L
76
typedef std::strong_ordering t1;
87

98
std::strong_ordering f1() { return std::strong_ordering::less; }
@@ -27,4 +26,3 @@ bool f8(std::strong_ordering a0) { return operator>(a0, 0); }
2726
bool f9(std::strong_ordering a0) { return operator<=(a0, 0); }
2827

2928
bool f10(std::strong_ordering a0) { return operator>=(a0, 0); }
30-
#endif
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
#include <cstddef>
55

6-
#if __cplusplus >= 201703L
76
using t1 = std::byte;
87
typedef std::size_t t9;
98

@@ -14,4 +13,3 @@ std::byte f2(const std::byte &a0, unsigned a1) { return operator>>(a0, a1); }
1413
std::byte f3(std::byte &a0, unsigned a1) { return operator<<=(a0, a1); }
1514

1615
std::byte f4(std::byte &a0, unsigned a1) { return operator>>=(a0, a1); }
17-
#endif

‎rules/new/src.cpp‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,3 @@ void *f3(std::size_t a0) { return ::operator new[](a0); }
1111

1212
void f4(void *a0) { return ::operator delete[](a0); }
1313

14-
#if __cplusplus >= 201703L
15-
template <typename T1> T1 *f5(T1 *a0) { return std::launder(a0); }
16-
#endif

‎rules/new/src_cxx17.cpp‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Copyright (c) 2022-present INESC-ID.
2+
// Distributed under the MIT license that can be found in the LICENSE file.
3+
4+
#include <new>
5+
6+
template <typename T1> T1 *f5(T1 *a0) { return std::launder(a0); }

0 commit comments

Comments
 (0)