Estou tentando associar varDecl()
uma especialização de modelo a tipos de um determinado nome. Por exemplo:
template <typename T>
class C { };
C<char> var;
Gostaria de combinar var
quando o argumento do modelo for char
. O comparador que estou usando até agora:
m varDecl(hasType(classTemplateSpecializationDecl(
hasAnyTemplateArgument(templateArgument(
# TODO: match type with the name 'char'
).bind("template_param"))
).bind("var")))
Saída de clang-query
:
Binding for "template_param":
TemplateArgument type 'char'
`-BuiltinType 0x13203c6b0 'char'
Binding for "var":
ClassTemplateSpecializationDecl 0x1538906f0 <var_test.cpp:3:1, line:4:11> col:7 class C definition implicit_instantiation
|-DefinitionData pass_in_registers empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
| |-DefaultConstructor exists trivial constexpr defaulted_is_constexpr
| |-CopyConstructor simple trivial has_const_param implicit_has_const_param
| |-MoveConstructor exists simple trivial
| |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
| |-MoveAssignment exists simple trivial needs_implicit
| `-Destructor simple irrelevant trivial needs_implicit
|-TemplateArgument type 'A'
| `-RecordType 0x15386ca80 'A'
| `-CXXRecord 0x15386c9f0 'A'
|-CXXRecordDecl 0x1538909c8 <col:1, col:7> col:7 implicit class C
|-CXXConstructorDecl 0x153890a88 <col:7> col:7 implicit used constexpr C 'void () noexcept' inline default trivial
| `-CompoundStmt 0x153891030 <col:7>
|-CXXConstructorDecl 0x153890c40 <col:7> col:7 implicit constexpr C 'void (const C<A> &)' inline default trivial noexcept-unevaluated 0x153890c40
| `-ParmVarDecl 0x153890d70 <col:7> col:7 'const C<A> &'
`-CXXConstructorDecl 0x153890e50 <col:7> col:7 implicit constexpr C 'void (C<A> &&)' inline default trivial noexcept-unevaluated 0x153890e50
`-ParmVarDecl 0x153890f80 <col:7> col:7 'C<A> &&'
Coisas que tentei:
refersToType(builtinType(hasName("char")))
Não funciona:
3:22: Error building matcher builtinType.
3:34: Incorrect type for arg 1. (Expected = Matcher<BuiltinType>) != (Actual = Matcher<NamedDecl>)
refersToDeclaration(decl())
também não parece combinar com nada.
Correspondente fixo
Use este combinador:
Ou seja,
refersToType(asString("char"))
vai ondeTODO
estava o na pergunta.Com essa mudança,
C<char> var;
é correspondido, enquanto (digamos)C<int> var2;
não é. (Testado com Clang-18.1.8 no Windows.)Explicação
refersToType
corresponde a umTemplateArgument
cujoArgKind
éType
, o que significa que carrega umQualType
.asString("char")
então corresponde a um argumentoQualType
que, quando transformado em string, é "char".Por que algumas outras coisas não funcionam?
A questão menciona tentar:
Isso não funciona porque
builtinType
deseja um argumento que restrinja um tipo, enquantohasName
restringe apenas declarações. Este último ponto pode ser observado na documentação , observando quehasName
tem um "tipo de retorno" (ou seja, é ) aMatcher<NamedDecl>
, eNamedDecl
é um tipo de declaração (uma noção sintática) em vez de um tipo de tipo (uma noção semântica).A questão também menciona tentar:
Isso não funciona porque
char
é um argumento de modelo de tiporefersToDeclaration
, enquanto corresponde apenas a argumentos de modelo de declaração . Este último seria algo comoC<&bar>
(endereço de alguma variável), onde o argumento está efetivamente nomeando uma declaração específica.Algo que tentei durante a experiência foi:
Isso não funciona porque
asString
restringeQualType
, enquantobuiltinType
aceita uma restrição emType
. (Observe queQualType
não é um tipo deType
, mas sim uma tupla contendo aType
e qualificadores opcionais comoconst
.) Uma restrição emBuiltinType
especificamente funcionaria, mas não há nenhuma; o conjunto de comparadores infelizmente está incompleto em comparação com o que pode ser examinado diretamente usando a API C++. Consequentemente, obuiltinType
refinamento acaba sendo contraproducente aqui.