systemc-clang 2.0.0
Parsing SystemC constructs
Loading...
Searching...
No Matches
TemplateParametersMatcher.h
Go to the documentation of this file.
1#ifndef _TEMPLATE_PARAMETERS_MATCHERS_H_
2#define _TEMPLATE_PARAMETERS_MATCHERS_H_
3
4#include "clang/ASTMatchers/ASTMatchFinder.h"
5#include "clang/ASTMatchers/ASTMatchers.h"
6#include "clang/ASTMatchers/ASTMatchersInternal.h"
7#include "clang/ASTMatchers/ASTMatchersMacros.h"
8#include "llvm/Support/Debug.h"
9
11#undef DEBUG_TYPE
12#define DEBUG_TYPE "HDL"
13
14using namespace clang::ast_matchers;
15using namespace systemc_clang;
16
17namespace sc_ast_matchers {
18AST_MATCHER(Type, isDependentNameType) { return (Node.isDependentType()); }
19}; // namespace sc_ast_matchers
20
21using namespace sc_ast_matchers;
22
23class TemplateParametersMatcher : public MatchFinder::MatchCallback {
24 private:
25 std::vector<const FieldDecl *> found_fields_args;
26 std::vector<const FieldDecl *> found_fields_parms;
27
28 public:
29 void registerMatchers(MatchFinder &finder) {
30 // Overview of the matcher
31 // Terminology: template parameter refers to the template typename name, and
32 // template arguments refers to the substituted type. For example, template
33 // <typename T> X{}; X<int> x; has the parameter as T and the argument as
34 // int.
35 //
36 // 1. Start matching within a ClassTemplateDecl. Note that the match() call
37 // has to be updated to ensure that the appropriate ClassTemplateDecl is
38 // provided.
39 // 2. The isExpansionInMainFile() makes the matcher focus on the provided
40 // file (input), and not the underlying C++ files.
41 //
42 // 3. We check if the ClassTemplateDecl has a CXXRecordDecl within it (note
43 // that it will have a CXXRecordDecl and a ClassTemplateSpecializationDecl,
44 // but we want the former to extract the template parameters).
45 // 4. For every fieldDecl that is a descendant, it is going to check if the
46 // type for the FieldDecl's desugared type is a TemplateSpecialization or a
47 // TemplateTypeParm. This should cover typedefs as well. An alternative way
48 // would be to just match with Type, and then in the callback one could cast
49 // it to respective types that one cares about.
50 //
51 /* clang-format off */
52
53 auto match_template_special_decl =
54 classTemplateSpecializationDecl(
55 cxxRecordDecl(forEachDescendant(fieldDecl(
56 ).bind("fd_arg")))
57 ).bind("special_template_decl");
58//
59 auto match_template_decl =
60 classTemplateDecl(
61 has(cxxRecordDecl(forEachDescendant(
62 fieldDecl(
63 // anyOf(
64 // hasType(hasUnqualifiedDesugaredType(recordType().bind("record_type")))
65 // , hasType(hasUnqualifiedDesugaredType(isDependentNameType()))
66 // , hasType(hasUnqualifiedDesugaredType(typedefType().bind("typedef_type")))
67 // , hasType(hasUnqualifiedDesugaredType(templateSpecializationType().bind("specialization_type")))
68 // , hasType(hasUnqualifiedDesugaredType(templateTypeParmType().bind("parm_type")))
69 // , hasType(hasUnqualifiedDesugaredType(builtinType().bind( "builtin_type")))
70 // ) // anyOf
71 ).bind("fd_parm"))
72 )
73 )
74 ).bind("template_decl");
75 /* clang-format on */
76
77 finder.addMatcher(match_template_decl, this);
78 finder.addMatcher(match_template_special_decl, this);
79 }
80
81 virtual void run(const MatchFinder::MatchResult &result) {
82 // auto decl{result.Nodes.getNodeAs<Decl>("decl")};
83 // auto template_decl{
84 // result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("template_decl")};
85
86 auto fd_arg{result.Nodes.getNodeAs<FieldDecl>("fd_arg")};
87 auto fd_parm{result.Nodes.getNodeAs<FieldDecl>("fd_parm")};
88
89 auto record_type{result.Nodes.getNodeAs<RecordType>("record_type")};
90 auto parm_type{result.Nodes.getNodeAs<TemplateTypeParmType>("parm_type")};
91 auto template_special{result.Nodes.getNodeAs<TemplateSpecializationType>(
92 "specialization_type")};
93 LLVM_DEBUG(llvm::dbgs()
94 << "=============== TEST Template Parm Matcher ====== \n");
95
96 if (fd_arg) {
97 LLVM_DEBUG(llvm::dbgs() << "Found a Arg FieldDecl\n");
98 fd_arg->dump(llvm::errs());
99 fd_arg->getType().getTypePtr()->dump();
100 found_fields_args.push_back(fd_arg);
101 }
102
103 if (fd_parm) {
104 LLVM_DEBUG(llvm::dbgs() << "Found a Parm FieldDecl\n");
105 fd_parm->dump(llvm::errs());
106 fd_parm->getType().getTypePtr()->dump();
107 found_fields_parms.push_back(fd_parm);
108 }
109
110 /*
111 if (fd) {
112 if (auto cxx = fd->getType().getTypePtr()->getAsCXXRecordDecl()) {
113 if (auto template_decl =
114 dyn_cast<ClassTemplateSpecializationDecl>(cxx)) {
115 (llvm::dbgs() << "#### TemplateSpecializationType\n");
116 template_decl->dump();
117
118 (llvm::dbgs() << "##### Try to find the template types\n");
119 FindTemplateTypes ftt{};
120 ftt.Enumerate(template_decl);
121 ftt.printTemplateArguments(llvm::outs());
122 (llvm::dbgs() << "##### END\n");
123
124 const TemplateArgumentList &arg_list{
125 template_decl->getTemplateArgs()};
126
127 const TemplateArgument &targ{arg_list.get(0)};
128 targ.getAsType().dump();
129
130 switch (targ.getKind()) {
131 case TemplateArgument::ArgKind::Integral: {
132 auto q{targ.getAsIntegral()};
133 (llvm::dbgs() << "@@ Integral: " << q << "\n");
134 }; break;
135 case TemplateArgument::ArgKind::Type: {
136 auto q{targ.getAsType()};
137 auto name{q.getAsString()};
138 (llvm::dbgs() << "@@ arg: " << name << "\n");
139 }; break;
140 case TemplateArgument::ArgKind::Expression: {
141 Expr *expr{targ.getAsExpr()};
142 DeclRefExpr *dexpr{dyn_cast<DeclRefExpr>(expr)};
143 if (dexpr) {
144 (llvm::dbgs() << "Template parameter: "
145 << dexpr->getNameInfo().getAsString() << "\n");
146 }
147 }
148 default: {
149 }
150 };
151 }
152
153 // Since this is a RecordType, we can reuse our template type parsing.
154 // if (record_type && fd) {
155 // (llvm::dbgs() << "#### RecordType\n");
156 // record_type->dump();
157 // FindTemplateTypes ftt{};
158 // ftt.Enumerate(record_type);
159 // ftt.printTemplateArguments(llvm::errs());
160 // }
161 (llvm::dbgs() << "\n");
162 }
163 }
164 */
165 }
166
167 void dump() {}
168 void getFields(std::vector<const FieldDecl *> &flds) { flds = found_fields_parms; }
169 void getArgFields(std::vector<const FieldDecl *> &flds) {
170 flds = found_fields_args;
171 }
172 void getParmFields(std::vector<const FieldDecl *> &flds) {
173 flds = found_fields_parms;
174 }
175};
176
177#endif
std::vector< const FieldDecl * > found_fields_parms
virtual void run(const MatchFinder::MatchResult &result)
void getFields(std::vector< const FieldDecl * > &flds)
std::vector< const FieldDecl * > found_fields_args
void getParmFields(std::vector< const FieldDecl * > &flds)
void registerMatchers(MatchFinder &finder)
void getArgFields(std::vector< const FieldDecl * > &flds)
AST_MATCHER(Type, isDependentNameType)