Search code examples
c++clanglibtoolingclang-ast-matchers

Clang AST: access member function templates from CXXRecordDecl


Say I have a dummy class like this:

class Stack
{
public:
  template<typename T>
  void push(T val)
  { (void)val; }

  template<typename T>
  T pop()
  { return 0; }

  bool empty() const
  { return true; }
};

The AST dump of which looks like:

  ...
  |-CXXRecordDecl 0x5610df147d60 <col:1, col:7> col:7 implicit class Stack
  |-AccessSpecDecl 0x5610df147df0 <line:3:1, col:7> col:1 public
  |-FunctionTemplateDecl 0x5610df1480e0 <line:4:3, line:6:16> line:5:8 push
  | |-TemplateTypeParmDecl 0x5610df147e18 <line:4:12, col:21> col:21 referenced typename depth 0 index 0 T
  | `-CXXMethodDecl 0x5610df148040 <line:5:3, line:6:16> line:5:8 push 'void (T)'
  |   |-ParmVarDecl 0x5610df147f00 <col:13, col:15> col:15 referenced val 'T'
  |   `-CompoundStmt 0x5610df1484f0 <line:6:3, col:16>
  |     `-CStyleCastExpr 0x5610df1484c8 <col:5, col:11> 'void' <ToVoid>
  |       `-DeclRefExpr 0x5610df148498 <col:11> 'T' lvalue ParmVar 0x5610df147f00 'val' 'T'
  |-FunctionTemplateDecl 0x5610df148300 <line:8:3, line:10:15> line:9:5 pop
  | |-TemplateTypeParmDecl 0x5610df148140 <line:8:12, col:21> col:21 referenced typename depth 0 index 0 T
  | `-CXXMethodDecl 0x5610df148260 <line:9:3, line:10:15> line:9:5 pop 'T ()'
  |   `-CompoundStmt 0x5610df148538 <line:10:3, col:15>
  |     `-ReturnStmt 0x5610df148528 <col:5, col:12>
  |       `-IntegerLiteral 0x5610df148508 <col:12> 'int' 0
  `-CXXMethodDecl 0x5610df1483e0 <line:12:3, line:13:18> line:12:8 empty 'bool () const'
    `-CompoundStmt 0x5610df148570 <line:13:3, col:18>
      `-ReturnStmt 0x5610df148560 <col:5, col:12>
        `-CXXBoolLiteralExpr 0x5610df148550 <col:12> 'bool' true

Given access to the CXXRecordDecl node for Stack, how can I access the FunctionTemplateDecl objects for push and pop? CXXRecorDecl::methods only returns the method declaration for empty and I don't see any other functions that might be helpful. Do I have to match the function template declarations separately and then later associate them with the class declaration?


Solution

  • I believe I have now figured it out, I will answer my own question in case this is useful for someone else:

    The way to do this is to first cast the given CXXRecordDecl to DeclContext, iterate over the contained declarations and try to cast them to FunctionTemplateDecl, pseudocode:

    clang::CXXRecordDecl const *record = // ...
    
    for (auto const *inner : static_cast<clang::DeclContext>(record)->decls()) {
      auto const *member_function_template = llvm::dyn_cast<clang::FunctionTemplateDecl>(inner);
      if (!member_function_template)
        continue;
    
      // do something useful
    }