Skip to content

Commit 2fd4d12

Browse files
authored
Merge branch 'master' into concepts
2 parents bd7c863 + 80bda18 commit 2fd4d12

85 files changed

Lines changed: 2251 additions & 501 deletions

File tree

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: 48 additions & 21 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>
@@ -1787,15 +1788,6 @@ void Converter::ConvertPrintf(clang::CallExpr *expr) {
17871788
StrCat(')');
17881789
}
17891790

1790-
std::optional<std::string> Converter::TryPluginConvert(clang::CallExpr *call) {
1791-
if (emplace_back_plugin_match(call)) {
1792-
Buffer buf(*this);
1793-
emplace_back_plugin_convert(call);
1794-
return std::move(buf).str();
1795-
}
1796-
return std::nullopt;
1797-
}
1798-
17991791
void Converter::ConvertVariadicArg(clang::Expr *arg) {
18001792
if (arg->getType()->isFunctionPointerType()) {
18011793
Convert(arg);
@@ -1850,12 +1842,6 @@ bool Converter::VisitCallExpr(clang::CallExpr *expr) {
18501842
return false;
18511843
}
18521844

1853-
if (auto plugin_str = TryPluginConvert(expr)) {
1854-
StrCat(*plugin_str);
1855-
SetFreshType(expr->getType());
1856-
return false;
1857-
}
1858-
18591845
if (Mapper::Contains(expr->getCallee())) {
18601846
if (Mapper::IsLibcPassthrough(GetCalleeOrExpr(expr))) {
18611847
ConvertGenericCallExpr(expr);
@@ -1986,8 +1972,10 @@ Converter::CallInfo Converter::CollectCallInfo(clang::CallExpr *expr) {
19861972
proto = ptr_ty->getPointeeType()->getAs<clang::FunctionProtoType>();
19871973
}
19881974
}
1989-
assert((function || proto) &&
1990-
"Either function decl or function prototype should be known");
1975+
if (!function && !proto) {
1976+
llvm::report_fatal_error(
1977+
"Either function decl or function prototype should be known");
1978+
}
19911979

19921980
unsigned num_args = expr->getNumArgs() - arg_begin;
19931981
unsigned num_named_params =
@@ -3620,6 +3608,7 @@ void Converter::ConvertArrayCXXConstructExpr(clang::CXXConstructExpr *expr) {
36203608
}
36213609

36223610
void Converter::ConvertCXXConstructExprArgs(clang::CXXConstructExpr *expr) {
3611+
HoistMaterializedTempBindings hoist_temps(*this, /*as_block=*/true);
36233612
auto ctor = expr->getConstructor();
36243613
StrCat(GetRecordName(ctor->getParent()), token::kDoubleColon,
36253614
GetCtorName(ctor));
@@ -3642,7 +3631,6 @@ void Converter::ConvertCXXConstructExprArgs(clang::CXXConstructExpr *expr) {
36423631
if (arg_idx < expr->getNumArgs()) {
36433632
clang::Expr *arg = expr->getArg(arg_idx++);
36443633
PushBrace brace(*this);
3645-
HoistMaterializedTempBindings hoist_temps(*this);
36463634

36473635
if (has_default) {
36483636
StrCat("Some(");
@@ -5054,6 +5042,8 @@ std::string Converter::ConvertIRFragment(
50545042
result += ConvertPlaceholder(expr, arg, ph_ctx);
50555043
} else if (std::get_if<TranslationRule::VaArgsFragment>(&frag)) {
50565044
result += ConvertVariadicTail(expr, all_args);
5045+
} else if (std::get_if<TranslationRule::InitFragment>(&frag)) {
5046+
result += ConvertInitFragment(expr, all_args);
50575047
} else if (auto *mc =
50585048
std::get_if<std::unique_ptr<MethodCallFragment>>(&frag)) {
50595049
result += ConvertMappedMethodCall(expr, **mc, args, num_args, ctx);
@@ -5082,6 +5072,43 @@ Converter::ConvertVariadicTail(clang::Expr *expr,
50825072
return std::move(buf).str();
50835073
}
50845074

5075+
std::string
5076+
Converter::ConvertInitFragment(clang::Expr *expr,
5077+
const std::vector<clang::Expr *> &all_args) {
5078+
const auto *tgt_ir = Mapper::GetExprRule(GetCalleeOrExpr(expr));
5079+
assert(tgt_ir && tgt_ir->init_type.valid());
5080+
auto *callee = clang::cast<clang::CallExpr>(expr)->getDirectCallee();
5081+
assert(callee);
5082+
auto type = GetSema()
5083+
.getTemplateInstantiationArgs(callee)(tgt_ir->init_type.depth,
5084+
tgt_ir->init_type.index)
5085+
.getAsType();
5086+
5087+
Buffer buf(*this);
5088+
ConvertConstructFromArgs(
5089+
type, llvm::ArrayRef(all_args).drop_front(tgt_ir->params.size()),
5090+
expr->getExprLoc());
5091+
return std::move(buf).str();
5092+
}
5093+
5094+
void Converter::ConvertConstructFromArgs(clang::QualType type,
5095+
llvm::ArrayRef<clang::Expr *> args,
5096+
clang::SourceLocation loc) {
5097+
auto *init = BuildInitExpr(GetSema(), type, args, loc);
5098+
assert(init && "type cannot be initialized from the arguments");
5099+
if (auto *ctor =
5100+
clang::dyn_cast<clang::CXXConstructExpr>(init->IgnoreImplicit())) {
5101+
ConvertConstructedValue(type, ctor);
5102+
return;
5103+
}
5104+
5105+
if (args.empty()) {
5106+
StrCat(GetDefaultAsString(type));
5107+
return;
5108+
}
5109+
Convert(init);
5110+
}
5111+
50855112
std::string Converter::AccessLValueObject(clang::MemberExpr *member) {
50865113
auto *object = member->getBase();
50875114
auto type = object->getType();
@@ -5180,9 +5207,9 @@ void Converter::dump_expr_kinds() {
51805207
<< ", isVoid: " << isVoid() << '\n';
51815208
}
51825209

5183-
void Converter::emplace_back_plugin_construct_arg(
5184-
clang::QualType elem_type, clang::CXXConstructExpr *ctor) {
5185-
ConvertVarInit(elem_type, ctor);
5210+
void Converter::ConvertConstructedValue(clang::QualType type,
5211+
clang::CXXConstructExpr *ctor) {
5212+
ConvertVarInit(type, ctor);
51865213
}
51875214

51885215
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
@@ -698,6 +698,16 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
698698
std::string ConvertVariadicTail(clang::Expr *expr,
699699
const std::vector<clang::Expr *> &all_args);
700700

701+
std::string ConvertInitFragment(clang::Expr *expr,
702+
const std::vector<clang::Expr *> &all_args);
703+
704+
void ConvertConstructFromArgs(clang::QualType type,
705+
llvm::ArrayRef<clang::Expr *> args,
706+
clang::SourceLocation loc);
707+
708+
virtual void ConvertConstructedValue(clang::QualType type,
709+
clang::CXXConstructExpr *ctor);
710+
701711
virtual std::string ConvertMappedMethodCall(
702712
clang::Expr *expr, const TranslationRule::MethodCallFragment &mc,
703713
clang::Expr **args, unsigned num_args, TempMaterializationCtx *ctx);
@@ -871,17 +881,23 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
871881
std::string *prev;
872882
std::string bindings;
873883
std::optional<Buffer> buf;
884+
bool as_block;
874885

875886
public:
876-
explicit HoistMaterializedTempBindings(Converter &c)
877-
: c(c), prev(c.materialized_temp_bindings_), buf(c) {
887+
explicit HoistMaterializedTempBindings(Converter &c, bool as_block = false)
888+
: c(c), prev(c.materialized_temp_bindings_), buf(c),
889+
as_block(as_block) {
878890
c.materialized_temp_bindings_ = &bindings;
879891
}
880892
~HoistMaterializedTempBindings() {
881893
c.materialized_temp_bindings_ = prev;
882894
std::string body = std::move(*buf).str();
883895
buf.reset();
884896

897+
if (as_block && !bindings.empty()) {
898+
c.StrCat('{', bindings, body, '}');
899+
return;
900+
}
885901
c.StrCat(bindings, body);
886902
}
887903
HoistMaterializedTempBindings(const HoistMaterializedTempBindings &) =
@@ -1058,19 +1074,6 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
10581074
std::string EmitMaterializedTempBinding(clang::QualType param_type,
10591075
clang::Expr *expr);
10601076

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

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

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
#include <clang/AST/ParentMapContext.h>
1111
#include <clang/Basic/SourceManager.h>
1212
#include <clang/Lex/Lexer.h>
13+
#include <clang/Sema/Initialization.h>
14+
#include <clang/Sema/Sema.h>
15+
#include <llvm/Support/ErrorHandling.h>
1316
#include <llvm/Support/Path.h>
1417
#include <llvm/Support/raw_ostream.h>
1518

@@ -830,7 +833,10 @@ std::string GetNamedDeclAsString(const clang::NamedDecl *decl) {
830833

831834
if (name.empty()) {
832835
auto *pdecl = llvm::dyn_cast<clang::ParmVarDecl>(decl);
833-
assert(pdecl && "Unexpected unnamed construct");
836+
if (!pdecl) {
837+
decl->dump();
838+
llvm::report_fatal_error("Unexpected unnamed construct");
839+
}
834840

835841
const auto *fn =
836842
llvm::dyn_cast<clang::FunctionDecl>(pdecl->getDeclContext());
@@ -1371,6 +1377,28 @@ BuildUnifiedArgs(clang::Expr *expr, clang::Expr **args, unsigned num_args) {
13711377
return all_args;
13721378
}
13731379

1380+
clang::Expr *BuildInitExpr(clang::Sema &sema, clang::QualType type,
1381+
llvm::ArrayRef<clang::Expr *> args,
1382+
clang::SourceLocation loc) {
1383+
llvm::SmallVector<clang::Expr *, 4> init_args(args.begin(), args.end());
1384+
auto kind = args.size() == 1 && clang::isa<clang::InitListExpr>(
1385+
args[0]->IgnoreParenImpCasts())
1386+
? clang::InitializationKind::CreateDirectList(loc)
1387+
: clang::InitializationKind::CreateDirect(loc, {}, {});
1388+
auto entity = clang::InitializedEntity::InitializeTemporary(type);
1389+
clang::InitializationSequence seq(sema, entity, kind, init_args);
1390+
if (!seq) {
1391+
return nullptr;
1392+
}
1393+
1394+
auto result = seq.Perform(sema, entity, kind, init_args);
1395+
if (result.isInvalid()) {
1396+
return nullptr;
1397+
}
1398+
1399+
return result.get();
1400+
}
1401+
13741402
clang::Expr *GetCallee(clang::CallExpr *expr) {
13751403
if (auto op_call = clang::dyn_cast<clang::CXXOperatorCallExpr>(expr)) {
13761404
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.
@@ -252,6 +256,10 @@ std::optional<clang::QualType> GetParamImplicitConvertTarget(clang::Expr *expr,
252256
std::vector<clang::Expr *>
253257
BuildUnifiedArgs(clang::Expr *expr, clang::Expr **args, unsigned num_args);
254258

259+
clang::Expr *BuildInitExpr(clang::Sema &sema, clang::QualType type,
260+
llvm::ArrayRef<clang::Expr *> args,
261+
clang::SourceLocation loc);
262+
255263
const clang::CXXForRangeStmt *
256264
GetParentForRange(clang::ASTContext &ctx, const clang::MemberExpr *member);
257265

‎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)