Ejemplo n.º 1
0
void PragmaDeclaration::semantic(Scope *sc)
{   // Should be merged with PragmaStatement

#if IN_LLVM
    Pragma llvm_internal = LLVMnone;
    std::string arg1str;
#endif

    //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->toString();
                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->toString();
            if (!se)
                error("string expected for library name, not '%s'", e->toChars());
            else
            {
                char *name = (char *)mem.malloc(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.free(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::mangle)
    {
        if (!args || args->dim != 1)
            error("string expected for mangled name");
        else
        {
            Expression *e = (*args)[0];

            e = e->semantic(sc);
            e = e->ctfeInterpret();
            (*args)[0] = e;

            if (e->op == TOKerror)
                goto Lnodecl;

            StringExp *se = e->toString();

            if (!se)
            {
                error("string expected for mangled name, not '%s'", e->toChars());
                return;
            }

            if (!se->len)
                error("zero-length string not allowed for mangled name");

            if (se->sz != 1)
                error("mangled name characters can only be of type char");

#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
        }
    }
#if IN_LLVM
    else if ((llvm_internal = DtoGetPragma(sc, this, arg1str)) != LLVMnone)
    {
        // nothing to do anymore
    }
#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];
#if IN_LLVM
                    // ignore errors in ignored pragmas.
                    global.gag++;
                    unsigned errors_save = global.errors;
#endif
                    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 IN_LLVM
                    // restore error state.
                    global.gag--;
                    global.errors = errors_save;
#endif
                }
                if (args->dim)
                    fprintf(global.stdmsg, ")");
            }
            fprintf(global.stdmsg, "\n");
        }
    }
    else
        error("unrecognized pragma(%s)", ident->toChars());

Ldecl:
    if (decl)
    {
        for (size_t i = 0; i < decl->dim; i++)
        {
            Dsymbol *s = (*decl)[i];

            s->semantic(sc);

            if (ident == Id::mangle)
            {
                StringExp *e = (*args)[0]->toString();

                char *name = (char *)mem.malloc(e->len + 1);
                memcpy(name, e->string, e->len);
                name[e->len] = 0;

                unsigned cnt = setMangleOverride(s, name);

                if (cnt > 1)
                    error("can only apply to a single declaration");
            }
#if IN_LLVM
            else
            {
                DtoCheckPragma(this, s, llvm_internal, arg1str);
            }
#endif

        }
    }
    return;

Lnodecl:
    if (decl)
    {
        error("pragma is missing closing ';'");
        goto Ldecl; // do them anyway, to avoid segfaults.
    }
}
Ejemplo n.º 2
0
void PragmaDeclaration::semantic(Scope *sc)
{   // Should be merged with PragmaStatement

#if IN_LLVM
    Pragma llvm_internal = LLVMnone;
    std::string arg1str;
#endif

    //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];

                e = e->semantic(sc);
                if (e->op != TOKerror && e->op != TOKtype)
                    e = e->ctfeInterpret();
                StringExp *se = e->toString();
                if (se)
                {
                    fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string);
                }
                else
                    fprintf(stdmsg, "%s", e->toChars());
            }
            fprintf(stdmsg, "\n");
        }
        goto Lnodecl;
    }
    else if (ident == Id::lib)
    {
        if (!args || args->dim != 1)
            error("string expected for library name");
        else
        {
            Expression *e = (*args)[0];

            e = e->semantic(sc);
            e = e->ctfeInterpret();
            (*args)[0] = e;
            if (e->op == TOKerror)
                goto Lnodecl;
            StringExp *se = e->toString();
            if (!se)
                error("string expected for library name, not '%s'", e->toChars());
            else if (global.params.verbose)
            {
                char *name = (char *)mem.malloc(se->len + 1);
                memcpy(name, se->string, se->len);
                name[se->len] = 0;
                printf("library   %s\n", name);
                mem.free(name);
            }
        }
        goto Lnodecl;
    }
#if IN_GCC
    else if (ident == Id::GNU_asm)
    {
        if (! args || args->dim != 2)
            error("identifier and string expected for asm name");
        else
        {
            Expression *e;
            Declaration *d = NULL;
            StringExp *s = NULL;

            e = (*args)[0];
            e = e->semantic(sc);
            if (e->op == TOKvar)
            {
                d = ((VarExp *)e)->var;
                if (! d->isFuncDeclaration() && ! d->isVarDeclaration())
                    d = NULL;
            }
            if (!d)
                error("first argument of GNU_asm must be a function or variable declaration");

            e = (*args)[1];
            e = e->semantic(sc);
            e = e->optimize(WANTvalue);
            e = e->toString();
            if (e && ((StringExp *)e)->sz == 1)
                s = ((StringExp *)e);
            else
                error("second argument of GNU_asm must be a character string");

            if (d && s)
                d->c_ident = Lexer::idPool((char*) s->string);
        }
        goto Lnodecl;
    }
#endif
#if DMDV2
    else if (ident == Id::startaddress)
    {
        if (!args || args->dim != 1)
            error("function name expected for start address");
        else
        {
            Expression *e = (*args)[0];
            e = e->semantic(sc);
            e = e->ctfeInterpret();
            (*args)[0] = e;
            Dsymbol *sa = getDsymbol(e);
            if (!sa || !sa->isFuncDeclaration())
                error("function name expected for start address, not '%s'", e->toChars());
        }
        goto Lnodecl;
    }
#endif
#if TARGET_NET
    else if (ident == Lexer::idPool("assembly"))
    {
    }
#endif // TARGET_NET
#if IN_LLVM
    else if ((llvm_internal = DtoGetPragma(sc, this, arg1str)) != LLVMnone)
    {
        // nothing to do anymore
    }
#endif
    else if (global.params.ignoreUnsupportedPragmas)
    {
        if (global.params.verbose)
        {
            /* Print unrecognized pragmas
             */
            printf("pragma    %s", ident->toChars());
            if (args)
            {
                for (size_t i = 0; i < args->dim; i++)
                {
#if IN_LLVM
                    // ignore errors in ignored pragmas.
                    global.gag++;
                    unsigned errors_save = global.errors;
#endif

                    Expression *e = (*args)[i];
                    e = e->semantic(sc);
                    e = e->ctfeInterpret();
                    if (i == 0)
                        printf(" (");
                    else
                        printf(",");
                    printf("%s", e->toChars());

#if IN_LLVM
                    // restore error state.
                    global.gag--;
                    global.errors = errors_save;
#endif
                }
                if (args->dim)
                    printf(")");
            }
            printf("\n");
        }
        goto Lnodecl;
    }
    else
        error("unrecognized pragma(%s)", ident->toChars());

Ldecl:
    if (decl)
    {
        for (size_t i = 0; i < decl->dim; i++)
        {
            Dsymbol *s = (*decl)[i];

            s->semantic(sc);

#if IN_LLVM
            DtoCheckPragma(this, s, llvm_internal, arg1str);
#endif
        }
    }
    return;

Lnodecl:
    if (decl)
    {
        error("pragma is missing closing ';'");
        goto Ldecl; // do them anyway, to avoid segfaults.
    }
}