source: src/Validate/ImplementEnumFunc.cpp @ 09bdf2d

Last change on this file since 09bdf2d was 0c327ce, checked in by JiadaL <j82liang@…>, 4 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.