diff options
Diffstat (limited to 'gcc/d/dmd/templateparamsem.d')
-rw-r--r-- | gcc/d/dmd/templateparamsem.d | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/gcc/d/dmd/templateparamsem.d b/gcc/d/dmd/templateparamsem.d new file mode 100644 index 00000000000..620492fc0c7 --- /dev/null +++ b/gcc/d/dmd/templateparamsem.d @@ -0,0 +1,190 @@ +/** + * Semantic analysis of template parameters. + * + * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved + * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) + * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/templateparamsem.d, _templateparamsem.d) + * Documentation: https://dlang.org/phobos/dmd_templateparamsem.html + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/templateparamsem.d + */ + +module dmd.templateparamsem; + +import dmd.arraytypes; +import dmd.dsymbol; +import dmd.dscope; +import dmd.dtemplate; +import dmd.globals; +import dmd.expression; +import dmd.expressionsem; +import dmd.root.rootobject; +import dmd.mtype; +import dmd.typesem; +import dmd.visitor; + +/************************************************ + * 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 + */ +extern(C++) bool tpsemantic(TemplateParameter tp, Scope* sc, TemplateParameters* parameters) +{ + scope v = new TemplateParameterSemanticVisitor(sc, parameters); + tp.accept(v); + return v.result; +} + + +private extern (C++) final class TemplateParameterSemanticVisitor : Visitor +{ + alias visit = Visitor.visit; + + Scope* sc; + TemplateParameters* parameters; + bool result; + + this(Scope* sc, TemplateParameters* parameters) + { + this.sc = sc; + this.parameters = parameters; + } + + override void visit(TemplateTypeParameter ttp) + { + //printf("TemplateTypeParameter.semantic('%s')\n", ident.toChars()); + if (ttp.specType && !reliesOnTident(ttp.specType, parameters)) + { + ttp.specType = ttp.specType.typeSemantic(ttp.loc, sc); + } + version (none) + { + // Don't do semantic() until instantiation + if (ttp.defaultType) + { + ttp.defaultType = ttp.defaultType.typeSemantic(ttp.loc, sc); + } + } + result = !(ttp.specType && isError(ttp.specType)); + } + + override void visit(TemplateValueParameter tvp) + { + tvp.valType = tvp.valType.typeSemantic(tvp.loc, sc); + version (none) + { + // defer semantic analysis to arg match + if (tvp.specValue) + { + Expression e = tvp.specValue; + sc = sc.startCTFE(); + e = e.semantic(sc); + sc = sc.endCTFE(); + e = e.implicitCastTo(sc, tvp.valType); + e = e.ctfeInterpret(); + if (e.op == TOK.int64 || e.op == TOK.float64 || + e.op == TOK.complex80 || e.op == TOK.null_ || e.op == TOK.string_) + tvp.specValue = e; + } + + if (tvp.defaultValue) + { + Expression e = defaultValue; + sc = sc.startCTFE(); + e = e.semantic(sc); + sc = sc.endCTFE(); + e = e.implicitCastTo(sc, tvp.valType); + e = e.ctfeInterpret(); + if (e.op == TOK.int64) + tvp.defaultValue = e; + } + } + result = !isError(tvp.valType); + } + + override void visit(TemplateAliasParameter tap) + { + if (tap.specType && !reliesOnTident(tap.specType, parameters)) + { + tap.specType = tap.specType.typeSemantic(tap.loc, sc); + } + tap.specAlias = aliasParameterSemantic(tap.loc, sc, tap.specAlias, parameters); + version (none) + { + // Don't do semantic() until instantiation + if (tap.defaultAlias) + tap.defaultAlias = tap.defaultAlias.semantic(tap.loc, sc); + } + result = !(tap.specType && isError(tap.specType)) && !(tap.specAlias && isError(tap.specAlias)); + } + + override void visit(TemplateTupleParameter ttp) + { + result = true; + } +} + +/*********************************************** + * 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) + return null; + + Expression ea = isExpression(o); + RootObject eaCTFE() + { + sc = sc.startCTFE(); + ea = ea.expressionSemantic(sc); + sc = sc.endCTFE(); + return ea.ctfeInterpret(); + } + Type ta = isType(o); + if (ta && (!parameters || !reliesOnTident(ta, parameters))) + { + Dsymbol s = ta.toDsymbol(sc); + if (s) + return s; + else if (TypeInstance ti = ta.isTypeInstance()) + { + Type t; + const errors = global.errors; + ta.resolve(loc, sc, ea, t, s); + // if we had an error evaluating the symbol, suppress further errors + if (!t && errors != global.errors) + return Type.terror; + // We might have something that looks like a type + // but is actually an expression or a dsymbol + // see https://issues.dlang.org/show_bug.cgi?id=16472 + if (t) + return t.typeSemantic(loc, sc); + else if (ea) + { + return eaCTFE(); + } + else if (s) + return s; + else + assert(0); + } + else + return ta.typeSemantic(loc, sc); + } + else if (ea) + return eaCTFE(); + return o; +} |