@@ -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) {
@@ -661,12 +679,18 @@ fn void Analyser.opaque_callback(void* arg, SrcLoc loc, Decl* d) {
661679 ma.error(loc," using opaque type '%s'", qt.diagName());
662680}
663681
664- fn FunctionDecl* Analyser.instantiateTemplateFunction(Analyser* ma, CallExpr* call, FunctionDecl* fd) {
665- TypeRef* template_arg = call.getTemplateArg();
682+ fn FunctionDecl* Analyser.instantiateFunctionTemplate(Analyser* ma, FunctionDecl* fd, u16 instance_ast_idx, Expr** args, u32 num_args) {
683+ // Only handle first argument for now, convert to type
684+ TypeRef* template_arg = ma.getTemplateArg(*args);
685+ if (!template_arg) return nil;
666686 QualType templateType = ma.analyseTypeRef(template_arg);
667687 if (templateType.isInvalid()) return nil;
668688
669- FunctionDecl* instance = ma.mod.findInstance(fd, templateType);
689+ // TODO create instiator, analyse/evaluate template expressions,
690+ // initialize TemplateSubst array from values or qualtypes,
691+ // compute instance name and check if name exists already
692+
693+ FunctionDecl* instance = (FunctionDecl*)ma.mod.findInstance(fd.asDecl(), templateType);
670694 if (!instance) {
671695 // note: template_arg decl is set here
672696 bool used_opaque = false;
@@ -676,11 +700,14 @@ fn FunctionDecl* Analyser.instantiateTemplateFunction(Analyser* ma, CallExpr* ca
676700 Decl* d = (Decl*)std;
677701 used_opaque = (std.isOpaque() && d.getModule() != ma.mod);
678702 }
703+ // TODO: use TemplateSpec in Instantiator
704+ const TemplateSpec* spec = fd.getTemplateSpec();
679705 Instantiator inst = {
680706 .c = ma.context,
681707 .ref = template_arg,
682- .template_name = fd.getTemplateNameIdx(),
683- .instance_ast_idx = call.getInstanceASTIdx(),
708+ .template_vars = spec.getTemplateVars(),
709+ .template_len = spec.getTemplateLen(),
710+ .instance_ast_idx = instance_ast_idx,
684711 .used_opaque = used_opaque,
685712 .arg = ma,
686713 .on_error = Analyser.opaque_callback,
@@ -691,6 +718,13 @@ fn FunctionDecl* Analyser.instantiateTemplateFunction(Analyser* ma, CallExpr* ca
691718 if (ma.has_error) return nil;
692719 d.setChecked();
693720
721+ // add instance to avoid recursive instantiation for the same type
722+ u16 instance_idx = ma.mod.addInstance(fd.asDecl(), templateType, instance.asDecl());
723+ char[64] name;
724+ // TODO: use a more readable name, eg: max$i32
725+ create_template_name(name, elemsof(name), fd.asDecl().getName(), instance_idx);
726+ d.setNameIdx(ma.astPool.addStr(name, true));
727+
694728 // Note: we need a separate scope for the body
695729 Module* template_mod = fd.asDecl().getModule();
696730 Analyser* analyser = ma.clone();
@@ -706,15 +740,7 @@ fn FunctionDecl* Analyser.instantiateTemplateFunction(Analyser* ma, CallExpr* ca
706740 analyser.free();
707741
708742 if (ma.has_error) return nil;
709-
710- u16 instance_idx = ma.mod.addInstance(fd, templateType, instance);
711- instance.setTemplateInstanceIdx(instance_idx);
712- char[64] name;
713- create_template_name(name, elemsof(name), d.getName(), instance_idx);
714- instance.setInstanceName(ma.astPool.addStr(name, true));
715743 }
716- call.setTemplateIdx(instance.getTemplateInstanceIdx());
717-
718744 return instance;
719745}
720746
0 commit comments