source: src/Validate/ImplementEnumFunc.cpp @ cc077f4

Last change on this file since cc077f4 was 5f210c0, checked in by JiadaL <j82liang@…>, 5 weeks ago

Change enum pos to signed int to avoid underflow; operator on enum will not have range check (but succ and pred still have range check

  • 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(
150                        getLocation(), new ast::NameExpr(getLocation(), "?++"),
151                        {prevInitExpr});
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 {
[236f133]207        assert (decl->isTyped());
[fc1a3e2]208        return genProto(
[5eb3f65]209                "value",
[fc1a3e2]210                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
211                {new ast::ObjectDecl(getLocation(), "_ret",
[236f133]212                                                        ast::deepCopy(decl->base))});
213        // else
214        //      return genQuasiValueProto();
[af746cc]215}
216
[236f133]217// ast::FunctionDecl* EnumAttrFuncGenerator::genQuasiValueProto() const {
218//      return genProto(
219//              "value",
220//              {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
221//              {new ast::ObjectDecl(getLocation(), "_ret",
222//                                              new ast::StructInstType(quasi_void_decl))});
223// }
224
[eb7586e]225ast::FunctionDecl* EnumAttrFuncGenerator::genFromIntProto() const {
226        return genProto(
[0c327ce]227                "fromInt_unsafe",
[5f210c0]228                {new ast::ObjectDecl(getLocation(), "_i", new ast::BasicType(ast::BasicKind::SignedInt))},
[eb7586e]229                {new ast::ObjectDecl(getLocation(), "_ret", new ast::EnumInstType(decl))}
230        );
231}
232
233ast::FunctionDecl* EnumAttrFuncGenerator::genFromInstanceProto() const {
234        return genProto(
235                "fromInstance",
236                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
[5f210c0]237                {new ast::ObjectDecl(getLocation(), "_ret", new ast::BasicType(ast::BasicKind::SignedInt))}
[eb7586e]238        );
239}
240
[85855b0]241ast::FunctionDecl* EnumAttrFuncGenerator::genTypeNameProto() const {
242        return genProto(
243                "type_name",
244                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
245                {new ast::ObjectDecl(
246                        getLocation(), "_ret",
[c2cf2d0]247                        new ast::PointerType(
248                                new ast::BasicType(ast::BasicKind::Char, ast::CV::Const)))});
[85855b0]249}
250
[eb7586e]251void EnumAttrFuncGenerator::genFromIntBody(ast::FunctionDecl* func) const {
252        auto params = func->params;
253        assert( params.size() == 1 );
254        auto param = params.front();
255        auto castExpr = new ast::CastExpr(
256                func->location,
257                new ast::VariableExpr(func->location, param),
258                new ast::EnumInstType(decl),
259                ast::GeneratedFlag::ExplicitCast
260        );
261        func->stmts = new ast::CompoundStmt(
262                func->location, {new ast::ReturnStmt(func->location, castExpr)}
263        );
264}
265
266void EnumAttrFuncGenerator::genFromInstanceBody(ast::FunctionDecl* func) const {
267        auto params = func->params;
268        assert( params.size() == 1 );
269        auto param = params.front();
270        ast::UntypedExpr* untyped = ast::UntypedExpr::createCall(
[5eb3f65]271                func->location, "posn", { new ast::VariableExpr(func->location, param) });
[eb7586e]272        func->stmts = new ast::CompoundStmt(
273                func->location, {new ast::ReturnStmt(func->location, untyped)}
274        );
275}
276
[c333ed2]277void EnumAttrFuncGenerator::genSuccPredBody(ast::FunctionDecl * func, const char* opt) const {
278        auto params = func->params;
279        assert( params.size() == 1 );
280        auto param = params.front();
281        auto enumToInt = new ast::CastExpr(
282                func->location,
283                new ast::VariableExpr(func->location, param),
[5f210c0]284                new ast::BasicType(ast::BasicKind::SignedInt),
[c333ed2]285                ast::GeneratedFlag::ExplicitCast
286        );
287        ast::UntypedExpr* addOneExpr = ast::UntypedExpr::createCall( func->location,
288                opt,
289                {enumToInt,
290                ast::ConstantExpr::from_int(func->location, 1)}
291        );
292        auto intToEnum = new ast::CastExpr(
293                func->location,
294                addOneExpr,
295                new ast::EnumInstType( decl ),
296                ast::GeneratedFlag::ExplicitCast
297        );
298        func->stmts = new ast::CompoundStmt(
299                func->location, {
300                        new ast::ReturnStmt(
301                                func->location,
302                                intToEnum
303                        )
304                }
305        );
[eb7586e]306}
307
[c333ed2]308void EnumAttrFuncGenerator::genSerialTraitFuncs() {
309        ast::FunctionDecl * protos[4] = {
310                genFromIntProto(),
311                genFromInstanceProto(),
[0c327ce]312                genInstToInstFuncProto("succ_unsafe"),
313                genInstToInstFuncProto("pred_unsafe")
[c333ed2]314        };
315        for (auto& proto: protos) produceForwardDecl(proto);
316        genFromIntBody(protos[0]);
317        genFromInstanceBody(protos[1]);
318        genSuccPredBody(protos[2], "?+?");
319        genSuccPredBody(protos[3], "?-?");
[6d9aa79]320        for (auto& proto: protos) produceDecl(proto);
[c333ed2]321}
322
323ast::FunctionDecl* EnumAttrFuncGenerator::genInstToInstFuncProto(const char * func) const {
[fc1a3e2]324        return genProto(
[c333ed2]325                func,
[fc1a3e2]326                {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
327                {new ast::ObjectDecl(getLocation(), "_ret",
328                                     new ast::EnumInstType(decl))});
[af746cc]329}
330
[c333ed2]331ast::FunctionDecl* EnumAttrFuncGenerator::genBoundedProto(const char * func) const {
332    return genProto(func, {}, {
[eb7586e]333        new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))
334    });
335}
336
[c333ed2]337void EnumAttrFuncGenerator::genBoundedBody(ast::FunctionDecl* func) const {
[eb7586e]338        const CodeLocation & loc = func->location;
[c333ed2]339        auto mem = func->name=="lowerBound"?  decl->members.front() : decl->members.back();
[85855b0]340        // auto expr = new ast::NameExpr( loc, mem->name );
341        auto expr = new ast::QualifiedNameExpr( loc, decl->name, mem->name );
[eb7586e]342        func->stmts = new ast::CompoundStmt( loc, {new ast::ReturnStmt(loc, expr)});
343}
344
345void EnumAttrFuncGenerator::genBoundedFunctions() {
[c333ed2]346        ast::FunctionDecl * boundedProtos[2] = {genBoundedProto("upperBound"), genBoundedProto("lowerBound")};
347        for (auto & protos: boundedProtos) {
348                produceForwardDecl(protos);
349                genBoundedBody(protos);
350                produceDecl(protos);
351        }
[eb7586e]352}
353
[af746cc]354ast::ObjectDecl* EnumAttrFuncGenerator::genAttrArrayProto(
[fc1a3e2]355        const ast::EnumAttribute attr, const CodeLocation& location,
356        std::vector<ast::ptr<ast::Init>>& inits) const {
357        ast::ArrayType* arrT = new ast::ArrayType(
358                attr == ast::EnumAttribute::Value
359                        ? decl->base
[c2cf2d0]360                        : new ast::PointerType(
361                                new ast::BasicType(ast::BasicKind::Char, ast::CV::Const)),
[fc1a3e2]362                ast::ConstantExpr::from_int(decl->location, decl->members.size()),
363                ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim);
364
365        ast::ObjectDecl* objDecl =
366                new ast::ObjectDecl(
367                        decl->location, decl->getUnmangeldArrayName( attr ),
368                        arrT, new ast::ListInit( location, std::move( inits ) ),
369                        ast::Storage::Static, ast::Linkage::AutoGen );
370
371        return objDecl;
[af746cc]372}
373
374void EnumAttrFuncGenerator::genValueOrLabelBody(
[fc1a3e2]375        ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const {
376        ast::UntypedExpr* untyped = ast::UntypedExpr::createCall(
377                func->location, "?[?]",
378                {new ast::NameExpr(func->location, arrDecl->name),
[eb7586e]379                new ast::CastExpr(
380                        func->location,
381                        new ast::VariableExpr( func->location, func->params.front() ),
[5f210c0]382                        new ast::BasicType( ast::BasicKind::SignedInt ),
[acb33f15]383                        ast::GeneratedFlag::ExplicitCast
384                )});
[fc1a3e2]385        func->stmts = new ast::CompoundStmt(
386                func->location, {new ast::ReturnStmt(func->location, untyped)});
[af746cc]387}
388
[236f133]389// void EnumAttrFuncGenerator::genQuasiValueBody(ast::FunctionDecl* func) const {
390//      auto location = func->location;
391//      const ast::ObjectDecl * objDecl = new ast::ObjectDecl(
392//              location, "_out", new ast::StructInstType( quasi_void_decl ));
393//      const ast::DeclStmt * declStmt = new ast::DeclStmt(location, objDecl);
394//      const ast::VariableExpr * varExpr = new ast::VariableExpr(location, objDecl);
395//      const ast::ReturnStmt * retStmt = new ast::ReturnStmt(location, varExpr);
[85855b0]396
[236f133]397//      func->stmts = new ast::CompoundStmt(
398//              location, {declStmt, retStmt}
399//      );
400// }
[85855b0]401
[af746cc]402void EnumAttrFuncGenerator::genPosnBody(ast::FunctionDecl* func) const {
[fc1a3e2]403        auto castExpr = new ast::CastExpr(
404                func->location,
405                new ast::VariableExpr(func->location, func->params.front()),
[5f210c0]406                new ast::BasicType( ast::BasicKind::SignedInt ),
[acb33f15]407                        ast::GeneratedFlag::ExplicitCast);
[fc1a3e2]408        func->stmts = new ast::CompoundStmt(
409                func->location, {new ast::ReturnStmt(func->location, castExpr)});
[af746cc]410}
411
[85855b0]412void EnumAttrFuncGenerator::genTypeNameBody(ast::FunctionDecl* func) const {
413        const ast::Expr * type_name = ast::ConstantExpr::from_string(func->location, decl->name);
414        func->stmts = new ast::CompoundStmt(
415                func->location, {new ast::ReturnStmt(func->location, type_name)}
416        );
417}
418
[c333ed2]419void EnumAttrFuncGenerator::genTypedEnumFunction(const ast::EnumAttribute attr) {
[85855b0]420        if (attr == ast::EnumAttribute::Value) {
[bb336a6]421                if (decl->isTyped()) {
[85855b0]422                        // TypedEnum's backing arrays
423                        std::vector<ast::ptr<ast::Init>> inits = genValueInit();
424                        ast::ObjectDecl* arrayProto =
425                                genAttrArrayProto(attr, getLocation(), inits);
426                        forwards.push_back(arrayProto);
427
428                        ast::FunctionDecl* funcProto = genValueProto();
429                        produceForwardDecl(funcProto);
430                        genValueOrLabelBody(funcProto, arrayProto);
431                        produceDecl(funcProto);
[236f133]432                } 
433                // else {
434                //      ast::FunctionDecl* funcProto = genQuasiValueProto();
435                //      produceForwardDecl(funcProto);
436                //      // genQuasiValueBody(funcProto);
437                //      produceDecl(funcProto);
438                // }
[85855b0]439        } else if (attr == ast::EnumAttribute::Label) {
440                std::vector<ast::ptr<ast::Init>> inits = genLabelInit();
[fc1a3e2]441                ast::ObjectDecl* arrayProto =
442                        genAttrArrayProto(attr, getLocation(), inits);
443                forwards.push_back(arrayProto);
[85855b0]444                ast::FunctionDecl* funcProto = genLabelProto();
[fc1a3e2]445                produceForwardDecl(funcProto);
446                genValueOrLabelBody(funcProto, arrayProto);
447                produceDecl(funcProto);
448        } else {
449                ast::FunctionDecl* funcProto = genPosnProto();
450                produceForwardDecl(funcProto);
451                genPosnBody(funcProto);
452                produceDecl(funcProto);
453        }
[af746cc]454}
455
[c333ed2]456void EnumAttrFuncGenerator::genTypedEnumFuncs() {
[725f777f]457        genTypedEnumFunction(ast::EnumAttribute::Value);
458        genTypedEnumFunction(ast::EnumAttribute::Label);
459        genTypedEnumFunction(ast::EnumAttribute::Posn);
[af746cc]460}
461
[85855b0]462void EnumAttrFuncGenerator::genTypeNameFunc() {
463        ast::FunctionDecl* funcProto = genTypeNameProto();
464        produceForwardDecl(funcProto);
465        genTypeNameBody(funcProto);
466        produceDecl(funcProto);
467}
468
[af746cc]469void EnumAttrFuncGenerator::generateAndAppendFunctions(
[fc1a3e2]470        std::list<ast::ptr<ast::Decl>>& decls) {
471        // Generate the functions (they go into forwards and definitions).
[725f777f]472        genTypeNameFunc();
[c333ed2]473        genTypedEnumFuncs();
[725f777f]474        genSerialTraitFuncs();
475        genBoundedFunctions();
[fc1a3e2]476        // Now export the lists contents.
477        decls.splice(decls.end(), forwards);
478        decls.splice(decls.end(), definitions);
[af746cc]479}
480
481// ---------------------------------------------------------
482
[fc1a3e2]483struct ImplementEnumFunc final :
484                public ast::WithDeclsToAdd<>, public ast::WithShortCircuiting {
485        void previsit(const ast::EnumDecl* enumDecl);
486        void previsit(const ast::FunctionDecl* functionDecl);
487        void postvisit(const ast::FunctionDecl* functionDecl);
[af746cc]488
[fc1a3e2]489private:
490        // Current level of nested functions.
491        unsigned int functionNesting = 0;
[af746cc]492};
493
494void ImplementEnumFunc::previsit(const ast::EnumDecl* enumDecl) {
[5ccc733]495        if (!enumDecl->body || !enumDecl->isCfa) return;
[fc1a3e2]496        ast::EnumInstType enumInst(enumDecl->name);
497        enumInst.base = enumDecl;
498        EnumAttrFuncGenerator gen(enumDecl, &enumInst, functionNesting);
[725f777f]499        gen.generateAndAppendFunctions(declsToAddAfter);
[af746cc]500}
501
502void ImplementEnumFunc::previsit(const ast::FunctionDecl*) {
[fc1a3e2]503        functionNesting += 1;
[af746cc]504}
505
506void ImplementEnumFunc::postvisit(const ast::FunctionDecl*) {
[fc1a3e2]507        functionNesting -= 1;
[af746cc]508}
509
[fc1a3e2]510} // namespace
[af746cc]511
512void implementEnumFunc(ast::TranslationUnit& translationUnit) {
[fc1a3e2]513        ast::Pass<ImplementEnumFunc>::run(translationUnit);
[af746cc]514}
[fc1a3e2]515
516} // namespace Validate
Note: See TracBrowser for help on using the repository browser.