Example #1
0
File: attrib.c Project: eco/dmd
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();
    }
}
Example #2
0
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();
    }
}
Example #3
0
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;
}
Example #4
0
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.
    }
}
Example #5
0
/***************************************************************************//**
 * 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;
}
Example #6
0
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;
	    }		 
	}