1 /** 2 * Semantic analysis of template parameters. 3 * 4 * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved 5 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 6 * License: $(LINK2 http://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 */ 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 52 this(Scope* sc, TemplateParameters* parameters) 53 { 54 this.sc = sc; 55 this.parameters = parameters; 56 } 57 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 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 == TOK.int64 || e.op == TOK.float64 || 91 e.op == TOK.complex80 || e.op == TOK.null_ || e.op == TOK.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 == TOK.int64) 104 tvp.defaultValue = e; 105 } 106 } 107 result = !isError(tvp.valType); 108 } 109 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 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 */ 143 RootObject aliasParameterSemantic(Loc loc, Scope* sc, RootObject o, TemplateParameters* parameters) 144 { 145 if (o) 146 { 147 Expression ea = isExpression(o); 148 Type ta = isType(o); 149 if (ta && (!parameters || !reliesOnTident(ta, parameters))) 150 { 151 Dsymbol s = ta.toDsymbol(sc); 152 if (s) 153 o = s; 154 else 155 o = ta.typeSemantic(loc, sc); 156 } 157 else if (ea) 158 { 159 sc = sc.startCTFE(); 160 ea = ea.expressionSemantic(sc); 161 sc = sc.endCTFE(); 162 o = ea.ctfeInterpret(); 163 } 164 } 165 return o; 166 }