Пример #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];

                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.
    }
}
Пример #2
0
void PragmaDeclaration::semantic(Scope *sc)
{   // Should be merged with PragmaStatement

#if IN_LLVM
    int llvm_internal = 0;
    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 = (Expression *)args->data[i];

                e = e->semantic(sc);
                e = e->optimize(WANTvalue | WANTinterpret);
                if (e->op == TOKstring)
                {
                    StringExp *se = (StringExp *)e;
                    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 = (Expression *)args->data[0];

            e = e->semantic(sc);
            e = e->optimize(WANTvalue | WANTinterpret);
            args->data[0] = (void *)e;
            if (e->op != TOKstring)
                error("string expected for library name, not '%s'", e->toChars());
            else if (global.params.verbose)
            {
                StringExp *se = (StringExp *)e;
                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 = (Expression *)args->data[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 = (Expression *)args->data[1];
            e = e->semantic(sc);
            e = e->optimize(WANTvalue);
            if (e->op == TOKstring && ((StringExp *)e)->sz == 1)
                s = ((StringExp *)e);
            else
                error("second argument of GNU_asm must be a char 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 = (Expression *)args->data[0];
            e = e->semantic(sc);
            e = e->optimize(WANTvalue | WANTinterpret);
            args->data[0] = (void *)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

// LDC
#if IN_LLVM

    // pragma(intrinsic, "string") { funcdecl(s) }
    else if (ident == Id::intrinsic)
    {
        Expression* expr = (Expression *)args->data[0];
        expr = expr->semantic(sc);
        if (!args || args->dim != 1 || !parseStringExp(expr, arg1str))
        {
             error("requires exactly 1 string literal parameter");
             fatal();
        }
        llvm_internal = LLVMintrinsic;
    }

    // pragma(notypeinfo) { typedecl(s) }
    else if (ident == Id::no_typeinfo)
    {
        if (args && args->dim > 0)
        {
             error("takes no parameters");
             fatal();
        }
        llvm_internal = LLVMno_typeinfo;
    }

    // pragma(nomoduleinfo) ;
    else if (ident == Id::no_moduleinfo)
    {
        if (args && args->dim > 0)
        {
             error("takes no parameters");
             fatal();
        }
        llvm_internal = LLVMno_moduleinfo;
    }

    // pragma(alloca) { funcdecl(s) }
    else if (ident == Id::Alloca)
    {
        if (args && args->dim > 0)
        {
             error("takes no parameters");
             fatal();
        }
        llvm_internal = LLVMalloca;
    }

    // pragma(va_start) { templdecl(s) }
    else if (ident == Id::vastart)
    {
        if (args && args->dim > 0)
        {
             error("takes no parameters");
             fatal();
        }
        llvm_internal = LLVMva_start;
    }

    // pragma(va_copy) { funcdecl(s) }
    else if (ident == Id::vacopy)
    {
        if (args && args->dim > 0)
        {
             error("takes no parameters");
             fatal();
        }
        llvm_internal = LLVMva_copy;
    }

    // pragma(va_end) { funcdecl(s) }
    else if (ident == Id::vaend)
    {
        if (args && args->dim > 0)
        {
             error("takes no parameters");
             fatal();
        }
        llvm_internal = LLVMva_end;
    }

    // pragma(va_arg) { templdecl(s) }
    else if (ident == Id::vaarg)
    {
        if (args && args->dim > 0)
        {
             error("takes no parameters");
             fatal();
        }
        llvm_internal = LLVMva_arg;
    }

    // pragma(fence) { templdecl(s) }
    else if (ident == Id::fence)
    {
        if (args && args->dim > 0)
        {
             error("takes no parameters");
             fatal();
        }
        llvm_internal = LLVMfence;
    }

    // pragma(atomic_load) { templdecl(s) }
    else if (ident == Id::atomic_load)
    {
        if (args && args->dim > 0)
        {
             error("takes no parameters");
             fatal();
        }
        llvm_internal = LLVMatomic_load;
    }

    // pragma(atomic_store) { templdecl(s) }
    else if (ident == Id::atomic_store)
    {
        if (args && args->dim > 0)
        {
             error("takes no parameters");
             fatal();
        }
        llvm_internal = LLVMatomic_store;
    }

    // pragma(atomic_cmp_xchg) { templdecl(s) }
    else if (ident == Id::atomic_cmp_xchg)
    {
        if (args && args->dim > 0)
        {
             error("takes no parameters");
             fatal();
        }
        llvm_internal = LLVMatomic_cmp_xchg;
    }

    // pragma(atomic_rmw, "string") { templdecl(s) }
    else if (ident == Id::atomic_rmw)
    {
        Expression* expr = (Expression *)args->data[0];
        expr = expr->semantic(sc);
        if (!args || args->dim != 1 || !parseStringExp(expr, arg1str))
        {
             error("requires exactly 1 string literal parameter");
             fatal();
        }
        llvm_internal = LLVMatomic_rmw;
    }

    // pragma(ldc, "string") { templdecl(s) }
    else if (ident == Id::ldc)
    {
        Expression* expr = (Expression *)args->data[0];
        expr = expr->semantic(sc);
        if (!args || args->dim != 1 || !parseStringExp(expr, arg1str))
        {
             error("requires exactly 1 string literal parameter");
             fatal();
        }
        else if (arg1str == "verbose")
        {
            sc->module->llvmForceLogging = true;
        }
        else
        {
            error("command '%s' invalid", expr->toChars());
            fatal();
        }
    }

    // pragma(llvm_inline_asm) { templdecl(s) }
    else if (ident == Id::llvm_inline_asm)
    {
        if (args && args->dim > 0)
        {
             error("takes no parameters");
             fatal();
        }
        llvm_internal = LLVMinline_asm;
    }

#endif // LDC


    else if (ignoreUnsupportedPragmas)
    {
        if (global.params.verbose)
        {
            /* Print unrecognized pragmas
             */
            printf("pragma    %s", ident->toChars());
            if (args)
            {
                for (size_t i = 0; i < args->dim; i++)
                {
                    // ignore errors in ignored pragmas.
                    global.gag++;
                    unsigned errors_save = global.errors;

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

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

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

            s->semantic(sc);

// LDC
#if IN_LLVM

        if (llvm_internal)
        {
        if (s->llvmInternal)
        {
            error("multiple LDC specific pragmas not allowed not affect the same declaration ('%s' at '%s')", s->toChars(), s->loc.toChars());
            fatal();
        }
        switch(llvm_internal)
        {
        case LLVMintrinsic:
            if (FuncDeclaration* fd = s->isFuncDeclaration())
            {
                fd->llvmInternal = llvm_internal;
                fd->intrinsicName = arg1str;
                fd->linkage = LINKintrinsic;
                ((TypeFunction*)fd->type)->linkage = LINKintrinsic;
            }
            else if (TemplateDeclaration* td = s->isTemplateDeclaration())
            {
                td->llvmInternal = llvm_internal;
                td->intrinsicName = arg1str;
            }
            else
            {
                error("only allowed on function declarations");
                fatal();
            }
            break;

        case LLVMatomic_rmw:
            if (TemplateDeclaration* td = s->isTemplateDeclaration())
            {
                td->llvmInternal = llvm_internal;
                td->intrinsicName = arg1str;
            }
            else
            {
                error("the '%s' pragma is only allowed on template declarations", ident->toChars());
                fatal();
            }
            break;

        case LLVMva_start:
        case LLVMva_arg:
        case LLVMatomic_load:
        case LLVMatomic_store:
        case LLVMatomic_cmp_xchg:
            if (TemplateDeclaration* td = s->isTemplateDeclaration())
            {
                if (td->parameters->dim != 1)
                {
                    error("the '%s' pragma template must have exactly one template parameter", ident->toChars());
                    fatal();
                }
                else if (!td->onemember)
                {
                    error("the '%s' pragma template must have exactly one member", ident->toChars());
                    fatal();
                }
                else if (td->overnext || td->overroot)
                {
                    error("the '%s' pragma template must not be overloaded", ident->toChars());
                    fatal();
                }
                td->llvmInternal = llvm_internal;
            }
            else
            {
                error("the '%s' pragma is only allowed on template declarations", ident->toChars());
                fatal();
            }
            break;

        case LLVMva_copy:
        case LLVMva_end:
        case LLVMfence:
            if (FuncDeclaration* fd = s->isFuncDeclaration())
            {
                fd->llvmInternal = llvm_internal;
            }
            else
            {
                error("the '%s' pragma is only allowed on function declarations", ident->toChars());
                fatal();
            }
            break;

        case LLVMno_typeinfo:
            s->llvmInternal = llvm_internal;
            break;

        case LLVMalloca:
            if (FuncDeclaration* fd = s->isFuncDeclaration())
            {
                fd->llvmInternal = llvm_internal;
            }
            else
            {
                error("the '%s' pragma must only be used on function declarations of type 'void* function(uint nbytes)'", ident->toChars());
                fatal();
            }
            break;

        case LLVMinline_asm:
            if (TemplateDeclaration* td = s->isTemplateDeclaration())
            {
                if (td->parameters->dim > 1)
                {
                    error("the '%s' pragma template must have exactly zero or one template parameters", ident->toChars());
                    fatal();
                }
                else if (!td->onemember)
                {
                    error("the '%s' pragma template must have exactly one member", ident->toChars());
                    fatal();
                }
                td->llvmInternal = llvm_internal;
            }
            else
            {
                error("the '%s' pragma is only allowed on template declarations", ident->toChars());
                fatal();
            }
            break;

        default:
            warning("the LDC specific pragma '%s' is not yet implemented, ignoring", ident->toChars());
        }
        }

#endif // LDC

    }
    }
    return;

Lnodecl:
    if (decl)
        error("pragma is missing closing ';'");
}
Пример #3
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->tdata()[i];

                e = e->semantic(sc);
                e = e->optimize(WANTvalue | WANTinterpret);
                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->tdata()[0];

            e = e->semantic(sc);
            e = e->optimize(WANTvalue | WANTinterpret);
            args->tdata()[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->tdata()[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->tdata()[1];
            e = e->semantic(sc);
            e = e->optimize(WANTvalue | WANTinterpret);
            e = e->toString();
            if (e && ((StringExp *)e)->sz == 1)
                s = ((StringExp *)e);
            else
                error("second argument of GNU_asm must be a char 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->tdata()[0];
            e = e->semantic(sc);
            e = e->optimize(WANTvalue | WANTinterpret);
            args->tdata()[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
    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++)
                {
                    Expression *e = args->tdata()[i];
                    e = e->semantic(sc);
                    e = e->optimize(WANTvalue | WANTinterpret);
                    if (i == 0)
                        printf(" (");
                    else
                        printf(",");
                    printf("%s", e->toChars());
                }
                if (args->dim)
                    printf(")");
            }
            printf("\n");
        }
        goto Lnodecl;
    }
    else
        error("unrecognized pragma(%s)", ident->toChars());

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

            s->semantic(sc);
        }
    }
    return;

Lnodecl:
    if (decl)
        error("pragma is missing closing ';'");
}
Пример #4
0
void PragmaDeclaration::semantic(Scope *sc)
{   // Should be merged with PragmaStatement
    Scope sc_save;

    //printf("\tPragmaDeclaration::semantic '%s'\n",toChars());
    if (ident == Id::msg)
    {
        if (args)
        {
            for (size_t i = 0; i < args->dim; i++)
            {
                Expression *e = args->tdata()[i];

                e = e->semantic(sc);
                e = e->optimize(WANTvalue | WANTinterpret);
                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->tdata()[0];

            e = e->semantic(sc);
            e = e->optimize(WANTvalue | WANTinterpret);
            args->tdata()[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 = (Expression *)args->data[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->tdata()[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;
    }
    else if (ident == Id::GNU_attribute || ident == Id::_GNU_attribute)
    {
        if (!global.params.useDeprecated && ident == Id::_GNU_attribute)
            error("pragma(GNU_attribute) is deprecated, use pragma(attribute) instead");

        sc_save = *sc;

        // An empty list is allowed.
        if (args && args->dim)
        {
            Expressions * a;

            if (sc->attributes)
                a = (Expressions *) sc->attributes->copy();
            else
                a = new Expressions;
            sc->attributes = a;

            for (unsigned i = 0; i < args->dim; i++)
            {
                Expression * e = args->tdata()[i];
                //e = e->semantic(sc);

                if (e->op == TOKidentifier)
                    ; // ok
                else if (e->op == TOKcall)
                {
                    CallExp * c = (CallExp *) e;
                    if (c->e1->op != TOKidentifier)
                        error("identifier or call expression expected for attribute");
                    if (c->arguments)
                        for (int unsigned ai = 0; ai < c->arguments->dim; ai++)
                        {
                            Expression * ea = c->arguments->tdata()[ai];
                            ea = ea->semantic(sc);
                            ea = ea->optimize(WANTvalue | WANTinterpret);
                            c->arguments->tdata()[ai] = ea;
                        }
                }
                else
                {
                    error("identifier or call expression expected for attribute");
                    continue;
                }
                a->push(e);
            }
        }
    }
    else if (ident == Id::GNU_set_attribute || ident == Id::_GNU_set_attribute)
    {
        if (!global.params.useDeprecated && ident == Id::_GNU_set_attribute)
            error("pragma(GNU_set_attribute) is deprecated, use pragma(set_attribute) instead");

        if (!args || args->dim < 1)
            error("declaration expected for setting attributes");
        else
        {
            Expressions ** p_attributes = NULL;     // list of existing attributes
            {
                Expression * e = args->tdata()[0];

                e = e->semantic(sc);
                if (e->op == TOKvar)
                {
                    Declaration * d = ((VarExp *)e)->var;
                    if (d->isFuncDeclaration() || d->isVarDeclaration())
                        p_attributes = & d->attributes;
                }
                else if (e->op == TOKtype)
                {
                    Type * t = ((TypeExp *)e)->type;
                    if (t->ty == Ttypedef)
                        p_attributes = & ((TypeTypedef *) t)->sym->attributes;
                    else if (t->ty == Tenum)
                        p_attributes = & ((TypeEnum *) t)->sym->attributes;
                    else if (t->ty == Tstruct)
                        p_attributes = & ((TypeStruct *) t)->sym->attributes;
                    else if (t->ty == Tclass)
                        p_attributes = & ((TypeClass *) t)->sym->attributes;
                }

                if (p_attributes == NULL)
                    error("first argument must be a function, variable, or type declaration");
            }

            Expressions * new_attrs = new Expressions;
            for (unsigned i = 1; i < args->dim; i++)
            {
                Expression * e = args->tdata()[i];
                //e = e->semantic(sc);

                if (e->op == TOKidentifier)
                    ; // ok
                else if (e->op == TOKcall)
                {
                    CallExp * c = (CallExp *) e;
                    if (c->e1->op != TOKidentifier)
                        error("identifier or call expression expected for attribute");
                    if (c->arguments)
                        for (int unsigned ai = 0; ai < c->arguments->dim; ai++)
                        {
                            Expression * ea = c->arguments->tdata()[ai];
                            ea = ea->semantic(sc);
                            ea = ea->optimize(WANTvalue | WANTinterpret);
                            c->arguments->tdata()[ai] = ea;
                        }
                }
                else
                {
                    error("identifier or call expression expected for attribute");
                    continue;
                }
                new_attrs->push(e);
            }

            if (p_attributes)
            {
                if (*p_attributes)
                {
                    *p_attributes = (Expressions *) (*p_attributes)->copy();
                    (*p_attributes)->append(new_attrs);
                }
                else
                    *p_attributes = new_attrs;
            }
        }
        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 = (Expression *)args->data[0];
            e = e->semantic(sc);
            e = e->optimize(WANTvalue | WANTinterpret);
            args->data[0] = (void *)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
    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++)
                {
                    Expression *e = (Expression *)args->data[i];
                    e = e->semantic(sc);
                    e = e->optimize(WANTvalue | WANTinterpret);
                    if (i == 0)
                        printf(" (");
                    else
                        printf(",");
                    printf("%s", e->toChars());
                }
                if (args->dim)
                    printf(")");
            }
            printf("\n");
        }
        goto Lnodecl;
    }
    else
        error("unrecognized pragma(%s)", ident->toChars());

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

            s->semantic(sc);
        }
    }

#if IN_GCC
    if (decl)
        if (ident == Id::GNU_attribute || ident == Id::_GNU_attribute)
            *sc = sc_save;
#endif
    return;

Lnodecl:
    if (decl)
        error("pragma is missing closing ';'");
}
Пример #5
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 = (Expression *)args->data[i];

		e = e->semantic(sc);
		if (e->op == TOKstring)
		{
		    StringExp *se = (StringExp *)e;
		    fprintf(stdmsg, "%.*s", se->len, se->string);
		}
		else
		    error("string expected for message, not '%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 = (Expression *)args->data[0];

	    e = e->semantic(sc);
	    args->data[0] = (void *)e;
	    if (e->op != TOKstring)
		error("string expected for library name, not '%s'", e->toChars());
	}
	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 = (Expression *)args->data[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 = (Expression *)args->data[1];
	    e = e->semantic(sc);
	    e = e->optimize(WANTvalue);
	    if (e->op == TOKstring && ((StringExp *)e)->sz == 1)
		s = ((StringExp *)e);
	    else
		error("second argument of GNU_asm must be a char string");

	    if (d && s)
		d->c_ident = Lexer::idPool((char*) s->string);
	}
	goto Lnodecl;
    }
#endif
    else
	error("unrecognized pragma(%s)", ident->toChars());

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

	    s->semantic(sc);
	}
    }
    return;

Lnodecl:
    if (decl)
	error("pragma is missing closing ';'");
}