33
44#include " converter/rules/registry.h"
55
6+ #include < clang/AST/Attr.h>
67#include < clang/AST/DeclCXX.h>
78#include < clang/AST/DeclTemplate.h>
89#include < clang/Basic/SourceManager.h>
@@ -273,22 +274,23 @@ struct TypeRuleMatch {
273274
274275TypeRuleMatch findType (clang::QualType use) {
275276 TypeRuleMatch best;
276- auto consider = [&](const RuleKeys::TypeKey &key) {
277- auto [begin, end] = types_.equal_range (key);
278- for (auto it = begin; it != end; ++it) {
279- auto match = AstMatcher::MatchType (*sema_, use, it->second .decl );
280- if (!match) {
281- continue ;
282- }
283- if (best.rule_decl ) {
284- if (match->depth > best.match .depth ) {
277+ auto &ctx = sema_->Context ;
278+ auto consider = [&](clang::QualType type, bool templates) {
279+ for (auto key : RuleKeys::GetTypeKeys (ctx, type)) {
280+ auto [begin, end] = types_.equal_range (key);
281+ for (auto it = begin; it != end; ++it) {
282+ if (!templates && llvm::isa<clang::TemplateDecl>(it->second .decl )) {
285283 continue ;
286284 }
287- if (match->depth == best.match .depth ) {
285+ auto match = AstMatcher::MatchType (*sema_, type, it->second .decl );
286+ if (!match) {
287+ continue ;
288+ }
289+ if (best.rule_decl ) {
288290 auto better = AstMatcher::MoreSpecializedType (*sema_, it->second .decl ,
289291 best.rule_decl ->decl );
290292 if (!better) {
291- use .dump (llvm::errs (), sema_-> Context );
293+ type .dump (llvm::errs (), ctx );
292294 it->second .decl ->dump (llvm::errs ());
293295 best.rule_decl ->decl ->dump (llvm::errs ());
294296 llvm::report_fatal_error (
@@ -298,12 +300,31 @@ TypeRuleMatch findType(clang::QualType use) {
298300 continue ;
299301 }
300302 }
303+ best = {&it->second , *std::move (match)};
301304 }
302- best = {&it->second , *std::move (match)};
303305 }
304306 };
305- for (auto key : RuleKeys::GetTypeKeys (sema_->Context , use)) {
306- consider (key);
307+ auto skipped = RuleDecls::SkipInternalTypedefs (ctx, use);
308+ if (RuleDecls::SpelledTypedef (ctx, skipped) !=
309+ RuleDecls::SpelledTypedef (ctx, use)) {
310+ consider (use, /* templates=*/ false );
311+ if (best.rule_decl ) {
312+ return best;
313+ }
314+ }
315+ use = skipped;
316+ if (auto tag = use->getAsTagDecl ();
317+ tag &&
318+ (IsUserDefinedDecl (tag) || tag->hasAttr <clang::TransparentUnionAttr>())) {
319+ return best;
320+ }
321+ consider (use, /* templates=*/ true );
322+ if (!best.rule_decl ) {
323+ auto spelled = RuleDecls::SpelledTypedef (ctx, use);
324+ if (spelled && !IsUserDefinedDecl (spelled)) {
325+ use.dump (llvm::errs (), ctx);
326+ llvm::report_fatal_error (" typedef has no type rule" );
327+ }
307328 }
308329 return best;
309330}
@@ -401,8 +422,11 @@ Matcher::Match<TranslationRule::TypeRule> Search(clang::ASTContext &ctx,
401422 if (!match.rule_decl ) {
402423 return {};
403424 }
404- return {&match.rule_decl ->rule ,
405- getBindings (match.rule_decl ->decl , match.match .args )};
425+ auto bindings = getBindings (match.rule_decl ->decl , match.match .args );
426+ if (auto generic = match.rule_decl ->rule .generic ) {
427+ return Search (ctx, bindings.at (generic - 1 ).getAsType ());
428+ }
429+ return {&match.rule_decl ->rule , std::move (bindings)};
406430}
407431
408432const TranslationRule::ExprRule *GetExprRule (clang::ASTContext &ctx,
0 commit comments