@@ -944,6 +944,67 @@ TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolDifference) {
944944 EXPECT_FALSE (testStructuralMatch (First, Second));
945945}
946946
947+ TEST_F (StructuralEquivalenceTemplateTest,
948+ TemplateVsSubstTemplateTemplateParmInArgEq) {
949+ auto t = makeDecls<ClassTemplateSpecializationDecl>(
950+ R"(
951+ template <typename P1> class Arg { };
952+ template <template <typename PP1> class P1> class Primary { };
953+
954+ void f() {
955+ // Make specialization with simple template.
956+ Primary <Arg> A;
957+ }
958+ )" ,
959+ R"(
960+ template <typename P1> class Arg { };
961+ template <template <typename PP1> class P1> class Primary { };
962+
963+ template <template <typename PP1> class P1> class Templ {
964+ void f() {
965+ // Make specialization with substituted template template param.
966+ Primary <P1> A;
967+ };
968+ };
969+
970+ // Instantiate with substitution Arg into P1.
971+ template class Templ <Arg>;
972+ )" ,
973+ Lang_CXX, classTemplateSpecializationDecl (hasName (" Primary" )));
974+ EXPECT_TRUE (testStructuralMatch (t));
975+ }
976+
977+ TEST_F (StructuralEquivalenceTemplateTest,
978+ TemplateVsSubstTemplateTemplateParmInArgNotEq) {
979+ auto t = makeDecls<ClassTemplateSpecializationDecl>(
980+ R"(
981+ template <typename P1> class Arg { };
982+ template <template <typename PP1> class P1> class Primary { };
983+
984+ void f() {
985+ // Make specialization with simple template.
986+ Primary <Arg> A;
987+ }
988+ )" ,
989+ R"(
990+ // Arg is different from the other, this should cause non-equivalence.
991+ template <typename P1> class Arg { int X; };
992+ template <template <typename PP1> class P1> class Primary { };
993+
994+ template <template <typename PP1> class P1> class Templ {
995+ void f() {
996+ // Make specialization with substituted template template param.
997+ Primary <P1> A;
998+ };
999+ };
1000+
1001+ // Instantiate with substitution Arg into P1.
1002+ template class Templ <Arg>;
1003+ )" ,
1004+ Lang_CXX, classTemplateSpecializationDecl (hasName (" Primary" )));
1005+ EXPECT_FALSE (testStructuralMatch (t));
1006+ }
1007+
9471008struct StructuralEquivalenceDependentTemplateArgsTest
9481009 : StructuralEquivalenceTemplateTest {};
9491010
@@ -1082,5 +1143,136 @@ TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
10821143 EXPECT_FALSE (testStructuralMatch (t));
10831144}
10841145
1146+ TEST_F (
1147+ StructuralEquivalenceTemplateTest,
1148+ ClassTemplSpecWithQualifiedAndNonQualifiedTypeArgsShouldBeEqual) {
1149+ auto t = makeDecls<ClassTemplateSpecializationDecl>(
1150+ R"(
1151+ template <class T> struct Primary {};
1152+ namespace N {
1153+ struct Arg;
1154+ }
1155+ // Explicit instantiation with qualified name.
1156+ template struct Primary<N::Arg>;
1157+ )" ,
1158+ R"(
1159+ template <class T> struct Primary {};
1160+ namespace N {
1161+ struct Arg;
1162+ }
1163+ using namespace N;
1164+ // Explicit instantiation with UNqualified name.
1165+ template struct Primary<Arg>;
1166+ )" ,
1167+ Lang_CXX,
1168+ classTemplateSpecializationDecl (hasName (" Primary" )));
1169+ EXPECT_TRUE (testStructuralMatch (t));
1170+ }
1171+
1172+ TEST_F (
1173+ StructuralEquivalenceTemplateTest,
1174+ ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTypeArgs) {
1175+ auto t = makeDecls<ClassTemplateSpecializationDecl>(
1176+ R"(
1177+ template <class T> struct Primary {};
1178+ namespace N {
1179+ struct Arg { int a; };
1180+ }
1181+ // Explicit instantiation with qualified name.
1182+ template struct Primary<N::Arg>;
1183+ )" ,
1184+ R"(
1185+ template <class T> struct Primary {};
1186+ namespace N {
1187+ // This struct is not equivalent with the other in the prev TU.
1188+ struct Arg { double b; }; // -- Field mismatch.
1189+ }
1190+ using namespace N;
1191+ // Explicit instantiation with UNqualified name.
1192+ template struct Primary<Arg>;
1193+ )" ,
1194+ Lang_CXX,
1195+ classTemplateSpecializationDecl (hasName (" Primary" )));
1196+ EXPECT_FALSE (testStructuralMatch (t));
1197+ }
1198+
1199+ TEST_F (
1200+ StructuralEquivalenceTemplateTest,
1201+ ClassTemplSpecWithQualifiedAndNonQualifiedTemplArgsShouldBeEqual) {
1202+ auto t = makeDecls<ClassTemplateSpecializationDecl>(
1203+ R"(
1204+ template <template <class> class T> struct Primary {};
1205+ namespace N {
1206+ template <class T> struct Arg;
1207+ }
1208+ // Explicit instantiation with qualified name.
1209+ template struct Primary<N::Arg>;
1210+ )" ,
1211+ R"(
1212+ template <template <class> class T> struct Primary {};
1213+ namespace N {
1214+ template <class T> struct Arg;
1215+ }
1216+ using namespace N;
1217+ // Explicit instantiation with UNqualified name.
1218+ template struct Primary<Arg>;
1219+ )" ,
1220+ Lang_CXX,
1221+ classTemplateSpecializationDecl (hasName (" Primary" )));
1222+ EXPECT_TRUE (testStructuralMatch (t));
1223+ }
1224+
1225+ TEST_F (
1226+ StructuralEquivalenceTemplateTest,
1227+ ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTemplArgs) {
1228+ auto t = makeDecls<ClassTemplateSpecializationDecl>(
1229+ R"(
1230+ template <template <class> class T> struct Primary {};
1231+ namespace N {
1232+ template <class T> struct Arg { int a; };
1233+ }
1234+ // Explicit instantiation with qualified name.
1235+ template struct Primary<N::Arg>;
1236+ )" ,
1237+ R"(
1238+ template <template <class> class T> struct Primary {};
1239+ namespace N {
1240+ // This template is not equivalent with the other in the prev TU.
1241+ template <class T> struct Arg { double b; }; // -- Field mismatch.
1242+ }
1243+ using namespace N;
1244+ // Explicit instantiation with UNqualified name.
1245+ template struct Primary<Arg>;
1246+ )" ,
1247+ Lang_CXX,
1248+ classTemplateSpecializationDecl (hasName (" Primary" )));
1249+ EXPECT_FALSE (testStructuralMatch (t));
1250+ }
1251+
1252+ TEST_F (
1253+ StructuralEquivalenceTemplateTest,
1254+ ClassTemplSpecWithInequivalentShadowedTemplArg) {
1255+ auto t = makeDecls<ClassTemplateSpecializationDecl>(
1256+ R"(
1257+ template <template <class> class T> struct Primary {};
1258+ template <class T> struct Arg { int a; };
1259+ // Explicit instantiation with ::Arg
1260+ template struct Primary<Arg>;
1261+ )" ,
1262+ R"(
1263+ template <template <class> class T> struct Primary {};
1264+ template <class T> struct Arg { int a; };
1265+ namespace N {
1266+ // This template is not equivalent with the other in the global scope.
1267+ template <class T> struct Arg { double b; }; // -- Field mismatch.
1268+ // Explicit instantiation with N::Arg which shadows ::Arg
1269+ template struct Primary<Arg>;
1270+ }
1271+ )" ,
1272+ Lang_CXX,
1273+ classTemplateSpecializationDecl (hasName (" Primary" )));
1274+ EXPECT_FALSE (testStructuralMatch (t));
1275+ }
1276+
10851277} // end namespace ast_matchers
10861278} // end namespace clang
0 commit comments