@@ -2369,6 +2369,80 @@ TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureOfReferenceType) {
2369
2369
" }" , matcher));
2370
2370
}
2371
2371
2372
+ TEST_P (ASTMatchersTest, IsDerivedFromRecursion) {
2373
+ if (!GetParam ().isCXX11OrLater ())
2374
+ return ;
2375
+
2376
+ // Check we don't crash on cycles in the traversal and inheritance hierarchy.
2377
+ // Clang will normally enforce there are no cycles, but matchers opted to
2378
+ // traverse primary template for dependent specializations, spuriously
2379
+ // creating the cycles.
2380
+ DeclarationMatcher matcher = cxxRecordDecl (isDerivedFrom (" X" ));
2381
+ EXPECT_TRUE (notMatches (R"cpp(
2382
+ template <typename T1, typename T2>
2383
+ struct M;
2384
+
2385
+ template <typename T1>
2386
+ struct M<T1, void> {};
2387
+
2388
+ template <typename T1, typename T2>
2389
+ struct L : M<T1, T2> {};
2390
+
2391
+ template <typename T1, typename T2>
2392
+ struct M : L<M<T1, T2>, M<T1, T2>> {};
2393
+ )cpp" ,
2394
+ matcher));
2395
+
2396
+ // Check the running time is not exponential. The number of subojects to
2397
+ // traverse grows as fibonacci numbers even though the number of bases to
2398
+ // traverse is quadratic.
2399
+ // The test will hang if implementation of matchers traverses all subojects.
2400
+ EXPECT_TRUE (notMatches (R"cpp(
2401
+ template <class T> struct A0 {};
2402
+ template <class T> struct A1 : A0<T> {};
2403
+ template <class T> struct A2 : A1<T>, A0<T> {};
2404
+ template <class T> struct A3 : A2<T>, A1<T> {};
2405
+ template <class T> struct A4 : A3<T>, A2<T> {};
2406
+ template <class T> struct A5 : A4<T>, A3<T> {};
2407
+ template <class T> struct A6 : A5<T>, A4<T> {};
2408
+ template <class T> struct A7 : A6<T>, A5<T> {};
2409
+ template <class T> struct A8 : A7<T>, A6<T> {};
2410
+ template <class T> struct A9 : A8<T>, A7<T> {};
2411
+ template <class T> struct A10 : A9<T>, A8<T> {};
2412
+ template <class T> struct A11 : A10<T>, A9<T> {};
2413
+ template <class T> struct A12 : A11<T>, A10<T> {};
2414
+ template <class T> struct A13 : A12<T>, A11<T> {};
2415
+ template <class T> struct A14 : A13<T>, A12<T> {};
2416
+ template <class T> struct A15 : A14<T>, A13<T> {};
2417
+ template <class T> struct A16 : A15<T>, A14<T> {};
2418
+ template <class T> struct A17 : A16<T>, A15<T> {};
2419
+ template <class T> struct A18 : A17<T>, A16<T> {};
2420
+ template <class T> struct A19 : A18<T>, A17<T> {};
2421
+ template <class T> struct A20 : A19<T>, A18<T> {};
2422
+ template <class T> struct A21 : A20<T>, A19<T> {};
2423
+ template <class T> struct A22 : A21<T>, A20<T> {};
2424
+ template <class T> struct A23 : A22<T>, A21<T> {};
2425
+ template <class T> struct A24 : A23<T>, A22<T> {};
2426
+ template <class T> struct A25 : A24<T>, A23<T> {};
2427
+ template <class T> struct A26 : A25<T>, A24<T> {};
2428
+ template <class T> struct A27 : A26<T>, A25<T> {};
2429
+ template <class T> struct A28 : A27<T>, A26<T> {};
2430
+ template <class T> struct A29 : A28<T>, A27<T> {};
2431
+ template <class T> struct A30 : A29<T>, A28<T> {};
2432
+ template <class T> struct A31 : A30<T>, A29<T> {};
2433
+ template <class T> struct A32 : A31<T>, A30<T> {};
2434
+ template <class T> struct A33 : A32<T>, A31<T> {};
2435
+ template <class T> struct A34 : A33<T>, A32<T> {};
2436
+ template <class T> struct A35 : A34<T>, A33<T> {};
2437
+ template <class T> struct A36 : A35<T>, A34<T> {};
2438
+ template <class T> struct A37 : A36<T>, A35<T> {};
2439
+ template <class T> struct A38 : A37<T>, A36<T> {};
2440
+ template <class T> struct A39 : A38<T>, A37<T> {};
2441
+ template <class T> struct A40 : A39<T>, A38<T> {};
2442
+ )cpp" ,
2443
+ matcher));
2444
+ }
2445
+
2372
2446
TEST (ASTMatchersTestObjC, ObjCMessageCalees) {
2373
2447
StatementMatcher MessagingFoo =
2374
2448
objcMessageExpr (callee (objcMethodDecl (hasName (" foo" ))));
0 commit comments