aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/dmd/templateparamsem.c
blob: 11cd52e351bff172c8c414eda80530f74f8753a7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

/* Compiler implementation of the D programming language
 * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
 * written by Walter Bright
 * http://www.digitalmars.com
 * Distributed under the Boost Software License, Version 1.0.
 * http://www.boost.org/LICENSE_1_0.txt
 */

#include "template.h"
#include "mtype.h"
#include "scope.h"
#include "visitor.h"

bool reliesOnTident(Type *t, TemplateParameters *tparams = NULL, size_t iStart = 0);

class TemplateParameterSemanticVisitor : public Visitor
{
public:
    Scope *sc;
    TemplateParameters *parameters;
    bool result;

    TemplateParameterSemanticVisitor(Scope *sc, TemplateParameters *parameters)
    {
        this->sc = sc;
        this->parameters = parameters;
	this->result = false;
    }

    void visit(TemplateTypeParameter *ttp)
    {
        //printf("TemplateTypeParameter::semantic('%s')\n", ident->toChars());
        if (ttp->specType && !reliesOnTident(ttp->specType, parameters))
        {
            ttp->specType = typeSemantic(ttp->specType, ttp->loc, sc);
        }
        result = !(ttp->specType && isError(ttp->specType));
    }

    void visit(TemplateValueParameter *tvp)
    {
        tvp->valType = typeSemantic(tvp->valType, tvp->loc, sc);

        result = !isError(tvp->valType);
    }

    void visit(TemplateAliasParameter *tap)
    {
        if (tap->specType && !reliesOnTident(tap->specType, parameters))
        {
            tap->specType = typeSemantic(tap->specType, tap->loc, sc);
        }
        tap->specAlias = aliasParameterSemantic(tap->loc, sc, tap->specAlias, parameters);
        result = !(tap->specType  && isError(tap->specType)) &&
            !(tap->specAlias && isError(tap->specAlias));
    }

    void visit(TemplateTupleParameter *)
    {
        result = true;
    }
};

/************************************************
 * Performs semantic on TemplateParameter AST nodes.
 *
 * Params:
 *      tp = element of `parameters` to be semantically analyzed
 *      sc = context
 *      parameters = array of `TemplateParameters` supplied to the `TemplateDeclaration`
 * Returns:
 *      `true` if no errors
 */
bool tpsemantic(TemplateParameter *tp, Scope *sc, TemplateParameters *parameters)
{
    TemplateParameterSemanticVisitor v(sc, parameters);
    tp->accept(&v);
    return v.result;
}

/***********************************************
 * Support function for performing semantic analysis on `TemplateAliasParameter`.
 *
 * Params:
 *      loc = location (for error messages)
 *      sc = context
 *      o = object to run semantic() on, the `TemplateAliasParameter`s `specAlias` or `defaultAlias`
 *      parameters = array of `TemplateParameters` supplied to the `TemplateDeclaration`
 * Returns:
 *      object resulting from running `semantic` on `o`
 */
RootObject *aliasParameterSemantic(Loc loc, Scope *sc, RootObject *o, TemplateParameters *parameters)
{
    if (o)
    {
        Expression *ea = isExpression(o);
        Type *ta = isType(o);
        if (ta && (!parameters || !reliesOnTident(ta, parameters)))
        {
            Dsymbol *s = ta->toDsymbol(sc);
            if (s)
                o = s;
            else
                o = typeSemantic(ta, loc, sc);
        }
        else if (ea)
        {
            sc = sc->startCTFE();
            ea = expressionSemantic(ea, sc);
            sc = sc->endCTFE();
            o = ea->ctfeInterpret();
        }
    }
    return o;
}