@@ -265,6 +265,102 @@ TEST(QualTypeNameTest, InlineNamespace) {
265
265
TypeNameVisitor::Lang_CXX11);
266
266
}
267
267
268
+ TEST (QualTypeNameTest, TemplatedClass) {
269
+ std::unique_ptr<ASTUnit> AST =
270
+ tooling::buildASTFromCode (" template <unsigned U1> struct A {\n "
271
+ " template <unsigned U2> struct B {};\n "
272
+ " };\n "
273
+ " template struct A<1>;\n "
274
+ " template struct A<2u>;\n "
275
+ " template struct A<1>::B<3>;\n "
276
+ " template struct A<2u>::B<4u>;\n " );
277
+
278
+ auto &Context = AST->getASTContext ();
279
+ auto &Policy = Context.getPrintingPolicy ();
280
+ auto getFullyQualifiedName = [&](QualType QT) {
281
+ return TypeName::getFullyQualifiedName (QT, Context, Policy);
282
+ };
283
+
284
+ auto *A = Context.getTranslationUnitDecl ()
285
+ ->lookup (&Context.Idents .get (" A" ))
286
+ .find_first <ClassTemplateDecl>();
287
+ ASSERT_NE (A, nullptr );
288
+
289
+ // A has two explicit instantiations: A<1> and A<2u>
290
+ auto ASpec = A->spec_begin ();
291
+ ASSERT_NE (ASpec, A->spec_end ());
292
+ auto *A1 = *ASpec;
293
+ ASpec++;
294
+ ASSERT_NE (ASpec, A->spec_end ());
295
+ auto *A2 = *ASpec;
296
+
297
+ // Their type names follow the records.
298
+ QualType A1RecordTy = Context.getRecordType (A1);
299
+ EXPECT_EQ (getFullyQualifiedName (A1RecordTy), " A<1>" );
300
+ QualType A2RecordTy = Context.getRecordType (A2);
301
+ EXPECT_EQ (getFullyQualifiedName (A2RecordTy), " A<2U>" );
302
+
303
+ // getTemplateSpecializationType() gives types that print the integral
304
+ // argument directly.
305
+ TemplateArgument Args1[] = {
306
+ {Context, llvm::APSInt::getUnsigned (1u ), Context.UnsignedIntTy }};
307
+ QualType A1TemplateSpecTy =
308
+ Context.getTemplateSpecializationType (TemplateName (A), Args1, A1RecordTy);
309
+ EXPECT_EQ (A1TemplateSpecTy.getAsString (), " A<1>" );
310
+
311
+ TemplateArgument Args2[] = {
312
+ {Context, llvm::APSInt::getUnsigned (2u ), Context.UnsignedIntTy }};
313
+ QualType A2TemplateSpecTy =
314
+ Context.getTemplateSpecializationType (TemplateName (A), Args2, A2RecordTy);
315
+ EXPECT_EQ (A2TemplateSpecTy.getAsString (), " A<2>" );
316
+
317
+ // Find A<1>::B and its specialization B<3>.
318
+ auto *A1B =
319
+ A1->lookup (&Context.Idents .get (" B" )).find_first <ClassTemplateDecl>();
320
+ ASSERT_NE (A1B, nullptr );
321
+ auto A1BSpec = A1B->spec_begin ();
322
+ ASSERT_NE (A1BSpec, A1B->spec_end ());
323
+ auto *A1B3 = *A1BSpec;
324
+ QualType A1B3RecordTy = Context.getRecordType (A1B3);
325
+ EXPECT_EQ (getFullyQualifiedName (A1B3RecordTy), " A<1>::B<3>" );
326
+
327
+ // Construct A<1>::B<3> and check name.
328
+ TemplateArgument Args3[] = {
329
+ {Context, llvm::APSInt::getUnsigned (3u ), Context.UnsignedIntTy }};
330
+ QualType A1B3TemplateSpecTy = Context.getTemplateSpecializationType (
331
+ TemplateName (A1B), Args3, A1B3RecordTy);
332
+ EXPECT_EQ (A1B3TemplateSpecTy.getAsString (), " B<3>" );
333
+
334
+ NestedNameSpecifier *A1Nested = NestedNameSpecifier::Create (
335
+ Context, nullptr , false , A1TemplateSpecTy.getTypePtr ());
336
+ QualType A1B3ElaboratedTy = Context.getElaboratedType (
337
+ ElaboratedTypeKeyword::None, A1Nested, A1B3TemplateSpecTy);
338
+ EXPECT_EQ (A1B3ElaboratedTy.getAsString (), " A<1>::B<3>" );
339
+
340
+ // Find A<2u>::B and its specialization B<4u>.
341
+ auto *A2B =
342
+ A2->lookup (&Context.Idents .get (" B" )).find_first <ClassTemplateDecl>();
343
+ ASSERT_NE (A2B, nullptr );
344
+ auto A2BSpec = A2B->spec_begin ();
345
+ ASSERT_NE (A2BSpec, A2B->spec_end ());
346
+ auto *A2B4 = *A2BSpec;
347
+ QualType A2B4RecordTy = Context.getRecordType (A2B4);
348
+ EXPECT_EQ (getFullyQualifiedName (A2B4RecordTy), " A<2U>::B<4U>" );
349
+
350
+ // Construct A<2>::B<4> and check name.
351
+ TemplateArgument Args4[] = {
352
+ {Context, llvm::APSInt::getUnsigned (4u ), Context.UnsignedIntTy }};
353
+ QualType A2B4TemplateSpecTy = Context.getTemplateSpecializationType (
354
+ TemplateName (A2B), Args4, A2B4RecordTy);
355
+ EXPECT_EQ (A2B4TemplateSpecTy.getAsString (), " B<4>" );
356
+
357
+ NestedNameSpecifier *A2Nested = NestedNameSpecifier::Create (
358
+ Context, nullptr , false , A2TemplateSpecTy.getTypePtr ());
359
+ QualType A2B4ElaboratedTy = Context.getElaboratedType (
360
+ ElaboratedTypeKeyword::None, A2Nested, A2B4TemplateSpecTy);
361
+ EXPECT_EQ (A2B4ElaboratedTy.getAsString (), " A<2>::B<4>" );
362
+ }
363
+
268
364
TEST (QualTypeNameTest, AnonStrucs) {
269
365
TypeNameVisitor AnonStrucs;
270
366
AnonStrucs.ExpectedQualTypeNames [" a" ] = " short" ;
0 commit comments