|
12 | 12 | #include <llvm/ADT/STLExtras.h> |
13 | 13 |
|
14 | 14 | #include <cassert> |
15 | | -#include <ranges> |
16 | | -#include <string> |
17 | | -#include <unordered_set> |
18 | 15 | #include <vector> |
19 | 16 |
|
20 | 17 | namespace cpp2rust::RuleDecls { |
21 | 18 |
|
22 | 19 | namespace { |
23 | 20 |
|
24 | | -std::string NameKey(const clang::NamedDecl *decl) { |
25 | | - std::vector<std::string> scopes; |
26 | | - for (auto scope = decl->getDeclContext(); scope; scope = scope->getParent()) { |
27 | | - if (auto ns = llvm::dyn_cast<clang::NamespaceDecl>(scope)) { |
28 | | - if (!ns->isInline() && !ns->isAnonymousNamespace()) { |
29 | | - scopes.push_back(ns->getNameAsString()); |
30 | | - } |
31 | | - } else if (auto record = llvm::dyn_cast<clang::RecordDecl>(scope)) { |
32 | | - scopes.push_back(record->getNameAsString()); |
33 | | - } else if (auto enum_decl = llvm::dyn_cast<clang::EnumDecl>(scope); |
34 | | - enum_decl && enum_decl->isScoped()) { |
35 | | - scopes.push_back(enum_decl->getNameAsString()); |
36 | | - } |
37 | | - } |
38 | | - std::string key; |
39 | | - for (const auto &scope : scopes | std::views::reverse) { |
40 | | - key += scope + '/'; |
41 | | - } |
42 | | - return key + decl->getNameAsString(); |
43 | | -} |
44 | | - |
45 | 21 | const clang::Decl *getScope(clang::QualType type) { |
46 | 22 | type = type.getNonReferenceType(); |
47 | 23 | if (type->isPointerType()) { |
@@ -188,85 +164,6 @@ ExprKey getExprKey(clang::ASTContext &ctx, const clang::Expr *expr) { |
188 | 164 | return {}; |
189 | 165 | } |
190 | 166 |
|
191 | | -void AddRequiredClasses(clang::QualType type, |
192 | | - std::unordered_set<std::string> &required) { |
193 | | - if (type.isNull()) { |
194 | | - return; |
195 | | - } |
196 | | - if (type->isPointerType() || type->isReferenceType()) { |
197 | | - return AddRequiredClasses(type->getPointeeType(), required); |
198 | | - } |
199 | | - if (auto array = type->getAsArrayTypeUnsafe()) { |
200 | | - return AddRequiredClasses(array->getElementType(), required); |
201 | | - } |
202 | | - if (auto fn = type->getAs<clang::FunctionType>()) { |
203 | | - AddRequiredClasses(fn->getReturnType(), required); |
204 | | - if (auto proto = llvm::dyn_cast<clang::FunctionProtoType>(fn)) { |
205 | | - for (auto param : proto->param_types()) { |
206 | | - AddRequiredClasses(param, required); |
207 | | - } |
208 | | - } |
209 | | - return; |
210 | | - } |
211 | | - if (auto name = type->getAs<clang::DependentNameType>()) { |
212 | | - auto qualifier = name->getQualifier(); |
213 | | - if (qualifier.getKind() == clang::NestedNameSpecifier::Kind::Type) { |
214 | | - AddRequiredClasses(clang::QualType(qualifier.getAsType(), 0), required); |
215 | | - } |
216 | | - return; |
217 | | - } |
218 | | - if (auto alias = type->getAs<clang::TypedefType>()) { |
219 | | - if (auto record = llvm::dyn_cast<clang::RecordDecl>( |
220 | | - alias->getDecl()->getDeclContext())) { |
221 | | - if (auto key = ClassKey(record); !key.empty()) { |
222 | | - required.insert(key); |
223 | | - } |
224 | | - } |
225 | | - } |
226 | | - const clang::NamedDecl *decl = type->getAsTagDecl(); |
227 | | - if (auto spec = type->getAs<clang::TemplateSpecializationType>()) { |
228 | | - for (const auto &arg : spec->template_arguments()) { |
229 | | - if (arg.getKind() == clang::TemplateArgument::Type) { |
230 | | - AddRequiredClasses(arg.getAsType(), required); |
231 | | - } |
232 | | - } |
233 | | - if (auto tmpl = spec->getTemplateName().getAsTemplateDecl(); |
234 | | - tmpl && llvm::isa<clang::ClassTemplateDecl>(tmpl)) { |
235 | | - decl = tmpl; |
236 | | - } |
237 | | - } |
238 | | - if (!decl) { |
239 | | - return; |
240 | | - } |
241 | | - if (auto key = ClassKey(decl); !key.empty()) { |
242 | | - required.insert(key); |
243 | | - } |
244 | | -} |
245 | | - |
246 | | -const clang::Expr *RuleExpr(const clang::Decl *decl) { |
247 | | - if (auto var = llvm::dyn_cast<clang::VarDecl>(decl)) { |
248 | | - return var->getInit(); |
249 | | - } |
250 | | - auto fn = decl->getAsFunction(); |
251 | | - if (!fn) { |
252 | | - return nullptr; |
253 | | - } |
254 | | - auto body = llvm::dyn_cast_or_null<clang::CompoundStmt>(fn->getBody()); |
255 | | - if (!body || body->size() != 1) { |
256 | | - return nullptr; |
257 | | - } |
258 | | - auto ret = llvm::dyn_cast<clang::ReturnStmt>(body->body_front()); |
259 | | - return ret ? ret->getRetValue() : nullptr; |
260 | | -} |
261 | | - |
262 | | -const clang::Expr *IgnoreImplicitAndFunctionalCast(const clang::Expr *expr) { |
263 | | - expr = expr->IgnoreImplicit(); |
264 | | - if (auto cast = llvm::dyn_cast<clang::CXXFunctionalCastExpr>(expr)) { |
265 | | - expr = cast->getSubExpr()->IgnoreImplicit(); |
266 | | - } |
267 | | - return expr; |
268 | | -} |
269 | | - |
270 | 167 | } // namespace |
271 | 168 |
|
272 | 169 | const clang::Expr *SkipImplicit(const clang::Expr *expr) { |
@@ -392,127 +289,6 @@ std::vector<const void *> GetTypeKeys(clang::ASTContext &ctx, |
392 | 289 |
|
393 | 290 | ExprKey GetDeclKey(const clang::NamedDecl *decl) { return getDeclKey(decl); } |
394 | 291 |
|
395 | | -std::string ClassKey(const clang::NamedDecl *decl) { |
396 | | - if (auto alias = llvm::dyn_cast<clang::TypedefNameDecl>(decl)) { |
397 | | - auto tag = alias->getUnderlyingType()->getAsTagDecl(); |
398 | | - if (!tag) { |
399 | | - return {}; |
400 | | - } |
401 | | - decl = tag; |
402 | | - } |
403 | | - if (auto spec = |
404 | | - llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(decl)) { |
405 | | - decl = spec->getSpecializedTemplate(); |
406 | | - } |
407 | | - if (auto tag = llvm::dyn_cast<clang::TagDecl>(decl); |
408 | | - tag && !tag->getIdentifier()) { |
409 | | - decl = tag->getTypedefNameForAnonDecl(); |
410 | | - if (!decl) { |
411 | | - return {}; |
412 | | - } |
413 | | - } |
414 | | - return NameKey(decl); |
415 | | -} |
416 | | - |
417 | | -std::string MemberName(clang::DeclarationName name) { |
418 | | - if (name.getNameKind() == clang::DeclarationName::CXXConversionFunctionName) { |
419 | | - return "operator"; |
420 | | - } |
421 | | - return name.getAsString(); |
422 | | -} |
423 | | - |
424 | | -std::string MemberKey(const std::string &class_key, const std::string &name) { |
425 | | - if (class_key.empty()) { |
426 | | - return {}; |
427 | | - } |
428 | | - return class_key + '/' + name; |
429 | | -} |
430 | | - |
431 | | -std::string ConstructorKey(const std::string &class_key) { |
432 | | - return MemberKey(class_key, class_key.substr(class_key.rfind('/') + 1)); |
433 | | -} |
434 | | - |
435 | | -std::string FunctionKey(const clang::FunctionDecl *decl) { |
436 | | - if (const clang::FunctionDecl *definition = nullptr; |
437 | | - decl->isDefined(definition) && |
438 | | - !decl->getASTContext().getSourceManager().isInSystemHeader( |
439 | | - definition->getLocation())) { |
440 | | - return {}; |
441 | | - } |
442 | | - if (auto method = llvm::dyn_cast<clang::CXXMethodDecl>(decl)) { |
443 | | - auto class_key = ClassKey(method->getParent()); |
444 | | - if (llvm::isa<clang::CXXConstructorDecl>(method)) { |
445 | | - return ConstructorKey(class_key); |
446 | | - } |
447 | | - return MemberKey(class_key, MemberName(method->getDeclName())); |
448 | | - } |
449 | | - return NameKey(decl); |
450 | | -} |
451 | | - |
452 | | -std::string DeclKey(const clang::NamedDecl *decl) { |
453 | | - if (auto fn = decl->getAsFunction()) { |
454 | | - return FunctionKey(fn); |
455 | | - } |
456 | | - if (auto record = llvm::dyn_cast<clang::RecordDecl>(decl->getDeclContext())) { |
457 | | - return MemberKey(ClassKey(record), MemberName(decl->getDeclName())); |
458 | | - } |
459 | | - return NameKey(decl); |
460 | | -} |
461 | | - |
462 | | -std::string ExprKeyString(clang::ASTContext &ctx, const clang::Expr *expr) { |
463 | | - expr = expr->IgnoreParenImpCasts(); |
464 | | - if (llvm::isa<clang::IntegerLiteral>(expr) && |
465 | | - expr->getBeginLoc().isMacroID()) { |
466 | | - return clang::Lexer::getImmediateMacroName( |
467 | | - expr->getBeginLoc(), ctx.getSourceManager(), ctx.getLangOpts()) |
468 | | - .str(); |
469 | | - } |
470 | | - if (auto call = llvm::dyn_cast<clang::CallExpr>(expr)) { |
471 | | - if (auto callee = call->getDirectCallee()) { |
472 | | - return FunctionKey(callee); |
473 | | - } |
474 | | - return {}; |
475 | | - } |
476 | | - if (auto construct = llvm::dyn_cast<clang::CXXConstructExpr>(expr)) { |
477 | | - return FunctionKey(construct->getConstructor()); |
478 | | - } |
479 | | - if (auto member = llvm::dyn_cast<clang::MemberExpr>(expr)) { |
480 | | - return DeclKey(member->getMemberDecl()); |
481 | | - } |
482 | | - if (auto ref = llvm::dyn_cast<clang::DeclRefExpr>(expr)) { |
483 | | - return DeclKey(ref->getDecl()); |
484 | | - } |
485 | | - if (auto unary = llvm::dyn_cast<clang::UnaryOperator>(expr)) { |
486 | | - return ExprKeyString(ctx, unary->getSubExpr()); |
487 | | - } |
488 | | - return {}; |
489 | | -} |
490 | | - |
491 | | -std::string TypeKey(clang::QualType type) { |
492 | | - if (auto decltype_type = |
493 | | - llvm::dyn_cast<clang::DecltypeType>(type.getTypePtr())) { |
494 | | - type = decltype_type->getUnderlyingType(); |
495 | | - } |
496 | | - if (auto typeof_type = |
497 | | - llvm::dyn_cast<clang::TypeOfExprType>(type.getTypePtr())) { |
498 | | - type = typeof_type->getUnderlyingExpr()->getType(); |
499 | | - } |
500 | | - if (auto alias = type->getAs<clang::TypedefType>(); |
501 | | - alias && type.getCanonicalType()->isBuiltinType()) { |
502 | | - return DeclKey(alias->getDecl()); |
503 | | - } |
504 | | - if (auto sugar = type->getAs<clang::PredefinedSugarType>()) { |
505 | | - return sugar->getIdentifier()->getName().str(); |
506 | | - } |
507 | | - if (auto builtin = type->getAs<clang::BuiltinType>()) { |
508 | | - return builtin->getName(clang::PrintingPolicy(clang::LangOptions())).str(); |
509 | | - } |
510 | | - if (auto tag = type->getAsTagDecl()) { |
511 | | - return ClassKey(tag); |
512 | | - } |
513 | | - return {}; |
514 | | -} |
515 | | - |
516 | 292 | clang::QualType EnableIfSameType(const clang::Decl *rule) { |
517 | 293 | auto tmpl = llvm::dyn_cast<clang::TemplateDecl>(rule); |
518 | 294 | if (!tmpl) { |
@@ -561,119 +337,4 @@ clang::QualType EnableIfSameType(const clang::Decl *rule) { |
561 | 337 | return {}; |
562 | 338 | } |
563 | 339 |
|
564 | | -std::string ClassOf(clang::QualType type) { |
565 | | - while (type->isPointerType() || type->isReferenceType()) { |
566 | | - type = type->getPointeeType(); |
567 | | - } |
568 | | - if (auto spec = type->getAs<clang::TemplateSpecializationType>()) { |
569 | | - auto decl = spec->getTemplateName().getAsTemplateDecl(); |
570 | | - if (decl && llvm::isa<clang::ClassTemplateDecl>(decl)) { |
571 | | - return ClassKey(decl); |
572 | | - } |
573 | | - return {}; |
574 | | - } |
575 | | - if (auto name = type->getAs<clang::DependentNameType>()) { |
576 | | - auto qualifier = name->getQualifier(); |
577 | | - if (qualifier.getKind() == clang::NestedNameSpecifier::Kind::Type) { |
578 | | - return ClassOf(clang::QualType(qualifier.getAsType(), 0)); |
579 | | - } |
580 | | - } |
581 | | - return {}; |
582 | | -} |
583 | | - |
584 | | -std::unordered_set<std::string> |
585 | | -RequiredClasses(const clang::Decl *rule, const clang::TypedefNameDecl *alias) { |
586 | | - std::unordered_set<std::string> required; |
587 | | - if (alias) { |
588 | | - AddRequiredClasses(alias->getUnderlyingType(), required); |
589 | | - } else if (auto fn = rule->getAsFunction()) { |
590 | | - AddRequiredClasses(fn->getType(), required); |
591 | | - } else if (auto var = llvm::dyn_cast<clang::VarDecl>(rule)) { |
592 | | - AddRequiredClasses(var->getType(), required); |
593 | | - } |
594 | | - return required; |
595 | | -} |
596 | | - |
597 | | -std::string ClassOfParameters(const clang::Decl *rule) { |
598 | | - auto fn = rule->getAsFunction(); |
599 | | - if (!fn) { |
600 | | - return {}; |
601 | | - } |
602 | | - for (const auto *param : fn->parameters()) { |
603 | | - if (auto class_key = ClassOf(param->getType()); !class_key.empty()) { |
604 | | - return class_key; |
605 | | - } |
606 | | - } |
607 | | - return {}; |
608 | | -} |
609 | | - |
610 | | -std::string ClassOfEnableIf(const clang::Decl *rule) { |
611 | | - auto same = EnableIfSameType(rule); |
612 | | - return same.isNull() ? std::string() : ClassOf(same); |
613 | | -} |
614 | | - |
615 | | -std::string DependentExprKey(const clang::Expr *expr) { |
616 | | - auto member = llvm::dyn_cast<clang::CXXDependentScopeMemberExpr>(expr); |
617 | | - if (auto call = llvm::dyn_cast<clang::CallExpr>(expr)) { |
618 | | - if (auto callee = call->getDirectCallee()) { |
619 | | - return FunctionKey(callee); |
620 | | - } |
621 | | - auto callee = call->getCallee()->IgnoreParenImpCasts(); |
622 | | - member = llvm::dyn_cast<clang::CXXDependentScopeMemberExpr>(callee); |
623 | | - if (auto overloads = llvm::dyn_cast<clang::UnresolvedMemberExpr>(callee); |
624 | | - overloads && overloads->decls_begin() != overloads->decls_end()) { |
625 | | - return DeclKey((*overloads->decls_begin())->getUnderlyingDecl()); |
626 | | - } |
627 | | - if (auto ref = llvm::dyn_cast<clang::DependentScopeDeclRefExpr>(callee)) { |
628 | | - auto qualifier = ref->getQualifier(); |
629 | | - if (qualifier.getKind() == clang::NestedNameSpecifier::Kind::Type) { |
630 | | - return MemberKey(ClassOf(clang::QualType(qualifier.getAsType(), 0)), |
631 | | - MemberName(ref->getDeclName())); |
632 | | - } |
633 | | - } |
634 | | - if (auto lookup = llvm::dyn_cast<clang::UnresolvedLookupExpr>(callee); |
635 | | - lookup && lookup->getQualifier() && |
636 | | - !llvm::isa<clang::CXXOperatorCallExpr>(call) && |
637 | | - lookup->decls_begin() != lookup->decls_end()) { |
638 | | - return DeclKey((*lookup->decls_begin())->getUnderlyingDecl()); |
639 | | - } |
640 | | - } |
641 | | - if (member && !member->isArrow() && |
642 | | - member->getBaseType() |
643 | | - .getNonReferenceType() |
644 | | - ->getAs<clang::TemplateSpecializationType>()) { |
645 | | - return MemberKey(ClassOf(member->getBaseType()), |
646 | | - MemberName(member->getMember())); |
647 | | - } |
648 | | - if (auto construct = |
649 | | - llvm::dyn_cast<clang::CXXUnresolvedConstructExpr>(expr)) { |
650 | | - auto class_key = ClassOf(construct->getTypeAsWritten()); |
651 | | - return ConstructorKey(class_key); |
652 | | - } |
653 | | - return {}; |
654 | | -} |
655 | | - |
656 | | -std::string RuleExprKey(clang::ASTContext &ctx, const clang::Decl *rule) { |
657 | | - auto expr = RuleExpr(rule); |
658 | | - if (!expr) { |
659 | | - return {}; |
660 | | - } |
661 | | - expr = IgnoreImplicitAndFunctionalCast(expr); |
662 | | - if (!expr->isTypeDependent() && !expr->isValueDependent()) { |
663 | | - return ExprKeyString(ctx, expr); |
664 | | - } |
665 | | - return DependentExprKey(expr); |
666 | | -} |
667 | | - |
668 | | -std::string RuleTypeKey(const clang::TypedefNameDecl *rule) { |
669 | | - auto type = rule->getUnderlyingType(); |
670 | | - while (type->isPointerType() || type->isReferenceType()) { |
671 | | - type = type->getPointeeType(); |
672 | | - } |
673 | | - if (!type->isDependentType()) { |
674 | | - return TypeKey(type); |
675 | | - } |
676 | | - return ClassOf(type); |
677 | | -} |
678 | | - |
679 | 340 | } // namespace cpp2rust::RuleDecls |
0 commit comments