Skip to content

Loading…

Issue 5933 & 7159 - Resolve forward reference to auto-return member function #535

Merged
merged 2 commits into from

4 participants

@9rnsr
D Programming Language member

Issue 5933 - Cannot retrieve the return type of an auto-return member function

Bug 5933 is synonym of bug 2810, and the fixing way is also almost same.

Issue 7159 - Forward reference when casting auto return method

@9rnsr
D Programming Language member

Added fix for bug 7159.

@Trass3r

fails the tests.

@9rnsr 9rnsr closed this
@9rnsr 9rnsr reopened this
@9rnsr
D Programming Language member

Updated with more better way.

@andralex
D Programming Language member

LGTM - please let's merge this baby. Thanks!

@WalterBright WalterBright merged commit 2ba68e1 into D-Programming-Language:master

1 check failed

Details default Fail: 2, Pending: 7
@WalterBright
D Programming Language member

Does not compile test suite:

Testing generated/linux/debug/32/unittest/std/numeric
std/numeric.d(398): Error: template instance opUnary!("+") opUnary!("+") does not match template dec
laration opUnary(string op)() if (__traits(compiles,mixin(op ~ "(get!real)")) || op == "++" || op ==
"--")
std/numeric.d(398): Error: function expected before (), not max().opUnary!("+") of type void
std/numeric.d(404): Error: template instance opUnary!("+") opUnary!("+") does not match template dec
laration opUnary(string op)() if (__traits(compiles,mixin(op ~ "(get!real)")) || op == "++" || op ==
"--")
std/numeric.d(404): Error: function expected before (), not min_normal().opUnary!("+") of type void
std/numeric.d(487): Error: undefined identifier 'sign', did you mean 'template sgn(F)(F x)'?
std/numeric.d(489): Error: CommonType!(int, __error) is used as a type
std/numeric.d(490): Error: CommonType!(uint, __error) is used as a type
std/numeric.d(492): Error: template std.numeric.CustomFloat!(5u, 10u, cast(CustomFloatFlags)31, 511)
.CustomFloat.toNormalized does not match any function template declaration. Candidates are:
std/numeric.d(218): std.numeric.CustomFloat!(5u, 10u, cast(CustomFloatFlags)31, 511).CustomFl
oat.toNormalized(T, U)(ref T sig, ref U exp)
std/numeric.d(492): Error: template std.numeric.CustomFloat!(5u, 10u, cast(CustomFloatFlags)31, 511)
.CustomFloat.toNormalized(T, U)(ref T sig, ref U exp) cannot deduce template function from argument
types !()(error,error)
std/numeric.d(496): Error: result.get.T_exp is used as a type
std/numeric.d(496): Error: undefined identifier 'exponent'
std/numeric.d(497): Error: result.get.T_sig is used as a type
std/numeric.d(497): Error: undefined identifier 'significand'
std/numeric.d(537): Error: template instance std.numeric.CustomFloat!(5u, 10u, cast(CustomFloatFlags
)31, 511).CustomFloat.get!(real) error instantiating
std/numeric.d(153): instantiated from here: CustomFloat!(5u, 10u, cast(CustomFloatFlags)31, 5
11)
std/numeric.d(543): instantiated from here: CustomFloat!(5, 10)
std/numeric.d(543): Error: template instance std.numeric.CustomFloat!(5, 10) error instantiating
std/numeric.d(398): Error: template instance opUnary!("+") opUnary!("+") does not match template dec
laration opUnary(string op)() if (__traits(compiles,mixin(op ~ "(get!real)")) || op == "++" || op ==
"--")
std/numeric.d(398): Error: function expected before (), not max().opUnary!("+") of type void
std/numeric.d(404): Error: template instance opUnary!("+") opUnary!("+") does not match template dec
laration opUnary(string op)() if (__traits(compiles,mixin(op ~ "(get!real)")) || op == "++" || op ==
"--")
std/numeric.d(404): Error: function expected before (), not min_normal().opUnary!("+") of type void
std/numeric.d(488): Error: undefined identifier 'sign', did you mean 'template sgn(F)(F x)'?
std/numeric.d(489): Error: CommonType!(int, __error) is used as a type
make[2]: *** [generated/linux/debug/32/unittest/std/numeric] Error 1
make[1]: *** [unittest] Error 2

@9rnsr
D Programming Language member

I'm sorry for keeping broken pull open. But, it has recently appeared by interacting other fixes.
I'm searching root problem, but it is impossible immediately.
We should simply revert this to fix auto-tester breaking.

P.S. @WalterBright, if you want to merge a pull request, please look its lastest auto-tester result before merging. If it is red, you might break trunk head with high probability.

@9rnsr 9rnsr added a commit to 9rnsr/dmd that referenced this pull request
@9rnsr 9rnsr Revert "Merge pull request #535 from 9rnsr/fix5933" to fix auto-teste…
…r breaking

This reverts commit 2ba68e1, reversing
changes made to e3daa5e.
fd4a975
@9rnsr
D Programming Language member

I opened reversion pull request: #1304

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Showing with 113 additions and 47 deletions.
  1. +1 −0 src/declaration.h
  2. +26 −47 src/expression.c
  3. +43 −0 src/func.c
  4. +43 −0 test/runnable/xtest46.d
View
1 src/declaration.h
@@ -632,6 +632,7 @@ struct FuncDeclaration : Declaration
void semantic(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
+ bool functionSemantic(Scope *sc);
// called from semantic3
void varArgs(Scope *sc, TypeFunction*, VarDeclaration *&, VarDeclaration *&);
VarDeclaration *declareThis(Scope *sc, AggregateDeclaration *ad);
View
73 src/expression.c
@@ -2994,45 +2994,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;
- }
-
- if (f->isUnitTestDeclaration())
- {
- error("cannot call unittest function %s", toChars());
- return new ErrorExp();
- }
- if (!f->type->deco)
- {
- error("forward reference to %s", toChars());
+ {
+ f = f->toAliasFunc();
+ if (!f->functionSemantic(sc))
return new ErrorExp();
- }
FuncDeclaration *fd = s->isFuncDeclaration();
fd->type = f->type;
return new VarExp(loc, fd, hasOverloads);
@@ -5025,8 +4990,12 @@ 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())
+ {
+ if (!f->functionSemantic(sc))
+ return new ErrorExp();
+ }
+
if (!type)
{ type = var->type;
#if 0
@@ -7121,16 +7090,26 @@ 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
{
+ if (!f->functionSemantic(sc))
+ 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
43 src/func.c
@@ -1681,6 +1681,49 @@ void FuncDeclaration::semantic3(Scope *sc)
//fflush(stdout);
}
+bool FuncDeclaration::functionSemantic(Scope *sc)
+{
+ if (!originalType && scope) // semantic not yet run
+ {
+ unsigned oldgag = global.gag;
+ if (global.isSpeculativeGagging() && !isSpeculative())
+ global.gag = 0;
+ semantic(scope);
+ global.gag = oldgag;
+ }
+
+ // if inferring return type, sematic3 needs to be run
+ if (scope && (inferRetType && type && !type->nextOf() ||
+ getFuncTemplateDecl(this)))
+ {
+ TemplateInstance *spec = 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;
+ semantic3(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;
+ }
+
+ if (isUnitTestDeclaration())
+ {
+ error("cannot call unittest function %s", toChars());
+ return false;
+ }
+ if (!type->deco)
+ {
+ error("forward reference to %s", toChars());
+ return false;
+ }
+
+ return true;
+}
+
void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
//printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
View
43 test/runnable/xtest46.d
@@ -4219,6 +4219,37 @@ void test5696()
}
/***************************************************/
+// 5933
+
+int dummyfunc();
+alias typeof(dummyfunc) FuncType;
+
+struct S5933a { auto x() { return 0; } }
+static assert(is(typeof(&S5933a.init.x) == int delegate()));
+
+struct S5933b { auto x() { return 0; } }
+static assert(is(typeof(S5933b.init.x) == FuncType));
+
+struct S5933c { auto x() { return 0; } }
+static assert(is(typeof(&S5933c.x) == int function()));
+
+struct S5933d { auto x() { return 0; } }
+static assert(is(typeof(S5933d.x) == FuncType));
+
+
+class C5933a { auto x() { return 0; } }
+static assert(is(typeof(&(new C5933b()).x) == int delegate()));
+
+class C5933b { auto x() { return 0; } }
+static assert(is(typeof((new C5933b()).x) == FuncType));
+
+class C5933c { auto x() { return 0; } }
+static assert(is(typeof(&C5933c.x) == int function()));
+
+class C5933d { auto x() { return 0; } }
+static assert(is(typeof(C5933d.x) == FuncType));
+
+/***************************************************/
// 6084
template TypeTuple6084(T...){ alias T TypeTuple6084; }
@@ -4831,6 +4862,18 @@ void test7150()
}
/***************************************************/
+// 7159
+
+class HomeController7159 {
+ void* foo() {
+ return cast(void*)&HomeController7159.displayDefault;
+ }
+ auto displayDefault() {
+ return 1;
+ }
+}
+
+/***************************************************/
// 7160
class HomeController {
Something went wrong with that request. Please try again.