2626
2727#include " converter/lex.h"
2828#include " converter/mapper.h"
29+ #include " converter/printer.h"
30+ #include " converter/rules/registry.h"
2931
3032// https://doc.rust-lang.org/reference/keywords.html
3133static const char rust_keywords[][12 ] = {
@@ -270,30 +272,6 @@ bool IsMut(clang::QualType qual_type) {
270272 qual_type->getPointeeType ().isConstQualified ());
271273}
272274
273- bool TypeImplementsByteRepr (clang::QualType qt) {
274- if (qt->isIntegerType () || qt->isFloatingType () || qt->isEnumeralType ()) {
275- return true ;
276- }
277- if (qt->isPointerType ()) {
278- return true ;
279- }
280- if (const auto *arr = qt->getAsArrayTypeUnsafe ()) {
281- return TypeImplementsByteRepr (arr->getElementType ());
282- }
283- if (const auto *rd = qt->getAsRecordDecl ()) {
284- if (rd->isUnion ()) {
285- return true ;
286- }
287- for (const auto *field : rd->fields ()) {
288- if (!TypeImplementsByteRepr (field->getType ())) {
289- return false ;
290- }
291- }
292- return true ;
293- }
294- return false ;
295- }
296-
297275bool RustSizeDivergesFromC (clang::QualType qt) {
298276 qt = qt.getCanonicalType ();
299277 // Records have Rc<RefCell<>> fields that diverge from the C size
@@ -352,6 +330,24 @@ bool IsOverloadedMethod(const clang::CXXMethodDecl *decl) {
352330 }) > 1 ;
353331}
354332
333+ unsigned GetMethodIndex (const clang::CXXMethodDecl *decl) {
334+ const clang::Decl *key = decl->getCanonicalDecl ();
335+ if (auto *tmpl = decl->getPrimaryTemplate ()) {
336+ key = tmpl->getCanonicalDecl ();
337+ }
338+ unsigned index = 0 ;
339+ for (auto *d : decl->getParent ()->decls ()) {
340+ if (clang::isa<clang::CXXMethodDecl, clang::FunctionTemplateDecl>(d)) {
341+ ++index;
342+ if (d->getCanonicalDecl () == key) {
343+ return index;
344+ }
345+ }
346+ }
347+ assert (false && " method not found in its record" );
348+ return 0 ;
349+ }
350+
355351const char *GetCopyOrMoveName (const clang::CXXMethodDecl *method) {
356352 if (auto *ctor = clang::dyn_cast<clang::CXXConstructorDecl>(method)) {
357353 if (ctor->isCopyConstructor ()) {
@@ -461,10 +457,6 @@ bool HasDefaultedCopyConstructor(const clang::RecordDecl *decl) {
461457 return !cxx->defaultedCopyConstructorIsDeleted ();
462458}
463459
464- bool RecordDerivesByteRepr (const clang::RecordDecl *decl) {
465- return !decl->isUnion () && decl->field_empty ();
466- }
467-
468460bool RecordHasOnlyReferenceFields (const clang::RecordDecl *decl) {
469461 for (auto *field : decl->fields ()) {
470462 if (!field->getType ()->isReferenceType ()) {
@@ -699,25 +691,26 @@ static std::string GetParamSignature(const clang::Decl *decl) {
699691}
700692
701693static std::string GetLexicalSpecializationID (const clang::Decl *decl) {
694+ auto &ctx = decl->getASTContext ();
702695 std::string id;
703696 if (const auto *var =
704697 clang::dyn_cast<clang::VarTemplateSpecializationDecl>(decl)) {
705698 id += clang::ASTNameGenerator (var->getASTContext ()).getName (var);
706699 }
707700 if (const auto *self =
708701 clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(decl)) {
709- id += Mapper ::ToString (Mapper:: GetTypeForDecl (self));
702+ id += Printer ::ToString (ctx, GetTypeForDecl (ctx, self));
710703 }
711704 if (const auto *spec =
712705 clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(
713706 decl->getLexicalDeclContext ());
714707 spec && decl->getLexicalDeclContext () != decl->getDeclContext ()) {
715- id += Mapper ::ToString (Mapper:: GetTypeForDecl (spec));
708+ id += Printer ::ToString (ctx, GetTypeForDecl (ctx, spec));
716709 }
717710 for (const auto *dc = decl->getDeclContext (); dc; dc = dc->getParent ()) {
718711 if (const auto *spec =
719712 clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(dc)) {
720- id += Mapper ::ToString (Mapper:: GetTypeForDecl (spec));
713+ id += Printer ::ToString (ctx, GetTypeForDecl (ctx, spec));
721714 }
722715 if (const auto *fn = clang::dyn_cast<clang::FunctionDecl>(dc);
723716 fn && fn->getTemplateSpecializationArgs ()) {
@@ -737,6 +730,35 @@ std::string GetMethodID(const clang::CXXMethodDecl *decl) {
737730 return decl->getQualifiedNameAsString () + GetID (decl);
738731}
739732
733+ clang::QualType GetTypeForDecl (clang::ASTContext &ctx,
734+ const clang::NamedDecl *decl) {
735+ if (const auto *spec =
736+ llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(decl)) {
737+ llvm::ArrayRef<clang::TemplateArgument> args =
738+ spec->getTemplateArgs ().asArray ();
739+ llvm::SmallVector<clang::TemplateArgument, 4 > canon (args.begin (),
740+ args.end ());
741+ ctx.canonicalizeTemplateArguments (canon);
742+
743+ return ctx.getTemplateSpecializationType (
744+ clang::ElaboratedTypeKeyword::None,
745+ clang::TemplateName (spec->getSpecializedTemplate ()), args, canon);
746+ }
747+
748+ const auto *rdecl = llvm::dyn_cast<clang::TagDecl>(decl);
749+ assert (rdecl && " Unsupported decl type" );
750+
751+ return ctx.getTagType (clang::ElaboratedTypeKeyword::None,
752+ rdecl->getQualifier (), rdecl, /* OwnsTag*/ false );
753+ }
754+
755+ bool HasFunctionParameterPack (const clang::FunctionDecl *decl) {
756+ if (auto *primary = decl->getPrimaryTemplate ()) {
757+ decl = primary->getTemplatedDecl ();
758+ }
759+ return decl->getNumParams () && decl->parameters ().back ()->isParameterPack ();
760+ }
761+
740762std::string DisambiguateAnonymousTag (const clang::TagDecl *tag) {
741763 if (!tag) {
742764 return " " ;
@@ -1451,15 +1473,15 @@ std::optional<clang::QualType> GetParamImplicitConvertTarget(clang::Expr *expr,
14511473}
14521474
14531475std::optional<IteratorCategory>
1454- GetStrongestIteratorCategory (clang::QualType type) {
1476+ GetStrongestIteratorCategory (clang::ASTContext &ctx, clang:: QualType type) {
14551477 type = type.getNonReferenceType ().getUnqualifiedType ();
1456- if (!Mapper::Contains (type)) {
1478+ if (!Mapper::Contains (ctx, type)) {
14571479 return std::nullopt ;
14581480 }
1459- if (Mapper ::MapsToRefcountPointer (type)) {
1481+ if (RuleRegistry ::MapsToRefcountPointer (ctx, type)) {
14601482 return IteratorCategory::Contiguous;
14611483 }
1462- auto mapped = Mapper::Map (type);
1484+ auto mapped = Mapper::Map (ctx, type);
14631485 if (mapped.empty ()) {
14641486 return std::nullopt ;
14651487 }
@@ -1536,15 +1558,17 @@ bool IsBuiltinVaStart(const clang::CallExpr *expr) {
15361558 return false ;
15371559}
15381560
1539- bool NeedsImplicitScalarCast (clang::QualType from, clang::QualType to) {
1561+ bool NeedsImplicitScalarCast (clang::ASTContext &ctx, clang::QualType from,
1562+ clang::QualType to) {
15401563 return !from.isNull () && !to.isNull () && from->isIntegerType () &&
15411564 to->isIntegerType () &&
15421565 from.getCanonicalType ().getUnqualifiedType () ==
15431566 to.getCanonicalType ().getUnqualifiedType () &&
1544- Mapper::Map (from) != Mapper::Map (to);
1567+ Mapper::Map (ctx, from) != Mapper::Map (ctx, to);
15451568}
15461569
1547- bool NeedsRefBindingTemp (const clang::Expr *arg, clang::QualType param_type) {
1570+ bool NeedsRefBindingTemp (clang::ASTContext &ctx, const clang::Expr *arg,
1571+ clang::QualType param_type) {
15481572 if (!param_type->isReferenceType ()) {
15491573 return false ;
15501574 }
@@ -1560,28 +1584,27 @@ bool NeedsRefBindingTemp(const clang::Expr *arg, clang::QualType param_type) {
15601584 // void foo(const size_t &) {} <-- size_t -> usize
15611585 // unsigned long x = 1; foo(x); <-- unsigned long -> u64
15621586 return param_type->getPointeeType ().isConstQualified () &&
1563- NeedsImplicitScalarCast (arg->IgnoreImplicit ()->getType (),
1587+ NeedsImplicitScalarCast (ctx, arg->IgnoreImplicit ()->getType (),
15641588 param_type.getNonReferenceType ());
15651589}
15661590
1567- bool IsSizeType (clang::QualType type) {
1568- auto rust_type = Mapper::Map (type);
1591+ bool IsSizeType (clang::ASTContext &ctx, clang:: QualType type) {
1592+ auto rust_type = Mapper::Map (ctx, type);
15691593 return rust_type == " usize" || rust_type == " isize" ;
15701594}
15711595
1572- std::optional<clang::QualType>
1573- GetOperandImplicitConversionTarget (const clang::BinaryOperator *op,
1574- const clang::Expr *operand,
1575- const clang::Expr *sibling) {
1596+ std::optional<clang::QualType> GetOperandImplicitConversionTarget (
1597+ clang::ASTContext &ctx, const clang::BinaryOperator *op,
1598+ const clang::Expr *operand, const clang::Expr *sibling) {
15761599 if (op->isComparisonOp ()) {
1577- if (NeedsImplicitScalarCast (operand->getType (), sibling->getType ()) &&
1578- IsSizeType (sibling->getType ())) {
1600+ if (NeedsImplicitScalarCast (ctx, operand->getType (), sibling->getType ()) &&
1601+ IsSizeType (ctx, sibling->getType ())) {
15791602 return sibling->getType ();
15801603 }
15811604 return std::nullopt ;
15821605 }
15831606 if ((op->isAdditiveOp () || op->isMultiplicativeOp () || op->isBitwiseOp ()) &&
1584- NeedsImplicitScalarCast (operand->getType (), op->getType ())) {
1607+ NeedsImplicitScalarCast (ctx, operand->getType (), op->getType ())) {
15851608 return op->getType ();
15861609 }
15871610 return std::nullopt ;
0 commit comments