@@ -89,39 +89,110 @@ using Func = void(T, const U&);
8989TEST (Rewriter, Var) {
9090 auto source = R"(
9191template <int i>
92- const int c = i + 321;
92+ const int c = i + 321 + i ;
9393
94- constexpr int x = 123;
94+ constexpr int x = 123 * 2 ;
9595
96+ constexpr int y = c<123 * 2>;
9697)" _cxx;
9798
99+ auto interp = ASTInterpreter{&source.unit };
100+
98101 auto control = source.control ();
99102
100103 auto c = source.getAs <VariableSymbol>(" c" );
101104 ASSERT_TRUE (c != nullptr );
102105 auto templateDeclaration = c->templateDeclaration ();
103106 ASSERT_TRUE (templateDeclaration != nullptr );
104107
108+ // extract the expression 123 * 2 from the AST
105109 auto x = source.getAs <VariableSymbol>(" x" );
106110 ASSERT_TRUE (x != nullptr );
107- auto xinit = x->initializer ();
111+ auto xinit = ast_cast<EqualInitializerAST>( x->initializer ())-> expression ;
108112 ASSERT_TRUE (xinit != nullptr );
109113
114+ // synthesize const auto i = 123 * 2;
115+
116+ // ### need to set scope and location
117+ auto templArg = control->newVariableSymbol (nullptr , {});
118+ templArg->setInitializer (xinit);
119+ templArg->setType (control->add_const (x->type ()));
120+ templArg->setConstValue (interp.evaluate (xinit));
121+ ASSERT_TRUE (templArg->constValue ().has_value ());
122+
110123 auto instance = subst (
111124 source, getTemplateBodyAs<SimpleDeclarationAST>(templateDeclaration),
112- {xinit });
125+ {templArg });
113126
114127 auto decl = instance->initDeclaratorList ->value ;
115128 ASSERT_TRUE (decl != nullptr );
116129
117130 auto init = ast_cast<EqualInitializerAST>(decl->initializer );
118131 ASSERT_TRUE (init);
119132
120- ASTInterpreter interp{&source.unit };
121-
122133 auto value = interp.evaluate (init->expression );
123134
124135 ASSERT_TRUE (value.has_value ());
125136
126- ASSERT_EQ (std::visit (ArithmeticCast<int >{}, *value), 123 + 321 );
137+ ASSERT_EQ (std::visit (ArithmeticCast<int >{}, *value), 123 * 2 + 321 + 123 * 2 );
138+ }
139+
140+ // simulate a template-id instantiation
141+ TEST (Rewriter, TemplateId) {
142+ auto source = R"(
143+ template <int i>
144+ const int c = i + 321 + i;
145+
146+ constexpr int y = c<123 * 2>;
147+ )" _cxx;
148+
149+ auto interp = ASTInterpreter{&source.unit };
150+
151+ auto control = source.control ();
152+
153+ auto y = source.getAs <VariableSymbol>(" y" );
154+ ASSERT_TRUE (y != nullptr );
155+ auto yinit = ast_cast<EqualInitializerAST>(y->initializer ())->expression ;
156+ ASSERT_TRUE (yinit != nullptr );
157+
158+ auto idExpr = ast_cast<IdExpressionAST>(yinit);
159+ ASSERT_TRUE (idExpr != nullptr );
160+
161+ ASSERT_TRUE (idExpr->symbol );
162+
163+ auto templateId = ast_cast<SimpleTemplateIdAST>(idExpr->unqualifiedId );
164+ ASSERT_TRUE (templateId != nullptr );
165+
166+ // get the primary template declaration
167+ auto templateSym =
168+ symbol_cast<VariableSymbol>(templateId->primaryTemplateSymbol );
169+ ASSERT_TRUE (templateSym != nullptr );
170+ auto templateDecl = getTemplateBodyAs<SimpleDeclarationAST>(
171+ templateSym->templateDeclaration ());
172+ ASSERT_TRUE (templateDecl != nullptr );
173+
174+ std::vector<TemplateArgument> templateArguments;
175+ for (auto arg : ListView{templateId->templateArgumentList }) {
176+ if (auto exprArg = ast_cast<ExpressionTemplateArgumentAST>(arg)) {
177+ auto expr = exprArg->expression ;
178+ // ### need to set scope and location
179+ auto templArg = control->newVariableSymbol (nullptr , {});
180+ templArg->setInitializer (expr);
181+ templArg->setType (control->add_const (expr->type ));
182+ templArg->setConstValue (interp.evaluate (expr));
183+ ASSERT_TRUE (templArg->constValue ().has_value ());
184+ templateArguments.push_back (templArg);
185+ }
186+ }
187+
188+ auto instance = subst (source, templateDecl, templateArguments);
189+ ASSERT_TRUE (instance != nullptr );
190+
191+ auto decl = instance->initDeclaratorList ->value ;
192+ ASSERT_TRUE (decl != nullptr );
193+ auto init = ast_cast<EqualInitializerAST>(decl->initializer );
194+ ASSERT_TRUE (init != nullptr );
195+ auto value = interp.evaluate (init->expression );
196+ ASSERT_TRUE (value.has_value ());
197+ ASSERT_EQ (std::visit (ArithmeticCast<int >{}, *value), 123 * 2 + 321 + 123 * 2 );
127198}
0 commit comments