确定 CXXMethodDecl 是否被实例化
Determine if a CXXMethodDecl is instantiated or not
我正在编写一个遍历 clang AST 并以特定格式打印出来的工具,但我不想打印函数模板,只是打印它们的(完整)专业化。我想知道如何确定 const CXXMethodDecl*
是否代表完全实例化的方法(它不是模板化的或者它是模板化方法的完整实例化)或未完全实例化的方法。这是我使用我的工具看到的示例:
template <typename Z>
class P
{
int lookup ();
};
template <typename Z>
int P<Z>::lookup ()
{
return Z::f();
}
struct X {
static int f();
};
template class P<X>;
构造以下 AST。我不想看到第一个 CXXRecordDecl
,因为它没有完全实例化,但我确实想看到第二个(已完全实例化)。
|-ClassTemplateDecl 0x3eff5b8 <minimal.cpp:1:1, line:5:1> line:2:7 Pte
| |-TemplateTypeParmDecl 0x3eff480 <line:1:11, col:20> col:20 typename depth 0 index 0 PTT
| |-CXXRecordDecl 0x3eff530 <line:2:1, line:5:1> line:2:7 class Pte definition
| | |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
| | | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr
| | | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
| | | |-MoveConstructor exists simple trivial needs_implicit
| | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
| | | |-MoveAssignment exists simple trivial needs_implicit
| | | `-Destructor simple irrelevant trivial needs_implicit
| | |-CXXRecordDecl 0x3eff800 <col:1, col:7> col:7 implicit class Pte
| | `-CXXMethodDecl 0x3eff910 <line:4:5, col:17> col:9 lookup 'int ()'
| `-ClassTemplateSpecialization 0x3f00010 'Pte'
|-CXXMethodDecl 0x3effbb0 parent 0x3eff530 prev 0x3eff910 <line:7:1, line:11:1> line:8:15 lookup 'int ()'
^^^^^^^^^^^^^^^^^^^^^^^^^^ I DO NOT WANT TO SEE THIS
| `-CompoundStmt 0x3effd50 <line:9:1, line:11:1>
| `-ReturnStmt 0x3effd40 <line:10:5, col:19>
| `-CallExpr 0x3effd20 <col:12, col:19> '<dependent type>'
| `-CXXDependentScopeMemberExpr 0x3effcd8 <col:12, col:17> '<dependent type>' lvalue ->f
|-CXXRecordDecl 0x3effd68 <line:13:1, line:15:1> line:13:8 referenced struct X definition
| |-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 needs_implicit defaulted_is_constexpr
| | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
| | |-MoveConstructor exists simple trivial needs_implicit
| | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
| | |-MoveAssignment exists simple trivial needs_implicit
| | `-Destructor simple irrelevant trivial needs_implicit
| |-CXXRecordDecl 0x3effe78 <col:1, col:8> col:8 implicit struct X
| `-CXXMethodDecl 0x3efff50 <line:14:5, col:18> col:16 used f 'int ()' static
`-ClassTemplateSpecializationDecl 0x3f00010 <line:17:1, col:21> col:16 class Pte definition
|-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 needs_implicit defaulted_is_constexpr
| |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
| |-MoveConstructor exists simple trivial needs_implicit
| |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
| |-MoveAssignment exists simple trivial needs_implicit
| `-Destructor simple irrelevant trivial needs_implicit
|-TemplateArgument type 'X'
|-CXXRecordDecl 0x3f001f8 prev 0x3f00010 <line:2:1, col:7> col:7 implicit class Pte
`-CXXMethodDecl 0x3f00280 <line:8:1, line:11:1> line:4:9 lookup 'int ()'
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ I want to see this
`-CompoundStmt 0x3f2e1b0 <line:9:1, line:11:1>
`-ReturnStmt 0x3f2e1a0 <line:10:5, col:19>
`-CallExpr 0x3f2e180 <col:12, col:19> 'int'
`-ImplicitCastExpr 0x3f2e168 <col:12, col:17> 'int (*)()' <FunctionToPointerDecay>
`-DeclRefExpr 0x3f2e110 <col:12, col:17> 'int ()' lvalue CXXMethod 0x3efff50 'f' 'int ()'
每当在模板中声明 type/function/variable 或者是模板时,clang 将其称为 依赖上下文 。您可能已经在模板中的 AST 节点周围看到 dependent 这个词。
我已经修改了您的原始测试用例以在非模板类型中包含模板化方法:
template <typename Z>
class P
{
int lookup ();
};
template <typename Z>
int P<Z>::lookup ()
{
return Z::f();
}
struct X {
static int f() { return 42; }
};
struct Y {
template <typename Z>
int foo() { return Z::f(); }
};
template class P<X>;
这是一个非常简单的递归 AST 访问器,它只打印出您感兴趣的函数:
class NonDependentMethodVisitor
: public clang::ASTConsumer,
public clang::RecursiveASTVisitor<NonDependentMethodVisitor> {
public:
void HandleTranslationUnit(clang::ASTContext &Context) {
this->TraverseTranslationUnitDecl(Context.getTranslationUnitDecl());
}
bool shouldVisitTemplateInstantiations() const { return true; }
bool VisitCXXMethodDecl(clang::CXXMethodDecl *MD) {
if (!MD->isDependentContext()) {
MD->dump();
}
return true;
}
};
这会为测试片段生成以下输出:
CXXMethodDecl 0x384eda0 <$TEST_DIR/test.cpp:14:5, col:33> col:16 used f 'int ()' static
`-CompoundStmt 0x384ee80 <col:20, col:33>
`-ReturnStmt 0x384ee70 <col:22, col:29>
`-IntegerLiteral 0x384ee50 <col:29> 'int' 42
CXXMethodDecl 0x387e170 <$TEST_DIR/test.cpp:8:1, line:11:1> line:4:9 lookup 'int ()'
`-CompoundStmt 0x387e450 <line:9:1, line:11:1>
`-ReturnStmt 0x387e440 <line:10:5, col:17>
`-CallExpr 0x387e420 <col:12, col:17> 'int'
`-ImplicitCastExpr 0x387e408 <col:12, col:15> 'int (*)()' <FunctionToPointerDecay>
`-DeclRefExpr 0x387e3b0 <col:12, col:15> 'int ()' lvalue CXXMethod 0x384eda0 'f' 'int ()'
希望这能回答您的问题!
我正在编写一个遍历 clang AST 并以特定格式打印出来的工具,但我不想打印函数模板,只是打印它们的(完整)专业化。我想知道如何确定 const CXXMethodDecl*
是否代表完全实例化的方法(它不是模板化的或者它是模板化方法的完整实例化)或未完全实例化的方法。这是我使用我的工具看到的示例:
template <typename Z>
class P
{
int lookup ();
};
template <typename Z>
int P<Z>::lookup ()
{
return Z::f();
}
struct X {
static int f();
};
template class P<X>;
构造以下 AST。我不想看到第一个 CXXRecordDecl
,因为它没有完全实例化,但我确实想看到第二个(已完全实例化)。
|-ClassTemplateDecl 0x3eff5b8 <minimal.cpp:1:1, line:5:1> line:2:7 Pte
| |-TemplateTypeParmDecl 0x3eff480 <line:1:11, col:20> col:20 typename depth 0 index 0 PTT
| |-CXXRecordDecl 0x3eff530 <line:2:1, line:5:1> line:2:7 class Pte definition
| | |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
| | | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr
| | | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
| | | |-MoveConstructor exists simple trivial needs_implicit
| | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
| | | |-MoveAssignment exists simple trivial needs_implicit
| | | `-Destructor simple irrelevant trivial needs_implicit
| | |-CXXRecordDecl 0x3eff800 <col:1, col:7> col:7 implicit class Pte
| | `-CXXMethodDecl 0x3eff910 <line:4:5, col:17> col:9 lookup 'int ()'
| `-ClassTemplateSpecialization 0x3f00010 'Pte'
|-CXXMethodDecl 0x3effbb0 parent 0x3eff530 prev 0x3eff910 <line:7:1, line:11:1> line:8:15 lookup 'int ()'
^^^^^^^^^^^^^^^^^^^^^^^^^^ I DO NOT WANT TO SEE THIS
| `-CompoundStmt 0x3effd50 <line:9:1, line:11:1>
| `-ReturnStmt 0x3effd40 <line:10:5, col:19>
| `-CallExpr 0x3effd20 <col:12, col:19> '<dependent type>'
| `-CXXDependentScopeMemberExpr 0x3effcd8 <col:12, col:17> '<dependent type>' lvalue ->f
|-CXXRecordDecl 0x3effd68 <line:13:1, line:15:1> line:13:8 referenced struct X definition
| |-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 needs_implicit defaulted_is_constexpr
| | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
| | |-MoveConstructor exists simple trivial needs_implicit
| | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
| | |-MoveAssignment exists simple trivial needs_implicit
| | `-Destructor simple irrelevant trivial needs_implicit
| |-CXXRecordDecl 0x3effe78 <col:1, col:8> col:8 implicit struct X
| `-CXXMethodDecl 0x3efff50 <line:14:5, col:18> col:16 used f 'int ()' static
`-ClassTemplateSpecializationDecl 0x3f00010 <line:17:1, col:21> col:16 class Pte definition
|-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 needs_implicit defaulted_is_constexpr
| |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
| |-MoveConstructor exists simple trivial needs_implicit
| |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
| |-MoveAssignment exists simple trivial needs_implicit
| `-Destructor simple irrelevant trivial needs_implicit
|-TemplateArgument type 'X'
|-CXXRecordDecl 0x3f001f8 prev 0x3f00010 <line:2:1, col:7> col:7 implicit class Pte
`-CXXMethodDecl 0x3f00280 <line:8:1, line:11:1> line:4:9 lookup 'int ()'
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ I want to see this
`-CompoundStmt 0x3f2e1b0 <line:9:1, line:11:1>
`-ReturnStmt 0x3f2e1a0 <line:10:5, col:19>
`-CallExpr 0x3f2e180 <col:12, col:19> 'int'
`-ImplicitCastExpr 0x3f2e168 <col:12, col:17> 'int (*)()' <FunctionToPointerDecay>
`-DeclRefExpr 0x3f2e110 <col:12, col:17> 'int ()' lvalue CXXMethod 0x3efff50 'f' 'int ()'
每当在模板中声明 type/function/variable 或者是模板时,clang 将其称为 依赖上下文 。您可能已经在模板中的 AST 节点周围看到 dependent 这个词。
我已经修改了您的原始测试用例以在非模板类型中包含模板化方法:
template <typename Z>
class P
{
int lookup ();
};
template <typename Z>
int P<Z>::lookup ()
{
return Z::f();
}
struct X {
static int f() { return 42; }
};
struct Y {
template <typename Z>
int foo() { return Z::f(); }
};
template class P<X>;
这是一个非常简单的递归 AST 访问器,它只打印出您感兴趣的函数:
class NonDependentMethodVisitor
: public clang::ASTConsumer,
public clang::RecursiveASTVisitor<NonDependentMethodVisitor> {
public:
void HandleTranslationUnit(clang::ASTContext &Context) {
this->TraverseTranslationUnitDecl(Context.getTranslationUnitDecl());
}
bool shouldVisitTemplateInstantiations() const { return true; }
bool VisitCXXMethodDecl(clang::CXXMethodDecl *MD) {
if (!MD->isDependentContext()) {
MD->dump();
}
return true;
}
};
这会为测试片段生成以下输出:
CXXMethodDecl 0x384eda0 <$TEST_DIR/test.cpp:14:5, col:33> col:16 used f 'int ()' static
`-CompoundStmt 0x384ee80 <col:20, col:33>
`-ReturnStmt 0x384ee70 <col:22, col:29>
`-IntegerLiteral 0x384ee50 <col:29> 'int' 42
CXXMethodDecl 0x387e170 <$TEST_DIR/test.cpp:8:1, line:11:1> line:4:9 lookup 'int ()'
`-CompoundStmt 0x387e450 <line:9:1, line:11:1>
`-ReturnStmt 0x387e440 <line:10:5, col:17>
`-CallExpr 0x387e420 <col:12, col:17> 'int'
`-ImplicitCastExpr 0x387e408 <col:12, col:15> 'int (*)()' <FunctionToPointerDecay>
`-DeclRefExpr 0x387e3b0 <col:12, col:15> 'int ()' lvalue CXXMethod 0x384eda0 'f' 'int ()'
希望这能回答您的问题!