]> git.ipfire.org Git - people/ms/gcc.git/blob - gcc/d/dmd/templateparamsem.d
d: Merge upstream dmd, druntime 4ca4140e58, phobos 454dff14d.
[people/ms/gcc.git] / gcc / d / dmd / templateparamsem.d
1 /**
2 * Semantic analysis of template parameters.
3 *
4 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
5 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
6 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/templateparamsem.d, _templateparamsem.d)
8 * Documentation: https://dlang.org/phobos/dmd_templateparamsem.html
9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/templateparamsem.d
10 */
11
12 module dmd.templateparamsem;
13
14 import dmd.arraytypes;
15 import dmd.dsymbol;
16 import dmd.dscope;
17 import dmd.dtemplate;
18 import dmd.globals;
19 import dmd.location;
20 import dmd.expression;
21 import dmd.expressionsem;
22 import dmd.root.rootobject;
23 import dmd.mtype;
24 import dmd.typesem;
25 import dmd.visitor;
26
27 /************************************************
28 * Performs semantic on TemplateParameter AST nodes.
29 *
30 * Params:
31 * tp = element of `parameters` to be semantically analyzed
32 * sc = context
33 * parameters = array of `TemplateParameters` supplied to the `TemplateDeclaration`
34 * Returns:
35 * `true` if no errors
36 */
37 extern(C++) bool tpsemantic(TemplateParameter tp, Scope* sc, TemplateParameters* parameters)
38 {
39 scope v = new TemplateParameterSemanticVisitor(sc, parameters);
40 tp.accept(v);
41 return v.result;
42 }
43
44
45 private extern (C++) final class TemplateParameterSemanticVisitor : Visitor
46 {
47 alias visit = Visitor.visit;
48
49 Scope* sc;
50 TemplateParameters* parameters;
51 bool result;
52
53 this(Scope* sc, TemplateParameters* parameters) scope
54 {
55 this.sc = sc;
56 this.parameters = parameters;
57 }
58
59 override void visit(TemplateTypeParameter ttp)
60 {
61 //printf("TemplateTypeParameter.semantic('%s')\n", ident.toChars());
62 if (ttp.specType && !reliesOnTident(ttp.specType, parameters))
63 {
64 ttp.specType = ttp.specType.typeSemantic(ttp.loc, sc);
65 }
66 version (none)
67 {
68 // Don't do semantic() until instantiation
69 if (ttp.defaultType)
70 {
71 ttp.defaultType = ttp.defaultType.typeSemantic(ttp.loc, sc);
72 }
73 }
74 result = !(ttp.specType && isError(ttp.specType));
75 }
76
77 override void visit(TemplateThisParameter ttp)
78 {
79 import dmd.errors;
80
81 if (!sc.getStructClassScope())
82 error(ttp.loc, "cannot use `this` outside an aggregate type");
83 visit(cast(TemplateTypeParameter)ttp);
84 }
85
86 override void visit(TemplateValueParameter tvp)
87 {
88 tvp.valType = tvp.valType.typeSemantic(tvp.loc, sc);
89 version (none)
90 {
91 // defer semantic analysis to arg match
92 if (tvp.specValue)
93 {
94 Expression e = tvp.specValue;
95 sc = sc.startCTFE();
96 e = e.semantic(sc);
97 sc = sc.endCTFE();
98 e = e.implicitCastTo(sc, tvp.valType);
99 e = e.ctfeInterpret();
100 if (e.op == EXP.int64 || e.op == EXP.float64 ||
101 e.op == EXP.complex80 || e.op == EXP.null_ || e.op == EXP.string_)
102 tvp.specValue = e;
103 }
104
105 if (tvp.defaultValue)
106 {
107 Expression e = defaultValue;
108 sc = sc.startCTFE();
109 e = e.semantic(sc);
110 sc = sc.endCTFE();
111 e = e.implicitCastTo(sc, tvp.valType);
112 e = e.ctfeInterpret();
113 if (e.op == EXP.int64)
114 tvp.defaultValue = e;
115 }
116 }
117 result = !isError(tvp.valType);
118 }
119
120 override void visit(TemplateAliasParameter tap)
121 {
122 if (tap.specType && !reliesOnTident(tap.specType, parameters))
123 {
124 tap.specType = tap.specType.typeSemantic(tap.loc, sc);
125 }
126 tap.specAlias = aliasParameterSemantic(tap.loc, sc, tap.specAlias, parameters);
127 version (none)
128 {
129 // Don't do semantic() until instantiation
130 if (tap.defaultAlias)
131 tap.defaultAlias = tap.defaultAlias.semantic(tap.loc, sc);
132 }
133 result = !(tap.specType && isError(tap.specType)) && !(tap.specAlias && isError(tap.specAlias));
134 }
135
136 override void visit(TemplateTupleParameter ttp)
137 {
138 result = true;
139 }
140 }
141
142 /***********************************************
143 * Support function for performing semantic analysis on `TemplateAliasParameter`.
144 *
145 * Params:
146 * loc = location (for error messages)
147 * sc = context
148 * o = object to run semantic() on, the `TemplateAliasParameter`s `specAlias` or `defaultAlias`
149 * parameters = array of `TemplateParameters` supplied to the `TemplateDeclaration`
150 * Returns:
151 * object resulting from running `semantic` on `o`
152 */
153 RootObject aliasParameterSemantic(Loc loc, Scope* sc, RootObject o, TemplateParameters* parameters)
154 {
155 if (!o)
156 return null;
157
158 Expression ea = isExpression(o);
159 RootObject eaCTFE()
160 {
161 sc = sc.startCTFE();
162 ea = ea.expressionSemantic(sc);
163 sc = sc.endCTFE();
164 return ea.ctfeInterpret();
165 }
166 Type ta = isType(o);
167 if (ta && (!parameters || !reliesOnTident(ta, parameters)))
168 {
169 Dsymbol s = ta.toDsymbol(sc);
170 if (s)
171 return s;
172 else if (TypeInstance ti = ta.isTypeInstance())
173 {
174 Type t;
175 const errors = global.errors;
176 ta.resolve(loc, sc, ea, t, s);
177 // if we had an error evaluating the symbol, suppress further errors
178 if (!t && errors != global.errors)
179 return Type.terror;
180 // We might have something that looks like a type
181 // but is actually an expression or a dsymbol
182 // see https://issues.dlang.org/show_bug.cgi?id=16472
183 if (t)
184 return t.typeSemantic(loc, sc);
185 else if (ea)
186 {
187 return eaCTFE();
188 }
189 else if (s)
190 return s;
191 else
192 assert(0);
193 }
194 else
195 return ta.typeSemantic(loc, sc);
196 }
197 else if (ea)
198 return eaCTFE();
199 return o;
200 }