Permalink
Browse files

Merge pull request #1543 from 9rnsr/fix5933

Issue 5933 & 7159 & 9377 - Invoke function semantic3 correctly where it is required.
  • Loading branch information...
2 parents ae95b0f + e914286 commit de4f8f6bf8dc9fcc1730ea4d7f2bbd3e74880f08 @WalterBright WalterBright committed Jan 24, 2013
View
@@ -641,6 +641,8 @@ struct FuncDeclaration : Declaration
void semantic(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
+ bool functionSemantic();
+ bool functionSemantic3();
// called from semantic3
VarDeclaration *declareThis(Scope *sc, AggregateDeclaration *ad);
int equals(Object *o);
View
@@ -928,18 +928,15 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
// If inferring return type, and semantic3() needs to be run if not already run
if (!tf->next && fd->inferRetType)
{
- TemplateInstance *spec = fd->isSpeculative();
- int olderrs = global.errors;
- // If it isn't speculative, we need to show errors
- unsigned oldgag = global.gag;
- if (global.gag && !spec)
- global.gag = 0;
- fd->semantic3(fd->scope);
- global.gag = oldgag;
- // Update the template instantiation with the number
- // of errors which occured.
- if (spec && global.errors != olderrs)
- spec->errors = global.errors - olderrs;
+ fd->functionSemantic();
+ }
+ else if (fd && fd->parent)
+ {
+ TemplateInstance *ti = fd->parent->isTemplateInstance();
+ if (ti && ti->tempdecl)
+ {
+ fd->functionSemantic3();
+ }
}
size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
@@ -3061,34 +3058,10 @@ Expression *DsymbolExp::semantic(Scope *sc)
}
f = s->isFuncDeclaration();
if (f)
- { f = f->toAliasFunc();
-
- if (!f->originalType && f->scope) // semantic not yet run
- {
- unsigned oldgag = global.gag;
- if (global.isSpeculativeGagging() && !f->isSpeculative())
- global.gag = 0;
- f->semantic(f->scope);
- global.gag = oldgag;
- }
-
- // if inferring return type, sematic3 needs to be run
- if (f->scope && (f->inferRetType && f->type && !f->type->nextOf() ||
- getFuncTemplateDecl(f)))
- {
- TemplateInstance *spec = f->isSpeculative();
- int olderrs = global.errors;
- // If it isn't speculative, we need to show errors
- unsigned oldgag = global.gag;
- if (global.gag && !spec)
- global.gag = 0;
- f->semantic3(f->scope);
- global.gag = oldgag;
- // Update the template instantiation with the number
- // of errors which occured.
- if (spec && global.errors != olderrs)
- spec->errors = global.errors - olderrs;
- }
+ {
+ f = f->toAliasFunc();
+ if (!f->functionSemantic())
+ return new ErrorExp();
if (f->isUnitTestDeclaration())
{
@@ -5110,8 +5083,13 @@ Expression *VarExp::semantic(Scope *sc)
#if LOGSEMANTIC
printf("VarExp::semantic(%s)\n", toChars());
#endif
-// if (var->sem == SemanticStart && var->scope) // if forward referenced
-// var->semantic(sc);
+ if (FuncDeclaration *f = var->isFuncDeclaration())
+ {
+ //printf("L%d fd = %s\n", __LINE__, f->toChars());
+ if (!f->functionSemantic())
+ return new ErrorExp();
+ }
+
if (!type)
{ type = var->type;
#if 0
@@ -7219,16 +7197,27 @@ Expression *DotVarExp::semantic(Scope *sc)
e1 = e1->semantic(sc);
e1 = e1->addDtorHook(sc);
- type = var->type;
- if (!type && global.errors)
- { // var is goofed up, just return 0
- return new ErrorExp();
- }
- assert(type);
Type *t1 = e1->type;
- if (!var->isFuncDeclaration()) // for functions, do checks after overload resolution
+ FuncDeclaration *f = var->isFuncDeclaration();
+ if (f) // for functions, do checks after overload resolution
{
+ //printf("L%d fd = %s\n", __LINE__, f->toChars());
+ if (!f->functionSemantic())
+ return new ErrorExp();
+
+ type = f->type;
+ assert(type);
+ }
+ else
+ {
+ type = var->type;
+ if (!type && global.errors)
+ { // var is goofed up, just return 0
+ goto Lerr;
+ }
+ assert(type);
+
if (t1->ty == Tpointer)
t1 = t1->nextOf();
View
@@ -1730,6 +1730,60 @@ void FuncDeclaration::semantic3(Scope *sc)
//fflush(stdout);
}
+bool FuncDeclaration::functionSemantic()
+{
+ if (scope && !originalType) // semantic not yet run
+ {
+ TemplateInstance *spec = isSpeculative();
+ unsigned olderrs = global.errors;
+ unsigned oldgag = global.gag;
+ if (global.gag && !spec)
+ global.gag = 0;
+ semantic(scope);
+ global.gag = oldgag;
+ if (spec && global.errors != olderrs)
+ spec->errors = global.errors - olderrs;
+ if (olderrs != global.errors) // if errors compiling this function
+ return false;
+ }
+
+ // if inferring return type, sematic3 needs to be run
+ if (scope && (inferRetType && type && !type->nextOf() ||
+ getFuncTemplateDecl(this)))
+ {
+ return functionSemantic3();
+ }
+
+ return true;
+}
+
+bool FuncDeclaration::functionSemantic3()
+{
+ if (scope)
+ {
+ /* Forward reference - we need to run semantic3 on this function.
+ * If errors are gagged, and it's not part of a speculative
+ * template instance, we need to temporarily ungag errors.
+ */
+ TemplateInstance *spec = isSpeculative();
+ unsigned olderrs = global.errors;
+ unsigned oldgag = global.gag;
+ if (global.gag && !spec)
+ global.gag = 0;
+ semantic3(scope);
+ global.gag = oldgag;
+
+ // If it is a speculatively-instantiated template, and errors occur,
+ // we need to mark the template as having errors.
+ if (spec && global.errors != olderrs)
+ spec->errors = global.errors - olderrs;
+ if (olderrs != global.errors) // if errors compiling this function
+ return false;
+ }
+
+ return true;
+}
+
void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
//printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
View
@@ -278,27 +278,8 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
error("circular dependency. Functions cannot be interpreted while being compiled");
return EXP_CANT_INTERPRET;
}
- if (semanticRun < PASSsemantic3 && scope)
- {
- /* Forward reference - we need to run semantic3 on this function.
- * If errors are gagged, and it's not part of a speculative
- * template instance, we need to temporarily ungag errors.
- */
- int olderrors = global.errors;
- int oldgag = global.gag;
- TemplateInstance *spec = isSpeculative();
- if (global.gag && !spec)
- global.gag = 0;
- semantic3(scope);
- global.gag = oldgag; // regag errors
-
- // If it is a speculatively-instantiated template, and errors occur,
- // we need to mark the template as having errors.
- if (spec && global.errors != olderrors)
- spec->errors = global.errors - olderrors;
- if (olderrors != global.errors) // if errors compiling this function
- return EXP_CANT_INTERPRET;
- }
+ if (!functionSemantic3())
+ return EXP_CANT_INTERPRET;
if (semanticRun < PASSsemantic3done)
return EXP_CANT_INTERPRET;
View
@@ -1306,28 +1306,13 @@ Type *Type::aliasthisOf()
FuncDeclaration *fd = (FuncDeclaration *)d;
Expression *ethis = this->defaultInit(0);
fd = fd->overloadResolve(0, ethis, NULL, 1);
- if (fd)
- { TypeFunction *tf = (TypeFunction *)fd->type;
- if (!tf->next && fd->inferRetType)
- {
- TemplateInstance *spec = fd->isSpeculative();
- int olderrs = global.errors;
- // If it isn't speculative, we need to show errors
- unsigned oldgag = global.gag;
- if (global.gag && !spec)
- global.gag = 0;
- fd->semantic3(fd->scope);
- global.gag = oldgag;
- // Update the template instantiation with the number
- // of errors which occured.
- if (spec && global.errors != olderrs)
- spec->errors = global.errors - olderrs;
- tf = (TypeFunction *)fd->type;
- }
- t = tf->next;
- if (tf->isWild())
- t = t->substWildTo(mod == 0 ? MODmutable : mod);
+ if (fd && fd->functionSemantic())
+ {
+ t = fd->type->nextOf();
+ t = t->substWildTo(mod == 0 ? MODmutable : mod);
}
+ else
+ return Type::terror;
}
return t;
}
@@ -1342,26 +1327,14 @@ Type *Type::aliasthisOf()
{ assert(td->scope);
Expression *ethis = defaultInit(0);
FuncDeclaration *fd = td->deduceFunctionTemplate(td->scope, 0, NULL, ethis, NULL, 1);
- if (fd)
+ if (fd && fd->functionSemantic())
{
- //if (!fd->type->nextOf() && fd->inferRetType)
- {
- TemplateInstance *spec = fd->isSpeculative();
- int olderrs = global.errors;
- fd->semantic3(fd->scope);
- // Update the template instantiation with the number
- // of errors which occured.
- if (spec && global.errors != olderrs)
- spec->errors = global.errors - olderrs;
- }
- if (!fd->errors)
- {
- Type *t = fd->type->nextOf();
- t = t->substWildTo(mod == 0 ? MODmutable : mod);
- return t;
- }
+ Type *t = fd->type->nextOf();
+ t = t->substWildTo(mod == 0 ? MODmutable : mod);
+ return t;
}
- return Type::terror;
+ else
+ return Type::terror;
}
//printf("%s\n", ad->aliasthis->kind());
}
View
@@ -2265,16 +2265,8 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
fd_best->type = tf->semantic(loc, sc);
}
}
- if (fd_best->scope)
- {
- TemplateInstance *spec = fd_best->isSpeculative();
- int olderrs = global.errors;
- fd_best->semantic3(fd_best->scope);
- // Update the template instantiation with the number
- // of errors which occured.
- if (spec && global.errors != olderrs)
- spec->errors = global.errors - olderrs;
- }
+
+ fd_best->functionSemantic();
return fd_best;
View
@@ -787,11 +787,7 @@ void ClassDeclaration::toObjFile(int multiobj)
if (fd && (fd->fbody || !isAbstract()))
{
// Ensure function has a return value (Bugzilla 4869)
- if (fd->type->ty == Tfunction && !((TypeFunction *)fd->type)->next)
- {
- assert(fd->scope);
- fd->semantic3(fd->scope);
- }
+ fd->functionSemantic();
Symbol *s = fd->toSymbol();
View
@@ -125,6 +125,7 @@ DISABLED_TESTS += testargtypes
DISABLED_TESTS += testxmm
DISABLED_SH_TESTS += test39
+DISABLED_SH_TESTS += test9377
endif
runnable_tests=$(wildcard runnable/*.d) $(wildcard runnable/*.sh)
View
@@ -93,7 +93,18 @@ template bug6661(Q)
const Q blaz = 6;
}
-static assert(is(typeof(bug6661!(int).blaz)));
+static assert(!is(typeof(bug6661!(int).blaz)));
+
+template bug6661x(Q)
+{
+ int qutz(Q y)
+ {
+ Q q = "abc";
+ return 67;
+ }
+}
+// should pass, but doesn't in current
+//static assert(!is(typeof(bug6661x!(int))));
/**************************************************
6599 ICE(constfold.c) or segfault
@@ -234,6 +234,25 @@ void test9072()
}
/***************************************************/
+// 5933 + Issue 8504 - Template attribute inferrence doesn't work
+
+int foo5933()(int a) { return a*a; }
+struct S5933
+{
+ double foo()(double a) { return a * a; }
+}
+// outside function
+static assert(typeof(foo5933!()).stringof == "pure nothrow @safe int(int a)");
+static assert(typeof(S5933.init.foo!()).stringof == "pure nothrow @safe double(double a)");
+
+void test5933()
+{
+ // inside function
+ static assert(typeof(foo5933!()).stringof == "pure nothrow @safe int(int a)");
+ static assert(typeof(S5933.init.foo!()).stringof == "pure nothrow @safe double(double a)");
+}
+
+/***************************************************/
// Add more tests regarding inferences later.
@@ -1,8 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ice5996.d(9): Error: undefined identifier anyOldGarbage
-fail_compilation/ice5996.d(12): Error: CTFE failed because of previous errors in bug5996
+fail_compilation/ice5996.d(8): Error: undefined identifier anyOldGarbage
---
*/
auto bug5996() {
@@ -0,0 +1,11 @@
+import std.c.stdio;
+
+import mul9377b;
+
+void abc()
+{
+ printf("mul9377b.abc()\n");
+ foo();
+ bar();
+}
+
Oops, something went wrong.

0 comments on commit de4f8f6

Please sign in to comment.