Skip to content

Commit 6a7cee4

Browse files
committed
Merge branch 'master' into lambda-testsuite
2 parents 91193fc + 7896632 commit 6a7cee4

49 files changed

Lines changed: 899 additions & 343 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎cpp2rust/converter/converter.cpp‎

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <clang/Basic/LangOptions.h>
99
#include <clang/Basic/SourceManager.h>
1010
#include <clang/Basic/Version.h>
11+
#include <clang/Sema/Template.h>
1112
#include <llvm/ADT/DenseMap.h>
1213
#include <llvm/Support/ConvertUTF.h>
1314
#include <llvm/Support/ErrorHandling.h>
@@ -1766,15 +1767,6 @@ void Converter::ConvertPrintf(clang::CallExpr *expr) {
17661767
StrCat(')');
17671768
}
17681769

1769-
std::optional<std::string> Converter::TryPluginConvert(clang::CallExpr *call) {
1770-
if (emplace_back_plugin_match(call)) {
1771-
Buffer buf(*this);
1772-
emplace_back_plugin_convert(call);
1773-
return std::move(buf).str();
1774-
}
1775-
return std::nullopt;
1776-
}
1777-
17781770
void Converter::ConvertVariadicArg(clang::Expr *arg) {
17791771
if (arg->getType()->isFunctionPointerType()) {
17801772
Convert(arg);
@@ -1829,12 +1821,6 @@ bool Converter::VisitCallExpr(clang::CallExpr *expr) {
18291821
return false;
18301822
}
18311823

1832-
if (auto plugin_str = TryPluginConvert(expr)) {
1833-
StrCat(*plugin_str);
1834-
SetFreshType(expr->getType());
1835-
return false;
1836-
}
1837-
18381824
if (Mapper::Contains(expr->getCallee())) {
18391825
if (Mapper::IsLibcPassthrough(GetCalleeOrExpr(expr))) {
18401826
ConvertGenericCallExpr(expr);
@@ -3625,6 +3611,7 @@ void Converter::ConvertArrayCXXConstructExpr(clang::CXXConstructExpr *expr) {
36253611
}
36263612

36273613
void Converter::ConvertCXXConstructExprArgs(clang::CXXConstructExpr *expr) {
3614+
HoistMaterializedTempBindings hoist_temps(*this, /*as_block=*/true);
36283615
auto ctor = expr->getConstructor();
36293616
StrCat(GetRecordName(ctor->getParent()), token::kDoubleColon,
36303617
GetCtorName(ctor));
@@ -3647,7 +3634,6 @@ void Converter::ConvertCXXConstructExprArgs(clang::CXXConstructExpr *expr) {
36473634
if (arg_idx < expr->getNumArgs()) {
36483635
clang::Expr *arg = expr->getArg(arg_idx++);
36493636
PushBrace brace(*this);
3650-
HoistMaterializedTempBindings hoist_temps(*this);
36513637

36523638
if (has_default) {
36533639
StrCat("Some(");
@@ -5044,6 +5030,8 @@ std::string Converter::ConvertIRFragment(
50445030
result += ConvertPlaceholder(expr, arg, ph_ctx);
50455031
} else if (std::get_if<TranslationRule::VaArgsFragment>(&frag)) {
50465032
result += ConvertVariadicTail(expr, all_args);
5033+
} else if (std::get_if<TranslationRule::InitFragment>(&frag)) {
5034+
result += ConvertInitFragment(expr, all_args);
50475035
} else if (auto *mc =
50485036
std::get_if<std::unique_ptr<MethodCallFragment>>(&frag)) {
50495037
result += ConvertMappedMethodCall(expr, **mc, args, num_args, ctx);
@@ -5072,6 +5060,43 @@ Converter::ConvertVariadicTail(clang::Expr *expr,
50725060
return std::move(buf).str();
50735061
}
50745062

5063+
std::string
5064+
Converter::ConvertInitFragment(clang::Expr *expr,
5065+
const std::vector<clang::Expr *> &all_args) {
5066+
const auto *tgt_ir = Mapper::GetExprRule(GetCalleeOrExpr(expr));
5067+
assert(tgt_ir && tgt_ir->init_type.valid());
5068+
auto *callee = clang::cast<clang::CallExpr>(expr)->getDirectCallee();
5069+
assert(callee);
5070+
auto type = GetSema()
5071+
.getTemplateInstantiationArgs(callee)(tgt_ir->init_type.depth,
5072+
tgt_ir->init_type.index)
5073+
.getAsType();
5074+
5075+
Buffer buf(*this);
5076+
ConvertConstructFromArgs(
5077+
type, llvm::ArrayRef(all_args).drop_front(tgt_ir->params.size()),
5078+
expr->getExprLoc());
5079+
return std::move(buf).str();
5080+
}
5081+
5082+
void Converter::ConvertConstructFromArgs(clang::QualType type,
5083+
llvm::ArrayRef<clang::Expr *> args,
5084+
clang::SourceLocation loc) {
5085+
auto *init = BuildInitExpr(GetSema(), type, args, loc);
5086+
assert(init && "type cannot be initialized from the arguments");
5087+
if (auto *ctor =
5088+
clang::dyn_cast<clang::CXXConstructExpr>(init->IgnoreImplicit())) {
5089+
ConvertConstructedValue(type, ctor);
5090+
return;
5091+
}
5092+
5093+
if (args.empty()) {
5094+
StrCat(GetDefaultAsString(type));
5095+
return;
5096+
}
5097+
Convert(init);
5098+
}
5099+
50755100
std::string Converter::AccessLValueObject(clang::MemberExpr *member) {
50765101
auto *object = member->getBase();
50775102
auto type = object->getType();
@@ -5170,9 +5195,9 @@ void Converter::dump_expr_kinds() {
51705195
<< ", isVoid: " << isVoid() << '\n';
51715196
}
51725197

5173-
void Converter::emplace_back_plugin_construct_arg(
5174-
clang::QualType elem_type, clang::CXXConstructExpr *ctor) {
5175-
ConvertVarInit(elem_type, ctor);
5198+
void Converter::ConvertConstructedValue(clang::QualType type,
5199+
clang::CXXConstructExpr *ctor) {
5200+
ConvertVarInit(type, ctor);
51765201
}
51775202

51785203
const char *Converter::GetPointerDerefPrefix(clang::QualType pointee_type) {

‎cpp2rust/converter/converter.h‎

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,16 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
692692
std::string ConvertVariadicTail(clang::Expr *expr,
693693
const std::vector<clang::Expr *> &all_args);
694694

695+
std::string ConvertInitFragment(clang::Expr *expr,
696+
const std::vector<clang::Expr *> &all_args);
697+
698+
void ConvertConstructFromArgs(clang::QualType type,
699+
llvm::ArrayRef<clang::Expr *> args,
700+
clang::SourceLocation loc);
701+
702+
virtual void ConvertConstructedValue(clang::QualType type,
703+
clang::CXXConstructExpr *ctor);
704+
695705
virtual std::string ConvertMappedMethodCall(
696706
clang::Expr *expr, const TranslationRule::MethodCallFragment &mc,
697707
clang::Expr **args, unsigned num_args, TempMaterializationCtx *ctx);
@@ -865,17 +875,23 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
865875
std::string *prev;
866876
std::string bindings;
867877
std::optional<Buffer> buf;
878+
bool as_block;
868879

869880
public:
870-
explicit HoistMaterializedTempBindings(Converter &c)
871-
: c(c), prev(c.materialized_temp_bindings_), buf(c) {
881+
explicit HoistMaterializedTempBindings(Converter &c, bool as_block = false)
882+
: c(c), prev(c.materialized_temp_bindings_), buf(c),
883+
as_block(as_block) {
872884
c.materialized_temp_bindings_ = &bindings;
873885
}
874886
~HoistMaterializedTempBindings() {
875887
c.materialized_temp_bindings_ = prev;
876888
std::string body = std::move(*buf).str();
877889
buf.reset();
878890

891+
if (as_block && !bindings.empty()) {
892+
c.StrCat('{', bindings, body, '}');
893+
return;
894+
}
879895
c.StrCat(bindings, body);
880896
}
881897
HoistMaterializedTempBindings(const HoistMaterializedTempBindings &) =
@@ -1052,19 +1068,6 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
10521068
std::string EmitMaterializedTempBinding(clang::QualType param_type,
10531069
clang::Expr *expr);
10541070

1055-
// TODO: move this into the Plugin infrastructure. Plugins are used for
1056-
// functions that cannot be translated using the rules/ directory. For
1057-
// example emplace_back, make_unique, printf, etc. Generally variadic
1058-
// argument functions and functions that use perfect forwarding.
1059-
std::optional<std::string> TryPluginConvert(clang::CallExpr *call);
1060-
1061-
bool emplace_back_plugin_match(clang::CallExpr *call);
1062-
virtual bool emplace_back_plugin_convert(clang::CallExpr *call);
1063-
virtual void emplace_back_plugin_construct_arg(clang::QualType elem_type,
1064-
clang::CXXConstructExpr *ctor);
1065-
virtual void emplace_back_emit_push(clang::CXXMemberCallExpr *call,
1066-
std::string_view arg);
1067-
10681071
virtual const char *GetPointerDerefPrefix(clang::QualType pointee_type);
10691072

10701073
TempMaterializationCtx CollectRefBindingTempArgs(clang::CallExpr *expr);

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include <clang/AST/Mangle.h>
99
#include <clang/AST/ParentMapContext.h>
1010
#include <clang/Basic/SourceManager.h>
11+
#include <clang/Sema/Initialization.h>
12+
#include <clang/Sema/Sema.h>
1113
#include <llvm/Support/ErrorHandling.h>
1214
#include <llvm/Support/Path.h>
1315
#include <llvm/Support/raw_ostream.h>
@@ -1312,6 +1314,28 @@ BuildUnifiedArgs(clang::Expr *expr, clang::Expr **args, unsigned num_args) {
13121314
return all_args;
13131315
}
13141316

1317+
clang::Expr *BuildInitExpr(clang::Sema &sema, clang::QualType type,
1318+
llvm::ArrayRef<clang::Expr *> args,
1319+
clang::SourceLocation loc) {
1320+
llvm::SmallVector<clang::Expr *, 4> init_args(args.begin(), args.end());
1321+
auto kind = args.size() == 1 && clang::isa<clang::InitListExpr>(
1322+
args[0]->IgnoreParenImpCasts())
1323+
? clang::InitializationKind::CreateDirectList(loc)
1324+
: clang::InitializationKind::CreateDirect(loc, {}, {});
1325+
auto entity = clang::InitializedEntity::InitializeTemporary(type);
1326+
clang::InitializationSequence seq(sema, entity, kind, init_args);
1327+
if (!seq) {
1328+
return nullptr;
1329+
}
1330+
1331+
auto result = seq.Perform(sema, entity, kind, init_args);
1332+
if (result.isInvalid()) {
1333+
return nullptr;
1334+
}
1335+
1336+
return result.get();
1337+
}
1338+
13151339
clang::Expr *GetCallee(clang::CallExpr *expr) {
13161340
if (auto op_call = clang::dyn_cast<clang::CXXOperatorCallExpr>(expr)) {
13171341
if (op_call->getOperator() == clang::OO_Call) {

‎cpp2rust/converter/converter_lib.h‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919

2020
#include "logging.h"
2121

22+
namespace clang {
23+
class Sema;
24+
} // namespace clang
25+
2226
namespace cpp2rust {
2327

2428
// Order matters: each category is a superset of the previous one.
@@ -245,6 +249,10 @@ std::optional<clang::QualType> GetParamImplicitConvertTarget(clang::Expr *expr,
245249
std::vector<clang::Expr *>
246250
BuildUnifiedArgs(clang::Expr *expr, clang::Expr **args, unsigned num_args);
247251

252+
clang::Expr *BuildInitExpr(clang::Sema &sema, clang::QualType type,
253+
llvm::ArrayRef<clang::Expr *> args,
254+
clang::SourceLocation loc);
255+
248256
const clang::CXXForRangeStmt *
249257
GetParentForRange(clang::ASTContext &ctx, const clang::MemberExpr *member);
250258

‎cpp2rust/converter/mapper.cpp‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ std::string GetExprMapKey(const std::string &str) {
7474
return result;
7575
}
7676

77+
constexpr const char kPackMarker[] = "&&...";
78+
7779
std::string GetTypeMapKey(const std::string &str) {
7880
auto n = str.find_first_of("<[");
7981
if (n == std::string::npos || str[n] == '<') {
@@ -898,6 +900,13 @@ std::string ToString(clang::QualType qual_type, ScalarSugar sugar) {
898900
return normalizeTranslationRule(std::move(type));
899901
}
900902

903+
bool HasFunctionParameterPack(const clang::FunctionDecl *decl) {
904+
if (auto *primary = decl->getPrimaryTemplate()) {
905+
decl = primary->getTemplatedDecl();
906+
}
907+
return decl->getNumParams() && decl->parameters().back()->isParameterPack();
908+
}
909+
901910
std::string ToString(const clang::NamedDecl *decl) {
902911
if (auto *record = clang::dyn_cast<clang::RecordDecl>(decl);
903912
record && !record->getIdentifier()) {
@@ -970,13 +979,27 @@ std::string ToString(const clang::NamedDecl *decl) {
970979
func_decl->printQualifiedName(os, getPrintPolicy());
971980
}
972981

982+
bool has_pack = HasFunctionParameterPack(func_decl);
983+
unsigned num_params = func_decl->getNumParams();
984+
if (has_pack) {
985+
const auto *primary = func_decl->getPrimaryTemplate();
986+
num_params =
987+
(primary ? primary->getTemplatedDecl() : func_decl)->getNumParams() - 1;
988+
}
989+
973990
os << '(';
974-
for (unsigned i = 0, n = func_decl->getNumParams(); i < n; ++i) {
991+
for (unsigned i = 0; i < num_params; ++i) {
975992
if (i) {
976993
os << ", ";
977994
}
978995
os << ToString(func_decl->getParamDecl(i)->getType());
979996
}
997+
if (has_pack) {
998+
if (num_params) {
999+
os << ", ";
1000+
}
1001+
os << kPackMarker;
1002+
}
9801003
if (func_decl->isVariadic()) {
9811004
if (func_decl->getNumParams()) {
9821005
os << ", ";

‎cpp2rust/converter/mapper.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ enum class ScalarSugar {
4646
kPreserve,
4747
};
4848

49+
bool HasFunctionParameterPack(const clang::FunctionDecl *decl);
50+
4951
clang::QualType GetTypeForDecl(const clang::NamedDecl *decl);
5052
std::string ToString(clang::QualType qual_type,
5153
ScalarSugar sugar = ScalarSugar::kDesugar);

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,10 +1126,7 @@ bool ConverterRefCount::VisitCallExpr(clang::CallExpr *expr) {
11261126

11271127
std::optional<TempMaterializationCtx> ctx;
11281128
std::string str;
1129-
if (auto plugin_str = TryPluginConvert(expr)) {
1130-
StrCat(*plugin_str);
1131-
return false;
1132-
} else {
1129+
{
11331130
PushConversionKind push(*this, ConversionKind::Unboxed);
11341131
Buffer buf(*this);
11351132
ctx = Converter::ConvertCallExpr(expr);
@@ -2685,24 +2682,10 @@ std::string ConverterRefCount::AccessLValueObject(clang::MemberExpr *member) {
26852682
return is_mut ? ConvertLValue(object) : ConvertRValue(object);
26862683
}
26872684

2688-
void ConverterRefCount::emplace_back_plugin_construct_arg(
2689-
clang::QualType elem_type, clang::CXXConstructExpr *ctor) {
2690-
PushUnboxedIfSimple push(*this, "Vec<%>", elem_type);
2691-
ConvertVarInit(elem_type, ctor);
2692-
}
2693-
2694-
void ConverterRefCount::emplace_back_emit_push(clang::CXXMemberCallExpr *call,
2695-
std::string_view arg) {
2696-
auto *obj = GetCallObject(call);
2697-
auto obj_type = obj->getType().getNonReferenceType();
2698-
if (obj_type->isPointerType()) {
2699-
obj_type = obj_type->getPointeeType();
2700-
}
2701-
StrCat(ConvertObject(obj), ".with_mut");
2702-
PushParen outer(*this);
2703-
StrCat("|__v: &mut ", ToString(obj_type.getNonReferenceType()), "| __v.push");
2704-
PushParen inner(*this);
2705-
StrCat(arg);
2685+
void ConverterRefCount::ConvertConstructedValue(clang::QualType type,
2686+
clang::CXXConstructExpr *ctor) {
2687+
PushConversionKind push(*this, ConversionKind::Unboxed);
2688+
ConvertVarInit(type, ctor);
27062689
}
27072690

27082691
const char *

‎cpp2rust/converter/models/converter_refcount.h‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -268,11 +268,8 @@ class ConverterRefCount final : public Converter {
268268
MaterializeTemp(const std::string &binding_name, clang::QualType param_type,
269269
clang::Expr *expr) override;
270270

271-
void
272-
emplace_back_plugin_construct_arg(clang::QualType elem_type,
273-
clang::CXXConstructExpr *ctor) override;
274-
void emplace_back_emit_push(clang::CXXMemberCallExpr *call,
275-
std::string_view arg) override;
271+
void ConvertConstructedValue(clang::QualType type,
272+
clang::CXXConstructExpr *ctor) override;
276273

277274
const char *GetPointerDerefSuffix(clang::QualType pointee_type);
278275
const char *GetPointerDerefPrefix(clang::QualType pointee_type) override;

0 commit comments

Comments
 (0)