Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cpp2rust/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,5 @@ target_link_libraries(cpp2rust PRIVATE cpp2rust_core)

add_clang_executable(cpp-rule-preprocessor PARTIAL_SOURCES_INTENDED cpp_rule_preprocessor.cpp)
target_link_libraries(cpp-rule-preprocessor PRIVATE cpp2rust_core)
target_compile_definitions(cpp-rule-preprocessor PRIVATE
"-DRULES_LIB_INCLUDE_DIR=\"${PROJECT_SOURCE_DIR}/rules/lib\"")
86 changes: 67 additions & 19 deletions cpp2rust/converter/mapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "converter/mapper.h"

#include <clang/AST/ExprCXX.h>
#include <clang/Basic/OperatorKinds.h>
#include <clang/Basic/SourceManager.h>
#include <clang/Lex/Lexer.h>
#include <llvm/Support/ThreadPool.h>
Expand Down Expand Up @@ -558,7 +559,8 @@ void addBuiltinTypes(Model model) {
add_size_rules(ctx_->getSignedSizeType(), {"ssize_t"}, "isize");
}

clang::QualType normalizeQualType(clang::QualType qual_type) {
clang::QualType normalizeQualType(clang::QualType qual_type,
const clang::DeclContext *dctx) {
assert(ctx_);

bool isLRef = qual_type->isLValueReferenceType();
Expand All @@ -584,6 +586,22 @@ clang::QualType normalizeQualType(clang::QualType qual_type) {
qual_type = qual_type.getCanonicalType();
}

bool sugared = false;
if (dctx && llvm::isa<clang::SubstTemplateTypeParmType>(qual_type)) {
const auto match = llvm::find_if(dctx->decls(), [&](const auto *d) {
const auto *td = llvm::dyn_cast<clang::TypedefNameDecl>(d);
return td && (td->getUnderlyingType().getCanonicalType() ==
qual_type.getCanonicalType());
});

if (match != dctx->decls().end()) {
qual_type =
ctx_->getTypedefType(clang::ElaboratedTypeKeyword::None, std::nullopt,
llvm::cast<clang::TypedefNameDecl>(*match));
sugared = true;
}
}

qual_type = qual_type.withFastQualifiers(qualifiers.getFastQualifiers());
if (qualifiers.hasNonFastQualifiers()) {
qual_type = ctx_->getQualifiedType(qual_type, qualifiers);
Expand All @@ -597,6 +615,9 @@ clang::QualType normalizeQualType(clang::QualType qual_type) {
qual_type = ctx_->getRValueReferenceType(qual_type);
}

if (sugared) {
return qual_type;
}
return qual_type.getCanonicalType().getUnqualifiedType().getDesugaredType(
*ctx_);
}
Expand Down Expand Up @@ -834,7 +855,8 @@ std::string ToRustName(std::string name) {
return ReplaceAll(name, "::", "_");
}

std::string ToString(clang::QualType qual_type, ScalarSugar sugar) {
std::string ToString(clang::QualType qual_type, ScalarSugar sugar,
const clang::DeclContext *dctx) {
assert(ctx_);

if (sugar == ScalarSugar::kPreserve) {
Expand Down Expand Up @@ -864,7 +886,7 @@ std::string ToString(clang::QualType qual_type, ScalarSugar sugar) {

if (auto cxx_record_decl = qual_type->getAsCXXRecordDecl()) {
if (cxx_record_decl->isLambda()) {
return ToString(cxx_record_decl->getLambdaCallOperator());
return ToString(cxx_record_decl->getLambdaCallOperator(), dctx);
}
}

Expand All @@ -880,11 +902,12 @@ std::string ToString(clang::QualType qual_type, ScalarSugar sugar) {

std::string type;
llvm::raw_string_ostream os(type);
normalizeQualType(qual_type).print(os, getPrintPolicy());
normalizeQualType(qual_type, dctx).print(os, getPrintPolicy());
return normalizeTranslationRule(std::move(type));
}

std::string ToString(const clang::NamedDecl *decl) {
std::string ToString(const clang::NamedDecl *decl,
const clang::DeclContext *dctx) {
if (auto *record = clang::dyn_cast<clang::RecordDecl>(decl);
record && !record->getIdentifier()) {
if (auto renamed = DisambiguateAnonymousTag(record); !renamed.empty()) {
Expand Down Expand Up @@ -921,9 +944,32 @@ std::string ToString(const clang::NamedDecl *decl) {
return normalizeTranslationRule(std::move(out));
}

os << ToString(func_decl->getReturnType()) << ' ';
if (const auto *method_decl =
llvm::dyn_cast<clang::CXXMethodDecl>(func_decl)) {
os << ToString(func_decl->getReturnType(), ScalarSugar::kDesugar, dctx)
<< ' ';
if (const auto op = func_decl->getOverloadedOperator();
op >= clang::OverloadedOperatorKind::OO_LessLess &&
op <= clang::OverloadedOperatorKind::OO_GreaterGreaterEqual) {
// ensure matchTemplate does not consider these operator names when matching
func_decl->getQualifier().print(os, getPrintPolicy());
os << "operator ";
switch (op) {
case clang::OverloadedOperatorKind::OO_LessLess:
os << "shl";
break;
case clang::OverloadedOperatorKind::OO_GreaterGreater:
os << "shr";
break;
case clang::OverloadedOperatorKind::OO_LessLessEqual:
os << "shleq";
break;
case clang::OverloadedOperatorKind::OO_GreaterGreaterEqual:
os << "shreq";
break;
default:
std::unreachable();
}
} else if (const auto *method_decl =
llvm::dyn_cast<clang::CXXMethodDecl>(func_decl)) {
if (method_decl->getParent()->isLambda() &&
method_decl->getOverloadedOperator() == clang::OO_Call) {
func_decl->printName(os, getPrintPolicy());
Expand All @@ -939,7 +985,8 @@ std::string ToString(const clang::NamedDecl *decl) {
if (i) {
os << ", ";
}
os << ToString(func_decl->getParamDecl(i)->getType());
os << ToString(func_decl->getParamDecl(i)->getType(), ScalarSugar::kDesugar,
dctx);
}
if (func_decl->isVariadic()) {
if (func_decl->getNumParams()) {
Expand Down Expand Up @@ -972,7 +1019,7 @@ std::string ToString(const clang::NamedDecl *decl) {
return normalizeTranslationRule(std::move(out));
}

std::string ToString(const clang::Expr *expr) {
std::string ToString(const clang::Expr *expr, const clang::DeclContext *dctx) {
if (!expr) {
assert(0 && "!expr");
}
Expand All @@ -991,13 +1038,13 @@ std::string ToString(const clang::Expr *expr) {

if (const auto *CE = llvm::dyn_cast<clang::CallExpr>(expr)) {
if (const auto *decl = CE->getDirectCallee()) {
return ToString(decl);
return ToString(decl, dctx);
}
}

if (const auto *ctor = llvm::dyn_cast<clang::CXXConstructExpr>(expr)) {
if (const auto *ctor_decl = ctor->getConstructor()) {
return ToString(ctor_decl);
return ToString(ctor_decl, dctx);
}
assert(0 && "expr is a CXXConstructExpr but could not get constructor");
}
Expand All @@ -1007,14 +1054,15 @@ std::string ToString(const clang::Expr *expr) {
llvm::dyn_cast<clang::NamedDecl>(ME->getMemberDecl())) {
if (const auto *method_decl =
llvm::dyn_cast<clang::CXXMethodDecl>(member_decl)) {
return ToString(method_decl);
return ToString(method_decl, dctx);
}
if (ME->isArrow()) {
auto *base = ME->getBase()->IgnoreParenImpCasts();
if (auto *op = llvm::dyn_cast<clang::CXXOperatorCallExpr>(base)) {
if (op->getOperator() == clang::OO_Arrow) {
return ToString(op->getArg(0)->getType()) + "->" +
ToString(member_decl);
return ToString(op->getArg(0)->getType(), ScalarSugar::kDesugar,
dctx) +
"->" + ToString(member_decl, dctx);
}
}
} else if (auto for_range = GetParentForRange(*ctx_, ME)) {
Expand All @@ -1026,7 +1074,7 @@ std::string ToString(const clang::Expr *expr) {
}
}
}
return ToString(member_decl);
return ToString(member_decl, dctx);
}
assert(0 && "expr is a MemberExpr but could not get named decl");
}
Expand All @@ -1036,15 +1084,15 @@ std::string ToString(const clang::Expr *expr) {
llvm::dyn_cast<clang::NamedDecl>(decl_ref->getDecl())) {
if (const auto *tmpl_decl =
llvm::dyn_cast<clang::FunctionTemplateDecl>(named_decl)) {
return ToString(tmpl_decl->getTemplatedDecl());
return ToString(tmpl_decl->getTemplatedDecl(), dctx);
}
return ToString(named_decl);
return ToString(named_decl, dctx);
}
return "";
}

if (const auto *uop = llvm::dyn_cast<clang::UnaryOperator>(expr)) {
auto sub = ToString(uop->getSubExpr());
auto sub = ToString(uop->getSubExpr(), dctx);
std::string_view opcode =
clang::UnaryOperator::getOpcodeStr(uop->getOpcode());
return uop->isPostfix() ? std::format("{}{}", sub, opcode)
Expand Down
9 changes: 6 additions & 3 deletions cpp2rust/converter/mapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,12 @@ enum class ScalarSugar {

clang::QualType GetTypeForDecl(const clang::NamedDecl *decl);
std::string ToString(clang::QualType qual_type,
ScalarSugar sugar = ScalarSugar::kDesugar);
std::string ToString(const clang::Expr *expr);
std::string ToString(const clang::NamedDecl *decl);
ScalarSugar sugar = ScalarSugar::kDesugar,
const clang::DeclContext *dctx = nullptr);
std::string ToString(const clang::Expr *expr,
const clang::DeclContext *dctx = nullptr);
std::string ToString(const clang::NamedDecl *decl,
const clang::DeclContext *dctx = nullptr);
std::string ToRustName(std::string name);

void LoadTranslationRules(Model model, clang::ASTContext &ctx,
Expand Down
Loading
Loading