Как сопоставить узел TemplateTypeParm в Clang AST с AST_Matchers? - PullRequest
1 голос
/ 20 июня 2019

Я пытаюсь получить тип шаблона RHS для TypeAliasDecl.

Пример:

using AliasOfType = AliasedType; // AliasedType itself is a template

Я могу получить AliasOfType в AST, используя clang::ast_matchers::typeAliasDecl. Я хочу получить AliasedType с clang::ast_matchers::.

Дамп AST clang::ast_matchers::typeAliasDecl выглядит следующим образом:

TypeAliasDecl 0x4fe22cf8 AliasOfType
  -SubstTemplateTypeParmType  0x4fe22cc0
   |-TemplateTypeParmType 0x4fe1a840 `AliasedType` dependent depth 0 index 0
   | `-TemplateTypeParm 0x4fe1a7f8 'AliasedType'

Так что интуитивно, я бы хотел найти совпадение с TemplateTypeParm, в котором мой предыдущий матч был предком. Однако я не нашел ast_matcher, который делает это. Там есть clang::ast_matchers::templateTypeParmType, но он выдает ошибки, если я пытаюсь указать что-либо в качестве параметра сужения, например:

templateTypeParmType(hasName("AliasedType"))

Ошибка, которую я получаю при попытке:

clang/ASTMatchers/ASTMatchersInternal.h:1347:13: error: ‘clang::ast_matchers::internal::Matcher< <template-parameter-1-1> >::Matcher(const clang::ast_matchers::internal::DynTypedMatcher&) [with T = clang::TemplateTypeParmType]’ is private within this context
 return {Matcher<T>(std::get<Is>(Params))...};

1 Ответ

1 голос
/ 21 июня 2019

Вы правы, не существует прямого сопоставителя, который проверял бы псевдоним типа псевдонима (это не так сложно реализовать самостоятельно, но я думаю, что это должно быть последним средством).

Тем не менее, существует средство has, которое согласно документации :

Соответствует узлам AST, у которых есть дочерние узлы AST, которые соответствуют при условии соответствия.

Другим важным моментом является то, что псевдоним типа обязательно будет иметь TypeLoc в качестве дочернего элемента. Вот небольшая цитата о различии между Type с и TypeLoc с (из Внутреннее руководство ):

мы повторно используем узлы Type при представлении одного и того же типа (но поддерживаем отдельные TypeLoc для каждого экземпляра, где записан тип)

Собрав все это вместе, мы получим следующее совпадение:

typeAliasDecl(has(typeLoc(loc(templateTypeParmType())).bind("x")))

Для этого фрагмента кода:

using NotInterestingAlias = int;

template <class AliasedType> class TemplateClass {
  using AliasOfType = AliasedType;
  using AliasOfSomeOtherType = double;
};

int main() { return 0; }

устройство сопоставления выдаст следующий вывод:

main.cpp:4:3: note: "root" binds here
  using AliasOfType = AliasedType;
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:4:23: note: "x" binds here
  using AliasOfType = AliasedType;
                      ^~~~~~~~~~~

Надеюсь, эта информация полезна. Счастливого взлома с Clang!

...