@@ -384,4 +384,298 @@ void test_compound_assignments() {
384
384
l2 >>= 1 ; // COMPLIANT - compound assignment, rule does not apply
385
385
l4 += l1; // COMPLIANT - compound assignment, rule does not apply
386
386
l4 -= s32; // COMPLIANT - compound assignment, rule does not apply
387
+ }
388
+
389
+ // Test user-defined operators - always non-extensible
390
+ struct UserDefinedOperators {
391
+ UserDefinedOperators (std::int32_t l1) {}
392
+
393
+ // Binary operators
394
+ UserDefinedOperators operator +(std::int32_t l1) const {
395
+ return UserDefinedOperators{0 };
396
+ }
397
+ UserDefinedOperators operator -(std::int32_t l1) const {
398
+ return UserDefinedOperators{0 };
399
+ }
400
+ UserDefinedOperators operator *(std::int32_t l1) const {
401
+ return UserDefinedOperators{0 };
402
+ }
403
+ UserDefinedOperators operator /(std::int32_t l1) const {
404
+ return UserDefinedOperators{0 };
405
+ }
406
+ UserDefinedOperators operator %(std::int32_t l1) const {
407
+ return UserDefinedOperators{0 };
408
+ }
409
+ UserDefinedOperators operator &(std::int32_t l1) const {
410
+ return UserDefinedOperators{0 };
411
+ }
412
+ UserDefinedOperators operator |(std::int32_t l1) const {
413
+ return UserDefinedOperators{0 };
414
+ }
415
+ UserDefinedOperators operator ^(std::int32_t l1) const {
416
+ return UserDefinedOperators{0 };
417
+ }
418
+ UserDefinedOperators operator <<(std::int32_t l1) const {
419
+ return UserDefinedOperators{0 };
420
+ }
421
+ UserDefinedOperators operator >>(std::int32_t l1) const {
422
+ return UserDefinedOperators{0 };
423
+ }
424
+
425
+ // Comparison operators
426
+ bool operator ==(std::int32_t l1) const { return true ; }
427
+ bool operator !=(std::int32_t l1) const { return false ; }
428
+ bool operator <(std::int32_t l1) const { return false ; }
429
+ bool operator <=(std::int32_t l1) const { return false ; }
430
+ bool operator >(std::int32_t l1) const { return false ; }
431
+ bool operator >=(std::int32_t l1) const { return false ; }
432
+
433
+ // Subscript operator
434
+ std::int32_t operator [](std::int32_t l1) const { return 0 ; }
435
+
436
+ // Function call operator
437
+ std::int32_t operator ()(std::int32_t l1) const { return 0 ; }
438
+ std::int32_t operator ()(std::int32_t l1, std::int32_t l2) const { return 0 ; }
439
+
440
+ // Assignment operators
441
+ UserDefinedOperators &operator =(std::int32_t l1) { return *this ; }
442
+ UserDefinedOperators &operator +=(std::int32_t l1) { return *this ; }
443
+ UserDefinedOperators &operator -=(std::int32_t l1) { return *this ; }
444
+ UserDefinedOperators &operator *=(std::int32_t l1) { return *this ; }
445
+ UserDefinedOperators &operator /=(std::int32_t l1) { return *this ; }
446
+ UserDefinedOperators &operator %=(std::int32_t l1) { return *this ; }
447
+ UserDefinedOperators &operator &=(std::int32_t l1) { return *this ; }
448
+ UserDefinedOperators &operator |=(std::int32_t l1) { return *this ; }
449
+ UserDefinedOperators &operator ^=(std::int32_t l1) { return *this ; }
450
+ UserDefinedOperators &operator <<=(std::int32_t l1) { return *this ; }
451
+ UserDefinedOperators &operator >>=(std::int32_t l1) { return *this ; }
452
+
453
+ // Increment/decrement operators
454
+ UserDefinedOperators &operator ++() { return *this ; }
455
+ UserDefinedOperators operator ++(int ) { return UserDefinedOperators{0 }; }
456
+ UserDefinedOperators &operator --() { return *this ; }
457
+ UserDefinedOperators operator --(int ) { return UserDefinedOperators{0 }; }
458
+ };
459
+
460
+ // Global user-defined operators
461
+ UserDefinedOperators operator +(std::int32_t l1,
462
+ const UserDefinedOperators &l2) {
463
+ return UserDefinedOperators{0 };
464
+ }
465
+
466
+ UserDefinedOperators operator -(std::int32_t l1,
467
+ const UserDefinedOperators &l2) {
468
+ return UserDefinedOperators{0 };
469
+ }
470
+
471
+ bool operator ==(std::int32_t l1, const UserDefinedOperators &l2) {
472
+ return true ;
473
+ }
474
+
475
+ void test_user_defined_operators () {
476
+ UserDefinedOperators l1{42 };
477
+ std::int32_t l2 = 10 ;
478
+ std::int16_t l3 = 5 ;
479
+ std::int64_t l4 = 100 ;
480
+ std::uint32_t l5 = 20 ;
481
+
482
+ // Member operators - non-extensible, exact type match required
483
+ l1 + l2; // COMPLIANT - exact type match
484
+ l1 + l3; // COMPLIANT - widening conversion is allowed
485
+ l1 + l4; // NON_COMPLIANT - different type
486
+ l1 + l5; // NON_COMPLIANT - different signedness
487
+
488
+ l1 - l2; // COMPLIANT - exact type match
489
+ l1 - l3; // COMPLIANT - widening conversion is allowed
490
+ l1 - l4; // NON_COMPLIANT - different type
491
+ l1 - l5; // NON_COMPLIANT - different signedness
492
+
493
+ l1 *l2; // COMPLIANT - exact type match
494
+ l1 *l3; // COMPLIANT - widening conversion is allowed
495
+ l1 *l4; // NON_COMPLIANT - different type
496
+ l1 *l5; // NON_COMPLIANT - different signedness
497
+
498
+ l1 / l2; // COMPLIANT - exact type match
499
+ l1 / l3; // COMPLIANT - widening conversion is allowed
500
+ l1 / l4; // NON_COMPLIANT - different type
501
+ l1 / l5; // NON_COMPLIANT - different signedness
502
+
503
+ l1 % l2; // COMPLIANT - exact type match
504
+ l1 % l3; // COMPLIANT - widening conversion is allowed
505
+ l1 % l4; // NON_COMPLIANT - different type
506
+ l1 % l5; // NON_COMPLIANT - different signedness
507
+
508
+ l1 & l2; // COMPLIANT - exact type match
509
+ l1 & l3; // COMPLIANT - widening conversion is allowed
510
+ l1 & l4; // NON_COMPLIANT - different type
511
+ l1 & l5; // NON_COMPLIANT - different signedness
512
+
513
+ l1 | l2; // COMPLIANT - exact type match
514
+ l1 | l3; // COMPLIANT - widening conversion is allowed
515
+ l1 | l4; // NON_COMPLIANT - different type
516
+ l1 | l5; // NON_COMPLIANT - different signedness
517
+
518
+ l1 ^ l2; // COMPLIANT - exact type match
519
+ l1 ^ l3; // COMPLIANT - widening conversion is allowed
520
+ l1 ^ l4; // NON_COMPLIANT - different type
521
+ l1 ^ l5; // NON_COMPLIANT - different signedness
522
+
523
+ l1 << l2; // COMPLIANT - exact type match
524
+ l1 << l3; // COMPLIANT - widening conversion is allowed
525
+ l1 << l4; // NON_COMPLIANT - different type
526
+ l1 << l5; // NON_COMPLIANT - different signedness
527
+
528
+ l1 >> l2; // COMPLIANT - exact type match
529
+ l1 >> l3; // COMPLIANT - widening conversion is allowed
530
+ l1 >> l4; // NON_COMPLIANT - different type
531
+ l1 >> l5; // NON_COMPLIANT - different signedness
532
+
533
+ // Comparison operators
534
+ l1 == l2; // COMPLIANT - exact type match
535
+ l1 == l3; // COMPLIANT - widening conversion is allowed
536
+ l1 == l4; // NON_COMPLIANT - different type
537
+ l1 == l5; // NON_COMPLIANT - different signedness
538
+
539
+ l1 != l2; // COMPLIANT - exact type match
540
+ l1 != l3; // COMPLIANT - widening conversion is allowed
541
+ l1 != l4; // NON_COMPLIANT - different type
542
+ l1 != l5; // NON_COMPLIANT - different signedness
543
+
544
+ l1 < l2; // COMPLIANT - exact type match
545
+ l1 < l3; // COMPLIANT - widening conversion is allowed
546
+ l1 < l4; // NON_COMPLIANT - different type
547
+ l1 < l5; // NON_COMPLIANT - different signedness
548
+
549
+ l1 <= l2; // COMPLIANT - exact type match
550
+ l1 <= l3; // COMPLIANT - widening conversion is allowed
551
+ l1 <= l4; // NON_COMPLIANT - different type
552
+ l1 <= l5; // NON_COMPLIANT
553
+
554
+ l1 > l2; // COMPLIANT - exact type match
555
+ l1 > l3; // COMPLIANT - widening conversion is allowed
556
+ l1 > l4; // NON_COMPLIANT
557
+ l1 > l5; // NON_COMPLIANT - different signedness
558
+
559
+ l1 >= l2; // COMPLIANT - exact type match
560
+ l1 >= l3; // COMPLIANT - widening conversion is allowed
561
+ l1 >= l4; // NON_COMPLIANT
562
+ l1 >= l5; // NON_COMPLIANT - different signedness
563
+
564
+ // Subscript operator
565
+ l1[l2]; // COMPLIANT - exact type match
566
+ l1[l3]; // COMPLIANT - widening conversion is allowed
567
+ l1[l4]; // NON_COMPLIANT - different type
568
+ l1[l5]; // NON_COMPLIANT - different signedness
569
+
570
+ // Function call operator
571
+ l1 (l2); // COMPLIANT - exact type match
572
+ l1 (l3); // COMPLIANT - widening conversion is allowed
573
+ l1 (l4); // NON_COMPLIANT - different type
574
+ l1 (l5); // NON_COMPLIANT - different signedness
575
+ l1 (l2, l2); // COMPLIANT - both exact type match
576
+ l1 (l2, l4); // NON_COMPLIANT - second parameter different type
577
+ l1 (l4, l2); // NON_COMPLIANT - first parameter different type
578
+ l1 (l4, l5); // NON_COMPLIANT - both parameters different type
579
+
580
+ // The presence of a default copy constructor for UserDefinedOperators means
581
+ // that assignments through operator= must be exact type matches.
582
+ l1 = l2; // COMPLIANT - exact type match
583
+ l1 = l3; // NON_COMPLIANT
584
+ l1 = l4; // NON_COMPLIANT
585
+ l1 = l5; // NON_COMPLIANT
586
+
587
+ l1 += l2; // COMPLIANT - exact type match
588
+ l1 += l3; // COMPLIANT - widening conversion is allowed
589
+ l1 += l4; // NON_COMPLIANT - different type
590
+ l1 += l5; // NON_COMPLIANT - different signedness
591
+
592
+ l1 -= l2; // COMPLIANT - exact type match
593
+ l1 -= l3; // COMPLIANT - widening conversion is allowed
594
+ l1 -= l4; // NON_COMPLIANT - different type
595
+ l1 -= l5; // NON_COMPLIANT - different signedness
596
+
597
+ l1 *= l2; // COMPLIANT - exact type match
598
+ l1 *= l3; // COMPLIANT - widening conversion is allowed
599
+ l1 *= l4; // NON_COMPLIANT - different type
600
+ l1 *= l5; // NON_COMPLIANT - different signedness
601
+
602
+ l1 /= l2; // COMPLIANT - exact type match
603
+ l1 /= l3; // COMPLIANT - widening conversion is allowed
604
+ l1 /= l4; // NON_COMPLIANT - different type
605
+ l1 /= l5; // NON_COMPLIANT - different signedness
606
+
607
+ l1 %= l2; // COMPLIANT - exact type match
608
+ l1 %= l3; // COMPLIANT - widening conversion is allowed
609
+ l1 %= l4; // NON_COMPLIANT - different type
610
+ l1 %= l5; // NON_COMPLIANT - different signedness
611
+
612
+ l1 &= l2; // COMPLIANT - exact type match
613
+ l1 &= l3; // COMPLIANT - widening conversion is allowed
614
+ l1 &= l4; // NON_COMPLIANT - different type
615
+ l1 &= l5; // NON_COMPLIANT - different signedness
616
+
617
+ l1 |= l2; // COMPLIANT - exact type match
618
+ l1 |= l3; // COMPLIANT - widening conversion is allowed
619
+ l1 |= l4; // NON_COMPLIANT - different type
620
+ l1 |= l5; // NON_COMPLIANT - different signedness
621
+
622
+ l1 ^= l2; // COMPLIANT - exact type match
623
+ l1 ^= l3; // COMPLIANT - widening conversion is allowed
624
+ l1 ^= l4; // NON_COMPLIANT - different type
625
+ l1 ^= l5; // NON_COMPLIANT - different signedness
626
+
627
+ l1 <<= l2; // COMPLIANT - exact type match
628
+ l1 <<= l3; // COMPLIANT - widening conversion is allowed
629
+ l1 <<= l4; // NON_COMPLIANT - different type
630
+ l1 <<= l5; // NON_COMPLIANT - different signedness
631
+
632
+ l1 >>= l2; // COMPLIANT - exact type match
633
+ l1 >>= l3; // COMPLIANT - widening conversion is allowed
634
+ l1 >>= l4; // NON_COMPLIANT - different type
635
+ l1 >>= l5; // NON_COMPLIANT - different signedness
636
+
637
+ // Global operators
638
+ l2 + l1; // COMPLIANT - exact type match
639
+ l3 + l1; // COMPLIANT - widening conversion is allowed
640
+ l4 + l1; // NON_COMPLIANT - different type
641
+ l5 + l1; // NON_COMPLIANT - different signedness
642
+
643
+ l2 - l1; // COMPLIANT - exact type match
644
+ l3 - l1; // COMPLIANT - widening conversion is allowed
645
+ l4 - l1; // NON_COMPLIANT - different type
646
+ l5 - l1; // NON_COMPLIANT - different signedness
647
+
648
+ l2 == l1; // COMPLIANT - exact type match
649
+ l3 == l1; // COMPLIANT - widening conversion is allowed
650
+ l4 == l1; // NON_COMPLIANT - different type
651
+ l5 == l1; // NON_COMPLIANT - different signedness
652
+ }
653
+
654
+ // Test user-defined operators with constants
655
+ void test_user_defined_operators_constants () {
656
+ UserDefinedOperators l1{42 };
657
+
658
+ // Constants with exact type match
659
+ l1 + 42 ; // COMPLIANT
660
+ l1 + 42L ; // COMPLIANT
661
+ l1 + 42LL ; // COMPLIANT
662
+ l1 + 42U ; // COMPLIANT
663
+ l1 + 42 .0f ; // NON_COMPLIANT - float constant
664
+
665
+ l1 == 42 ; // COMPLIANT - integer constant is int/int32_t
666
+ l1 == 42L ; // COMPLIANT - long constant
667
+ l1 == 42LL ; // COMPLIANT - long long constant
668
+ l1 == 42U ; // COMPLIANT - unsigned constant
669
+
670
+ l1[42 ]; // COMPLIANT - integer constant is int/int32_t
671
+ l1[42L ]; // COMPLIANT - long constant
672
+ l1[42LL ]; // COMPLIANT - long long constant
673
+ l1[42U ]; // COMPLIANT - unsigned constant
674
+
675
+ // The presence of a default copy constructor for UserDefinedOperators means
676
+ // that assignments through operator= must be exact type matches.
677
+ l1 = 42 ; // COMPLIANT - integer constant is int/int32_t
678
+ l1 = 42L ; // NON_COMPLIANT
679
+ l1 = 42LL ; // NON_COMPLIANT
680
+ l1 = 42U ; // NON_COMPLIANT
387
681
}
0 commit comments