source: src/Validate/ImplementEnumFunc.cpp@ d6c5faa2

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