@@ -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;
@@ -84,17 +109,10 @@ fn QualType Analyser.analyseCallExpr(Analyser* ma, Expr** e_ptr) {
84109 if (fd.hasAttrNoReturn()) call.setNoreturn();
85110
86111 if (fd.isTemplate()) {
87- if (!call.getTemplateArg()) {
88- ma.errorRange(e.getLoc(), e.getRange(), "function %s requires a template argument", fd.asDecl().getFullName());
89- return QualType_Invalid;
90- }
91- fd = ma.instantiateTemplateFunction(call, fd);
92- if (!fd) return QualType_Invalid;
93- } else {
94- if (call.getTemplateArg()) {
95- ma.errorRange(e.getLoc(), e.getRange(), "function %s is not a template function", fd.asDecl().getFullName());
96- return QualType_Invalid;
97- }
112+ // TODO handle default type arguments
113+ // TODO auto-instantiate based on actual argument types
114+ ma.errorRange(e.getLoc(), e.getRange(), "function %s requires a template argument", fd.asDecl().getFullName());
115+ return QualType_Invalid;
98116 }
99117
100118 if (fd.hasAttrDeprecated() && !ma.warnings.no_deprecated) {
@@ -659,12 +677,18 @@ fn void Analyser.opaque_callback(void* arg, SrcLoc loc, Decl* d) {
659677 ma.error(loc," using opaque type '%s'", qt.diagName());
660678}
661679
662- fn FunctionDecl* Analyser.instantiateTemplateFunction(Analyser* ma, CallExpr* call, FunctionDecl* fd) {
663- TypeRef* template_arg = call.getTemplateArg();
680+ fn FunctionDecl* Analyser.instantiateFunctionTemplate(Analyser* ma, FunctionDecl* fd, u16 instance_ast_idx, Expr** args, u32 num_args) {
681+ // Only handle first argument for now, convert to type
682+ TypeRef* template_arg = ma.getTemplateArg(*args);
683+ if (!template_arg) return nil;
664684 QualType templateType = ma.analyseTypeRef(template_arg);
665685 if (templateType.isInvalid()) return nil;
666686
667- FunctionDecl* instance = ma.mod.findInstance(fd, templateType);
687+ // TODO create instiator, analyse/evaluate template expressions,
688+ // initialize TemplateSubst array from values or qualtypes,
689+ // compute instance name and check if name exists already
690+
691+ FunctionDecl* instance = (FunctionDecl*)ma.mod.findInstance(fd.asDecl(), templateType);
668692 if (!instance) {
669693 // note: template_arg decl is set here
670694 bool used_opaque = false;
@@ -674,11 +698,14 @@ fn FunctionDecl* Analyser.instantiateTemplateFunction(Analyser* ma, CallExpr* ca
674698 Decl* d = (Decl*)std;
675699 used_opaque = (std.isOpaque() && d.getModule() != ma.mod);
676700 }
701+ // TODO: use TemplateSpec in Instantiator
702+ const TemplateSpec* spec = fd.getTemplateSpec();
677703 Instantiator inst = {
678704 .c = ma.context,
679705 .ref = template_arg,
680- .template_name = fd.getTemplateNameIdx(),
681- .instance_ast_idx = call.getInstanceASTIdx(),
706+ .template_vars = spec.getTemplateVars(),
707+ .template_len = spec.getTemplateLen(),
708+ .instance_ast_idx = instance_ast_idx,
682709 .used_opaque = used_opaque,
683710 .arg = ma,
684711 .on_error = Analyser.opaque_callback,
@@ -689,6 +716,13 @@ fn FunctionDecl* Analyser.instantiateTemplateFunction(Analyser* ma, CallExpr* ca
689716 if (ma.has_error) return nil;
690717 d.setChecked();
691718
719+ // add instance to avoid recursive instantiation for the same type
720+ u16 instance_idx = ma.mod.addInstance(fd.asDecl(), templateType, instance.asDecl());
721+ char[64] name;
722+ // TODO: use a more readable name, eg: max$i32
723+ create_template_name(name, elemsof(name), fd.asDecl().getName(), instance_idx);
724+ d.setNameIdx(ma.astPool.addStr(name, true));
725+
692726 // Note: we need a separate scope for the body
693727 Module* template_mod = fd.asDecl().getModule();
694728 Analyser* analyser = create(ma.diags, ma.context, ma.astPool, ma.builder, ma.allmodules, ma.warnings, ma.check_only);
@@ -704,15 +738,7 @@ fn FunctionDecl* Analyser.instantiateTemplateFunction(Analyser* ma, CallExpr* ca
704738 analyser.free();
705739
706740 if (ma.has_error) return nil;
707-
708- u16 instance_idx = ma.mod.addInstance(fd, templateType, instance);
709- instance.setTemplateInstanceIdx(instance_idx);
710- char[64] name;
711- create_template_name(name, elemsof(name), d.getName(), instance_idx);
712- instance.setInstanceName(ma.astPool.addStr(name, true));
713741 }
714- call.setTemplateIdx(instance.getTemplateInstanceIdx());
715-
716742 return instance;
717743}
718744
0 commit comments