// kandr.cc see license.txt for copyright and terms of use // support routines for the K&R extension #include "kandr.h" // this module #include "generic_aux.h" // genericSetNext #include "cc_lang.h" // CCLang // implemented in implint.cc bool filterOutImplIntFirstParam (SourceLoc loc, IDeclarator *base, FakeList *¶ms); // -------------------- AST extensions --------------------- D_func *D_name::getD_func() {return NULL;} D_func *D_pointer::getD_func() {return base->getD_func();} D_func *D_reference::getD_func() {return base->getD_func();} D_func *D_func::getD_func() { // you have to be careful that there may be another one nested down // inside if the user used this funky syntax: // int (*oink2(x))(int) D_func *df = base->getD_func(); if (df) return df; else return this; } D_func *D_array::getD_func() {return base->getD_func();} D_func *D_bitfield::getD_func() {return NULL;} D_func *D_ptrToMember::getD_func() {return base->getD_func();} D_func *D_grouping::getD_func() {return base->getD_func();} void PQ_name::setNext(PQ_name *newNext) { next = newNext; } // ---------------------- parsing support --------------------- // return a parameter AST list constructed as if the K&R-defined // function had been defined the usual way; NOTE: this imitates // nonterm(FakeList*) ParameterDeclarationList in cc.gr // exactly because I didn't want to think hard about how to use // Scott's datastructures correctly as I wasted so much time on that // yesterday FakeList* kAndR_makeParamList (FakeList *kAndR_params, PtrMap &declsForParams) { if (!kAndR_params) return FakeList::emptyList(); PQ_name *pqName = kAndR_params->first(); ASTTypeId *d = declsForParams.get(pqName->name); // if it has no declaration then it is an int if (!d) { d = new ASTTypeId (new TS_simple(pqName->loc, ST_INT), new Declarator (new D_name (pqName->loc, // I'll make a new PQ_name to be safe that we have no // aliasing problems new PQ_name(pqName->loc, pqName->name)), NULL /*_init*/)); } else { // mutate the location of the declaration to match that of the // place where the variable is first mentioned in the list; this // is only to allow cqual/tests/oldstyle2.c to pass d->decl->decl->loc = pqName->loc; } FakeList *list = kAndR_makeParamList(kAndR_params->butFirst(), declsForParams); // FIX: why doesn't this segfault??; ah, because you can call // methods on null pointers as long as they are not virtual d->setNext(list->first()); return FakeList::makeList(d); } // create a Function definition with K&R params Function *makeKandRdefn(SourceLoc loc, Declaration *rds, IDeclarator *id, S_compound *ds, S_compound *b) { Function *ret = new Function ( rds->dflags, // decl flags (static, extern, etc.) rds->spec, // type specifier for return value new Declarator(id, NULL), // declarator with fn name, params NULL, // ctor member inits b, // function body statement NULL // exception handlers ); fixUpKandRFunctionDef(rds, id, ds); return ret; } // convert ds to params and insert void fixUpKandRFunctionDef (Declaration *rds, IDeclarator *id, S_compound *ds) { // Find the declarations for these params // S_compound(ASTList stmts) for each name, build an // ASTTypeId of the corresponding declarations. Note that this // may involve taking apart a declaration with multiple // Declarator-s for a single DeclSpecifier. PtrMap declsForParams; FOREACH_ASTLIST_NC(Statement, ds->stmts, nameIter) { S_decl *sdecl = nameIter.data()->asS_decl(); Declaration *declaration = dynamic_cast(sdecl->decl); xassert(declaration); FAKELIST_FOREACH_NC(Declarator, declaration->decllist, dcltor) { // clone TypeSpecifier and Declarator ASTTypeId *atid = new ASTTypeId(declaration->spec->clone(), dcltor->clone()); StringRef name = dcltor->decl->getDeclaratorId()->getName(); declsForParams.add(name, atid); } } // Find the place where the params we are building should go. D_func *df = id->getD_func(); xassert(df); xassert(!df->params); //FakeList *params // Find the "parameter" list which is just the names, without // types, "params" if a K&R function: // FakeList *kAndR_params // For each one, look up the declaration above and // build a Parameter for it. df->params = kAndR_makeParamList(df->kAndR_params, declsForParams); // **** rds->spec = NULL; // stole it above (ownership transfer) delete rds; // was just a carrier of dflags/spec } D_func *new_D_func_kandr (CCLang &lang, SourceLoc loc, IDeclarator *base, FakeList *params, CVFlags cv, ExceptionSpec /*nullable*/ *exnSpec, FakeList *kAndR_params) { if (lang.allowImplicitInt && !filterOutImplIntFirstParam(loc, base, params)) { return NULL; } return new D_func(loc, base, params, cv, exnSpec, kAndR_params); } // EOF