34
34
35
35
namespace cxx {
36
36
37
+ namespace {
38
+ struct GetTemplateDeclaration {
39
+ auto operator ()(ClassSymbol* symbol) -> TemplateDeclarationAST* {
40
+ return symbol->templateDeclaration ();
41
+ }
42
+
43
+ auto operator ()(VariableSymbol* symbol) -> TemplateDeclarationAST* {
44
+ return symbol->templateDeclaration ();
45
+ }
46
+
47
+ auto operator ()(TypeAliasSymbol* symbol) -> TemplateDeclarationAST* {
48
+ return symbol->templateDeclaration ();
49
+ }
50
+
51
+ auto operator ()(Symbol*) -> TemplateDeclarationAST* { return nullptr ; }
52
+ };
53
+
54
+ struct GetDeclaration {
55
+ auto operator ()(ClassSymbol* symbol) -> AST* { return symbol->declaration (); }
56
+
57
+ auto operator ()(VariableSymbol* symbol) -> AST* {
58
+ return symbol->templateDeclaration ()->declaration ;
59
+ }
60
+
61
+ auto operator ()(TypeAliasSymbol* symbol) -> AST* {
62
+ return symbol->templateDeclaration ()->declaration ;
63
+ }
64
+
65
+ auto operator ()(Symbol*) -> AST* { return nullptr ; }
66
+ };
67
+
68
+ struct GetSpecialization {
69
+ const std::vector<TemplateArgument>& templateArguments;
70
+
71
+ auto operator ()(ClassSymbol* symbol) -> Symbol* {
72
+ return symbol->findSpecialization (templateArguments);
73
+ }
74
+
75
+ auto operator ()(VariableSymbol* symbol) -> Symbol* {
76
+ return symbol->findSpecialization (templateArguments);
77
+ }
78
+
79
+ auto operator ()(TypeAliasSymbol* symbol) -> Symbol* {
80
+ return symbol->findSpecialization (templateArguments);
81
+ }
82
+
83
+ auto operator ()(Symbol*) -> Symbol* { return nullptr ; }
84
+ };
85
+
86
+ struct Instantiate {
87
+ ASTRewriter& rewriter;
88
+
89
+ auto operator ()(ClassSymbol* symbol) -> Symbol* {
90
+ auto classSpecifier = ast_cast<ClassSpecifierAST>(symbol->declaration ());
91
+ if (!classSpecifier) return nullptr ;
92
+
93
+ auto instance =
94
+ ast_cast<ClassSpecifierAST>(rewriter.specifier (classSpecifier));
95
+
96
+ if (!instance) return nullptr ;
97
+
98
+ return instance->symbol ;
99
+ }
100
+
101
+ auto operator ()(VariableSymbol* symbol) -> Symbol* {
102
+ auto declaration = symbol->templateDeclaration ()->declaration ;
103
+ auto instance = ast_cast<SimpleDeclarationAST>(
104
+ rewriter.declaration (ast_cast<SimpleDeclarationAST>(declaration)));
105
+
106
+ if (!instance) return nullptr ;
107
+
108
+ auto instantiatedSymbol = instance->initDeclaratorList ->value ->symbol ;
109
+ auto instantiatedVariable = symbol_cast<VariableSymbol>(instantiatedSymbol);
110
+
111
+ return instantiatedVariable;
112
+ }
113
+
114
+ auto operator ()(TypeAliasSymbol* symbol) -> Symbol* {
115
+ auto declaration = symbol->templateDeclaration ()->declaration ;
116
+
117
+ auto instance = ast_cast<AliasDeclarationAST>(
118
+ rewriter.declaration (ast_cast<AliasDeclarationAST>(declaration)));
119
+
120
+ if (!instance) return nullptr ;
121
+
122
+ return instance->symbol ;
123
+ }
124
+
125
+ auto operator ()(Symbol*) -> Symbol* { return nullptr ; }
126
+ };
127
+ } // namespace
128
+
37
129
ASTRewriter::ASTRewriter (TranslationUnit* unit, ScopeSymbol* scope,
38
130
const std::vector<TemplateArgument>& templateArguments)
39
131
: unit_(unit), templateArguments_(templateArguments), binder_(unit_) {
@@ -91,69 +183,18 @@ auto ASTRewriter::getParameterPack(ExpressionAST* ast) -> ParameterPackSymbol* {
91
183
return nullptr ;
92
184
}
93
185
94
- auto ASTRewriter::instantiateClassTemplate (
95
- TranslationUnit* unit, List<TemplateArgumentAST*>* templateArgumentList,
96
- ClassSymbol* classSymbol) -> ClassSymbol* {
97
- auto templateDecl = classSymbol->templateDeclaration ();
98
-
99
- if (!classSymbol->declaration ()) return nullptr ;
100
-
101
- auto templateArguments =
102
- make_substitution (unit, templateDecl, templateArgumentList);
103
-
104
- auto is_primary_template = [&]() -> bool {
105
- int expected = 0 ;
106
- for (const auto & arg : templateArguments) {
107
- if (!std::holds_alternative<Symbol*>(arg)) return false ;
108
-
109
- auto ty = type_cast<TypeParameterType>(std::get<Symbol*>(arg)->type ());
110
- if (!ty) return false ;
111
-
112
- if (ty->index () != expected) return false ;
113
- ++expected;
114
- }
115
- return true ;
116
- };
117
-
118
- if (is_primary_template ()) {
119
- // if this is a primary template, we can just return the class symbol
120
- return classSymbol;
121
- }
122
-
123
- auto subst = classSymbol->findSpecialization (templateArguments);
124
- if (subst) {
125
- return subst;
126
- }
127
-
128
- auto classSpecifier = ast_cast<ClassSpecifierAST>(classSymbol->declaration ());
129
- if (!classSpecifier) return nullptr ;
130
-
131
- auto parentScope = classSymbol->enclosingNonTemplateParametersScope ();
132
-
133
- auto rewriter = ASTRewriter{unit, parentScope, templateArguments};
134
- rewriter.depth_ = templateDecl->depth ;
135
-
136
- rewriter.binder ().setInstantiatingSymbol (classSymbol);
137
-
138
- auto instance =
139
- ast_cast<ClassSpecifierAST>(rewriter.specifier (classSpecifier));
140
-
141
- if (!instance) return nullptr ;
142
-
143
- auto classInstance = instance->symbol ;
144
-
145
- return classInstance;
146
- }
147
-
148
- auto ASTRewriter::instantiateTypeAliasTemplate (
149
- TranslationUnit* unit, List<TemplateArgumentAST*>* templateArgumentList,
150
- TypeAliasSymbol* typeAliasSymbol) -> TypeAliasSymbol* {
151
- auto templateDecl = typeAliasSymbol->templateDeclaration ();
186
+ auto ASTRewriter::instantiate (TranslationUnit* unit,
187
+ List<TemplateArgumentAST*>* templateArgumentList,
188
+ Symbol* symbol) -> Symbol* {
189
+ auto classSymbol = symbol_cast<ClassSymbol>(symbol);
190
+ auto variableSymbol = symbol_cast<VariableSymbol>(symbol);
191
+ auto typeAliasSymbol = symbol_cast<TypeAliasSymbol>(symbol);
152
192
153
- auto aliasDeclaration =
154
- ast_cast<AliasDeclarationAST>( templateDecl-> declaration ) ;
193
+ auto templateDecl = visit (GetTemplateDeclaration{}, symbol);
194
+ if (! templateDecl) return nullptr ;
155
195
156
- if (!aliasDeclaration) return nullptr ;
196
+ auto declaration = visit (GetDeclaration{}, symbol);
197
+ if (!declaration) return nullptr ;
157
198
158
199
auto templateArguments =
159
200
make_substitution (unit, templateDecl, templateArgumentList);
@@ -174,93 +215,21 @@ auto ASTRewriter::instantiateTypeAliasTemplate(
174
215
175
216
if (is_primary_template ()) {
176
217
// if this is a primary template, we can just return the class symbol
177
- return typeAliasSymbol ;
218
+ return symbol ;
178
219
}
179
220
180
- #if false
181
- auto subst = typeAliasSymbol->findSpecialization (templateArguments);
182
- if (subst) {
183
- return subst;
184
- }
185
- #endif
186
-
187
- auto parentScope = typeAliasSymbol->parent ();
188
- while (parentScope->isTemplateParameters ()) {
189
- parentScope = parentScope->parent ();
190
- }
191
-
192
- auto rewriter = ASTRewriter{unit, parentScope, templateArguments};
193
-
194
- rewriter.binder ().setInstantiatingSymbol (typeAliasSymbol);
195
-
196
- auto instance =
197
- ast_cast<AliasDeclarationAST>(rewriter.declaration (aliasDeclaration));
198
-
199
- if (!instance) return nullptr ;
200
-
201
- return instance->symbol ;
202
- }
203
-
204
- auto ASTRewriter::instantiateVariableTemplate (
205
- TranslationUnit* unit, List<TemplateArgumentAST*>* templateArgumentList,
206
- VariableSymbol* variableSymbol) -> VariableSymbol* {
207
- auto templateDecl = variableSymbol->templateDeclaration ();
208
-
209
- if (!templateDecl) {
210
- unit->error (variableSymbol->location (), " not a template" );
211
- return nullptr ;
212
- }
221
+ auto specialization = visit (GetSpecialization{templateArguments}, symbol);
213
222
214
- auto variableDeclaration =
215
- ast_cast<SimpleDeclarationAST>(templateDecl->declaration );
223
+ if (specialization) return specialization;
216
224
217
- if (!variableDeclaration) return nullptr ;
218
-
219
- auto templateArguments =
220
- make_substitution (unit, templateDecl, templateArgumentList);
221
-
222
- auto is_primary_template = [&]() -> bool {
223
- int expected = 0 ;
224
- for (const auto & arg : templateArguments) {
225
- if (!std::holds_alternative<Symbol*>(arg)) return false ;
226
-
227
- auto ty = type_cast<TypeParameterType>(std::get<Symbol*>(arg)->type ());
228
- if (!ty) return false ;
229
-
230
- if (ty->index () != expected) return false ;
231
- ++expected;
232
- }
233
- return true ;
234
- };
235
-
236
- if (is_primary_template ()) {
237
- // if this is a primary template, we can just return the class symbol
238
- return variableSymbol;
239
- }
240
-
241
- auto subst = variableSymbol->findSpecialization (templateArguments);
242
- if (subst) {
243
- return subst;
244
- }
245
-
246
- auto parentScope = variableSymbol->parent ();
247
- while (parentScope->isTemplateParameters ()) {
248
- parentScope = parentScope->parent ();
249
- }
225
+ auto parentScope = symbol->enclosingNonTemplateParametersScope ();
250
226
251
227
auto rewriter = ASTRewriter{unit, parentScope, templateArguments};
228
+ rewriter.depth_ = templateDecl->depth ;
252
229
253
- rewriter.binder ().setInstantiatingSymbol (variableSymbol);
254
-
255
- auto instance =
256
- ast_cast<SimpleDeclarationAST>(rewriter.declaration (variableDeclaration));
257
-
258
- if (!instance) return nullptr ;
259
-
260
- auto instantiatedSymbol = instance->initDeclaratorList ->value ->symbol ;
261
- auto instantiatedVariable = symbol_cast<VariableSymbol>(instantiatedSymbol);
230
+ rewriter.binder ().setInstantiatingSymbol (symbol);
262
231
263
- return instantiatedVariable ;
232
+ return visit (Instantiate{rewriter}, symbol) ;
264
233
}
265
234
266
235
auto ASTRewriter::make_substitution (
0 commit comments