xref: /netbsd-src/external/gpl3/gcc/dist/gcc/d/dmd/templateparamsem.d (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /**
2  * Semantic analysis of template parameters.
3  *
4  * Copyright:   Copyright (C) 1999-2022 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.expression;
20 import dmd.expressionsem;
21 import dmd.root.rootobject;
22 import dmd.mtype;
23 import dmd.typesem;
24 import dmd.visitor;
25 
26 /************************************************
27  * Performs semantic on TemplateParameter AST nodes.
28  *
29  * Params:
30  *      tp = element of `parameters` to be semantically analyzed
31  *      sc = context
32  *      parameters = array of `TemplateParameters` supplied to the `TemplateDeclaration`
33  * Returns:
34  *      `true` if no errors
35  */
tpsemantic(TemplateParameter tp,Scope * sc,TemplateParameters * parameters)36 extern(C++) bool tpsemantic(TemplateParameter tp, Scope* sc, TemplateParameters* parameters)
37 {
38     scope v = new TemplateParameterSemanticVisitor(sc, parameters);
39     tp.accept(v);
40     return v.result;
41 }
42 
43 
44 private extern (C++) final class TemplateParameterSemanticVisitor : Visitor
45 {
46     alias visit = Visitor.visit;
47 
48     Scope* sc;
49     TemplateParameters* parameters;
50     bool result;
51 
this(Scope * sc,TemplateParameters * parameters)52     this(Scope* sc, TemplateParameters* parameters)
53     {
54         this.sc = sc;
55         this.parameters = parameters;
56     }
57 
visit(TemplateTypeParameter ttp)58     override void visit(TemplateTypeParameter ttp)
59     {
60         //printf("TemplateTypeParameter.semantic('%s')\n", ident.toChars());
61         if (ttp.specType && !reliesOnTident(ttp.specType, parameters))
62         {
63             ttp.specType = ttp.specType.typeSemantic(ttp.loc, sc);
64         }
65         version (none)
66         {
67             // Don't do semantic() until instantiation
68             if (ttp.defaultType)
69             {
70                 ttp.defaultType = ttp.defaultType.typeSemantic(ttp.loc, sc);
71             }
72         }
73         result = !(ttp.specType && isError(ttp.specType));
74     }
75 
visit(TemplateValueParameter tvp)76     override void visit(TemplateValueParameter tvp)
77     {
78         tvp.valType = tvp.valType.typeSemantic(tvp.loc, sc);
79         version (none)
80         {
81             // defer semantic analysis to arg match
82             if (tvp.specValue)
83             {
84                 Expression e = tvp.specValue;
85                 sc = sc.startCTFE();
86                 e = e.semantic(sc);
87                 sc = sc.endCTFE();
88                 e = e.implicitCastTo(sc, tvp.valType);
89                 e = e.ctfeInterpret();
90                 if (e.op == EXP.int64 || e.op == EXP.float64 ||
91                     e.op == EXP.complex80 || e.op == EXP.null_ || e.op == EXP.string_)
92                     tvp.specValue = e;
93             }
94 
95             if (tvp.defaultValue)
96             {
97                 Expression e = defaultValue;
98                 sc = sc.startCTFE();
99                 e = e.semantic(sc);
100                 sc = sc.endCTFE();
101                 e = e.implicitCastTo(sc, tvp.valType);
102                 e = e.ctfeInterpret();
103                 if (e.op == EXP.int64)
104                     tvp.defaultValue = e;
105             }
106         }
107         result = !isError(tvp.valType);
108     }
109 
visit(TemplateAliasParameter tap)110     override void visit(TemplateAliasParameter tap)
111     {
112         if (tap.specType && !reliesOnTident(tap.specType, parameters))
113         {
114             tap.specType = tap.specType.typeSemantic(tap.loc, sc);
115         }
116         tap.specAlias = aliasParameterSemantic(tap.loc, sc, tap.specAlias, parameters);
117         version (none)
118         {
119             // Don't do semantic() until instantiation
120             if (tap.defaultAlias)
121                 tap.defaultAlias = tap.defaultAlias.semantic(tap.loc, sc);
122         }
123         result = !(tap.specType && isError(tap.specType)) && !(tap.specAlias && isError(tap.specAlias));
124     }
125 
visit(TemplateTupleParameter ttp)126     override void visit(TemplateTupleParameter ttp)
127     {
128         result = true;
129     }
130 }
131 
132 /***********************************************
133  * Support function for performing semantic analysis on `TemplateAliasParameter`.
134  *
135  * Params:
136  *      loc = location (for error messages)
137  *      sc = context
138  *      o = object to run semantic() on, the `TemplateAliasParameter`s `specAlias` or `defaultAlias`
139  *      parameters = array of `TemplateParameters` supplied to the `TemplateDeclaration`
140  * Returns:
141  *      object resulting from running `semantic` on `o`
142  */
aliasParameterSemantic(Loc loc,Scope * sc,RootObject o,TemplateParameters * parameters)143 RootObject aliasParameterSemantic(Loc loc, Scope* sc, RootObject o, TemplateParameters* parameters)
144 {
145     if (!o)
146         return null;
147 
148     Expression ea = isExpression(o);
149     RootObject eaCTFE()
150     {
151         sc = sc.startCTFE();
152         ea = ea.expressionSemantic(sc);
153         sc = sc.endCTFE();
154         return ea.ctfeInterpret();
155     }
156     Type ta = isType(o);
157     if (ta && (!parameters || !reliesOnTident(ta, parameters)))
158     {
159         Dsymbol s = ta.toDsymbol(sc);
160         if (s)
161             return s;
162         else if (TypeInstance ti = ta.isTypeInstance())
163         {
164             Type t;
165             const errors = global.errors;
166             ta.resolve(loc, sc, ea, t, s);
167             // if we had an error evaluating the symbol, suppress further errors
168             if (!t && errors != global.errors)
169                 return Type.terror;
170             // We might have something that looks like a type
171             // but is actually an expression or a dsymbol
172             // see https://issues.dlang.org/show_bug.cgi?id=16472
173             if (t)
174                 return t.typeSemantic(loc, sc);
175             else if (ea)
176             {
177                 return eaCTFE();
178             }
179             else if (s)
180                 return s;
181             else
182                 assert(0);
183         }
184         else
185             return ta.typeSemantic(loc, sc);
186     }
187     else if (ea)
188         return eaCTFE();
189     return o;
190 }
191