@@ -29,6 +29,31 @@ const char[] DiagTooManyArgs = "too many arguments to %sfunction call, expected
2929const char[] DiagTooFewArgs = "too few arguments to %sfunction call, expected %d, have %d";
3030const char[] NoteDeclaredHere = "'%s' is defined here";
3131
32+ fn QualType Analyser.analyseTemplateExpr(Analyser* ma, Expr** e_ptr) {
33+ Expr* e = *e_ptr;
34+ TemplateExpr* tp = (TemplateExpr*)e;
35+ Expr** func = tp.getFunc2();
36+ Expr* origFn = tp.getFunc(); // store here to avoid the likely inserted FunctionPointerDecay cast
37+ QualType qt = ma.analyseExpr(func, true, RHS);
38+ if (qt.isInvalid()) return QualType_Invalid;
39+ FunctionType* ft = qt.getFunctionTypeOrNil();
40+ if (!ft) {
41+ ma.errorRange(origFn.getLoc(), origFn.getRange(), "object type %s is not a function template", qt.diagName());
42+ return QualType_Invalid;
43+ }
44+ FunctionDecl* fd = ft.getDecl();
45+ if (!fd.isTemplate() || fd.isTemplateTypeFunction()) {
46+ ma.errorRange(e.getLoc(), e.getRange(), "function %s is not a template function", fd.asDecl().getFullName());
47+ return QualType_Invalid;
48+ }
49+
50+ FunctionDecl* fd2 = ma.instantiateFunctionTemplate(fd, tp.getInstanceASTIdx(), tp.getArgs(), tp.getNumArgs());
51+ if (!fd2) return QualType_Invalid;
52+ fd2.asDecl().setUsed();
53+ tp.setDecl(fd2.asDecl());
54+ return fd2.asDecl().getType();
55+ }
56+
3257fn QualType Analyser.analyseCallExpr(Analyser* ma, Expr** e_ptr) {
3358 Expr* e = *e_ptr;
3459 CallExpr* call = (CallExpr*)e;
@@ -60,17 +85,10 @@ fn QualType Analyser.analyseCallExpr(Analyser* ma, Expr** e_ptr) {
6085 if (fd.hasAttrNoReturn()) call.setNoreturn();
6186
6287 if (fd.isTemplate()) {
63- if (!call.getTemplateArg()) {
64- ma.errorRange(e.getLoc(), e.getRange(), "function %s requires a template argument", fd.asDecl().getFullName());
65- return QualType_Invalid;
66- }
67- fd = ma.instantiateTemplateFunction(call, fd);
68- if (!fd) return QualType_Invalid;
69- } else {
70- if (call.getTemplateArg()) {
71- ma.errorRange(e.getLoc(), e.getRange(), "function %s is not a template function", fd.asDecl().getFullName());
72- return QualType_Invalid;
73- }
88+ // TODO handle default type arguments
89+ // TODO auto-instantiate based on actual argument types
90+ ma.errorRange(e.getLoc(), e.getRange(), "function %s requires a template argument", fd.asDecl().getFullName());
91+ return QualType_Invalid;
7492 }
7593
7694 if (fd.hasAttrDeprecated() && !ma.warnings.no_deprecated) {
@@ -624,12 +642,18 @@ fn void Analyser.opaque_callback(void* arg, SrcLoc loc, Decl* d) {
624642 ma.error(loc," using opaque type '%s'", qt.diagName());
625643}
626644
627- fn FunctionDecl* Analyser.instantiateTemplateFunction(Analyser* ma, CallExpr* call, FunctionDecl* fd) {
628- TypeRef* template_arg = call.getTemplateArg();
645+ fn FunctionDecl* Analyser.instantiateFunctionTemplate(Analyser* ma, FunctionDecl* fd, u16 instance_ast_idx, Expr** args, u32 num_args) {
646+ // Only handle first argument for now, convert to type
647+ TypeRef* template_arg = ma.getTemplateArg(*args);
648+ if (!template_arg) return nil;
629649 QualType templateType = ma.analyseTypeRef(template_arg);
630650 if (templateType.isInvalid()) return nil;
631651
632- FunctionDecl* instance = ma.mod.findInstance(fd, templateType);
652+ // TODO create instiator, analyse/evaluate template expressions,
653+ // initialize TemplateSubst array from values or qualtypes,
654+ // compute instance name and check if name exists already
655+
656+ FunctionDecl* instance = (FunctionDecl*)ma.mod.findInstance(fd.asDecl(), templateType);
633657 if (!instance) {
634658 // note: template_arg decl is set here
635659 bool used_opaque = false;
@@ -639,11 +663,14 @@ fn FunctionDecl* Analyser.instantiateTemplateFunction(Analyser* ma, CallExpr* ca
639663 Decl* d = (Decl*)std;
640664 used_opaque = (std.isOpaque() && d.getModule() != ma.mod);
641665 }
666+ // TODO: use TemplateSpec in Instantiator
667+ const TemplateSpec* spec = fd.getTemplateSpec();
642668 Instantiator inst = {
643669 .c = ma.context,
644670 .ref = template_arg,
645- .template_name = fd.getTemplateNameIdx(),
646- .instance_ast_idx = call.getInstanceASTIdx(),
671+ .template_vars = spec.getTemplateVars(),
672+ .template_len = spec.getTemplateLen(),
673+ .instance_ast_idx = instance_ast_idx,
647674 .used_opaque = used_opaque,
648675 .arg = ma,
649676 .on_error = Analyser.opaque_callback,
@@ -654,6 +681,13 @@ fn FunctionDecl* Analyser.instantiateTemplateFunction(Analyser* ma, CallExpr* ca
654681 if (ma.has_error) return nil;
655682 d.setChecked();
656683
684+ // add instance to avoid recursive instantiation for the same type
685+ u16 instance_idx = ma.mod.addInstance(fd.asDecl(), templateType, instance.asDecl());
686+ char[64] name;
687+ // TODO: use a more readable name, eg: max$i32
688+ create_template_name(name, fd.asDecl().getName(), instance_idx);
689+ d.setNameIdx(ma.astPool.addStr(name, true));
690+
657691 // Note: we need a separate scope for the body
658692 Module* template_mod = fd.asDecl().getModule();
659693 Analyser* analyser = create(ma.diags, ma.context, ma.astPool, ma.builder, ma.allmodules, ma.warnings);
@@ -669,15 +703,7 @@ fn FunctionDecl* Analyser.instantiateTemplateFunction(Analyser* ma, CallExpr* ca
669703 analyser.free();
670704
671705 if (ma.has_error) return nil;
672-
673- u16 instance_idx = ma.mod.addInstance(fd, templateType, instance);
674- instance.setTemplateInstanceIdx(instance_idx);
675- char[64] name;
676- create_template_name(name, d.getName(), instance_idx);
677- instance.setInstanceName(ma.astPool.addStr(name, true));
678706 }
679- call.setTemplateIdx(instance.getTemplateInstanceIdx());
680-
681707 return instance;
682708}
683709
0 commit comments