1616#include < llvm/ADT/SmallBitVector.h>
1717
1818#include < cassert>
19+ #include < compare>
1920#include < optional>
2021#include < string>
2122#include < variant>
2223#include < vector>
2324
2425#include " converter/rules/decls.h"
26+ #include " converter/rules/rule_keys.h"
2527
2628namespace cpp2rust ::AstMatcher {
2729
@@ -50,18 +52,25 @@ bool hasSameArgTypes(clang::ASTContext &ctx, const clang::Expr *use,
5052struct MacroUsage {
5153 std::string name;
5254
53- bool operator == (const MacroUsage &) const = default ;
55+ auto operator <=> (const MacroUsage &) const = default ;
5456};
5557
5658struct RewrittenOperatorUsage {
5759 const clang::Decl *decl;
5860 clang::BinaryOperatorKind op;
5961
60- bool operator == (const RewrittenOperatorUsage &) const = default ;
62+ auto operator <=> (const RewrittenOperatorUsage &) const = default ;
6163};
6264
63- using ResolvedDecl = std::variant<std::monostate, const clang::Decl *,
64- MacroUsage, RewrittenOperatorUsage>;
65+ struct AggregateUsage {
66+ RuleKeys::TypeKey type;
67+
68+ auto operator <=>(const AggregateUsage &) const = default ;
69+ };
70+
71+ using ResolvedDecl =
72+ std::variant<std::monostate, const clang::Decl *, MacroUsage,
73+ RewrittenOperatorUsage, AggregateUsage>;
6574
6675ResolvedDecl getResolvedDecl (clang::ASTContext &ctx, const clang::Expr *expr,
6776 bool must_resolve) {
@@ -85,6 +94,17 @@ ResolvedDecl getResolvedDecl(clang::ASTContext &ctx, const clang::Expr *expr,
8594 if (auto cast = llvm::dyn_cast<clang::ExplicitCastExpr>(expr)) {
8695 return getResolvedDecl (ctx, cast->getSubExpr (), must_resolve);
8796 }
97+ if (auto list = llvm::dyn_cast<clang::InitListExpr>(expr);
98+ list && list->getType ()->isRecordType ()) {
99+ return AggregateUsage{*RuleKeys::GetTypeKey (list->getType ())};
100+ }
101+ if (llvm::isa<clang::CXXStdInitializerListExpr>(expr)) {
102+ return AggregateUsage{*RuleKeys::GetTypeKey (expr->getType ())};
103+ }
104+ if (auto construct = llvm::dyn_cast<clang::CXXUnresolvedConstructExpr>(expr);
105+ construct && construct->isListInitialization ()) {
106+ return AggregateUsage{*RuleKeys::GetTypeKey (construct->getTypeAsWritten ())};
107+ }
88108 if (auto call = llvm::dyn_cast<clang::CallExpr>(expr)) {
89109 if (auto callee = call->getDirectCallee ()) {
90110 return callee->getCanonicalDecl ();
@@ -149,6 +169,11 @@ std::vector<clang::Expr *> getOperands(clang::ASTContext &ctx,
149169 operands.insert (operands.end (), call->arg_begin (), call->arg_end ());
150170 } else if (auto construct = llvm::dyn_cast<clang::CXXConstructExpr>(expr)) {
151171 operands.assign (construct->arg_begin (), construct->arg_end ());
172+ } else if (auto list = llvm::dyn_cast<clang::InitListExpr>(expr)) {
173+ operands.assign (list->inits ().begin (), list->inits ().end ());
174+ } else if (auto list =
175+ llvm::dyn_cast<clang::CXXStdInitializerListExpr>(expr)) {
176+ operands.push_back (list->getSubExpr ()->IgnoreImplicit ());
152177 } else if (auto member = llvm::dyn_cast<clang::MemberExpr>(expr)) {
153178 auto macro_base =
154179 RuleDecls::GetMacroMemberBase (ctx.getSourceManager (), member);
@@ -233,7 +258,10 @@ clang::TemplateArgumentListInfo getResultArgs(clang::Sema &sema,
233258 clang::TemplateArgumentListInfo explicit_args (loc, loc);
234259 llvm::SmallBitVector deducible;
235260 sema.MarkDeducedTemplateParameters (rule, deducible);
236- if (deducible.all ()) {
261+ bool aggregate =
262+ llvm::isa<clang::InitListExpr, clang::CXXStdInitializerListExpr>(
263+ RuleDecls::SkipImplicit (use));
264+ if (deducible.all () && !aggregate) {
237265 return explicit_args;
238266 }
239267 auto params = rule->getTemplateParameters ();
@@ -247,7 +275,7 @@ clang::TemplateArgumentListInfo getResultArgs(clang::Sema &sema,
247275 return explicit_args;
248276 }
249277 auto last = static_cast <unsigned >(deducible.find_last_unset ());
250- for (unsigned i = 0 ; i <= last; ++i) {
278+ for (unsigned i = 0 ; i < params-> size () && i < = last; ++i) {
251279 auto param = params->getParam (i);
252280 if (param->isParameterPack () || (*deduced)[i].isNull ()) {
253281 break ;
@@ -320,6 +348,17 @@ MatchResult matchTemplate(clang::Sema &sema, const clang::Expr *use,
320348 auto explicit_args = getResultArgs (sema, rule, use);
321349 auto specialization =
322350 deduce (sema, rule, explicit_args, getOperands (ctx, use));
351+ if (!specialization) {
352+ return std::nullopt ;
353+ }
354+ if (std::holds_alternative<AggregateUsage>(usage_decl)) {
355+ auto returned = RuleDecls::GetReturned (rule->getTemplatedDecl ());
356+ if (getResolvedDecl (ctx, returned, /* must_resolve=*/ false ) != usage_decl) {
357+ return std::nullopt ;
358+ }
359+ checkCallable (sema, use, rule->getTemplatedDecl ());
360+ return specialization->getTemplateSpecializationArgs ()->asArray ();
361+ }
323362 auto returned =
324363 substituteSpecializationInRuleTmpl (sema, rule, specialization);
325364 if (!returned ||
0 commit comments