Exemple #1
0
bool Module::read(Loc loc)
{
    //printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars());
    if (srcfile->read())
    {
        if (!strcmp(srcfile->toChars(), "object.d"))
        {
            ::error(loc, "cannot find source code for runtime library file 'object.d'");
#if IN_LLVM
            errorSupplemental(loc, "ldc2 might not be correctly installed.");
            errorSupplemental(loc, "Please check your ldc2.conf configuration file.");
            errorSupplemental(loc, "Installation instructions can be found at http://wiki.dlang.org/LDC.");
#else
            errorSupplemental(loc, "dmd might not be correctly installed. Run 'dmd -man' for installation instructions.");
#endif
        }
        else
        {
            // if module is not named 'package' but we're trying to read 'package.d', we're looking for a package module
            bool isPackageMod = (strcmp(toChars(), "package") != 0) &&
                                (strcmp(srcfile->name->name(), "package.d") == 0);

            if (isPackageMod)
                ::error(loc, "importing package '%s' requires a 'package.d' file which cannot be found in '%s'",
                    toChars(), srcfile->toChars());
            else
                error(loc, "is in file '%s' which cannot be read", srcfile->toChars());
        }

        if (!global.gag)
        {   /* Print path
             */
            if (global.path)
            {
                for (size_t i = 0; i < global.path->dim; i++)
                {
                    const char *p = (*global.path)[i];
                    fprintf(stderr, "import path[%llu] = %s\n", (ulonglong)i, p);
                }
            }
            else
                fprintf(stderr, "Specify path to file '%s' with -I switch\n", srcfile->toChars());
            fatal();
        }
        return false;
    }
    return true;
}
Exemple #2
0
bool Module::read(Loc loc)
{
    //printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars());
    if (srcfile->read())
    {
        if (!strcmp(srcfile->toChars(), "object.d"))
        {
            ::error(loc, "cannot find source code for runtime library file 'object.d'");
            errorSupplemental(loc, "dmd might not be correctly installed. Run 'dmd -man' for installation instructions.");
        }
        else
        {
            error(loc, "is in file '%s' which cannot be read", srcfile->toChars());
        }

        if (!global.gag)
        {   /* Print path
             */
            if (global.path)
            {
                for (size_t i = 0; i < global.path->dim; i++)
                {
                    char *p = (*global.path)[i];
                    fprintf(stdmsg, "import path[%llu] = %s\n", (ulonglong)i, p);
                }
            }
            else
                fprintf(stdmsg, "Specify path to file '%s' with -I switch\n", srcfile->toChars());
            fatal();
        }
        return false;
    }
    return true;
}
Exemple #3
0
void StaticAssert::semantic2(Scope *sc)
{
    //printf("StaticAssert::semantic2() %s\n", toChars());
    ScopeDsymbol *sds = new ScopeDsymbol();
    sc = sc->push(sds);
    sc->flags |= SCOPEstaticassert;

    sc = sc->startCTFE();
    Expression *e = exp->semantic(sc);
    e = resolveProperties(sc, e);
    sc = sc->endCTFE();
    sc = sc->pop();

    // Simplify expression, to make error messages nicer if CTFE fails
    e = e->optimize(0);

    if (!e->type->checkBoolean())
    {
        if (e->type->toBasetype() != Type::terror)
            exp->error("expression %s of type %s does not have a boolean value", exp->toChars(), e->type->toChars());
        return;
    }
    unsigned olderrs = global.errors;
    e = e->ctfeInterpret();
    if (global.errors != olderrs)
    {
        errorSupplemental(loc, "while evaluating: static assert(%s)", exp->toChars());
    }
    else if (e->isBool(false))
    {
        if (msg)
        {
            sc = sc->startCTFE();
            msg = msg->semantic(sc);
            msg = resolveProperties(sc, msg);
            sc = sc->endCTFE();
            msg = msg->ctfeInterpret();
            if (StringExp * se = msg->toStringExp())
            {
                // same with pragma(msg)
                se = se->toUTF8(sc);
                error("\"%.*s\"", (int)se->len, (char *)se->string);
            }
            else
                error("%s", msg->toChars());
        }
        else
            error("(%s) is false", exp->toChars());
        if (sc->tinst)
            sc->tinst->printInstantiationTrace();
        if (!global.gag)
              fatal();
    }
    else if (!e->isBool(true))
    {
        error("(%s) is not evaluatable at compile time", exp->toChars());
    }
}
Exemple #4
0
template <typename DECL> static void ensureDecl(DECL *decl, const char *msg) {
  if (!decl || !decl->type) {
    Logger::println("Missing class declaration: %s\n", msg);
    error(Loc(), "Missing class declaration: %s", msg);
    errorSupplemental(Loc(),
                      "Please check that object.di is included and valid");
    fatal();
  }
}
Exemple #5
0
void StaticAssert::semantic2(Scope *sc)
{
    //printf("StaticAssert::semantic2() %s\n", toChars());
    ScopeDsymbol *sd = new ScopeDsymbol();
    sc = sc->push(sd);
    sc->flags |= SCOPEstaticassert;
    Expression *e = exp->ctfeSemantic(sc);
    e = resolveProperties(sc, e);
    // Simplify expression, to make error messages nicer if CTFE fails
    e = e->optimize(0);
    sc = sc->pop();
    if (!e->type->checkBoolean())
    {
        if (e->type->toBasetype() != Type::terror)
            exp->error("expression %s of type %s does not have a boolean value", exp->toChars(), e->type->toChars());
        return;
    }
    unsigned olderrs = global.errors;
    e = e->ctfeInterpret();
    if (global.errors != olderrs)
    {
        errorSupplemental(loc, "while evaluating: static assert(%s)", exp->toChars());
    }
    else if (e->isBool(FALSE))
    {
        if (msg)
        {   HdrGenState hgs;
            OutBuffer buf;

            msg = msg->ctfeSemantic(sc);
            msg = resolveProperties(sc, msg);
            msg = msg->ctfeInterpret();
            hgs.console = 1;
            StringExp * s = msg->toString();
            if (s)
            {   s->postfix = 0; // Don't display a trailing 'c'
                msg = s;
            }
            msg->toCBuffer(&buf, &hgs);
            error("%s", buf.toChars());
        }
        else
            error("(%s) is false", exp->toChars());
        if (sc->tinst)
            sc->tinst->printInstantiationTrace();
        if (!global.gag)
              fatal();
    }
    else if (!e->isBool(TRUE))
    {
        error("(%s) is not evaluatable at compile time", exp->toChars());
    }
}
Exemple #6
0
void StaticAssert::semantic2(Scope *sc)
{
    //printf("StaticAssert::semantic2() %s\n", toChars());
    Expression *e = exp->semantic(sc);
    if (!e->type->checkBoolean())
    {
        if (e->type->toBasetype() != Type::terror)
            exp->error("expression %s of type %s does not have a boolean value", exp->toChars(), e->type->toChars());
        return;
    }
    unsigned olderrs = global.errors;
    e = e->ctfeInterpret();
    if (global.errors != olderrs)
    {
        errorSupplemental(loc, "while evaluating: static assert(%s)", exp->toChars());
    }
    else if (e->isBool(FALSE))
    {
        if (msg)
        {   HdrGenState hgs;
            OutBuffer buf;

            msg = msg->semantic(sc);
            msg = msg->ctfeInterpret();
            hgs.console = 1;
            msg->toCBuffer(&buf, &hgs);
            error("%s", buf.toChars());
        }
        else
            error("(%s) is false", exp->toChars());
        if (sc->tinst)
            sc->tinst->printInstantiationTrace();
        if (!global.gag)
              fatal();
    }
    else if (!e->isBool(TRUE))
    {
        error("(%s) is not evaluatable at compile time", exp->toChars());
    }
}
Exemple #7
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.
    }
}
Exemple #8
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 = e->optimize(WANTvalue | WANTinterpret);
                if (e->op == TOKerror)
                {   errorSupplemental(loc, "while evaluating pragma(msg, %s)", (*args)[i]->toChars());
                    return;
                }
                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->optimize(WANTvalue | WANTinterpret);
            (*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 | WANTinterpret);
            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->optimize(WANTvalue | WANTinterpret);
            (*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++)
                {
                    Expression *e = (*args)[i];
                    // ignore errors in ignored pragmas.
                    global.gag++;
                    unsigned errors_save = global.errors;

                    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());

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.
    }
}
Exemple #9
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)[i];

                e = e->semantic(sc);
                if (e->op != TOKerror && e->op != TOKtype)
                    e = e->ctfeInterpret();
                if (e->op == TOKerror)
                {   errorSupplemental(loc, "while evaluating pragma(msg, %s)", (*args)[i]->toChars());
                    return;
                }
                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;
                fprintf(stdmsg, "library   %s\n", name);
                mem.free(name);
            }
        }
        goto Lnodecl;
    }
#ifdef 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->ctfeInterpret();
            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)
    {
        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)[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)
    {
        if (!args || args->dim < 1)
            error("declaration expected for setting attributes");
        else
        {
            Expressions ** p_attributes = NULL;     // list of existing attributes
            {
                Expression * e = (*args)[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)[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 = (*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
    else if (global.params.ignoreUnsupportedPragmas)
    {
        if (global.params.verbose)
        {
            /* Print unrecognized pragmas
             */
            fprintf(stdmsg, "pragma    %s", ident->toChars());
            if (args)
            {
                for (size_t i = 0; i < args->dim; i++)
                {
                    Expression *e = (*args)[i];
                    e = e->semantic(sc);
                    e = e->ctfeInterpret();
                    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());

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

            s->semantic(sc);
        }
    }
#ifdef IN_GCC
    if (decl)
    {
        if (ident == Id::GNU_attribute)
            *sc = sc_save;
    }
#endif
    return;

Lnodecl:
    if (decl)
    {
        error("pragma is missing closing ';'");
        goto Ldecl; // do them anyway, to avoid segfaults.
    }
}
Exemple #10
0
void StructDeclaration::semantic(Scope *sc)
{
    //printf("+StructDeclaration::semantic(this=%p, %s '%s', sizeok = %d)\n", this, parent->toChars(), toChars(), sizeok);

    //static int count; if (++count == 20) halt();

    if (semanticRun >= PASSsemanticdone)
        return;
    unsigned dprogress_save = Module::dprogress;
    int errors = global.errors;

    Scope *scx = NULL;
    if (scope)
    {
        sc = scope;
        scx = scope;            // save so we don't make redundant copies
        scope = NULL;
    }

    if (!parent)
    {
        assert(sc->parent && sc->func);
        parent = sc->parent;
    }
    assert(parent && !isAnonymous());
    type = type->semantic(loc, sc);

    if (type->ty == Tstruct && ((TypeStruct *)type)->sym != this)
    {
        TemplateInstance *ti = ((TypeStruct *)type)->sym->isInstantiated();
        if (ti && isError(ti))
            ((TypeStruct *)type)->sym = this;
    }

    // Ungag errors when not speculative
    Ungag ungag = ungagSpeculative();

    if (semanticRun == PASSinit)
    {
        protection = sc->protection;

        alignment = sc->structalign;

        storage_class |= sc->stc;
        if (storage_class & STCdeprecated)
            isdeprecated = true;
        if (storage_class & STCabstract)
            error("structs, unions cannot be abstract");
        userAttribDecl = sc->userAttribDecl;
    }
    else if (symtab)
    {
        if (sizeok == SIZEOKdone || !scx)
        {
            semanticRun = PASSsemanticdone;
            return;
        }
    }
    semanticRun = PASSsemantic;

    if (!members)               // if opaque declaration
    {
        semanticRun = PASSsemanticdone;
        return;
    }
    if (!symtab)
        symtab = new DsymbolTable();

    if (sizeok == SIZEOKnone)            // if not already done the addMember step
    {
        for (size_t i = 0; i < members->dim; i++)
        {
            Dsymbol *s = (*members)[i];
            //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
            s->addMember(sc, this, 1);
        }
    }

    sizeok = SIZEOKnone;
    Scope *sc2 = sc->push(this);
    sc2->stc &= STCsafe | STCtrusted | STCsystem;
    sc2->parent = this;
    if (isUnionDeclaration())
        sc2->inunion = 1;
    sc2->protection = Prot(PROTpublic);
    sc2->explicitProtection = 0;
    sc2->structalign = STRUCTALIGN_DEFAULT;
    sc2->userAttribDecl = NULL;

    /* Set scope so if there are forward references, we still might be able to
     * resolve individual members like enums.
     */
    for (size_t i = 0; i < members->dim; i++)
    {
        Dsymbol *s = (*members)[i];
        //printf("struct: setScope %s %s\n", s->kind(), s->toChars());
        s->setScope(sc2);
    }

    for (size_t i = 0; i < members->dim; i++)
    {
        Dsymbol *s = (*members)[i];
        s->importAll(sc2);
    }

    for (size_t i = 0; i < members->dim; i++)
    {
        Dsymbol *s = (*members)[i];

        /* If this is the last member, see if we can finish setting the size.
         * This could be much better - finish setting the size after the last
         * field was processed. The problem is the chicken-and-egg determination
         * of when that is. See Bugzilla 7426 for more info.
         */
        if (i + 1 == members->dim)
        {
            if (sizeok == SIZEOKnone && s->isAliasDeclaration())
                finalizeSize(sc2);
        }
        s->semantic(sc2);
    }
    finalizeSize(sc2);

    if (sizeok == SIZEOKfwd)
    {
        // semantic() failed because of forward references.
        // Unwind what we did, and defer it for later
        for (size_t i = 0; i < fields.dim; i++)
        {
            VarDeclaration *vd = fields[i];
            vd->offset = 0;
        }
        fields.setDim(0);
        structsize = 0;
        alignsize = 0;

        scope = scx ? scx : sc->copy();
        scope->setNoFree();
        scope->module->addDeferredSemantic(this);

        Module::dprogress = dprogress_save;
        //printf("\tdeferring %s\n", toChars());
        return;
    }

    Module::dprogress++;
    semanticRun = PASSsemanticdone;

    //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());

    // Determine if struct is all zeros or not
    zeroInit = 1;
    for (size_t i = 0; i < fields.dim; i++)
    {
        VarDeclaration *vd = fields[i];
        if (!vd->isDataseg())
        {
            if (vd->init)
            {
                // Should examine init to see if it is really all 0's
                zeroInit = 0;
                break;
            }
            else
            {
                if (!vd->type->isZeroInit(loc))
                {
                    zeroInit = 0;
                    break;
                }
            }
        }
    }

    dtor = buildDtor(this, sc2);
    postblit = buildPostBlit(this, sc2);
    cpctor = buildCpCtor(this, sc2);

    buildOpAssign(this, sc2);
    buildOpEquals(this, sc2);

    xeq = buildXopEquals(this, sc2);
    xcmp = buildXopCmp(this, sc2);
    xhash = buildXtoHash(this, sc2);

    /* Even if the struct is merely imported and its semantic3 is not run,
     * the TypeInfo object would be speculatively stored in each object
     * files. To set correct function pointer, run semantic3 for xeq and xcmp.
     */
    //if ((xeq && xeq != xerreq || xcmp && xcmp != xerrcmp) && isImportedSym(this))
    //    Module::addDeferredSemantic3(this);
    /* Defer requesting semantic3 until TypeInfo generation is actually invoked.
     * See semanticTypeInfo().
     */
    inv = buildInv(this, sc2);

    sc2->pop();

    /* Look for special member functions.
     */
    ctor = searchCtor();
    aggNew =       (NewDeclaration *)search(Loc(), Id::classNew);
    aggDelete = (DeleteDeclaration *)search(Loc(), Id::classDelete);

    if (ctor)
    {
        Dsymbol *scall = search(Loc(), Id::call);
        if (scall)
        {
            unsigned xerrors = global.startGagging();
            sc = sc->push();
            sc->speculative = true;
            FuncDeclaration *fcall = resolveFuncCall(loc, sc, scall, NULL, NULL, NULL, 1);
            sc = sc->pop();
            global.endGagging(xerrors);

            if (fcall && fcall->isStatic())
            {
                error(fcall->loc, "static opCall is hidden by constructors and can never be called");
                errorSupplemental(fcall->loc, "Please use a factory method instead, or replace all constructors with static opCall.");
            }
        }
    }

    TypeTuple *tup = toArgTypes(type);
    size_t dim = tup->arguments->dim;
    if (dim >= 1)
    {
        assert(dim <= 2);
        arg1type = (*tup->arguments)[0]->type;
        if (dim == 2)
            arg2type = (*tup->arguments)[1]->type;
    }

    if (sc->func)
        semantic2(sc);

    if (global.errors != errors)
    {
        // The type is no good.
        type = Type::terror;
        this->errors = true;
        if (deferred)
            deferred->errors = true;
    }

    if (deferred && !global.gag)
    {
        deferred->semantic2(sc);
        deferred->semantic3(sc);
    }

#if 0
    if (type->ty == Tstruct && ((TypeStruct *)type)->sym != this)
    {
        printf("this = %p %s\n", this, this->toChars());
        printf("type = %d sym = %p\n", type->ty, ((TypeStruct *)type)->sym);
    }
#endif
    assert(type->ty != Tstruct || ((TypeStruct *)type)->sym == this);
}