source: src/Validate/ImplementEnumFunc.cpp@ 332e93a

Last change on this file since 332e93a was 90e683b, checked in by Andrew Beach <ajbeach@…>, 8 months ago

I set out to do a enum rework. It ended up being much the same and I unwound the core rework. But I hope the new names are a bit clearer and other minor fixes are helpful, so I am keeping those.

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