From e99b1850d896933cb2b7f474f87e5cc7ec0dd376 Mon Sep 17 00:00:00 2001 From: k-hara Date: Sat, 30 Jul 2011 14:47:13 +0900 Subject: [PATCH] Issue 6404 - Cannot check ref-ness of auto ref parameter in template constraint --- src/template.c | 41 +++++++++++++++++++++++++-------------- src/template.h | 8 ++++---- test/runnable/template9.d | 21 ++++++++++++++++++++ 3 files changed, 51 insertions(+), 19 deletions(-) diff --git a/src/template.c b/src/template.c index 48b555e04e01..af49a2e154f1 100644 --- a/src/template.c +++ b/src/template.c @@ -589,7 +589,7 @@ int TemplateDeclaration::overloadInsert(Dsymbol *s) * Declare all the function parameters as variables * and add them to the scope */ -void TemplateDeclaration::makeParamNamesVisibleInConstraint(Scope *paramscope) +void TemplateDeclaration::makeParamNamesVisibleInConstraint(Scope *paramscope, Expressions *fargs) { /* We do this ONLY if there is only one function in the template. */ @@ -619,6 +619,17 @@ void TemplateDeclaration::makeParamNamesVisibleInConstraint(Scope *paramscope) v->storage_class |= STCvariadic; v->storage_class |= fparam->storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor); + if (fparam->storageClass & STCauto) + { + if (fargs && i < fargs->dim) + { Expression *farg = fargs->tdata()[i]; + if (farg->isLvalue()) + ; // ref parameter + else + v->storage_class &= ~STCref; // value parameter + } + } + v->semantic(paramscope); if (!paramscope->insert(v)) error("parameter %s.%s is already defined", toChars(), v->toChars()); @@ -641,7 +652,7 @@ void TemplateDeclaration::makeParamNamesVisibleInConstraint(Scope *paramscope) */ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, - Objects *dedtypes, int flag) + Objects *dedtypes, Expressions *fargs, int flag) { MATCH m; int dedtypes_dim = dedtypes->dim; @@ -739,7 +750,7 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, if (m && constraint && !(flag & 1)) { /* Check to see if constraint is satisfied. */ - makeParamNamesVisibleInConstraint(paramscope); + makeParamNamesVisibleInConstraint(paramscope, fargs); Expression *e = constraint->syntaxCopy(); Scope *sc = paramscope->push(); sc->flags |= SCOPEstaticif; @@ -808,7 +819,7 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, * 0 td2 is more specialized than this */ -MATCH TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2) +MATCH TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2, Expressions *fargs) { /* This works by taking the template parameters to this template * declaration and feeding them to td2 as if it were a template @@ -846,7 +857,7 @@ MATCH TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2) dedtypes.setDim(td2->parameters->dim); // Attempt a type deduction - MATCH m = td2->matchWithInstance(&ti, &dedtypes, 1); + MATCH m = td2->matchWithInstance(&ti, &dedtypes, fargs, 1); if (m) { /* A non-variadic template is more specialized than a @@ -1334,7 +1345,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec if (constraint) { /* Check to see if constraint is satisfied. */ - makeParamNamesVisibleInConstraint(paramscope); + makeParamNamesVisibleInConstraint(paramscope, fargs); Expression *e = constraint->syntaxCopy(); paramscope->flags |= SCOPEstaticif; @@ -1573,8 +1584,8 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, { // Disambiguate by picking the most specialized TemplateDeclaration - MATCH c1 = td->leastAsSpecialized(td_best); - MATCH c2 = td_best->leastAsSpecialized(td); + MATCH c1 = td->leastAsSpecialized(td_best, fargs); + MATCH c2 = td_best->leastAsSpecialized(td, fargs); //printf("c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) @@ -3797,7 +3808,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) assert((size_t)tempdecl->scope > 0x10000); // Deduce tdtypes tdtypes.setDim(tempdecl->parameters->dim); - if (!tempdecl->matchWithInstance(this, &tdtypes, 2)) + if (!tempdecl->matchWithInstance(this, &tdtypes, fargs, 2)) { error("incompatible arguments for template instantiation"); inst = this; @@ -3818,7 +3829,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) tempdecl = findTemplateDeclaration(sc); if (tempdecl) - tempdecl = findBestMatch(sc); + tempdecl = findBestMatch(sc, fargs); if (!tempdecl || global.errors) { inst = this; //printf("error return %p, %d\n", tempdecl, global.errors); @@ -4446,7 +4457,7 @@ TemplateDeclaration *TemplateInstance::findTemplateDeclaration(Scope *sc) return tempdecl; } -TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc) +TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs) { /* Since there can be multiple TemplateDeclaration's with the same * name, look for the best match. @@ -4493,7 +4504,7 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc) dedtypes.setDim(td->parameters->dim); dedtypes.zero(); assert(td->semanticRun); - m = td->matchWithInstance(this, &dedtypes, 0); + m = td->matchWithInstance(this, &dedtypes, fargs, 0); //printf("matchWithInstance = %d\n", m); if (!m) // no match at all continue; @@ -4505,8 +4516,8 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc) { // Disambiguate by picking the most specialized TemplateDeclaration - MATCH c1 = td->leastAsSpecialized(td_best); - MATCH c2 = td_best->leastAsSpecialized(td); + MATCH c1 = td->leastAsSpecialized(td_best, fargs); + MATCH c2 = td_best->leastAsSpecialized(td, fargs); //printf("c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) @@ -5263,7 +5274,7 @@ void TemplateMixin::semantic(Scope *sc) if (errors) return; - tempdecl = findBestMatch(sc); + tempdecl = findBestMatch(sc, NULL); if (!tempdecl) { inst = this; return; // error recovery diff --git a/src/template.h b/src/template.h index 706dbcb0c947..1bcf4a5e0a87 100644 --- a/src/template.h +++ b/src/template.h @@ -84,8 +84,8 @@ struct TemplateDeclaration : ScopeDsymbol void toJsonBuffer(OutBuffer *buf); // void toDocBuffer(OutBuffer *buf); - MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag); - MATCH leastAsSpecialized(TemplateDeclaration *td2); + MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, Expressions *fargs, int flag); + MATCH leastAsSpecialized(TemplateDeclaration *td2, Expressions *fargs); MATCH deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, Objects *dedargs); FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, int flags = 0); @@ -96,7 +96,7 @@ struct TemplateDeclaration : ScopeDsymbol TemplateTupleParameter *isVariadic(); int isOverloadable(); - void makeParamNamesVisibleInConstraint(Scope *paramscope); + void makeParamNamesVisibleInConstraint(Scope *paramscope, Expressions *fargs); }; struct TemplateParameter @@ -324,7 +324,7 @@ struct TemplateInstance : ScopeDsymbol static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags); void semanticTiargs(Scope *sc); TemplateDeclaration *findTemplateDeclaration(Scope *sc); - TemplateDeclaration *findBestMatch(Scope *sc); + TemplateDeclaration *findBestMatch(Scope *sc, Expressions *fargs); void declareParameters(Scope *sc); int hasNestedArgs(Objects *tiargs); Identifier *genIdent(Objects *args); diff --git a/test/runnable/template9.d b/test/runnable/template9.d index 627201735a02..a467222884a1 100644 --- a/test/runnable/template9.d +++ b/test/runnable/template9.d @@ -201,6 +201,26 @@ template _ElemType(T) { alias r type; } +/**********************************/ +// 6404 + +// receive only rvalue +void rvalue(T)(auto ref T x) if (!__traits(isRef, x)) {} + +// receive only lvalue +void lvalue(T)(auto ref T x) if ( __traits(isRef, x)) {} + +void test6404() +{ + int n; + + static assert(!__traits(compiles, rvalue(n))); + static assert( __traits(compiles, rvalue(0))); + + static assert( __traits(compiles, lvalue(n))); + static assert(!__traits(compiles, lvalue(0))); +} + /**********************************/ int main() @@ -214,6 +234,7 @@ int main() test7(); test8(); test9(); + test6404(); printf("Success\n"); return 0;