Skip to content

Commit be4ef00

Browse files
authored
Merge branch 'master' into address-of-variadic-function
2 parents deaf7cd + a8ca6ad commit be4ef00

21 files changed

Lines changed: 1235 additions & 75 deletions

‎cpp2rust/converter/converter.cpp‎

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "converter/converter.h"
55

66
#include <clang/AST/APValue.h>
7+
#include <clang/AST/IgnoreExpr.h>
78
#include <clang/AST/ParentMapContext.h>
89
#include <clang/Basic/LangOptions.h>
910
#include <clang/Basic/SourceManager.h>
@@ -517,6 +518,9 @@ bool Converter::ConvertVarDeclSkipInit(clang::VarDecl *decl) {
517518
ENSURE(decl_ids_.insert(GetID(decl)).second);
518519
global_inits_.push_back(ForceGlobalInit(decl));
519520
} else if (decl->isStaticLocal()) {
521+
if (!globals_.insert(name).second) {
522+
return false;
523+
}
520524
StrCat(keyword::kStatic, keyword_mut_);
521525
} else if (decl->isLocalVarDecl()) {
522526
StrCat(keyword::kLet);
@@ -2007,6 +2011,16 @@ std::string Converter::GetFunctionRefName(const clang::FunctionDecl *fn_decl) {
20072011

20082012
void Converter::ConvertFunctionToFunctionPointer(
20092013
const clang::FunctionDecl *fn_decl) {
2014+
if (auto *method = clang::dyn_cast<clang::CXXMethodDecl>(fn_decl);
2015+
method && method->isLambdaStaticInvoker()) {
2016+
assert(!method->getParent()->isGenericLambda());
2017+
StrCat("Some");
2018+
PushParen paren(*this);
2019+
ConvertLambdaClosure(method->getParent(),
2020+
method->getParent()->getLambdaCallOperator());
2021+
computed_expr_type_ = ComputedExprType::FreshPointer;
2022+
return;
2023+
}
20102024
StrCat(std::format("Some({})", GetFunctionRefName(fn_decl)));
20112025
computed_expr_type_ = ComputedExprType::FreshPointer;
20122026
}
@@ -2058,7 +2072,11 @@ Converter::CallInfo Converter::CollectCallInfo(clang::CallExpr *expr) {
20582072
unsigned num_named_params =
20592073
function ? function->getNumParams() : proto->getNumParams();
20602074
info.is_variadic = function ? function->isVariadic() : proto->isVariadic();
2061-
info.is_fn_ptr_call = !function || AsLambdaClass(callee->getType());
2075+
info.is_fn_ptr_call =
2076+
!function || AsLambdaClass(callee->getType()) ||
2077+
clang::isa<clang::SubstNonTypeTemplateParmExpr>(
2078+
clang::IgnoreExprNodes(callee, clang::IgnoreParensSingleStep,
2079+
clang::IgnoreImplicitCastsSingleStep));
20622080
info.is_libc_passthrough = RuleRegistry::IsLibcPassthrough(ctx_, expr);
20632081

20642082
for (unsigned i = 0; i < num_named_params && i < num_args; ++i) {
@@ -3236,6 +3254,13 @@ std::string Converter::ConvertDeclRef(clang::Expr *expr,
32363254
}
32373255

32383256
bool Converter::VisitDeclRefExpr(clang::DeclRefExpr *expr) {
3257+
if (auto param =
3258+
clang::dyn_cast<clang::TemplateParamObjectDecl>(expr->getDecl());
3259+
param && AsLambdaClass(param->getType())) {
3260+
StrCat(GetDefaultAsString(param->getType()));
3261+
computed_expr_type_ = ComputedExprType::FreshValue;
3262+
return false;
3263+
}
32393264
if (auto init = AsLambdaUncapturedConstant(curr_function_, expr)) {
32403265
Convert(init);
32413266
return false;
@@ -4266,10 +4291,6 @@ std::string Converter::GetArrayDefaultAsString(clang::QualType qual_type) {
42664291
std::string Converter::GetDefaultAsString(clang::QualType qual_type) {
42674292
if (auto lambda = AsLambdaClass(qual_type);
42684293
lambda && lambda->captures().empty()) {
4269-
if (HasStaticLocal(lambda->getLambdaCallOperator()->getBody())) {
4270-
llvm::report_fatal_error("default-constructed lambda with a static local "
4271-
"is not supported yet");
4272-
}
42734294
Buffer buf(*this);
42744295
ConvertCapturelessLambda(lambda);
42754296
return std::move(buf).str();

‎cpp2rust/converter/converter.h‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
// Distributed under the MIT license that can be found in the LICENSE file.
55

66
#include <clang/AST/ASTContext.h>
7+
#include <clang/AST/Mangle.h>
78
#include <clang/AST/RecursiveASTVisitor.h>
89
#include <clang/Sema/Sema.h>
910

1011
#include <functional>
1112
#include <map>
13+
#include <memory>
1214
#include <optional>
1315
#include <string>
1416
#include <type_traits>
@@ -32,9 +34,18 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
3234
const char *keyword_unsafe = "unsafe",
3335
const char *keyword_mut = keyword::kMut)
3436
: rs_code_(&rs_code), ctx_(ctx), keyword_unsafe_(keyword_unsafe),
35-
keyword_mut_(keyword_mut) {}
37+
keyword_mut_(keyword_mut) {
38+
if (!GetNameGenerator()) {
39+
name_generator_ = std::make_unique<clang::ASTNameGenerator>(ctx);
40+
SetNameGenerator(name_generator_.get());
41+
}
42+
}
3643

37-
virtual ~Converter() = default;
44+
virtual ~Converter() {
45+
if (name_generator_) {
46+
SetNameGenerator(nullptr);
47+
}
48+
}
3849

3950
Converter(const Converter &) = delete;
4051
Converter &operator=(const Converter &) = delete;
@@ -784,6 +795,7 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
784795

785796
std::string *rs_code_;
786797
clang::ASTContext &ctx_;
798+
std::unique_ptr<clang::ASTNameGenerator> name_generator_;
787799
clang::FunctionDecl *curr_function_ = nullptr;
788800
bool in_function_formals_ = false;
789801
enum class MethodTarget : uint8_t {

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,24 @@ std::string GetNumAsString(llvm::APFloat value) {
296296
bool IsUserDefinedDecl(const clang::Decl *decl) {
297297
const auto &ctx = decl->getASTContext();
298298
const auto &src_mgr = ctx.getSourceManager();
299+
if (auto fn = llvm::dyn_cast<clang::FunctionDecl>(decl)) {
300+
if (const clang::FunctionDecl *definition = nullptr;
301+
fn->isDefined(definition)) {
302+
decl = definition;
303+
} else if (llvm::any_of(fn->redecls(), [&](auto redecl) {
304+
return src_mgr.isInSystemHeader(redecl->getLocation());
305+
})) {
306+
return false;
307+
}
308+
} else if (auto var = llvm::dyn_cast<clang::VarDecl>(decl)) {
309+
if (auto definition = var->getDefinition()) {
310+
decl = definition;
311+
} else if (llvm::any_of(var->redecls(), [&](auto redecl) {
312+
return src_mgr.isInSystemHeader(redecl->getLocation());
313+
})) {
314+
return false;
315+
}
316+
}
299317
auto src_loc = decl->getLocation();
300318
if (auto *spec =
301319
clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(decl);
@@ -822,12 +840,25 @@ static std::string GetParamSignature(const clang::Decl *decl) {
822840
return args;
823841
}
824842

843+
static clang::ASTNameGenerator *name_generator = nullptr;
844+
845+
void SetNameGenerator(clang::ASTNameGenerator *generator) {
846+
name_generator = generator;
847+
}
848+
849+
clang::ASTNameGenerator *GetNameGenerator() { return name_generator; }
850+
851+
static std::string GetMangledName(const clang::Decl *decl) {
852+
assert(name_generator);
853+
return name_generator->getName(decl);
854+
}
855+
825856
static std::string GetLexicalSpecializationID(const clang::Decl *decl) {
826857
auto &ctx = decl->getASTContext();
827858
std::string id;
828859
if (const auto *var =
829860
clang::dyn_cast<clang::VarTemplateSpecializationDecl>(decl)) {
830-
id += clang::ASTNameGenerator(var->getASTContext()).getName(var);
861+
id += GetMangledName(var);
831862
}
832863
if (const auto *self =
833864
clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(decl)) {
@@ -846,7 +877,7 @@ static std::string GetLexicalSpecializationID(const clang::Decl *decl) {
846877
}
847878
if (const auto *fn = clang::dyn_cast<clang::FunctionDecl>(dc);
848879
fn && fn->getTemplateSpecializationArgs()) {
849-
id += clang::ASTNameGenerator(fn->getASTContext()).getName(fn);
880+
id += GetMangledName(fn);
850881
}
851882
}
852883
return id;
@@ -919,9 +950,7 @@ std::string DisambiguateAnonymousTag(const clang::TagDecl *tag) {
919950
static std::unordered_map<std::string, size_t> type_mapping;
920951

921952
static size_t GetDeclId(const clang::NamedDecl *decl, bool internal) {
922-
std::string key =
923-
clang::ASTNameGenerator(decl->getASTContext()).getName(decl) +
924-
GetParamSignature(decl);
953+
std::string key = GetMangledName(decl) + GetParamSignature(decl);
925954
if (internal) {
926955
key += GetLocationID(decl);
927956
}
@@ -982,9 +1011,11 @@ std::string GetNamedDeclAsString(const clang::NamedDecl *decl) {
9821011
target = record;
9831012
}
9841013
}
1014+
auto *record = clang::dyn_cast<clang::CXXRecordDecl>(target);
9851015
return std::format(
986-
"anon_{}", type_mapping.try_emplace(GetID(target), type_mapping.size())
987-
.first->second);
1016+
"{}_{}", record && record->isLambda() ? "lambda" : "anon",
1017+
type_mapping.try_emplace(GetID(target), type_mapping.size())
1018+
.first->second);
9881019
}
9891020

9901021
std::optional<size_t> id;
@@ -1346,21 +1377,6 @@ clang::QualType GetDeclRefType(const clang::FunctionDecl *fn,
13461377
return field ? field->getType() : decl->getType();
13471378
}
13481379

1349-
bool HasStaticLocal(const clang::Stmt *stmt) {
1350-
if (!stmt) {
1351-
return false;
1352-
}
1353-
if (auto decl_stmt = clang::dyn_cast<clang::DeclStmt>(stmt)) {
1354-
for (auto decl : decl_stmt->decls()) {
1355-
if (auto var = clang::dyn_cast<clang::VarDecl>(decl);
1356-
var && var->isStaticLocal()) {
1357-
return true;
1358-
}
1359-
}
1360-
}
1361-
return llvm::any_of(stmt->children(), HasStaticLocal);
1362-
}
1363-
13641380
bool IsUserOperatorCall(const clang::CXXOperatorCallExpr *expr) {
13651381
const auto *callee = expr->getDirectCallee();
13661382
if (!callee || AsLambdaOperatorCall(callee)) {

‎cpp2rust/converter/converter_lib.h‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <clang/AST/Decl.h>
88
#include <clang/AST/DeclCXX.h>
99
#include <clang/AST/Expr.h>
10+
#include <clang/AST/Mangle.h>
1011
#include <clang/AST/StmtCXX.h>
1112
#include <clang/AST/Type.h>
1213
#include <llvm/ADT/APSInt.h>
@@ -181,6 +182,10 @@ unsigned GetColumnNumber(const clang::Decl *decl);
181182

182183
unsigned GetArraySize(clang::QualType array_type);
183184

185+
void SetNameGenerator(clang::ASTNameGenerator *generator);
186+
187+
clang::ASTNameGenerator *GetNameGenerator();
188+
184189
std::string GetID(const clang::Decl *decl);
185190
std::string GetMethodID(const clang::CXXMethodDecl *decl);
186191

@@ -247,8 +252,6 @@ clang::QualType GetDeclRefType(const clang::FunctionDecl *fn,
247252
const clang::Expr *expr,
248253
const clang::ValueDecl *decl);
249254

250-
bool HasStaticLocal(const clang::Stmt *stmt);
251-
252255
bool IsSameTypeComparison(const clang::FunctionDecl *fn,
253256
const clang::CXXRecordDecl *record);
254257

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,6 +1567,12 @@ void ConverterRefCount::ConvertLambdaToFunctionPointer(
15671567

15681568
void ConverterRefCount::ConvertFunctionToFunctionPointer(
15691569
const clang::FunctionDecl *fn_decl) {
1570+
if (auto *method = clang::dyn_cast<clang::CXXMethodDecl>(fn_decl);
1571+
method && method->isLambdaStaticInvoker()) {
1572+
ConvertCapturelessLambda(method->getParent());
1573+
computed_expr_type_ = ComputedExprType::FreshPointer;
1574+
return;
1575+
}
15701576
StrCat(std::format("FnPtr::<{}>::new({})",
15711577
ConvertFunctionPointerType(
15721578
fn_decl->getType()->getAs<clang::FunctionProtoType>()),

‎cpp2rust/converter/rules/rules_loader.cpp‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -389,10 +389,7 @@ std::string ConstructorKey(const std::string &class_key) {
389389
}
390390

391391
std::string FunctionKey(const clang::FunctionDecl *decl) {
392-
if (const clang::FunctionDecl *definition = nullptr;
393-
decl->isDefined(definition) &&
394-
!decl->getASTContext().getSourceManager().isInSystemHeader(
395-
definition->getLocation())) {
392+
if (decl->isDefined() && IsUserDefinedDecl(decl)) {
396393
return {};
397394
}
398395
if (auto method = llvm::dyn_cast<clang::CXXMethodDecl>(decl)) {
@@ -409,6 +406,11 @@ std::string DeclKey(const clang::NamedDecl *decl) {
409406
if (auto fn = decl->getAsFunction()) {
410407
return FunctionKey(fn);
411408
}
409+
if (auto var = llvm::dyn_cast<clang::VarDecl>(decl);
410+
var && var->hasDefinition() != clang::VarDecl::DeclarationOnly &&
411+
IsUserDefinedDecl(var)) {
412+
return {};
413+
}
412414
if (auto record = llvm::dyn_cast<clang::RecordDecl>(decl->getDeclContext())) {
413415
return MemberKey(ClassKey(record), MemberName(decl->getDeclName()));
414416
}

‎tests/unit/lambda_as_field.cpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// ADDITIONAL_COMPILE_FLAGS: -std=c++23
22
// no-compile
3+
// Blocked by https://github.com/Cpp2Rust/cpp2rust/issues/435
34
#include <assert.h>
45
#include <utility>
56

‎tests/unit/lambda_decltype_type.cpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// ADDITIONAL_COMPILE_FLAGS: -std=c++23
22
// no-compile
3+
// Blocked by https://github.com/Cpp2Rust/cpp2rust/issues/435
34
#include <assert.h>
45

56
template <typename Cmp> struct Sorted {

‎tests/unit/lambda_immediate_init.cpp‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
// no-compile: refcount
2-
// translation-fail: unsafe
31
#include <assert.h>
42

53
int pick(int x = [] { return 237; }()) { return x; }
64

75
struct S {
86
int j = 10;
9-
int i = [this]() { return j * 2; }();
7+
// Below will only work after: https://github.com/Cpp2Rust/cpp2rust/issues/248
8+
// int i = [this]() { return j * 2; }();
109
int k = [] { return 3; }() + 1;
1110
};
1211

@@ -23,11 +22,13 @@ int main() {
2322
assert(pick(1) == 1);
2423

2524
S s;
26-
assert(s.i == 20);
25+
// assert(s.i == 20);
2726
assert(s.k == 4);
2827

28+
/*
2929
S t{5};
3030
assert(t.i == 10);
31+
*/
3132

3233
assert(g == 10);
3334

‎tests/unit/lambda_static_local.cpp‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// ADDITIONAL_COMPILE_FLAGS: -std=c++23
2-
// translation-fail
32
#include <assert.h>
43

54
static int a;

0 commit comments

Comments
 (0)