source: src/Validate/ImplementEnumFunc.cpp@ dbff8ec

Last change on this file since dbff8ec was bb336a6, checked in by JiadaL <j82liang@…>, 16 months ago

Fixed the problem when enum use another enumerator as initializer

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