void AttribDeclaration::setScope(Scope *sc) { Dsymbols *d = include(sc, NULL); //printf("\tAttribDeclaration::setScope '%s', d = %p\n",toChars(), d); if (d) { Scope *sc2 = newScope(sc); for (size_t i = 0; i < d->dim; i++) { Dsymbol *s = (*d)[i]; s->setScope(sc2); } if (sc2 != sc) sc2->pop(); } }
void AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sds) { Dsymbols *d = include(sc, sds); if (d) { Scope *sc2 = newScope(sc); for (size_t i = 0; i < d->dim; i++) { Dsymbol *s = (*d)[i]; //printf("\taddMember %s to %s\n", s->toChars(), sds->toChars()); s->addMember(sc2, sds); } if (sc2 != sc) sc2->pop(); } }
Scope *flattenScope(Scope *scope) { Scope *destinationScope = newScope(NULL); // Traverse every level of scope while(scope) { Vector *vars = scope->variables; for(int i = 0; i < vars->size; i++) { ScopeElement *elem = vectorGet(vars, i); char *identifier = elem->identifier; // If it hasn't already been declared in the flattened scope, "declare it" if(inLocalScope(destinationScope, identifier)) { error(REDECL_GLOBAL_VAR, identifier); } else { vectorAdd(destinationScope->variables, elem); } } scope = scope->enclosingScope; } return destinationScope; }
void PragmaDeclaration::semantic(Scope *sc) { // Should be merged with PragmaStatement //printf("\tPragmaDeclaration::semantic '%s'\n",toChars()); if (ident == Id::msg) { if (args) { for (size_t i = 0; i < args->dim; i++) { Expression *e = (*args)[i]; sc = sc->startCTFE(); e = e->semantic(sc); e = resolveProperties(sc, e); sc = sc->endCTFE(); // pragma(msg) is allowed to contain types as well as expressions e = ctfeInterpretForPragmaMsg(e); if (e->op == TOKerror) { errorSupplemental(loc, "while evaluating pragma(msg, %s)", (*args)[i]->toChars()); return; } StringExp *se = e->toStringExp(); if (se) { se = se->toUTF8(sc); fprintf(stderr, "%.*s", (int)se->len, (char *)se->string); } else fprintf(stderr, "%s", e->toChars()); } fprintf(stderr, "\n"); } goto Lnodecl; } else if (ident == Id::lib) { if (!args || args->dim != 1) error("string expected for library name"); else { Expression *e = (*args)[0]; sc = sc->startCTFE(); e = e->semantic(sc); e = resolveProperties(sc, e); sc = sc->endCTFE(); e = e->ctfeInterpret(); (*args)[0] = e; if (e->op == TOKerror) goto Lnodecl; StringExp *se = e->toStringExp(); if (!se) error("string expected for library name, not '%s'", e->toChars()); else { char *name = (char *)mem.xmalloc(se->len + 1); memcpy(name, se->string, se->len); name[se->len] = 0; if (global.params.verbose) fprintf(global.stdmsg, "library %s\n", name); if (global.params.moduleDeps && !global.params.moduleDepsFile) { OutBuffer *ob = global.params.moduleDeps; Module *imod = sc->instantiatingModule(); ob->writestring("depsLib "); ob->writestring(imod->toPrettyChars()); ob->writestring(" ("); escapePath(ob, imod->srcfile->toChars()); ob->writestring(") : "); ob->writestring((char *) name); ob->writenl(); } mem.xfree(name); } } goto Lnodecl; } else if (ident == Id::startaddress) { if (!args || args->dim != 1) error("function name expected for start address"); else { /* Bugzilla 11980: * resolveProperties and ctfeInterpret call are not necessary. */ Expression *e = (*args)[0]; sc = sc->startCTFE(); e = e->semantic(sc); sc = sc->endCTFE(); (*args)[0] = e; Dsymbol *sa = getDsymbol(e); if (!sa || !sa->isFuncDeclaration()) error("function name expected for start address, not '%s'", e->toChars()); } goto Lnodecl; } else if (ident == Id::Pinline) { goto Ldecl; } else if (ident == Id::mangle) { if (!args) args = new Expressions(); if (args->dim != 1) { error("string expected for mangled name"); args->setDim(1); (*args)[0] = new ErrorExp(); // error recovery goto Ldecl; } Expression *e = (*args)[0]; e = e->semantic(sc); e = e->ctfeInterpret(); (*args)[0] = e; if (e->op == TOKerror) goto Ldecl; StringExp *se = e->toStringExp(); if (!se) { error("string expected for mangled name, not '%s'", e->toChars()); goto Ldecl; } if (!se->len) { error("zero-length string not allowed for mangled name"); goto Ldecl; } if (se->sz != 1) { error("mangled name characters can only be of type char"); goto Ldecl; } #if 1 /* Note: D language specification should not have any assumption about backend * implementation. Ideally pragma(mangle) can accept a string of any content. * * Therefore, this validation is compiler implementation specific. */ for (size_t i = 0; i < se->len; ) { utf8_t *p = (utf8_t *)se->string; dchar_t c = p[i]; if (c < 0x80) { if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c >= '0' && c <= '9' || c != 0 && strchr("$%().:?@[]_", c)) { ++i; continue; } else { error("char 0x%02x not allowed in mangled name", c); break; } } if (const char* msg = utf_decodeChar((utf8_t *)se->string, se->len, &i, &c)) { error("%s", msg); break; } if (!isUniAlpha(c)) { error("char 0x%04x not allowed in mangled name", c); break; } } #endif } else if (global.params.ignoreUnsupportedPragmas) { if (global.params.verbose) { /* Print unrecognized pragmas */ fprintf(global.stdmsg, "pragma %s", ident->toChars()); if (args) { for (size_t i = 0; i < args->dim; i++) { Expression *e = (*args)[i]; sc = sc->startCTFE(); e = e->semantic(sc); e = resolveProperties(sc, e); sc = sc->endCTFE(); e = e->ctfeInterpret(); if (i == 0) fprintf(global.stdmsg, " ("); else fprintf(global.stdmsg, ","); fprintf(global.stdmsg, "%s", e->toChars()); } if (args->dim) fprintf(global.stdmsg, ")"); } fprintf(global.stdmsg, "\n"); } goto Lnodecl; } else error("unrecognized pragma(%s)", ident->toChars()); Ldecl: if (decl) { Scope *sc2 = newScope(sc); for (size_t i = 0; i < decl->dim; i++) { Dsymbol *s = (*decl)[i]; s->semantic(sc2); if (ident == Id::mangle) { assert(args && args->dim == 1); if (StringExp *se = (*args)[0]->toStringExp()) { char *name = (char *)mem.xmalloc(se->len + 1); memcpy(name, se->string, se->len); name[se->len] = 0; unsigned cnt = setMangleOverride(s, name); if (cnt > 1) error("can only apply to a single declaration"); } } } if (sc2 != sc) sc2->pop(); } return; Lnodecl: if (decl) { error("pragma is missing closing ';'"); goto Ldecl; // do them anyway, to avoid segfaults. } }
/***************************************************************************//** * Allocates and initializes a new scope on the heap and appends it to the end * of the given scope. ******************************************************************************/ void addScope(struct Scope* base, size_t offset) { struct Scope* scope = newScope(); scope->offset = base->bottom + offset; base->next = scope; }
static void buildSymbolTable2(TreeNode *syntaxTree) { int i; /* iterate over node children */ HashNodePtr luSymbol; /* symbol being looked up */ char errorMessage[80]; /* used to decorate RETURN nodes with enclosing procedure */ static TreeNode *enclosingFunction = NULL; while (syntaxTree != NULL) { /* * Examine current symbol: if it's a declaration, insert into * symbol table. */ if (syntaxTree->nodekind == DecK) insertSymbol(syntaxTree->name, syntaxTree, syntaxTree->lineno); /* If entering a new function, tell the symbol table */ if ((syntaxTree->nodekind == DecK) && (syntaxTree->kind.dec == FuncDecK)) { /* record the enclosing procedure declaration */ enclosingFunction = syntaxTree; if (TraceAnalyse) /* * For functions at least, it's nice to tell the user * whereabouts in the program the variable comes into * scope. We don't bother printing out compound-stmt * scopes */ drawRuler(listing, syntaxTree->name); newScope(); ++scopeDepth; } /* If entering a compound-statement, create a new scope as well */ if ((syntaxTree->nodekind == StmtK) && (syntaxTree->kind.stmt == CompoundK)) { newScope(); ++scopeDepth; } /* * If the current node is an identifier, it needs to be checked * against the symbol table, and annotated with a pointer back to * it's declaration. */ if (((syntaxTree->nodekind == ExpK) /* identifier reference... */ && (syntaxTree->kind.exp == IdK)) || ((syntaxTree->nodekind == StmtK) /* function call... */ && (syntaxTree->kind.stmt == CallK))) { DEBUG_ONLY( fprintf(listing, "*** Annotating identifier \"%s\" on line %d\n", syntaxTree->name, syntaxTree->lineno); ); luSymbol = lookupSymbol(syntaxTree->name); if (luSymbol == NULL) { /* operation failed; say so to user */ sprintf(errorMessage, "identifier \"%s\" unknown or out of scope\n", syntaxTree->name); flagSemanticError(errorMessage); } else { /* * Annotate identifier tree-node with a pointer to it's * declaration. */ syntaxTree->declaration = luSymbol->declaration; } }