Mercurial > projects > ldc
diff dmd/dsymbol.c @ 159:5acec6b2eef8 trunk
[svn r175] merged dmd 1.029
author | ChristianK |
---|---|
date | Thu, 01 May 2008 15:15:28 +0200 |
parents | ccd07d9f2ce9 |
children | aaade6ded589 |
line wrap: on
line diff
--- a/dmd/dsymbol.c Thu May 01 13:33:02 2008 +0200 +++ b/dmd/dsymbol.c Thu May 01 15:15:28 2008 +0200 @@ -1,1007 +1,1007 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2007 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include <stdio.h> -#include <string.h> -#include <assert.h> - -#include "mem.h" - -#include "mars.h" -#include "dsymbol.h" -#include "aggregate.h" -#include "identifier.h" -#include "module.h" -#include "mtype.h" -#include "expression.h" -#include "statement.h" -#include "declaration.h" -#include "id.h" -#include "scope.h" -#include "init.h" -#include "import.h" -#include "template.h" - -#include "../gen/enums.h" - -/****************************** Dsymbol ******************************/ - -Dsymbol::Dsymbol() -{ - //printf("Dsymbol::Dsymbol(%p)\n", this); - this->ident = NULL; - this->c_ident = NULL; - this->parent = NULL; - this->csym = NULL; - this->isym = NULL; - this->loc = 0; - this->comment = NULL; - - this->llvmInternal = LLVMnone; - this->llvmInternal1 = NULL; - this->llvmInternal2 = NULL; -} - -Dsymbol::Dsymbol(Identifier *ident) -{ - //printf("Dsymbol::Dsymbol(%p, ident)\n", this); - this->ident = ident; - this->c_ident = NULL; - this->parent = NULL; - this->csym = NULL; - this->isym = NULL; - this->loc = 0; - this->comment = NULL; - - this->llvmInternal = LLVMnone; - this->llvmInternal1 = NULL; - this->llvmInternal2 = NULL; -} - -int Dsymbol::equals(Object *o) -{ Dsymbol *s; - - if (this == o) - return TRUE; - s = (Dsymbol *)(o); - if (s && ident->equals(s->ident)) - return TRUE; - return FALSE; -} - -/************************************** - * Copy the syntax. - * Used for template instantiations. - * If s is NULL, allocate the new object, otherwise fill it in. - */ - -Dsymbol *Dsymbol::syntaxCopy(Dsymbol *s) -{ - print(); - printf("%s %s\n", kind(), toChars()); - assert(0); - return NULL; -} - -/************************************** - * Determine if this symbol is only one. - * Returns: - * FALSE, *ps = NULL: There are 2 or more symbols - * TRUE, *ps = NULL: There are zero symbols - * TRUE, *ps = symbol: The one and only one symbol - */ - -int Dsymbol::oneMember(Dsymbol **ps) -{ - //printf("Dsymbol::oneMember()\n"); - *ps = this; - return TRUE; -} - -/***************************************** - * Same as Dsymbol::oneMember(), but look at an array of Dsymbols. - */ - -int Dsymbol::oneMembers(Array *members, Dsymbol **ps) -{ - //printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0); - Dsymbol *s = NULL; - - if (members) - { - for (int i = 0; i < members->dim; i++) - { Dsymbol *sx = (Dsymbol *)members->data[i]; - - int x = sx->oneMember(ps); - //printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps); - if (!x) - { - //printf("\tfalse 1\n"); - assert(*ps == NULL); - return FALSE; - } - if (*ps) - { - if (s) // more than one symbol - { *ps = NULL; - //printf("\tfalse 2\n"); - return FALSE; - } - s = *ps; - } - } - } - *ps = s; // s is the one symbol, NULL if none - //printf("\ttrue\n"); - return TRUE; -} - -/***************************************** - * Is Dsymbol a variable that contains pointers? - */ - -int Dsymbol::hasPointers() -{ - //printf("Dsymbol::hasPointers() %s\n", toChars()); - return 0; -} - -char *Dsymbol::toChars() -{ - return ident ? ident->toChars() : (char *)"__anonymous"; -} - -char *Dsymbol::toPrettyChars() -{ Dsymbol *p; - char *s; - char *q; - size_t len; - - //printf("Dsymbol::toPrettyChars() '%s'\n", toChars()); - if (!parent) - return toChars(); - - len = 0; - for (p = this; p; p = p->parent) - len += strlen(p->toChars()) + 1; - - s = (char *)mem.malloc(len); - q = s + len - 1; - *q = 0; - for (p = this; p; p = p->parent) - { - char *t = p->toChars(); - len = strlen(t); - q -= len; - memcpy(q, t, len); - if (q == s) - break; - q--; - *q = '.'; - } - return s; -} - -char *Dsymbol::locToChars() -{ - OutBuffer buf; - char *p; - - Module *m = getModule(); - - if (m && m->srcfile) - loc.filename = m->srcfile->toChars(); - return loc.toChars(); -} - -char *Dsymbol::kind() -{ - return "symbol"; -} - -/********************************* - * If this symbol is really an alias for another, - * return that other. - */ - -Dsymbol *Dsymbol::toAlias() -{ - return this; -} - -Dsymbol *Dsymbol::toParent() -{ - return parent ? parent->pastMixin() : NULL; -} - -Dsymbol *Dsymbol::pastMixin() -{ - Dsymbol *s = this; - - //printf("Dsymbol::pastMixin() %s\n", toChars()); - while (s && s->isTemplateMixin()) - s = s->parent; - return s; -} - -/********************************** - * Use this instead of toParent() when looking for the - * 'this' pointer of the enclosing function/class. - */ - -Dsymbol *Dsymbol::toParent2() -{ - Dsymbol *s = parent; - while (s && s->isTemplateInstance()) - s = s->parent; - return s; -} - - -int Dsymbol::isAnonymous() -{ - return ident ? 0 : 1; -} - -void Dsymbol::semantic(Scope *sc) -{ - error("%p has no semantic routine", this); -} - -void Dsymbol::semantic2(Scope *sc) -{ - // Most Dsymbols have no further semantic analysis needed -} - -void Dsymbol::semantic3(Scope *sc) -{ - // Most Dsymbols have no further semantic analysis needed -} - -void Dsymbol::inlineScan() -{ - // Most Dsymbols have no further semantic analysis needed -} - -Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags) -{ - //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars()); - return NULL; -} - -/*************************************** - * Search for identifier id as a member of 'this'. - * id may be a template instance. - * Returns: - * symbol found, NULL if not - */ - -Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id) -{ - //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars()); - Dsymbol *s = toAlias(); - Dsymbol *sm; - - switch (id->dyncast()) - { - case DYNCAST_IDENTIFIER: - sm = s->search(loc, id, 0); - break; - - case DYNCAST_DSYMBOL: - { // It's a template instance - //printf("\ttemplate instance id\n"); - Dsymbol *st = (Dsymbol *)id; - TemplateInstance *ti = st->isTemplateInstance(); - id = ti->name; - sm = s->search(loc, id, 0); - if (!sm) - { error("template identifier %s is not a member of %s %s", - id->toChars(), s->kind(), s->toChars()); - return NULL; - } - sm = sm->toAlias(); - TemplateDeclaration *td = sm->isTemplateDeclaration(); - if (!td) - { - error("%s is not a template, it is a %s", id->toChars(), sm->kind()); - return NULL; - } - ti->tempdecl = td; - if (!ti->semanticdone) - ti->semantic(sc); - sm = ti->toAlias(); - break; - } - - default: - assert(0); - } - return sm; -} - -int Dsymbol::overloadInsert(Dsymbol *s) -{ - //printf("Dsymbol::overloadInsert('%s')\n", s->toChars()); - return FALSE; -} - -void Dsymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ - buf->writestring(toChars()); -} - -unsigned Dsymbol::size(Loc loc) -{ - error("Dsymbol '%s' has no size\n", toChars()); - return 0; -} - -int Dsymbol::isforwardRef() -{ - return FALSE; -} - -AggregateDeclaration *Dsymbol::isThis() -{ - return NULL; -} - -ClassDeclaration *Dsymbol::isClassMember() // are we a member of a class? -{ - Dsymbol *parent = toParent(); - if (parent && parent->isClassDeclaration()) - return (ClassDeclaration *)parent; - return NULL; -} - -void Dsymbol::defineRef(Dsymbol *s) -{ - assert(0); -} - -int Dsymbol::isExport() -{ - return FALSE; -} - -int Dsymbol::isImportedSymbol() -{ - return FALSE; -} - -int Dsymbol::isDeprecated() -{ - return FALSE; -} - -LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()? -{ - return NULL; -} - -AggregateDeclaration *Dsymbol::isMember() // is this a member of an AggregateDeclaration? -{ - Dsymbol *parent = toParent(); - return parent ? parent->isAggregateDeclaration() : NULL; -} - -Type *Dsymbol::getType() -{ - return NULL; -} - -int Dsymbol::needThis() -{ - return FALSE; -} - -int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) -{ - //printf("Dsymbol::addMember('%s')\n", toChars()); - //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sd->toChars()); - //printf("Dsymbol::addMember(this = %p, '%s' sd = %p, sd->symtab = %p)\n", this, toChars(), sd, sd->symtab); - parent = sd; - if (!isAnonymous()) // no name, so can't add it to symbol table - { - if (!sd->symtab->insert(this)) // if name is already defined - { - Dsymbol *s2; - - s2 = sd->symtab->lookup(ident); - if (!s2->overloadInsert(this)) - { - sd->multiplyDefined(0, this, s2); - } - } - if (sd->isAggregateDeclaration() || sd->isEnumDeclaration()) - { - if (ident == Id::__sizeof || ident == Id::alignof || ident == Id::mangleof) - error(".%s property cannot be redefined", ident->toChars()); - } - return 1; - } - return 0; -} - -void Dsymbol::error(const char *format, ...) -{ - //printf("Dsymbol::error()\n"); - if (!global.gag) - { - char *p = locToChars(); - - if (*p) - fprintf(stdmsg, "%s: ", p); - mem.free(p); - - if (isAnonymous()) - fprintf(stdmsg, "%s ", kind()); - else - fprintf(stdmsg, "%s %s ", kind(), toPrettyChars()); - - va_list ap; - va_start(ap, format); - vfprintf(stdmsg, format, ap); - va_end(ap); - - fprintf(stdmsg, "\n"); - fflush(stdmsg); - } - global.errors++; - - //fatal(); -} - -void Dsymbol::error(Loc loc, const char *format, ...) -{ - if (!global.gag) - { - char *p = loc.toChars(); - if (!*p) - p = locToChars(); - - if (*p) - fprintf(stdmsg, "%s: ", p); - mem.free(p); - - fprintf(stdmsg, "%s %s ", kind(), toPrettyChars()); - - va_list ap; - va_start(ap, format); - vfprintf(stdmsg, format, ap); - va_end(ap); - - fprintf(stdmsg, "\n"); - fflush(stdmsg); - } - - global.errors++; - - //fatal(); -} - -void Dsymbol::checkDeprecated(Loc loc, Scope *sc) -{ - if (!global.params.useDeprecated && isDeprecated()) - { - // Don't complain if we're inside a deprecated symbol's scope - for (Dsymbol *sp = sc->parent; sp; sp = sp->parent) - { if (sp->isDeprecated()) - return; - } - - for (; sc; sc = sc->enclosing) - { - if (sc->scopesym && sc->scopesym->isDeprecated()) - return; - } - - error(loc, "is deprecated"); - } -} - -/********************************** - * Determine which Module a Dsymbol is in. - */ - -Module *Dsymbol::getModule() -{ - Module *m; - Dsymbol *s; - - //printf("Dsymbol::getModule()\n"); - s = this; - while (s) - { - //printf("\ts = '%s'\n", s->toChars()); - m = s->isModule(); - if (m) - return m; - s = s->parent; - } - return NULL; -} - -/************************************* - */ - -enum PROT Dsymbol::prot() -{ - return PROTpublic; -} - -/************************************* - * Do syntax copy of an array of Dsymbol's. - */ - - -Array *Dsymbol::arraySyntaxCopy(Array *a) -{ - - Array *b = NULL; - if (a) - { - b = a->copy(); - for (int i = 0; i < b->dim; i++) - { - Dsymbol *s = (Dsymbol *)b->data[i]; - - s = s->syntaxCopy(NULL); - b->data[i] = (void *)s; - } - } - return b; -} - - -/**************************************** - * Add documentation comment to Dsymbol. - * Ignore NULL comments. - */ - -void Dsymbol::addComment(unsigned char *comment) -{ -// if (comment) -// printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars()); - - if (!this->comment) - this->comment = comment; -#if 1 - else if (comment && strcmp((char *)comment, (char *)this->comment)) - { // Concatenate the two - this->comment = Lexer::combineComments(this->comment, comment); - } -#endif -} - - -/********************************* ScopeDsymbol ****************************/ - -ScopeDsymbol::ScopeDsymbol() - : Dsymbol() -{ - members = NULL; - symtab = NULL; - imports = NULL; - prots = NULL; -} - -ScopeDsymbol::ScopeDsymbol(Identifier *id) - : Dsymbol(id) -{ - members = NULL; - symtab = NULL; - imports = NULL; - prots = NULL; -} - -Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s) -{ - //printf("ScopeDsymbol::syntaxCopy('%s')\n", toChars()); - - ScopeDsymbol *sd; - if (s) - sd = (ScopeDsymbol *)s; - else - sd = new ScopeDsymbol(ident); - sd->members = arraySyntaxCopy(members); - return sd; -} - -Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags) -{ Dsymbol *s; - int i; - - //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags); - // Look in symbols declared in this module - s = symtab ? symtab->lookup(ident) : NULL; - if (s) - { - //printf("\ts = '%s.%s'\n",toChars(),s->toChars()); - } - else if (imports) - { - // Look in imported modules - for (i = 0; i < imports->dim; i++) - { ScopeDsymbol *ss = (ScopeDsymbol *)imports->data[i]; - Dsymbol *s2; - - // If private import, don't search it - if (flags & 1 && prots[i] == PROTprivate) - continue; - - //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport()); - s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0); - if (!s) - s = s2; - else if (s2 && s != s2) - { - if (s->toAlias() == s2->toAlias()) - { - if (s->isDeprecated()) - s = s2; - } - else - { - /* Two imports of the same module should be regarded as - * the same. - */ - Import *i1 = s->isImport(); - Import *i2 = s2->isImport(); - if (!(i1 && i2 && - (i1->mod == i2->mod || - (!i1->parent->isImport() && !i2->parent->isImport() && - i1->ident->equals(i2->ident)) - ) - ) - ) - { - ss->multiplyDefined(loc, s, s2); - break; - } - } - } - } - if (s) - { - Declaration *d = s->isDeclaration(); - if (d && d->protection == PROTprivate && !d->parent->isTemplateMixin()) - error("%s is private", d->toPrettyChars()); - } - } - return s; -} - -void ScopeDsymbol::importScope(ScopeDsymbol *s, enum PROT protection) -{ - //printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection); - - // No circular or redundant import's - if (s != this) - { - if (!imports) - imports = new Array(); - else - { - for (int i = 0; i < imports->dim; i++) - { ScopeDsymbol *ss; - - ss = (ScopeDsymbol *) imports->data[i]; - if (ss == s) - { - if (protection > prots[i]) - prots[i] = protection; // upgrade access - return; - } - } - } - imports->push(s); - prots = (unsigned char *)mem.realloc(prots, imports->dim * sizeof(prots[0])); - prots[imports->dim - 1] = protection; - } -} - -int ScopeDsymbol::isforwardRef() -{ - return (members == NULL); -} - -void ScopeDsymbol::defineRef(Dsymbol *s) -{ - ScopeDsymbol *ss; - - ss = s->isScopeDsymbol(); - members = ss->members; - ss->members = NULL; -} - -void ScopeDsymbol::multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2) -{ -#if 0 - printf("ScopeDsymbol::multiplyDefined()\n"); - printf("s1 = %p, '%s' kind = '%s', parent = %s\n", s1, s1->toChars(), s1->kind(), s1->parent ? s1->parent->toChars() : ""); - printf("s2 = %p, '%s' kind = '%s', parent = %s\n", s2, s2->toChars(), s2->kind(), s2->parent ? s2->parent->toChars() : ""); -#endif - if (loc.filename) - { ::error(loc, "%s at %s conflicts with %s at %s", - s1->toPrettyChars(), - s1->locToChars(), - s2->toPrettyChars(), - s2->locToChars()); - } - else - { - s1->error(loc, "conflicts with %s %s at %s", - s2->kind(), - s2->toPrettyChars(), - s2->locToChars()); - } -} - -Dsymbol *ScopeDsymbol::nameCollision(Dsymbol *s) -{ - Dsymbol *sprev; - - // Look to see if we are defining a forward referenced symbol - - sprev = symtab->lookup(s->ident); - assert(sprev); - if (s->equals(sprev)) // if the same symbol - { - if (s->isforwardRef()) // if second declaration is a forward reference - return sprev; - if (sprev->isforwardRef()) - { - sprev->defineRef(s); // copy data from s into sprev - return sprev; - } - } - multiplyDefined(0, s, sprev); - return sprev; -} - -char *ScopeDsymbol::kind() -{ - return "ScopeDsymbol"; -} - - -/******************************************* - * Look for member of the form: - * const(MemberInfo)[] getMembers(string); - * Returns NULL if not found - */ - -#if V2 -FuncDeclaration *ScopeDsymbol::findGetMembers() -{ - Dsymbol *s = search_function(this, Id::getmembers); - FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL; - -#if 0 // Finish - static TypeFunction *tfgetmembers; - - if (!tfgetmembers) - { - Scope sc; - Arguments *arguments = new Arguments; - Arguments *arg = new Argument(STCin, Type::tchar->constOf()->arrayOf(), NULL, NULL); - arguments->push(arg); - - Type *tret = NULL; - tfgetmembers = new TypeFunction(arguments, tret, 0, LINKd); - tfgetmembers = (TypeFunction *)tfgetmembers->semantic(0, &sc); - } - if (fdx) - fdx = fdx->overloadExactMatch(tfgetmembers); -#endif - if (fdx && fdx->isVirtual()) - fdx = NULL; - - return fdx; -} -#endif - - -/****************************** WithScopeSymbol ******************************/ - -WithScopeSymbol::WithScopeSymbol(WithStatement *withstate) - : ScopeDsymbol() -{ - this->withstate = withstate; -} - -Dsymbol *WithScopeSymbol::search(Loc loc, Identifier *ident, int flags) -{ - // Acts as proxy to the with class declaration - return withstate->exp->type->toDsymbol(NULL)->search(loc, ident, 0); -} - -/****************************** ArrayScopeSymbol ******************************/ - -ArrayScopeSymbol::ArrayScopeSymbol(Expression *e) - : ScopeDsymbol() -{ - assert(e->op == TOKindex || e->op == TOKslice); - exp = e; - type = NULL; - td = NULL; -} - -ArrayScopeSymbol::ArrayScopeSymbol(TypeTuple *t) - : ScopeDsymbol() -{ - exp = NULL; - type = t; - td = NULL; -} - -ArrayScopeSymbol::ArrayScopeSymbol(TupleDeclaration *s) - : ScopeDsymbol() -{ - exp = NULL; - type = NULL; - td = s; -} - -Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) -{ - //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident->toChars(), flags); - if (ident == Id::length || ident == Id::dollar) - { VarDeclaration **pvar; - Expression *ce; - - L1: - - if (td) - { - VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); - Expression *e = new IntegerExp(0, td->objects->dim, Type::tsize_t); - v->init = new ExpInitializer(0, e); - v->storage_class |= STCconst; - return v; - } - - if (type) - { - VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); - Expression *e = new IntegerExp(0, type->arguments->dim, Type::tsize_t); - v->init = new ExpInitializer(0, e); - v->storage_class |= STCconst; - return v; - } - - if (exp->op == TOKindex) - { - IndexExp *ie = (IndexExp *)exp; - - pvar = &ie->lengthVar; - ce = ie->e1; - } - else if (exp->op == TOKslice) - { - SliceExp *se = (SliceExp *)exp; - - pvar = &se->lengthVar; - ce = se->e1; - } - else - return NULL; - - if (ce->op == TOKtype) - { - Type *t = ((TypeExp *)ce)->type; - if (t->ty == Ttuple) - { type = (TypeTuple *)t; - goto L1; - } - } - - if (!*pvar) - { - VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); - - if (ce->op == TOKstring) - { /* It is for a string literal, so the - * length will be a const. - */ - Expression *e = new IntegerExp(0, ((StringExp *)ce)->len, Type::tsize_t); - v->init = new ExpInitializer(0, e); - v->storage_class |= STCconst; - } - else if (ce->op == TOKarrayliteral) - { /* It is for an array literal, so the - * length will be a const. - */ - Expression *e = new IntegerExp(0, ((ArrayLiteralExp *)ce)->elements->dim, Type::tsize_t); - v->init = new ExpInitializer(0, e); - v->storage_class |= STCconst; - } - else if (ce->op == TOKtuple) - { /* It is for an expression tuple, so the - * length will be a const. - */ - Expression *e = new IntegerExp(0, ((TupleExp *)ce)->exps->dim, Type::tsize_t); - v->init = new ExpInitializer(0, e); - v->storage_class |= STCconst; - } - *pvar = v; - } - return (*pvar); - } - return NULL; -} - - -/****************************** DsymbolTable ******************************/ - -DsymbolTable::DsymbolTable() -{ - tab = new StringTable; -} - -DsymbolTable::~DsymbolTable() -{ - delete tab; -} - -Dsymbol *DsymbolTable::lookup(Identifier *ident) -{ StringValue *sv; - -#ifdef DEBUG - assert(ident); - assert(tab); -#endif - sv = tab->lookup((char*)ident->string, ident->len); - return (Dsymbol *)(sv ? sv->ptrvalue : NULL); -} - -Dsymbol *DsymbolTable::insert(Dsymbol *s) -{ StringValue *sv; - Identifier *ident; - - //printf("DsymbolTable::insert(this = %p, '%s')\n", this, s->ident->toChars()); - ident = s->ident; -#ifdef DEBUG - assert(ident); - assert(tab); -#endif - sv = tab->insert(ident->toChars(), ident->len); - if (!sv) - return NULL; // already in table - sv->ptrvalue = s; - return s; -} - -Dsymbol *DsymbolTable::insert(Identifier *ident, Dsymbol *s) -{ StringValue *sv; - - //printf("DsymbolTable::insert()\n"); - sv = tab->insert(ident->toChars(), ident->len); - if (!sv) - return NULL; // already in table - sv->ptrvalue = s; - return s; -} - -Dsymbol *DsymbolTable::update(Dsymbol *s) -{ StringValue *sv; - Identifier *ident; - - ident = s->ident; - sv = tab->update(ident->toChars(), ident->len); - sv->ptrvalue = s; - return s; -} - - - - + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2007 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// http://www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include "mem.h" + +#include "mars.h" +#include "dsymbol.h" +#include "aggregate.h" +#include "identifier.h" +#include "module.h" +#include "mtype.h" +#include "expression.h" +#include "statement.h" +#include "declaration.h" +#include "id.h" +#include "scope.h" +#include "init.h" +#include "import.h" +#include "template.h" + +#include "../gen/enums.h" + +/****************************** Dsymbol ******************************/ + +Dsymbol::Dsymbol() +{ + //printf("Dsymbol::Dsymbol(%p)\n", this); + this->ident = NULL; + this->c_ident = NULL; + this->parent = NULL; + this->csym = NULL; + this->isym = NULL; + this->loc = 0; + this->comment = NULL; + + this->llvmInternal = LLVMnone; + this->llvmInternal1 = NULL; + this->llvmInternal2 = NULL; +} + +Dsymbol::Dsymbol(Identifier *ident) +{ + //printf("Dsymbol::Dsymbol(%p, ident)\n", this); + this->ident = ident; + this->c_ident = NULL; + this->parent = NULL; + this->csym = NULL; + this->isym = NULL; + this->loc = 0; + this->comment = NULL; + + this->llvmInternal = LLVMnone; + this->llvmInternal1 = NULL; + this->llvmInternal2 = NULL; +} + +int Dsymbol::equals(Object *o) +{ Dsymbol *s; + + if (this == o) + return TRUE; + s = (Dsymbol *)(o); + if (s && ident->equals(s->ident)) + return TRUE; + return FALSE; +} + +/************************************** + * Copy the syntax. + * Used for template instantiations. + * If s is NULL, allocate the new object, otherwise fill it in. + */ + +Dsymbol *Dsymbol::syntaxCopy(Dsymbol *s) +{ + print(); + printf("%s %s\n", kind(), toChars()); + assert(0); + return NULL; +} + +/************************************** + * Determine if this symbol is only one. + * Returns: + * FALSE, *ps = NULL: There are 2 or more symbols + * TRUE, *ps = NULL: There are zero symbols + * TRUE, *ps = symbol: The one and only one symbol + */ + +int Dsymbol::oneMember(Dsymbol **ps) +{ + //printf("Dsymbol::oneMember()\n"); + *ps = this; + return TRUE; +} + +/***************************************** + * Same as Dsymbol::oneMember(), but look at an array of Dsymbols. + */ + +int Dsymbol::oneMembers(Array *members, Dsymbol **ps) +{ + //printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0); + Dsymbol *s = NULL; + + if (members) + { + for (int i = 0; i < members->dim; i++) + { Dsymbol *sx = (Dsymbol *)members->data[i]; + + int x = sx->oneMember(ps); + //printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps); + if (!x) + { + //printf("\tfalse 1\n"); + assert(*ps == NULL); + return FALSE; + } + if (*ps) + { + if (s) // more than one symbol + { *ps = NULL; + //printf("\tfalse 2\n"); + return FALSE; + } + s = *ps; + } + } + } + *ps = s; // s is the one symbol, NULL if none + //printf("\ttrue\n"); + return TRUE; +} + +/***************************************** + * Is Dsymbol a variable that contains pointers? + */ + +int Dsymbol::hasPointers() +{ + //printf("Dsymbol::hasPointers() %s\n", toChars()); + return 0; +} + +char *Dsymbol::toChars() +{ + return ident ? ident->toChars() : (char *)"__anonymous"; +} + +char *Dsymbol::toPrettyChars() +{ Dsymbol *p; + char *s; + char *q; + size_t len; + + //printf("Dsymbol::toPrettyChars() '%s'\n", toChars()); + if (!parent) + return toChars(); + + len = 0; + for (p = this; p; p = p->parent) + len += strlen(p->toChars()) + 1; + + s = (char *)mem.malloc(len); + q = s + len - 1; + *q = 0; + for (p = this; p; p = p->parent) + { + char *t = p->toChars(); + len = strlen(t); + q -= len; + memcpy(q, t, len); + if (q == s) + break; + q--; + *q = '.'; + } + return s; +} + +char *Dsymbol::locToChars() +{ + OutBuffer buf; + char *p; + + Module *m = getModule(); + + if (m && m->srcfile) + loc.filename = m->srcfile->toChars(); + return loc.toChars(); +} + +char *Dsymbol::kind() +{ + return "symbol"; +} + +/********************************* + * If this symbol is really an alias for another, + * return that other. + */ + +Dsymbol *Dsymbol::toAlias() +{ + return this; +} + +Dsymbol *Dsymbol::toParent() +{ + return parent ? parent->pastMixin() : NULL; +} + +Dsymbol *Dsymbol::pastMixin() +{ + Dsymbol *s = this; + + //printf("Dsymbol::pastMixin() %s\n", toChars()); + while (s && s->isTemplateMixin()) + s = s->parent; + return s; +} + +/********************************** + * Use this instead of toParent() when looking for the + * 'this' pointer of the enclosing function/class. + */ + +Dsymbol *Dsymbol::toParent2() +{ + Dsymbol *s = parent; + while (s && s->isTemplateInstance()) + s = s->parent; + return s; +} + + +int Dsymbol::isAnonymous() +{ + return ident ? 0 : 1; +} + +void Dsymbol::semantic(Scope *sc) +{ + error("%p has no semantic routine", this); +} + +void Dsymbol::semantic2(Scope *sc) +{ + // Most Dsymbols have no further semantic analysis needed +} + +void Dsymbol::semantic3(Scope *sc) +{ + // Most Dsymbols have no further semantic analysis needed +} + +void Dsymbol::inlineScan() +{ + // Most Dsymbols have no further semantic analysis needed +} + +Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags) +{ + //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars()); + return NULL; +} + +/*************************************** + * Search for identifier id as a member of 'this'. + * id may be a template instance. + * Returns: + * symbol found, NULL if not + */ + +Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id) +{ + //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars()); + Dsymbol *s = toAlias(); + Dsymbol *sm; + + switch (id->dyncast()) + { + case DYNCAST_IDENTIFIER: + sm = s->search(loc, id, 0); + break; + + case DYNCAST_DSYMBOL: + { // It's a template instance + //printf("\ttemplate instance id\n"); + Dsymbol *st = (Dsymbol *)id; + TemplateInstance *ti = st->isTemplateInstance(); + id = ti->name; + sm = s->search(loc, id, 0); + if (!sm) + { error("template identifier %s is not a member of %s %s", + id->toChars(), s->kind(), s->toChars()); + return NULL; + } + sm = sm->toAlias(); + TemplateDeclaration *td = sm->isTemplateDeclaration(); + if (!td) + { + error("%s is not a template, it is a %s", id->toChars(), sm->kind()); + return NULL; + } + ti->tempdecl = td; + if (!ti->semanticdone) + ti->semantic(sc); + sm = ti->toAlias(); + break; + } + + default: + assert(0); + } + return sm; +} + +int Dsymbol::overloadInsert(Dsymbol *s) +{ + //printf("Dsymbol::overloadInsert('%s')\n", s->toChars()); + return FALSE; +} + +void Dsymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + buf->writestring(toChars()); +} + +unsigned Dsymbol::size(Loc loc) +{ + error("Dsymbol '%s' has no size\n", toChars()); + return 0; +} + +int Dsymbol::isforwardRef() +{ + return FALSE; +} + +AggregateDeclaration *Dsymbol::isThis() +{ + return NULL; +} + +ClassDeclaration *Dsymbol::isClassMember() // are we a member of a class? +{ + Dsymbol *parent = toParent(); + if (parent && parent->isClassDeclaration()) + return (ClassDeclaration *)parent; + return NULL; +} + +void Dsymbol::defineRef(Dsymbol *s) +{ + assert(0); +} + +int Dsymbol::isExport() +{ + return FALSE; +} + +int Dsymbol::isImportedSymbol() +{ + return FALSE; +} + +int Dsymbol::isDeprecated() +{ + return FALSE; +} + +LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()? +{ + return NULL; +} + +AggregateDeclaration *Dsymbol::isMember() // is this a member of an AggregateDeclaration? +{ + Dsymbol *parent = toParent(); + return parent ? parent->isAggregateDeclaration() : NULL; +} + +Type *Dsymbol::getType() +{ + return NULL; +} + +int Dsymbol::needThis() +{ + return FALSE; +} + +int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) +{ + //printf("Dsymbol::addMember('%s')\n", toChars()); + //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sd->toChars()); + //printf("Dsymbol::addMember(this = %p, '%s' sd = %p, sd->symtab = %p)\n", this, toChars(), sd, sd->symtab); + parent = sd; + if (!isAnonymous()) // no name, so can't add it to symbol table + { + if (!sd->symtab->insert(this)) // if name is already defined + { + Dsymbol *s2; + + s2 = sd->symtab->lookup(ident); + if (!s2->overloadInsert(this)) + { + sd->multiplyDefined(0, this, s2); + } + } + if (sd->isAggregateDeclaration() || sd->isEnumDeclaration()) + { + if (ident == Id::__sizeof || ident == Id::alignof || ident == Id::mangleof) + error(".%s property cannot be redefined", ident->toChars()); + } + return 1; + } + return 0; +} + +void Dsymbol::error(const char *format, ...) +{ + //printf("Dsymbol::error()\n"); + if (!global.gag) + { + char *p = locToChars(); + + if (*p) + fprintf(stdmsg, "%s: ", p); + mem.free(p); + + if (isAnonymous()) + fprintf(stdmsg, "%s ", kind()); + else + fprintf(stdmsg, "%s %s ", kind(), toPrettyChars()); + + va_list ap; + va_start(ap, format); + vfprintf(stdmsg, format, ap); + va_end(ap); + + fprintf(stdmsg, "\n"); + fflush(stdmsg); + } + global.errors++; + + //fatal(); +} + +void Dsymbol::error(Loc loc, const char *format, ...) +{ + if (!global.gag) + { + char *p = loc.toChars(); + if (!*p) + p = locToChars(); + + if (*p) + fprintf(stdmsg, "%s: ", p); + mem.free(p); + + fprintf(stdmsg, "%s %s ", kind(), toPrettyChars()); + + va_list ap; + va_start(ap, format); + vfprintf(stdmsg, format, ap); + va_end(ap); + + fprintf(stdmsg, "\n"); + fflush(stdmsg); + } + + global.errors++; + + //fatal(); +} + +void Dsymbol::checkDeprecated(Loc loc, Scope *sc) +{ + if (!global.params.useDeprecated && isDeprecated()) + { + // Don't complain if we're inside a deprecated symbol's scope + for (Dsymbol *sp = sc->parent; sp; sp = sp->parent) + { if (sp->isDeprecated()) + return; + } + + for (; sc; sc = sc->enclosing) + { + if (sc->scopesym && sc->scopesym->isDeprecated()) + return; + } + + error(loc, "is deprecated"); + } +} + +/********************************** + * Determine which Module a Dsymbol is in. + */ + +Module *Dsymbol::getModule() +{ + Module *m; + Dsymbol *s; + + //printf("Dsymbol::getModule()\n"); + s = this; + while (s) + { + //printf("\ts = '%s'\n", s->toChars()); + m = s->isModule(); + if (m) + return m; + s = s->parent; + } + return NULL; +} + +/************************************* + */ + +enum PROT Dsymbol::prot() +{ + return PROTpublic; +} + +/************************************* + * Do syntax copy of an array of Dsymbol's. + */ + + +Array *Dsymbol::arraySyntaxCopy(Array *a) +{ + + Array *b = NULL; + if (a) + { + b = a->copy(); + for (int i = 0; i < b->dim; i++) + { + Dsymbol *s = (Dsymbol *)b->data[i]; + + s = s->syntaxCopy(NULL); + b->data[i] = (void *)s; + } + } + return b; +} + + +/**************************************** + * Add documentation comment to Dsymbol. + * Ignore NULL comments. + */ + +void Dsymbol::addComment(unsigned char *comment) +{ +// if (comment) +// printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars()); + + if (!this->comment) + this->comment = comment; +#if 1 + else if (comment && strcmp((char *)comment, (char *)this->comment)) + { // Concatenate the two + this->comment = Lexer::combineComments(this->comment, comment); + } +#endif +} + + +/********************************* ScopeDsymbol ****************************/ + +ScopeDsymbol::ScopeDsymbol() + : Dsymbol() +{ + members = NULL; + symtab = NULL; + imports = NULL; + prots = NULL; +} + +ScopeDsymbol::ScopeDsymbol(Identifier *id) + : Dsymbol(id) +{ + members = NULL; + symtab = NULL; + imports = NULL; + prots = NULL; +} + +Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s) +{ + //printf("ScopeDsymbol::syntaxCopy('%s')\n", toChars()); + + ScopeDsymbol *sd; + if (s) + sd = (ScopeDsymbol *)s; + else + sd = new ScopeDsymbol(ident); + sd->members = arraySyntaxCopy(members); + return sd; +} + +Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags) +{ Dsymbol *s; + int i; + + //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags); + // Look in symbols declared in this module + s = symtab ? symtab->lookup(ident) : NULL; + if (s) + { + //printf("\ts = '%s.%s'\n",toChars(),s->toChars()); + } + else if (imports) + { + // Look in imported modules + for (i = 0; i < imports->dim; i++) + { ScopeDsymbol *ss = (ScopeDsymbol *)imports->data[i]; + Dsymbol *s2; + + // If private import, don't search it + if (flags & 1 && prots[i] == PROTprivate) + continue; + + //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport()); + s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0); + if (!s) + s = s2; + else if (s2 && s != s2) + { + if (s->toAlias() == s2->toAlias()) + { + if (s->isDeprecated()) + s = s2; + } + else + { + /* Two imports of the same module should be regarded as + * the same. + */ + Import *i1 = s->isImport(); + Import *i2 = s2->isImport(); + if (!(i1 && i2 && + (i1->mod == i2->mod || + (!i1->parent->isImport() && !i2->parent->isImport() && + i1->ident->equals(i2->ident)) + ) + ) + ) + { + ss->multiplyDefined(loc, s, s2); + break; + } + } + } + } + if (s) + { + Declaration *d = s->isDeclaration(); + if (d && d->protection == PROTprivate && !d->parent->isTemplateMixin()) + error("%s is private", d->toPrettyChars()); + } + } + return s; +} + +void ScopeDsymbol::importScope(ScopeDsymbol *s, enum PROT protection) +{ + //printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection); + + // No circular or redundant import's + if (s != this) + { + if (!imports) + imports = new Array(); + else + { + for (int i = 0; i < imports->dim; i++) + { ScopeDsymbol *ss; + + ss = (ScopeDsymbol *) imports->data[i]; + if (ss == s) + { + if (protection > prots[i]) + prots[i] = protection; // upgrade access + return; + } + } + } + imports->push(s); + prots = (unsigned char *)mem.realloc(prots, imports->dim * sizeof(prots[0])); + prots[imports->dim - 1] = protection; + } +} + +int ScopeDsymbol::isforwardRef() +{ + return (members == NULL); +} + +void ScopeDsymbol::defineRef(Dsymbol *s) +{ + ScopeDsymbol *ss; + + ss = s->isScopeDsymbol(); + members = ss->members; + ss->members = NULL; +} + +void ScopeDsymbol::multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2) +{ +#if 0 + printf("ScopeDsymbol::multiplyDefined()\n"); + printf("s1 = %p, '%s' kind = '%s', parent = %s\n", s1, s1->toChars(), s1->kind(), s1->parent ? s1->parent->toChars() : ""); + printf("s2 = %p, '%s' kind = '%s', parent = %s\n", s2, s2->toChars(), s2->kind(), s2->parent ? s2->parent->toChars() : ""); +#endif + if (loc.filename) + { ::error(loc, "%s at %s conflicts with %s at %s", + s1->toPrettyChars(), + s1->locToChars(), + s2->toPrettyChars(), + s2->locToChars()); + } + else + { + s1->error(loc, "conflicts with %s %s at %s", + s2->kind(), + s2->toPrettyChars(), + s2->locToChars()); + } +} + +Dsymbol *ScopeDsymbol::nameCollision(Dsymbol *s) +{ + Dsymbol *sprev; + + // Look to see if we are defining a forward referenced symbol + + sprev = symtab->lookup(s->ident); + assert(sprev); + if (s->equals(sprev)) // if the same symbol + { + if (s->isforwardRef()) // if second declaration is a forward reference + return sprev; + if (sprev->isforwardRef()) + { + sprev->defineRef(s); // copy data from s into sprev + return sprev; + } + } + multiplyDefined(0, s, sprev); + return sprev; +} + +char *ScopeDsymbol::kind() +{ + return "ScopeDsymbol"; +} + + +/******************************************* + * Look for member of the form: + * const(MemberInfo)[] getMembers(string); + * Returns NULL if not found + */ + +#if V2 +FuncDeclaration *ScopeDsymbol::findGetMembers() +{ + Dsymbol *s = search_function(this, Id::getmembers); + FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL; + +#if 0 // Finish + static TypeFunction *tfgetmembers; + + if (!tfgetmembers) + { + Scope sc; + Arguments *arguments = new Arguments; + Arguments *arg = new Argument(STCin, Type::tchar->constOf()->arrayOf(), NULL, NULL); + arguments->push(arg); + + Type *tret = NULL; + tfgetmembers = new TypeFunction(arguments, tret, 0, LINKd); + tfgetmembers = (TypeFunction *)tfgetmembers->semantic(0, &sc); + } + if (fdx) + fdx = fdx->overloadExactMatch(tfgetmembers); +#endif + if (fdx && fdx->isVirtual()) + fdx = NULL; + + return fdx; +} +#endif + + +/****************************** WithScopeSymbol ******************************/ + +WithScopeSymbol::WithScopeSymbol(WithStatement *withstate) + : ScopeDsymbol() +{ + this->withstate = withstate; +} + +Dsymbol *WithScopeSymbol::search(Loc loc, Identifier *ident, int flags) +{ + // Acts as proxy to the with class declaration + return withstate->exp->type->toDsymbol(NULL)->search(loc, ident, 0); +} + +/****************************** ArrayScopeSymbol ******************************/ + +ArrayScopeSymbol::ArrayScopeSymbol(Expression *e) + : ScopeDsymbol() +{ + assert(e->op == TOKindex || e->op == TOKslice); + exp = e; + type = NULL; + td = NULL; +} + +ArrayScopeSymbol::ArrayScopeSymbol(TypeTuple *t) + : ScopeDsymbol() +{ + exp = NULL; + type = t; + td = NULL; +} + +ArrayScopeSymbol::ArrayScopeSymbol(TupleDeclaration *s) + : ScopeDsymbol() +{ + exp = NULL; + type = NULL; + td = s; +} + +Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) +{ + //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident->toChars(), flags); + if (ident == Id::length || ident == Id::dollar) + { VarDeclaration **pvar; + Expression *ce; + + L1: + + if (td) + { + VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); + Expression *e = new IntegerExp(0, td->objects->dim, Type::tsize_t); + v->init = new ExpInitializer(0, e); + v->storage_class |= STCconst; + return v; + } + + if (type) + { + VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); + Expression *e = new IntegerExp(0, type->arguments->dim, Type::tsize_t); + v->init = new ExpInitializer(0, e); + v->storage_class |= STCconst; + return v; + } + + if (exp->op == TOKindex) + { + IndexExp *ie = (IndexExp *)exp; + + pvar = &ie->lengthVar; + ce = ie->e1; + } + else if (exp->op == TOKslice) + { + SliceExp *se = (SliceExp *)exp; + + pvar = &se->lengthVar; + ce = se->e1; + } + else + return NULL; + + if (ce->op == TOKtype) + { + Type *t = ((TypeExp *)ce)->type; + if (t->ty == Ttuple) + { type = (TypeTuple *)t; + goto L1; + } + } + + if (!*pvar) + { + VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); + + if (ce->op == TOKstring) + { /* It is for a string literal, so the + * length will be a const. + */ + Expression *e = new IntegerExp(0, ((StringExp *)ce)->len, Type::tsize_t); + v->init = new ExpInitializer(0, e); + v->storage_class |= STCconst; + } + else if (ce->op == TOKarrayliteral) + { /* It is for an array literal, so the + * length will be a const. + */ + Expression *e = new IntegerExp(0, ((ArrayLiteralExp *)ce)->elements->dim, Type::tsize_t); + v->init = new ExpInitializer(0, e); + v->storage_class |= STCconst; + } + else if (ce->op == TOKtuple) + { /* It is for an expression tuple, so the + * length will be a const. + */ + Expression *e = new IntegerExp(0, ((TupleExp *)ce)->exps->dim, Type::tsize_t); + v->init = new ExpInitializer(0, e); + v->storage_class |= STCconst; + } + *pvar = v; + } + return (*pvar); + } + return NULL; +} + + +/****************************** DsymbolTable ******************************/ + +DsymbolTable::DsymbolTable() +{ + tab = new StringTable; +} + +DsymbolTable::~DsymbolTable() +{ + delete tab; +} + +Dsymbol *DsymbolTable::lookup(Identifier *ident) +{ StringValue *sv; + +#ifdef DEBUG + assert(ident); + assert(tab); +#endif + sv = tab->lookup((char*)ident->string, ident->len); + return (Dsymbol *)(sv ? sv->ptrvalue : NULL); +} + +Dsymbol *DsymbolTable::insert(Dsymbol *s) +{ StringValue *sv; + Identifier *ident; + + //printf("DsymbolTable::insert(this = %p, '%s')\n", this, s->ident->toChars()); + ident = s->ident; +#ifdef DEBUG + assert(ident); + assert(tab); +#endif + sv = tab->insert(ident->toChars(), ident->len); + if (!sv) + return NULL; // already in table + sv->ptrvalue = s; + return s; +} + +Dsymbol *DsymbolTable::insert(Identifier *ident, Dsymbol *s) +{ StringValue *sv; + + //printf("DsymbolTable::insert()\n"); + sv = tab->insert(ident->toChars(), ident->len); + if (!sv) + return NULL; // already in table + sv->ptrvalue = s; + return s; +} + +Dsymbol *DsymbolTable::update(Dsymbol *s) +{ StringValue *sv; + Identifier *ident; + + ident = s->ident; + sv = tab->update(ident->toChars(), ident->len); + sv->ptrvalue = s; + return s; +} + + + +