Skip to content

Commit 70d9a7f

Browse files
authored
Remove ReplaceNonUniformLibcField (#538)
1 parent f9e0fb7 commit 70d9a7f

24 files changed

Lines changed: 384 additions & 71 deletions

‎cpp2rust/converter/converter.cpp‎

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3518,6 +3518,7 @@ void Converter::SetUFCSReceiver(clang::Expr *base, bool is_arrow,
35183518
void Converter::ConvertMemberExpr(clang::MemberExpr *expr) {
35193519
if (auto mapped = GetMappedAsString(expr); !mapped.empty()) {
35203520
if (RuleRegistry::ReturnsPointer(ctx_, expr)) {
3521+
PushParen paren(*this);
35213522
StrCat(token::kStar, mapped);
35223523
} else {
35233524
StrCat(mapped);
@@ -3526,11 +3527,6 @@ void Converter::ConvertMemberExpr(clang::MemberExpr *expr) {
35263527
}
35273528

35283529
auto *member = expr->getMemberDecl();
3529-
auto [inner, record, name_override] = ReplaceNonUniformLibcField(expr);
3530-
if (inner) {
3531-
expr = inner;
3532-
}
3533-
35343530
auto *base = expr->getBase();
35353531
bool base_is_this = clang::isa<clang::CXXThisExpr>(base->IgnoreCasts()) &&
35363532
!ThisIsRustPtr() && !AsLambdaOperatorCall(curr_function_);
@@ -3549,8 +3545,6 @@ void Converter::ConvertMemberExpr(clang::MemberExpr *expr) {
35493545
method && IsOverloadedMethod(method)) {
35503546
StrCat(token::kDot);
35513547
StrCat(GetMethodName(method));
3552-
} else if (!name_override.empty()) {
3553-
StrCat(token::kDot, name_override);
35543548
} else if (member->getDeclName().isIdentifier()) {
35553549
StrCat(token::kDot);
35563550
StrCat(GetNamedDeclAsString(member));

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 5 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#include "converter/lex.h"
3030
#include "converter/mapper.h"
31+
#include "converter/rules/decls.h"
3132
#include "converter/rules/registry.h"
3233

3334
// https://doc.rust-lang.org/reference/keywords.html
@@ -222,45 +223,6 @@ clang::Expr *SubscriptedArray(clang::Expr *base) {
222223
}
223224

224225
// TODO: this will be gone when the AST matcher lands
225-
std::tuple<clang::MemberExpr *, clang::RecordDecl *, std::string>
226-
ReplaceNonUniformLibcField(clang::MemberExpr *expr) {
227-
// Example: ::struct stat::st_mtim::tv_sec -> ::libc::stat::st_mtime
228-
struct Mapping {
229-
const char *record;
230-
const char *inner_field;
231-
const char *leaf_field;
232-
const char *replacement;
233-
};
234-
static constexpr Mapping kFields[] = {
235-
{"stat", "st_mtim", "tv_sec", "st_mtime"}, // Linux
236-
{"stat", "st_mtimespec", "tv_sec", "st_mtime"}, // macOS
237-
{"in6_addr", "__in6_u", "__u6_addr8", "s6_addr"},
238-
};
239-
240-
auto getNamedIdentifierOrNull = [](auto *decl) {
241-
return decl && decl->getDeclName().isIdentifier() ? decl : nullptr;
242-
};
243-
244-
if (auto leaf = getNamedIdentifierOrNull(expr->getMemberDecl())) {
245-
if (auto inner = clang::dyn_cast<clang::MemberExpr>(
246-
expr->getBase()->IgnoreParenImpCasts())) {
247-
if (auto field = getNamedIdentifierOrNull(
248-
clang::dyn_cast<clang::FieldDecl>(inner->getMemberDecl()))) {
249-
if (getNamedIdentifierOrNull(field->getParent())) {
250-
for (const auto &m : kFields) {
251-
if (field->getParent()->getName() == m.record &&
252-
field->getName() == m.inner_field &&
253-
leaf->getName() == m.leaf_field) {
254-
return {inner, field->getParent(), m.replacement};
255-
}
256-
}
257-
}
258-
}
259-
}
260-
}
261-
return {nullptr, nullptr, ""};
262-
}
263-
264226
bool IsStringLiteralExpr(const clang::Expr *expr) {
265227
const auto *stripped = expr->IgnoreParens()->IgnoreImplicit();
266228
return clang::isa<clang::StringLiteral>(stripped) ||
@@ -1883,7 +1845,10 @@ BuildUnifiedArgs(clang::Expr *expr, clang::Expr **args, unsigned num_args) {
18831845
if (auto *mcall = clang::dyn_cast<clang::CXXMemberCallExpr>(expr)) {
18841846
all_args.push_back(mcall->getImplicitObjectArgument());
18851847
} else if (auto *member = clang::dyn_cast<clang::MemberExpr>(expr)) {
1886-
all_args.push_back(member->getBase());
1848+
auto *base = RuleDecls::GetMacroMemberBase(
1849+
member->getMemberDecl()->getASTContext().getSourceManager(), member);
1850+
all_args.push_back(
1851+
const_cast<clang::Expr *>(base ? base : member->getBase()));
18871852
}
18881853
for (unsigned i = 0; i < num_args; ++i) {
18891854
all_args.push_back(args[i]);

‎cpp2rust/converter/converter_lib.h‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,6 @@ bool IsUnionArrayMember(const clang::Expr *base);
6060

6161
clang::Expr *SubscriptedArray(clang::Expr *base);
6262

63-
std::tuple<clang::MemberExpr *, clang::RecordDecl *, std::string>
64-
ReplaceNonUniformLibcField(clang::MemberExpr *expr);
65-
6663
bool IsStringLiteralExpr(const clang::Expr *expr);
6764

6865
bool IsCodeUnitStringLiteral(const clang::StringLiteral *expr);

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1981,14 +1981,7 @@ void ConverterRefCount::ConvertUnionMemberAccessor(clang::MemberExpr *expr) {
19811981
auto member = expr->getMemberDecl();
19821982
auto *record = clang::cast<clang::RecordDecl>(member->getDeclContext());
19831983
auto name = GetNamedDeclAsString(member);
1984-
auto *accessed = expr;
1985-
if (auto [inner, libc_record, libc_name] = ReplaceNonUniformLibcField(expr);
1986-
inner) {
1987-
record = libc_record;
1988-
name = libc_name;
1989-
accessed = inner;
1990-
}
1991-
auto ptr = ConvertRecordPtr(accessed);
1984+
auto ptr = ConvertRecordPtr(expr);
19921985
auto str = std::format("{}::{}({}{})", GetRecordName(record), name, ptr,
19931986
isFresh() ? "" : ".clone()");
19941987

@@ -2028,6 +2021,22 @@ bool ConverterRefCount::VisitMemberExpr(clang::MemberExpr *expr) {
20282021
}
20292022
bool known = Mapper::Contains(ctx_, expr);
20302023

2024+
if (known && RuleRegistry::ReturnsPointer(ctx_, expr)) {
2025+
auto str = GetMappedAsString(expr);
2026+
if (isAddrOf()) {
2027+
StrCat(str);
2028+
computed_expr_type_ = ComputedExprType::FreshPointer;
2029+
return false;
2030+
}
2031+
if (isLValue()) {
2032+
pending_deref_.set(str, /*fresh=*/true);
2033+
return false;
2034+
}
2035+
StrCat(DerefPtrExpr(str, expr->getType()));
2036+
SetDerefFreshness(expr->getType());
2037+
return false;
2038+
}
2039+
20312040
if (auto *method = clang::dyn_cast<clang::CXXMethodDecl>(member);
20322041
method && !known) {
20332042
if (IsMethodOnPtr(method)) {

‎cpp2rust/converter/rules/decls.cpp‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,33 @@ const clang::Expr *GetReturned(const clang::FunctionDecl *rule) {
5050
return returned;
5151
}
5252

53+
namespace {
54+
clang::FileID getMacroExpansion(const clang::SourceManager &sm,
55+
clang::SourceLocation loc) {
56+
while (loc.isMacroID() && sm.isMacroArgExpansion(loc)) {
57+
loc = sm.getImmediateSpellingLoc(loc);
58+
}
59+
return loc.isMacroID() ? sm.getFileID(loc) : clang::FileID();
60+
}
61+
} // namespace
62+
63+
const clang::Expr *GetMacroMemberBase(const clang::SourceManager &sm,
64+
const clang::MemberExpr *member) {
65+
auto file = getMacroExpansion(sm, member->getMemberLoc());
66+
if (file.isInvalid() ||
67+
sm.getSLocEntry(file).getExpansion().isFunctionMacroExpansion()) {
68+
return nullptr;
69+
}
70+
const clang::Expr *base = member->getBase();
71+
while (true) {
72+
auto inner = llvm::dyn_cast<clang::MemberExpr>(base->IgnoreParenImpCasts());
73+
if (!inner || getMacroExpansion(sm, inner->getMemberLoc()) != file) {
74+
return base;
75+
}
76+
base = inner->getBase();
77+
}
78+
}
79+
5380
clang::QualType EnableIfSameType(const clang::Decl *rule) {
5481
auto tmpl = llvm::dyn_cast<clang::TemplateDecl>(rule);
5582
if (!tmpl) {

‎cpp2rust/converter/rules/decls.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <clang/AST/TemplateBase.h>
1010
#include <clang/AST/Type.h>
1111
#include <clang/Basic/Diagnostic.h>
12+
#include <clang/Basic/SourceManager.h>
1213
#include <clang/Sema/Sema.h>
1314

1415
#include <optional>
@@ -38,6 +39,9 @@ const clang::Expr *SkipImplicit(const clang::Expr *expr);
3839

3940
const clang::Expr *GetReturned(const clang::FunctionDecl *rule);
4041

42+
const clang::Expr *GetMacroMemberBase(const clang::SourceManager &sm,
43+
const clang::MemberExpr *member);
44+
4145
clang::QualType EnableIfSameType(const clang::Decl *rule);
4246

4347
std::optional<std::vector<clang::TemplateArgument>>

‎cpp2rust/converter/rules/expr_matcher.cpp‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ ResolvedDecl getResolvedDecl(clang::ASTContext &ctx, const clang::Expr *expr,
9292
} else if (auto construct = llvm::dyn_cast<clang::CXXConstructExpr>(expr)) {
9393
return construct->getConstructor()->getCanonicalDecl();
9494
} else if (auto member = llvm::dyn_cast<clang::MemberExpr>(expr)) {
95+
auto &sm = ctx.getSourceManager();
96+
if (RuleDecls::GetMacroMemberBase(sm, member)) {
97+
return MacroUsage{clang::Lexer::getImmediateMacroName(
98+
member->getMemberLoc(), sm, ctx.getLangOpts())
99+
.str()};
100+
}
95101
return member->getMemberDecl()->getCanonicalDecl();
96102
} else if (auto ref = llvm::dyn_cast<clang::DeclRefExpr>(expr)) {
97103
return ref->getDecl()->getCanonicalDecl();
@@ -144,7 +150,11 @@ std::vector<clang::Expr *> getOperands(clang::ASTContext &ctx,
144150
} else if (auto construct = llvm::dyn_cast<clang::CXXConstructExpr>(expr)) {
145151
operands.assign(construct->arg_begin(), construct->arg_end());
146152
} else if (auto member = llvm::dyn_cast<clang::MemberExpr>(expr)) {
147-
auto base = member->getBase()->IgnoreParenImpCasts();
153+
auto macro_base =
154+
RuleDecls::GetMacroMemberBase(ctx.getSourceManager(), member);
155+
auto base =
156+
const_cast<clang::Expr *>(macro_base ? macro_base : member->getBase())
157+
->IgnoreParenImpCasts();
148158
if (auto arrow = llvm::dyn_cast<clang::CXXOperatorCallExpr>(base);
149159
arrow && arrow->getOperator() == clang::OO_Arrow) {
150160
base = arrow->getArg(0);

‎cpp2rust/converter/rules/rule_keys.cpp‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,12 @@ std::optional<ExprKey> getExprKey(clang::ASTContext &ctx,
160160
return Unqualified{ref->getDeclName()};
161161
}
162162
if (auto member = llvm::dyn_cast<clang::MemberExpr>(expr)) {
163+
auto &sm = ctx.getSourceManager();
164+
if (RuleDecls::GetMacroMemberBase(sm, member)) {
165+
auto macro = clang::Lexer::getImmediateMacroName(member->getMemberLoc(),
166+
sm, ctx.getLangOpts());
167+
return Unqualified{clang::DeclarationName(&ctx.Idents.get(macro))};
168+
}
163169
return getDeclKey(member->getMemberDecl());
164170
}
165171
if (auto ref = llvm::dyn_cast<clang::DeclRefExpr>(expr)) {

‎cpp2rust/converter/rules/rules_loader.cpp‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <vector>
2626

2727
#include "converter/converter_lib.h"
28+
#include "converter/rules/decls.h"
2829
#include "logging.h"
2930

3031
namespace cpp2rust::RulesLoader {
@@ -442,6 +443,12 @@ std::string ExprKey(clang::ASTContext &ctx, const clang::Expr *expr) {
442443
return FunctionKey(construct->getConstructor());
443444
}
444445
if (auto member = llvm::dyn_cast<clang::MemberExpr>(expr)) {
446+
if (RuleDecls::GetMacroMemberBase(ctx.getSourceManager(), member)) {
447+
return clang::Lexer::getImmediateMacroName(member->getMemberLoc(),
448+
ctx.getSourceManager(),
449+
ctx.getLangOpts())
450+
.str();
451+
}
445452
return DeclKey(member->getMemberDecl());
446453
}
447454
if (auto ref = llvm::dyn_cast<clang::DeclRefExpr>(expr)) {

‎rules/ip/src.c‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,8 @@ int f5(void) { return IPPROTO_MPTCP; }
1919
#endif
2020

2121
int f6(void) { return TCP_NODELAY; }
22+
23+
#pragma clang diagnostic push
24+
#pragma clang diagnostic ignored "-Wreturn-stack-address"
25+
uint8_t *f7(struct in6_addr a0) { return a0.s6_addr; }
26+
#pragma clang diagnostic pop

0 commit comments

Comments
 (0)