Skip to content

Commit 23abd4d

Browse files
committed
Merge branch 'master' into inet
2 parents 0eebdca + a9c50e7 commit 23abd4d

107 files changed

Lines changed: 5722 additions & 71 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: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,6 +1593,11 @@ bool Converter::VisitCallExpr(clang::CallExpr *expr) {
15931593
}
15941594

15951595
if (Mapper::Contains(expr->getCallee())) {
1596+
if (Mapper::IsLibcPassthrough(GetCalleeOrExpr(expr))) {
1597+
ConvertGenericCallExpr(expr);
1598+
return false;
1599+
}
1600+
15961601
auto **args = expr->getArgs();
15971602
auto num_args = expr->getNumArgs();
15981603
auto ctx = CollectRefBindingTempArgs(expr);
@@ -1667,20 +1672,20 @@ Converter::CallInfo Converter::CollectCallInfo(clang::CallExpr *expr) {
16671672
using Kind = CallArg::Kind;
16681673

16691674
CallInfo info;
1670-
info.callee = expr->getCallee();
1675+
info.expr = expr;
1676+
auto callee = GetCallee(expr);
16711677
unsigned arg_begin = 0;
16721678
if (auto op_call = llvm::dyn_cast<clang::CXXOperatorCallExpr>(expr)) {
16731679
if (op_call->getOperator() == clang::OO_Call) {
1674-
info.callee = op_call->getArg(0);
16751680
arg_begin = 1;
16761681
}
16771682
}
16781683

1679-
const auto *function =
1680-
expr->getCalleeDecl() ? expr->getCalleeDecl()->getAsFunction() : nullptr;
1684+
auto decl = expr->getCalleeDecl();
1685+
const auto *function = decl ? decl->getAsFunction() : nullptr;
16811686
const clang::FunctionProtoType *proto = nullptr;
16821687
if (!function) {
1683-
auto callee_ty = info.callee->getType().getDesugaredType(ctx_);
1688+
auto callee_ty = callee->getType().getDesugaredType(ctx_);
16841689
if (auto ptr_ty = callee_ty->getAs<clang::PointerType>()) {
16851690
proto = ptr_ty->getPointeeType()->getAs<clang::FunctionProtoType>();
16861691
}
@@ -1693,6 +1698,7 @@ Converter::CallInfo Converter::CollectCallInfo(clang::CallExpr *expr) {
16931698
function ? function->getNumParams() : proto->getNumParams();
16941699
info.is_variadic = function ? function->isVariadic() : proto->isVariadic();
16951700
info.is_fn_ptr_call = !function;
1701+
info.is_libc_passthrough = Mapper::IsLibcPassthrough(GetCalleeOrExpr(expr));
16961702

16971703
for (unsigned i = 0; i < num_named_params && i < num_args; ++i) {
16981704
auto *arg = expr->getArg(i + arg_begin);
@@ -1704,7 +1710,8 @@ Converter::CallInfo Converter::CollectCallInfo(clang::CallExpr *expr) {
17041710
: proto->getParamType(i),
17051711
.expr = arg,
17061712
.has_default = function && function->getParamDecl(i)->hasDefaultArg(),
1707-
.kind = IsLiteral(arg) ? Kind::Inline : Kind::Hoisted,
1713+
.kind = (IsLiteral(arg) || info.is_libc_passthrough) ? Kind::Inline
1714+
: Kind::Hoisted,
17081715
};
17091716
bool is_materialize = clang::isa<clang::MaterializeTemporaryExpr>(arg);
17101717
if (is_materialize && ca.param_type->isLValueReferenceType()) {
@@ -1778,7 +1785,9 @@ void Converter::EmitArgList(const CallInfo &info) {
17781785
using Kind = CallArg::Kind;
17791786
PushParen call_args(*this);
17801787

1781-
for (const auto &ca : info.args) {
1788+
for (unsigned i = 0; i < info.args.size(); i++) {
1789+
const auto &ca = info.args[i];
1790+
17821791
if (ca.has_default) {
17831792
StrCat("Some");
17841793
}
@@ -1794,6 +1803,10 @@ void Converter::EmitArgList(const CallInfo &info) {
17941803
break;
17951804
case Kind::Inline:
17961805
ConvertParamTy(ca.param_type, ca.expr);
1806+
if (info.is_libc_passthrough) {
1807+
StrCat(std::format(
1808+
"as {}", Mapper::GetParamType(GetCalleeOrExpr(info.expr), i)));
1809+
}
17971810
break;
17981811
}
17991812
}
@@ -1802,14 +1815,19 @@ void Converter::EmitArgList(const CallInfo &info) {
18021815
}
18031816

18041817
if (info.is_variadic) {
1805-
StrCat(token::kRef);
1806-
PushBracket push(*this);
1818+
if (!info.is_libc_passthrough) {
1819+
StrCat(token::kRef);
1820+
}
1821+
PushBracket push(*this, !info.is_libc_passthrough);
18071822
for (auto *arg : info.variadic_args) {
18081823
{
18091824
PushParen p(*this);
18101825
ConvertVariadicArg(arg);
18111826
}
1812-
StrCat(".into()", token::kComma);
1827+
if (!info.is_libc_passthrough) {
1828+
StrCat(".into()");
1829+
}
1830+
StrCat(token::kComma);
18131831
}
18141832
}
18151833
}
@@ -1818,10 +1836,14 @@ void Converter::EmitCall(CallInfo &&info) {
18181836
EmitHoistedArgs(info);
18191837

18201838
if (info.is_fn_ptr_call) {
1821-
EmitFnPtrCall(info.callee);
1839+
EmitFnPtrCall(GetCallee(info.expr));
1840+
} else if (info.is_libc_passthrough) {
1841+
auto *direct_callee = info.expr->getDirectCallee();
1842+
assert(direct_callee);
1843+
StrCat("libc::", direct_callee->getName());
18221844
} else {
18231845
PushExprKind push(*this, ExprKind::Callee);
1824-
Convert(info.callee);
1846+
Convert(GetCallee(info.expr));
18251847
}
18261848

18271849
EmitArgList(info);
@@ -4256,6 +4278,8 @@ std::string Converter::ConvertIRFragment(
42564278
.is_index_base = ph->is_index_base,
42574279
};
42584280
result += ConvertPlaceholder(expr, arg, ph_ctx);
4281+
} else if (std::get_if<TranslationRule::VaArgsFragment>(&frag)) {
4282+
result += ConvertVariadicTail(expr, all_args);
42594283
} else if (auto *mc =
42604284
std::get_if<std::unique_ptr<MethodCallFragment>>(&frag)) {
42614285
result += ConvertMappedMethodCall(expr, **mc, args, num_args, ctx);
@@ -4265,6 +4289,25 @@ std::string Converter::ConvertIRFragment(
42654289
return result;
42664290
}
42674291

4292+
std::string
4293+
Converter::ConvertVariadicTail(clang::Expr *expr,
4294+
const std::vector<clang::Expr *> &all_args) {
4295+
const auto *tgt_ir = Mapper::GetExprRule(GetCalleeOrExpr(expr));
4296+
unsigned fixed = tgt_ir ? tgt_ir->params.size() : 0;
4297+
4298+
Buffer buf(*this);
4299+
StrCat("&[");
4300+
for (unsigned i = fixed; i < all_args.size(); ++i) {
4301+
{
4302+
PushParen p(*this);
4303+
ConvertVariadicArg(all_args[i]);
4304+
}
4305+
StrCat(".into()", token::kComma);
4306+
}
4307+
StrCat("]");
4308+
return std::move(buf).str();
4309+
}
4310+
42684311
std::string Converter::AccessLValueObject(clang::MemberExpr *member) {
42694312
auto *object = member->getBase();
42704313
auto type = object->getType();

‎cpp2rust/converter/converter.h‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,10 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
249249
struct CallInfo {
250250
std::vector<CallArg> args;
251251
std::vector<clang::Expr *> variadic_args;
252-
clang::Expr *callee;
252+
clang::CallExpr *expr;
253253
bool is_variadic;
254254
bool is_fn_ptr_call;
255+
bool is_libc_passthrough;
255256
};
256257

257258
CallInfo CollectCallInfo(clang::CallExpr *expr);
@@ -586,6 +587,9 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
586587
std::string ConvertPlaceholder(clang::Expr *expr, clang::Expr *arg,
587588
const PlaceholderCtx &ph_ctx);
588589

590+
std::string ConvertVariadicTail(clang::Expr *expr,
591+
const std::vector<clang::Expr *> &all_args);
592+
589593
virtual std::string ConvertMappedMethodCall(
590594
clang::Expr *expr, const TranslationRule::MethodCallFragment &mc,
591595
clang::Expr **args, unsigned num_args, TempMaterializationCtx *ctx);

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,9 @@ static void GetAllVarsImpl(const clang::Stmt *stmt,
687687
}
688688

689689
if (auto *decl_ref = clang::dyn_cast<clang::DeclRefExpr>(stmt)) {
690-
vars.insert(decl_ref->getDecl());
690+
if (!clang::isa<clang::EnumConstantDecl>(decl_ref->getDecl())) {
691+
vars.insert(decl_ref->getDecl());
692+
}
691693
} else if (auto *member = clang::dyn_cast<clang::MemberExpr>(stmt)) {
692694
vars.insert(member->getMemberDecl());
693695
GetAllVarsImpl(member->getBase(), vars);
@@ -766,6 +768,15 @@ BuildUnifiedArgs(clang::Expr *expr, clang::Expr **args, unsigned num_args) {
766768
return all_args;
767769
}
768770

771+
clang::Expr *GetCallee(clang::CallExpr *expr) {
772+
if (auto op_call = clang::dyn_cast<clang::CXXOperatorCallExpr>(expr)) {
773+
if (op_call->getOperator() == clang::OO_Call) {
774+
return op_call->getArg(0);
775+
}
776+
}
777+
return expr->getCallee();
778+
}
779+
769780
clang::Expr *GetCalleeOrExpr(clang::Expr *expr) {
770781
if (auto *call = clang::dyn_cast<clang::CallExpr>(expr)) {
771782
return call->getCallee();

‎cpp2rust/converter/converter_lib.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ void ForEachTemplateArgument(
144144

145145
clang::Expr *GetCallObject(clang::CallExpr *expr);
146146

147+
clang::Expr *GetCallee(clang::CallExpr *expr);
148+
147149
std::unordered_set<const clang::ValueDecl *>
148150
GetAllVars(const clang::Stmt *stmt);
149151

‎cpp2rust/converter/mapper.cpp‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,19 @@ const TranslationRule::ExprRule *GetExprRule(const clang::Expr *expr) {
649649
return search(expr);
650650
}
651651

652+
bool IsLibcPassthrough(const clang::Expr *expr) {
653+
const auto *tgt_ir = GetExprRule(expr);
654+
if (tgt_ir == nullptr || !tgt_ir->body.empty() || !tgt_ir->is_extern) {
655+
return false;
656+
}
657+
const auto *ref =
658+
clang::dyn_cast<clang::DeclRefExpr>(expr->IgnoreParenImpCasts());
659+
const auto *decl = ref != nullptr ? ref->getDecl() : nullptr;
660+
return decl != nullptr &&
661+
decl->getASTContext().getSourceManager().isInSystemHeader(
662+
decl->getLocation());
663+
}
664+
652665
std::string MapFunctionName(const clang::FunctionDecl *decl) {
653666
assert(decl);
654667
if (!IsUserDefinedDecl(decl) &&
@@ -928,6 +941,12 @@ std::string ToString(const clang::NamedDecl *decl) {
928941
}
929942
os << ToString(func_decl->getParamDecl(i)->getType());
930943
}
944+
if (func_decl->isVariadic()) {
945+
if (func_decl->getNumParams()) {
946+
os << ", ";
947+
}
948+
os << "...";
949+
}
931950
os << ')';
932951

933952
if (const auto *method_decl =

‎cpp2rust/converter/mapper.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ bool Contains(const clang::Expr *expr);
3030
std::string Map(clang::QualType qual_type);
3131
std::string MapInitializer(clang::QualType qual_type);
3232
const TranslationRule::ExprRule *GetExprRule(const clang::Expr *expr);
33+
bool IsLibcPassthrough(const clang::Expr *expr);
3334
std::string MapFunctionName(const clang::FunctionDecl *decl);
3435
std::string InstantiateTemplate(const clang::Expr *expr, unsigned n);
3536
bool ReturnsPointer(const clang::Expr *expr);

‎cpp2rust/converter/translation_rule.cpp‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ std::vector<BodyFragment> ParseBodyFragmentsJSON(const llvm::json::Array &arr) {
8686
} else if (auto *mc = frag_obj->getObject("method_call")) {
8787
result.push_back(std::make_unique<MethodCallFragment>(
8888
ParseMethodCallFragmentJSON(*mc)));
89+
} else if (frag_obj->get("va_args")) {
90+
result.push_back(VaArgsFragment{});
8991
}
9092
}
9193
return result;
@@ -104,11 +106,17 @@ ExprRule ParseExprRuleJSON(const llvm::json::Object &obj) {
104106
}
105107
}
106108

107-
if (auto *rt = obj.getObject("return_type"))
109+
if (auto *rt = obj.getObject("return_type")) {
108110
ir.return_type = ParseTypeInfoJSON(*rt);
111+
}
109112

110-
if (auto ms = obj.getBoolean("multi_statement"))
113+
if (auto ms = obj.getBoolean("multi_statement")) {
111114
ir.multi_statement = *ms;
115+
}
116+
117+
if (auto v = obj.getBoolean("is_extern")) {
118+
ir.is_extern = *v;
119+
}
112120

113121
if (auto *generics = obj.getObject("generics")) {
114122
for (auto &[key, val] : *generics) {
@@ -222,6 +230,8 @@ void BodyFragmentDump(const BodyFragment &frag) {
222230
p->dump();
223231
} else if (auto *g = std::get_if<GenericFragment>(&frag)) {
224232
g->dump();
233+
} else if (auto *v = std::get_if<VaArgsFragment>(&frag)) {
234+
v->dump();
225235
} else if (auto *mc =
226236
std::get_if<std::unique_ptr<MethodCallFragment>>(&frag)) {
227237
(*mc)->dump();
@@ -232,6 +242,8 @@ void BodyFragmentDump(const BodyFragment &frag) {
232242

233243
void TextFragment::dump() const { log() << " text: \"" << text << "\"\n"; }
234244

245+
void VaArgsFragment::dump() const { log() << " va_args\n"; }
246+
235247
void PlaceholderFragment::dump() const {
236248
log() << " placeholder: " << n;
237249
switch (access) {

‎cpp2rust/converter/translation_rule.h‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,15 @@ struct GenericFragment {
3939
void dump() const;
4040
};
4141

42+
struct VaArgsFragment {
43+
void dump() const;
44+
};
45+
4246
struct MethodCallFragment; // forward declaration
4347

4448
using BodyFragment =
4549
std::variant<TextFragment, PlaceholderFragment, GenericFragment,
46-
std::unique_ptr<MethodCallFragment>>;
50+
VaArgsFragment, std::unique_ptr<MethodCallFragment>>;
4751

4852
struct MethodCallFragment {
4953
std::vector<BodyFragment> receiver;
@@ -71,6 +75,7 @@ struct ExprRule {
7175
std::vector<std::vector<std::string>> generics; // "T1" -> ["Ord", "Clone"]
7276
std::vector<BodyFragment> body;
7377
bool multi_statement = false;
78+
bool is_extern = false;
7479

7580
void dump() const;
7681
void validate(const std::string &name) const;

‎cpp2rust/cpp_rule_preprocessor.cpp‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,10 @@ class Callback : public clang::ast_matchers::MatchFinder::MatchCallback {
544544
if (const auto *ttp =
545545
llvm::dyn_cast<clang::TemplateTypeParmDecl>(param)) {
546546
clang::QualType type;
547+
if (param->isTemplateParameterPack()) {
548+
out.emplace_back(clang::TemplateArgument::getEmptyPack());
549+
continue;
550+
}
547551
if (ttp->hasDefaultArgument()) {
548552
clang::QualType hint = getDefaultArg(decl, ttp, out);
549553
assert(!hint.isNull() && "Failed retrieving type hint");
@@ -613,7 +617,14 @@ class Callback : public clang::ast_matchers::MatchFinder::MatchCallback {
613617
clang::OverloadCandidateSet &candidates) {
614618
clang::LookupResult decls(*sema_, name, loc_,
615619
clang::Sema::LookupOrdinaryName);
616-
sema_->LookupQualifiedName(decls, sema_->getStdNamespace());
620+
if (clang::NamespaceDecl *std_ns = sema_->getStdNamespace()) {
621+
sema_->LookupQualifiedName(decls, std_ns);
622+
}
623+
if (decls.empty()) {
624+
decls.clear();
625+
sema_->LookupQualifiedName(decls,
626+
sema_->Context.getTranslationUnitDecl());
627+
}
617628
for (auto *ndecl : decls) {
618629
if (auto *candidate = createCandidate(ndecl, callArgs, explicitTArgs)) {
619630
sema_->AddOverloadCandidate(
@@ -780,6 +791,7 @@ class Callback : public clang::ast_matchers::MatchFinder::MatchCallback {
780791
cxxConstructorNameLookup(rule->getReturnType(), callArgs, candidates);
781792
break;
782793
case LookupKind::ADL:
794+
regularNameLookup(callArgs, &explicitTArgs, name, candidates);
783795
adlLookup(callArgs, name, candidates);
784796
break;
785797
}

‎libc-dep/Cargo.toml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ edition = "2024"
55

66
[dependencies]
77
libc = "0.2"
8+
nix = { version = "0.30", features = ["socket", "net", "fs", "poll", "time", "user", "dir", "term", "event", "hostname"] }
9+
jiff = "0.2"

0 commit comments

Comments
 (0)