Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 26 additions & 15 deletions src/template.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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());
Expand All @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions src/template.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -96,7 +96,7 @@ struct TemplateDeclaration : ScopeDsymbol
TemplateTupleParameter *isVariadic();
int isOverloadable();

void makeParamNamesVisibleInConstraint(Scope *paramscope);
void makeParamNamesVisibleInConstraint(Scope *paramscope, Expressions *fargs);
};

struct TemplateParameter
Expand Down Expand Up @@ -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);
Expand Down
21 changes: 21 additions & 0 deletions test/runnable/template9.d
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -214,6 +234,7 @@ int main()
test7();
test8();
test9();
test6404();

printf("Success\n");
return 0;
Expand Down