source: src/Validate/ImplementEnumFunc.cpp@ d02d223

Last change on this file since d02d223 was 0c327ce, checked in by JiadaL <j82liang@…>, 15 months ago
  1. Add bound check to Serial function: now compiler generates the unchecked functions in ImplementEnumFunc, and enum.hfa implements the bound check on top. Todo: Wrapped the checked version into a trait; 2. countof is now works on any type that implement Countof(). Because Countof() is implemented in enum.hfa for all CfaEnum, we can call countof on { T | CfaEnum(T) }
  • Property mode set to 100644
File size: 17.2 KB
RevLine 
[af746cc]1#include "AST/Create.hpp"
2#include "AST/Pass.hpp"
3#include "AST/TranslationUnit.hpp"
[c92bdcc]4#include "CodeGen/OperatorTable.hpp" // for isCtorDtor, isCtorDtorAssign
5#include "InitTweak/InitTweak.hpp" // for isAssignment, isCopyConstructor
[af746cc]6namespace Validate {
7
8namespace {
9class EnumAttrFuncGenerator {
[fc1a3e2]10 const ast::EnumDecl* decl;
11 unsigned int functionNesting;
[85855b0]12 const ast::StructDecl* quasi_void_decl;
[fc1a3e2]13 ast::Linkage::Spec proto_linkage;
14
15public:
16 std::list<ast::ptr<ast::Decl>> forwards;
17 std::list<ast::ptr<ast::Decl>> definitions;
18
19 void generateAndAppendFunctions(std::list<ast::ptr<ast::Decl>>&);
20
21 EnumAttrFuncGenerator(
22 const ast::EnumDecl* decl,
[822332e]23 const ast::EnumInstType*,
[fc1a3e2]24 unsigned int functionNesting )
25 : decl(decl),
26 functionNesting{functionNesting},
[236f133]27 // quasi_void_decl(new ast::StructDecl(decl->location,
28 // "quasi_void", ast::AggregateDecl::Struct,
29 // {}, ast::Linkage::AutoGen)),
[fc1a3e2]30 proto_linkage{ast::Linkage::Cforall} {}
31
32private:
33 const CodeLocation& getLocation() const { return decl->location; }
34
35 ast::FunctionDecl* genProto(
36 std::string&& name, std::vector<ast::ptr<ast::DeclWithType>>&& params,
37 std::vector<ast::ptr<ast::DeclWithType>>&& returns) const;
38
39 void produceDecl(const ast::FunctionDecl* decl);
40 void produceForwardDecl(const ast::FunctionDecl* decl);
41
42 const ast::Decl* getDecl() const { return decl; }
43
[c333ed2]44 // Implement Bounded trait
45 void genBoundedFunctions();
46 ast::FunctionDecl* genBoundedProto(const char *) const;
47 void genBoundedBody(ast::FunctionDecl* func) const;
[eb7586e]48
[c333ed2]49 // Implement Serial trait
50 void genSerialTraitFuncs();
51 ast::FunctionDecl* genFromIntProto() const;
52 ast::FunctionDecl* genFromInstanceProto() const;
53 ast::FunctionDecl* genInstToInstFuncProto(const char* func) const;
[822332e]54 void genFromIntBody(ast::FunctionDecl *) const;
[c333ed2]55 void genFromInstanceBody(ast::FunctionDecl *) const;
56 void genSuccPredBody(ast::FunctionDecl *, const char *) const;
[eb7586e]57
[85855b0]58 void genTypeNameFunc();
59
[c333ed2]60 // Implement TypedEnum trait
61 void genTypedEnumFuncs();
62 void genTypedEnumFunction(const ast::EnumAttribute attr);
[fc1a3e2]63 ast::FunctionDecl* genPosnProto() const;
64 ast::FunctionDecl* genLabelProto() const;
65 ast::FunctionDecl* genValueProto() const;
[85855b0]66 ast::FunctionDecl* genQuasiValueProto() const;
67 ast::FunctionDecl* genTypeNameProto() const;
68
[c333ed2]69 void genValueOrLabelBody(
70 ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const;
71 void genPosnBody(ast::FunctionDecl* func) const;
[85855b0]72 void genQuasiValueBody(ast::FunctionDecl* func) const;
73 void genTypeNameBody(ast::FunctionDecl* func) const;
[fc1a3e2]74
75 // ----------------------------------------------------
76
77 const ast::Init* getAutoInit(const ast::Init* prev) const;
78
79 std::vector<ast::ptr<ast::Init>> genLabelInit() const;
80
81 std::vector<ast::ptr<ast::Init>> genValueInit() const;
82 ast::ObjectDecl* genAttrArrayProto(
83 const ast::EnumAttribute attr, const CodeLocation& location,
84 std::vector<ast::ptr<ast::Init>>& inits) const;
[af746cc]85};
86
87std::vector<ast::ptr<ast::Init>> EnumAttrFuncGenerator::genLabelInit() const {
[fc1a3e2]88 std::vector<ast::ptr<ast::Init>> inits;
89 for (size_t i = 0; i < decl->members.size(); i++) {
90 ast::ptr<ast::Decl> mem = decl->members.at(i);
91 auto memAsObjectDecl = mem.as<ast::ObjectDecl>();
92 assert(memAsObjectDecl);
93 inits.emplace_back(new ast::SingleInit(
94 mem->location,
95 ast::ConstantExpr::from_string(mem->location, mem->name)));
96 }
97 return inits;
[af746cc]98}
99
100std::vector<ast::ptr<ast::Init>> EnumAttrFuncGenerator::genValueInit() const {
[fc1a3e2]101 std::vector<ast::ptr<ast::Init>> inits;
102 for (size_t i = 0; i < decl->members.size(); i++) {
103 ast::ptr<ast::Decl> mem = decl->members.at(i);
104 auto memAsObjectDecl = mem.as<ast::ObjectDecl>();
105 assert(memAsObjectDecl);
[bb336a6]106 if (auto& init = memAsObjectDecl->init) {
[9d5eacb]107 if ( auto singleInit = init.as<ast::SingleInit>() ) {
108 if ( auto nameExpr = singleInit->value.as<ast::NameExpr>() ) {
109 auto name = nameExpr->name;
110 if (auto it = std::find_if(decl->members.begin(), decl->members.end(),
111 [name](ast::ptr<ast::Decl> mem_decl) {
112 return (mem_decl->name == name);
113 }); it != std::end(decl->members)
114 ) {
115 auto index = std::distance( decl->members.begin(), it );
116 auto targetInit = inits.at(index).strict_as<ast::SingleInit>();
117 auto targetExpr = targetInit->value;
118 inits.push_back( new ast::SingleInit( targetExpr->location, targetExpr ) );
119 continue;
120 }
[bb336a6]121 }
122 }
[fc1a3e2]123 inits.emplace_back(memAsObjectDecl->init);
124 } else {
125 const CodeLocation& location = mem->location;
126 if (i == 0) {
127 inits.emplace_back(new ast::SingleInit(
128 location, ast::ConstantExpr::from_int(mem->location, 0)));
129 } else {
130 inits.emplace_back(getAutoInit(inits.at(i - 1)));
131 }
132 }
133 }
134 return inits;
[af746cc]135}
[85855b0]136
[af746cc]137const ast::Init* EnumAttrFuncGenerator::getAutoInit(
[fc1a3e2]138 const ast::Init* prev) const {
139 if (prev == nullptr) {
140 return new ast::SingleInit(
141 getLocation(), ast::ConstantExpr::from_int(getLocation(), 0));
142 }
143 auto prevInit = dynamic_cast<const ast::SingleInit*>(prev);
144 assert(prevInit);
145 auto prevInitExpr = prevInit->value;
146 if (auto constInit = prevInitExpr.as<ast::ConstantExpr>()) {
147 // Assume no string literal for now
148 return new ast::SingleInit(
149 getLocation(), ast::ConstantExpr::from_int(
150 getLocation(), constInit->intValue() + 1));
151 } else {
152 auto untypedThisInit = new ast::UntypedExpr(
153 getLocation(), new ast::NameExpr(getLocation(), "?++"),
154 {prevInitExpr});
155 return new ast::SingleInit(getLocation(), untypedThisInit);
156 }
[af746cc]157}
158
159ast::FunctionDecl* EnumAttrFuncGenerator::genProto(
[fc1a3e2]160 std::string&& name, std::vector<ast::ptr<ast::DeclWithType>>&& params,
161 std::vector<ast::ptr<ast::DeclWithType>>&& returns) const {
162 ast::FunctionDecl* decl = new ast::FunctionDecl(
163 // Auto-generated routines use the type declaration's location.
164 getLocation(), std::move(name), {}, {}, std::move(params),
165 std::move(returns),
166 // Only a prototype, no body.
167 nullptr,
168 // Use static storage if we are at the top level.
169 (0 < functionNesting) ? ast::Storage::Classes() : ast::Storage::Static,
170 proto_linkage, std::vector<ast::ptr<ast::Attribute>>(),
171 // Auto-generated routines are inline to avoid conflicts.
172 ast::Function::Specs(ast::Function::Inline));
173 decl->fixUniqueId();
174 return decl;
[af746cc]175}
176
177void EnumAttrFuncGenerator::produceDecl(const ast::FunctionDecl* decl) {
[fc1a3e2]178 assert(nullptr != decl->stmts);
[af746cc]179
[fc1a3e2]180 definitions.push_back(decl);
[af746cc]181}
182
183void EnumAttrFuncGenerator::produceForwardDecl(const ast::FunctionDecl* decl) {
[fc1a3e2]184 if (0 != functionNesting) return;
185 ast::FunctionDecl* fwd =
186 (decl->stmts) ? ast::asForward(decl) : ast::deepCopy(decl);
187 fwd->fixUniqueId();
188 forwards.push_back(fwd);
[af746cc]189}
190
191ast::FunctionDecl* EnumAttrFuncGenerator::genPosnProto() const {
192 return genProto(
[5eb3f65]193 "posn",
[af746cc]194 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
195 {new ast::ObjectDecl(getLocation(), "_ret",
[cf191ac]196 new ast::BasicType(ast::BasicKind::UnsignedInt))});
[af746cc]197}
198
199ast::FunctionDecl* EnumAttrFuncGenerator::genLabelProto() const {
[fc1a3e2]200 return genProto(
[5eb3f65]201 "label",
[fc1a3e2]202 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
203 {new ast::ObjectDecl(
204 getLocation(), "_ret",
[c2cf2d0]205 new ast::PointerType(
206 new ast::BasicType(ast::BasicKind::Char, ast::CV::Const)))});
[af746cc]207}
208
209ast::FunctionDecl* EnumAttrFuncGenerator::genValueProto() const {
[236f133]210 assert (decl->isTyped());
[fc1a3e2]211 return genProto(
[5eb3f65]212 "value",
[fc1a3e2]213 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
214 {new ast::ObjectDecl(getLocation(), "_ret",
[236f133]215 ast::deepCopy(decl->base))});
216 // else
217 // return genQuasiValueProto();
[af746cc]218}
219
[236f133]220// ast::FunctionDecl* EnumAttrFuncGenerator::genQuasiValueProto() const {
221// return genProto(
222// "value",
223// {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
224// {new ast::ObjectDecl(getLocation(), "_ret",
225// new ast::StructInstType(quasi_void_decl))});
226// }
227
[eb7586e]228ast::FunctionDecl* EnumAttrFuncGenerator::genFromIntProto() const {
229 return genProto(
[0c327ce]230 "fromInt_unsafe",
[eb7586e]231 {new ast::ObjectDecl(getLocation(), "_i", new ast::BasicType(ast::BasicKind::UnsignedInt))},
232 {new ast::ObjectDecl(getLocation(), "_ret", new ast::EnumInstType(decl))}
233 );
234}
235
236ast::FunctionDecl* EnumAttrFuncGenerator::genFromInstanceProto() const {
237 return genProto(
238 "fromInstance",
239 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
240 {new ast::ObjectDecl(getLocation(), "_ret", new ast::BasicType(ast::BasicKind::UnsignedInt))}
241 );
242}
243
[85855b0]244ast::FunctionDecl* EnumAttrFuncGenerator::genTypeNameProto() const {
245 return genProto(
246 "type_name",
247 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
248 {new ast::ObjectDecl(
249 getLocation(), "_ret",
[c2cf2d0]250 new ast::PointerType(
251 new ast::BasicType(ast::BasicKind::Char, ast::CV::Const)))});
[85855b0]252}
253
[eb7586e]254void EnumAttrFuncGenerator::genFromIntBody(ast::FunctionDecl* func) const {
255 auto params = func->params;
256 assert( params.size() == 1 );
257 auto param = params.front();
258 auto castExpr = new ast::CastExpr(
259 func->location,
260 new ast::VariableExpr(func->location, param),
261 new ast::EnumInstType(decl),
262 ast::GeneratedFlag::ExplicitCast
263 );
264 func->stmts = new ast::CompoundStmt(
265 func->location, {new ast::ReturnStmt(func->location, castExpr)}
266 );
267}
268
269void EnumAttrFuncGenerator::genFromInstanceBody(ast::FunctionDecl* func) const {
270 auto params = func->params;
271 assert( params.size() == 1 );
272 auto param = params.front();
273 ast::UntypedExpr* untyped = ast::UntypedExpr::createCall(
[5eb3f65]274 func->location, "posn", { new ast::VariableExpr(func->location, param) });
[eb7586e]275 func->stmts = new ast::CompoundStmt(
276 func->location, {new ast::ReturnStmt(func->location, untyped)}
277 );
278}
279
[c333ed2]280void EnumAttrFuncGenerator::genSuccPredBody(ast::FunctionDecl * func, const char* opt) const {
281 auto params = func->params;
282 assert( params.size() == 1 );
283 auto param = params.front();
284 auto enumToInt = new ast::CastExpr(
285 func->location,
286 new ast::VariableExpr(func->location, param),
287 new ast::BasicType(ast::BasicKind::UnsignedInt),
288 ast::GeneratedFlag::ExplicitCast
289 );
290 ast::UntypedExpr* addOneExpr = ast::UntypedExpr::createCall( func->location,
291 opt,
292 {enumToInt,
293 ast::ConstantExpr::from_int(func->location, 1)}
294 );
295 auto intToEnum = new ast::CastExpr(
296 func->location,
297 addOneExpr,
298 new ast::EnumInstType( decl ),
299 ast::GeneratedFlag::ExplicitCast
300 );
301 func->stmts = new ast::CompoundStmt(
302 func->location, {
303 new ast::ReturnStmt(
304 func->location,
305 intToEnum
306 )
307 }
308 );
[eb7586e]309}
310
[c333ed2]311void EnumAttrFuncGenerator::genSerialTraitFuncs() {
312 ast::FunctionDecl * protos[4] = {
313 genFromIntProto(),
314 genFromInstanceProto(),
[0c327ce]315 genInstToInstFuncProto("succ_unsafe"),
316 genInstToInstFuncProto("pred_unsafe")
[c333ed2]317 };
318 for (auto& proto: protos) produceForwardDecl(proto);
319 genFromIntBody(protos[0]);
320 genFromInstanceBody(protos[1]);
321 genSuccPredBody(protos[2], "?+?");
322 genSuccPredBody(protos[3], "?-?");
[6d9aa79]323 for (auto& proto: protos) produceDecl(proto);
[c333ed2]324}
325
326ast::FunctionDecl* EnumAttrFuncGenerator::genInstToInstFuncProto(const char * func) const {
[fc1a3e2]327 return genProto(
[c333ed2]328 func,
[fc1a3e2]329 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
330 {new ast::ObjectDecl(getLocation(), "_ret",
331 new ast::EnumInstType(decl))});
[af746cc]332}
333
[c333ed2]334ast::FunctionDecl* EnumAttrFuncGenerator::genBoundedProto(const char * func) const {
335 return genProto(func, {}, {
[eb7586e]336 new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))
337 });
338}
339
[c333ed2]340void EnumAttrFuncGenerator::genBoundedBody(ast::FunctionDecl* func) const {
[eb7586e]341 const CodeLocation & loc = func->location;
[c333ed2]342 auto mem = func->name=="lowerBound"? decl->members.front() : decl->members.back();
[85855b0]343 // auto expr = new ast::NameExpr( loc, mem->name );
344 auto expr = new ast::QualifiedNameExpr( loc, decl->name, mem->name );
[eb7586e]345 func->stmts = new ast::CompoundStmt( loc, {new ast::ReturnStmt(loc, expr)});
346}
347
348void EnumAttrFuncGenerator::genBoundedFunctions() {
[c333ed2]349 ast::FunctionDecl * boundedProtos[2] = {genBoundedProto("upperBound"), genBoundedProto("lowerBound")};
350 for (auto & protos: boundedProtos) {
351 produceForwardDecl(protos);
352 genBoundedBody(protos);
353 produceDecl(protos);
354 }
[eb7586e]355}
356
[af746cc]357ast::ObjectDecl* EnumAttrFuncGenerator::genAttrArrayProto(
[fc1a3e2]358 const ast::EnumAttribute attr, const CodeLocation& location,
359 std::vector<ast::ptr<ast::Init>>& inits) const {
360 ast::ArrayType* arrT = new ast::ArrayType(
361 attr == ast::EnumAttribute::Value
362 ? decl->base
[c2cf2d0]363 : new ast::PointerType(
364 new ast::BasicType(ast::BasicKind::Char, ast::CV::Const)),
[fc1a3e2]365 ast::ConstantExpr::from_int(decl->location, decl->members.size()),
366 ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim);
367
368 ast::ObjectDecl* objDecl =
369 new ast::ObjectDecl(
370 decl->location, decl->getUnmangeldArrayName( attr ),
371 arrT, new ast::ListInit( location, std::move( inits ) ),
372 ast::Storage::Static, ast::Linkage::AutoGen );
373
374 return objDecl;
[af746cc]375}
376
377void EnumAttrFuncGenerator::genValueOrLabelBody(
[fc1a3e2]378 ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const {
379 ast::UntypedExpr* untyped = ast::UntypedExpr::createCall(
380 func->location, "?[?]",
381 {new ast::NameExpr(func->location, arrDecl->name),
[eb7586e]382 new ast::CastExpr(
383 func->location,
384 new ast::VariableExpr( func->location, func->params.front() ),
[acb33f15]385 new ast::BasicType( ast::BasicKind::UnsignedInt ),
386 ast::GeneratedFlag::ExplicitCast
387 )});
[fc1a3e2]388 func->stmts = new ast::CompoundStmt(
389 func->location, {new ast::ReturnStmt(func->location, untyped)});
[af746cc]390}
391
[236f133]392// void EnumAttrFuncGenerator::genQuasiValueBody(ast::FunctionDecl* func) const {
393// auto location = func->location;
394// const ast::ObjectDecl * objDecl = new ast::ObjectDecl(
395// location, "_out", new ast::StructInstType( quasi_void_decl ));
396// const ast::DeclStmt * declStmt = new ast::DeclStmt(location, objDecl);
397// const ast::VariableExpr * varExpr = new ast::VariableExpr(location, objDecl);
398// const ast::ReturnStmt * retStmt = new ast::ReturnStmt(location, varExpr);
[85855b0]399
[236f133]400// func->stmts = new ast::CompoundStmt(
401// location, {declStmt, retStmt}
402// );
403// }
[85855b0]404
[af746cc]405void EnumAttrFuncGenerator::genPosnBody(ast::FunctionDecl* func) const {
[fc1a3e2]406 auto castExpr = new ast::CastExpr(
407 func->location,
408 new ast::VariableExpr(func->location, func->params.front()),
[acb33f15]409 new ast::BasicType( ast::BasicKind::UnsignedInt ),
410 ast::GeneratedFlag::ExplicitCast);
[fc1a3e2]411 func->stmts = new ast::CompoundStmt(
412 func->location, {new ast::ReturnStmt(func->location, castExpr)});
[af746cc]413}
414
[85855b0]415void EnumAttrFuncGenerator::genTypeNameBody(ast::FunctionDecl* func) const {
416 const ast::Expr * type_name = ast::ConstantExpr::from_string(func->location, decl->name);
417 func->stmts = new ast::CompoundStmt(
418 func->location, {new ast::ReturnStmt(func->location, type_name)}
419 );
420}
421
[c333ed2]422void EnumAttrFuncGenerator::genTypedEnumFunction(const ast::EnumAttribute attr) {
[85855b0]423 if (attr == ast::EnumAttribute::Value) {
[bb336a6]424 if (decl->isTyped()) {
[85855b0]425 // TypedEnum's backing arrays
426 std::vector<ast::ptr<ast::Init>> inits = genValueInit();
427 ast::ObjectDecl* arrayProto =
428 genAttrArrayProto(attr, getLocation(), inits);
429 forwards.push_back(arrayProto);
430
431 ast::FunctionDecl* funcProto = genValueProto();
432 produceForwardDecl(funcProto);
433 genValueOrLabelBody(funcProto, arrayProto);
434 produceDecl(funcProto);
[236f133]435 }
436 // else {
437 // ast::FunctionDecl* funcProto = genQuasiValueProto();
438 // produceForwardDecl(funcProto);
439 // // genQuasiValueBody(funcProto);
440 // produceDecl(funcProto);
441 // }
[85855b0]442 } else if (attr == ast::EnumAttribute::Label) {
443 std::vector<ast::ptr<ast::Init>> inits = genLabelInit();
[fc1a3e2]444 ast::ObjectDecl* arrayProto =
445 genAttrArrayProto(attr, getLocation(), inits);
446 forwards.push_back(arrayProto);
[85855b0]447 ast::FunctionDecl* funcProto = genLabelProto();
[fc1a3e2]448 produceForwardDecl(funcProto);
449 genValueOrLabelBody(funcProto, arrayProto);
450 produceDecl(funcProto);
451 } else {
452 ast::FunctionDecl* funcProto = genPosnProto();
453 produceForwardDecl(funcProto);
454 genPosnBody(funcProto);
455 produceDecl(funcProto);
456 }
[af746cc]457}
458
[c333ed2]459void EnumAttrFuncGenerator::genTypedEnumFuncs() {
[725f777f]460 genTypedEnumFunction(ast::EnumAttribute::Value);
461 genTypedEnumFunction(ast::EnumAttribute::Label);
462 genTypedEnumFunction(ast::EnumAttribute::Posn);
[af746cc]463}
464
[85855b0]465void EnumAttrFuncGenerator::genTypeNameFunc() {
466 ast::FunctionDecl* funcProto = genTypeNameProto();
467 produceForwardDecl(funcProto);
468 genTypeNameBody(funcProto);
469 produceDecl(funcProto);
470}
471
[af746cc]472void EnumAttrFuncGenerator::generateAndAppendFunctions(
[fc1a3e2]473 std::list<ast::ptr<ast::Decl>>& decls) {
474 // Generate the functions (they go into forwards and definitions).
[725f777f]475 genTypeNameFunc();
[c333ed2]476 genTypedEnumFuncs();
[725f777f]477 genSerialTraitFuncs();
478 genBoundedFunctions();
[fc1a3e2]479 // Now export the lists contents.
480 decls.splice(decls.end(), forwards);
481 decls.splice(decls.end(), definitions);
[af746cc]482}
483
484// ---------------------------------------------------------
485
[fc1a3e2]486struct ImplementEnumFunc final :
487 public ast::WithDeclsToAdd<>, public ast::WithShortCircuiting {
488 void previsit(const ast::EnumDecl* enumDecl);
489 void previsit(const ast::FunctionDecl* functionDecl);
490 void postvisit(const ast::FunctionDecl* functionDecl);
[af746cc]491
[fc1a3e2]492private:
493 // Current level of nested functions.
494 unsigned int functionNesting = 0;
[af746cc]495};
496
497void ImplementEnumFunc::previsit(const ast::EnumDecl* enumDecl) {
[5ccc733]498 if (!enumDecl->body || !enumDecl->isCfa) return;
[fc1a3e2]499 ast::EnumInstType enumInst(enumDecl->name);
500 enumInst.base = enumDecl;
501 EnumAttrFuncGenerator gen(enumDecl, &enumInst, functionNesting);
[725f777f]502 gen.generateAndAppendFunctions(declsToAddAfter);
[af746cc]503}
504
505void ImplementEnumFunc::previsit(const ast::FunctionDecl*) {
[fc1a3e2]506 functionNesting += 1;
[af746cc]507}
508
509void ImplementEnumFunc::postvisit(const ast::FunctionDecl*) {
[fc1a3e2]510 functionNesting -= 1;
[af746cc]511}
512
[fc1a3e2]513} // namespace
[af746cc]514
515void implementEnumFunc(ast::TranslationUnit& translationUnit) {
[fc1a3e2]516 ast::Pass<ImplementEnumFunc>::run(translationUnit);
[af746cc]517}
[fc1a3e2]518
519} // namespace Validate
Note: See TracBrowser for help on using the repository browser.