Skip to content

Commit

Permalink
Merge pull request #3107 from 9rnsr/fix11931
Browse files Browse the repository at this point in the history
[REG2.065a] Issue 11931 - Linkers "Symbol Undefined" again with dmd HEAD when -g specified
  • Loading branch information
WalterBright authored and AndrewEdwards committed Jan 22, 2014
1 parent ee4af52 commit 010ffc6
Show file tree
Hide file tree
Showing 15 changed files with 294 additions and 129 deletions.
3 changes: 2 additions & 1 deletion src/declaration.h
Expand Up @@ -617,7 +617,7 @@ class FuncDeclaration : public Declaration
int inlineNest; // !=0 if nested inline
bool isArrayOp; // true if array operation
FuncDeclaration *dArrayOp; // D version of array op for ctfe
int semantic3Errors; // !=0 if errors in semantic3
bool semantic3Errors; // true if errors in semantic3
// this function's frame ptr
ForeachStatement *fes; // if foreach body, this is the foreach
bool introducing; // true if 'introducing' function
Expand Down Expand Up @@ -738,6 +738,7 @@ class FuncDeclaration : public Declaration
void toObjFile(int multiobj); // compile to .obj file
int cvMember(unsigned char *p);
void buildClosure(IRState *irs);
bool needsCodegen();

FuncDeclaration *isFuncDeclaration() { return this; }

Expand Down
27 changes: 27 additions & 0 deletions src/dsymbol.c
Expand Up @@ -810,6 +810,33 @@ void Dsymbol::addComment(const utf8_t *comment)
}
}

/****************************************
* Returns true if this symbol is defined in non-root module.
*/

bool Dsymbol::inNonRoot()
{
Dsymbol *s = parent;
for (; s; s = s->parent)
{
if (TemplateInstance *ti = s->isTemplateInstance())
{
if (ti->isTemplateMixin())
continue;
if (!ti->instantiatingModule || !ti->instantiatingModule->isRoot())
return true;
return false;
}
else if (Module *m = s->isModule())
{
if (!m->isRoot())
return true;
break;
}
}
return false;
}

/********************************* OverloadSet ****************************/

OverloadSet::OverloadSet(Identifier *ident)
Expand Down
2 changes: 2 additions & 0 deletions src/dsymbol.h
Expand Up @@ -217,6 +217,8 @@ class Dsymbol : public RootObject
virtual void emitComment(Scope *sc);
void emitDitto(Scope *sc);

bool inNonRoot();

// Backend

virtual Symbol *toSymbol(); // to backend symbol
Expand Down
103 changes: 85 additions & 18 deletions src/func.c
Expand Up @@ -74,7 +74,7 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
ctfeCode = NULL;
isArrayOp = 0;
dArrayOp = NULL;
semantic3Errors = 0;
semantic3Errors = false;
fes = NULL;
introducing = 0;
tintro = NULL;
Expand Down Expand Up @@ -971,7 +971,7 @@ void FuncDeclaration::semantic3(Scope *sc)
if (semanticRun >= PASSsemantic3)
return;
semanticRun = PASSsemantic3;
semantic3Errors = 0;
semantic3Errors = false;

if (!type || type->ty != Tfunction)
return;
Expand Down Expand Up @@ -1855,22 +1855,12 @@ void FuncDeclaration::semantic3(Scope *sc)
sc = sc->pop();
}

if (global.gag && global.errors != nerrors)
{
/* Errors happened when compiling this function.
*/
semanticRun = PASSsemanticdone; // Ensure errors get reported again
/* Except that re-running semantic3() doesn't always produce errors a second
* time through.
* See Bugzilla 8348
* Need a better way to deal with this than gagging.
*/
}
else
{
semanticRun = PASSsemantic3done;
semantic3Errors = global.errors - nerrors;
}
/* If this function had speculatively instantiated, error reproduction will be
* done by TemplateInstance::semantic.
* Otherwise, error gagging should be temporarily ungagged by functionSemantic3.
*/
semanticRun = PASSsemantic3done;
semantic3Errors = (global.errors != nerrors);
if (type->ty == Terror)
errors = true;
//printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
Expand Down Expand Up @@ -3809,6 +3799,83 @@ bool FuncDeclaration::hasNestedFrameRefs()
return false;
}

/***********************************************
* Returns true if this function is not defined in non-root module, nor
* obviously instantiated in non-root module.
*
* Note: ti->instantiatingModule does not stabilize until semantic analysis is completed,
* so don't call this function during semantic analysis to return precise result.
*/

bool FuncDeclaration::needsCodegen()
{
assert(semanticRun == PASSsemantic3done);

if (!isInstantiated() && inNonRoot())
return false;

if (global.params.useUnitTests ||
global.params.allInst ||
/* The issue is that if the importee is compiled with a different -debug
* setting than the importer, the importer may believe it exists
* in the compiled importee when it does not, when the instantiation
* is behind a conditional debug declaration.
*/
global.params.debuglevel) // workaround for Bugzilla 11239
{
return true;
}

FuncDeclaration *fd = this;
Lagain:
TemplateInstance *ti = fd->isInstantiated();
if (ti && ti->instantiatingModule && !ti->instantiatingModule->isRoot())
{
Module *mi = ti->instantiatingModule;

// If mi imports any root modules, we still need to generate the code.
for (size_t i = 0; i < Module::amodules.dim; ++i)
{
Module *m = Module::amodules[i];
m->insearch = 0;
}
bool importsRoot = false;
for (size_t i = 0; i < Module::amodules.dim; ++i)
{
Module *m = Module::amodules[i];
if (m->isRoot() && mi->imports(m))
{
importsRoot = true;
break;
}
}
for (size_t i = 0; i < Module::amodules.dim; ++i)
{
Module *m = Module::amodules[i];
m->insearch = 0;
}
if (!importsRoot)
{
//printf("instantiated by %s %s\n", ti->instantiatingModule->toChars(), ti->toChars());
return false;
}
}

if (fd->isNested())
{
/* Bugzilla 11863: The enclosing function must have its code generated first.
* Therefore if parent is instantiated in non-root, this function also prevent
* code generation.
*/
fd = fd->toParent2()->isFuncDeclaration();
if (fd)
goto Lagain;
}
//if (AggregateDeclaration *ad = fd->isMember2()) { ... }

return true;
}

/*********************************************
* Return the function's parameter list, and whether
* it is variadic or not.
Expand Down

0 comments on commit 010ffc6

Please sign in to comment.