@@ -944,6 +944,67 @@ TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolDifference) {
944
944
EXPECT_FALSE (testStructuralMatch (First, Second));
945
945
}
946
946
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
+
947
1008
struct StructuralEquivalenceDependentTemplateArgsTest
948
1009
: StructuralEquivalenceTemplateTest {};
949
1010
@@ -1082,5 +1143,136 @@ TEST_F(StructuralEquivalenceDependentTemplateArgsTest,
1082
1143
EXPECT_FALSE (testStructuralMatch (t));
1083
1144
}
1084
1145
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
+
1085
1277
} // end namespace ast_matchers
1086
1278
} // end namespace clang
0 commit comments