@@ -57,6 +57,7 @@ class TestValueFlow : public TestFixture {
57
57
58
58
TEST_CASE (valueFlowNumber);
59
59
TEST_CASE (valueFlowString);
60
+ TEST_CASE (valueFlowTypeTraits);
60
61
TEST_CASE (valueFlowPointerAlias);
61
62
TEST_CASE (valueFlowLifetime);
62
63
TEST_CASE (valueFlowArrayElement);
@@ -532,6 +533,21 @@ class TestValueFlow : public TestFixture {
532
533
return values.size () == 1U && !values.front ().isTokValue () ? values.front () : ValueFlow::Value ();
533
534
}
534
535
536
+ #define testKnownValueOfTok (...) testKnownValueOfTok_(__FILE__, __LINE__, __VA_ARGS__)
537
+ bool testKnownValueOfTok_ (const char * file,
538
+ int line,
539
+ const char code[],
540
+ const char tokstr[],
541
+ int value,
542
+ const Settings* s = nullptr ,
543
+ bool cpp = true )
544
+ {
545
+ std::list<ValueFlow::Value> values = removeImpossible (tokenValues_ (file, line, code, tokstr, s, cpp));
546
+ return std::any_of (values.begin (), values.end (), [&](const ValueFlow::Value& v) {
547
+ return v.isKnown () && v.isIntValue () && v.intvalue == value;
548
+ });
549
+ }
550
+
535
551
static std::list<ValueFlow::Value> removeSymbolicTok (std::list<ValueFlow::Value> values)
536
552
{
537
553
values.remove_if ([](const ValueFlow::Value& v) {
@@ -596,6 +612,136 @@ class TestValueFlow : public TestFixture {
596
612
ASSERT_EQUALS (true , testValueOfX (code, 2 , " \" abc\" " , ValueFlow::Value::ValueType::TOK));
597
613
}
598
614
615
+ void valueFlowTypeTraits ()
616
+ {
617
+ ASSERT_EQUALS (true , testKnownValueOfTok (" std::is_void<void>{};" , " {" , 1 ));
618
+ ASSERT_EQUALS (true , testKnownValueOfTok (" std::is_void<void>::value;" , " :: value" , 1 ));
619
+ ASSERT_EQUALS (true , testKnownValueOfTok (" std::is_void_v<void>;" , " ::" , 1 ));
620
+
621
+ // is_void
622
+ ASSERT_EQUALS (true , testKnownValueOfTok (" std::is_void<int>{};" , " {" , 0 ));
623
+ ASSERT_EQUALS (true , testKnownValueOfTok (" std::is_void<void*>{};" , " {" , 0 ));
624
+ ASSERT_EQUALS (true , testKnownValueOfTok (" std::is_void<const void>{};" , " {" , 1 ));
625
+ ASSERT_EQUALS (true , testKnownValueOfTok (" std::is_void<volatile void>{};" , " {" , 1 ));
626
+
627
+ // is_lvalue_reference
628
+ ASSERT_EQUALS (true , testKnownValueOfTok (" std::is_lvalue_reference<int>{};" , " {" , 0 ));
629
+ ASSERT_EQUALS (true , testKnownValueOfTok (" std::is_lvalue_reference<int&>{};" , " {" , 1 ));
630
+ ASSERT_EQUALS (true , testKnownValueOfTok (" std::is_lvalue_reference<int&&>{};" , " {" , 0 ));
631
+
632
+ // is_rvalue_reference
633
+ ASSERT_EQUALS (true , testKnownValueOfTok (" std::is_rvalue_reference<int>{};" , " {" , 0 ));
634
+ ASSERT_EQUALS (true , testKnownValueOfTok (" std::is_rvalue_reference<int&>{};" , " {" , 0 ));
635
+ ASSERT_EQUALS (true , testKnownValueOfTok (" std::is_rvalue_reference<int&&>{};" , " {" , 1 ));
636
+
637
+ // is_reference
638
+ ASSERT_EQUALS (true , testKnownValueOfTok (" std::is_reference<int>{};" , " {" , 0 ));
639
+ ASSERT_EQUALS (true , testKnownValueOfTok (" std::is_reference<int&>{};" , " {" , 1 ));
640
+ ASSERT_EQUALS (true , testKnownValueOfTok (" std::is_reference<int&&>{};" , " {" , 1 ));
641
+
642
+ {
643
+ const char * code;
644
+ code = " void bar();\n "
645
+ " void foo() { std::is_void<decltype(bar())>::value; }" ;
646
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 1 ));
647
+
648
+ code = " int bar();\n "
649
+ " void foo() { std::is_void<decltype(bar())>::value; }" ;
650
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 0 ));
651
+
652
+ code = " void bar();\n "
653
+ " void foo() { std::is_void<decltype(bar)>::value; }" ;
654
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 0 ));
655
+
656
+ code = " class A;\n "
657
+ " void foo() { std::is_lvalue_reference<A>::value; }" ;
658
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 0 ));
659
+
660
+ code = " class A;\n "
661
+ " void foo() { std::is_lvalue_reference<A&>::value; }" ;
662
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 1 ));
663
+
664
+ code = " class A;\n "
665
+ " void foo() { std::is_lvalue_reference<A&&>::value; }" ;
666
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 0 ));
667
+
668
+ code = " class A;\n "
669
+ " void foo() { std::is_rvalue_reference<A>::value; }" ;
670
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 0 ));
671
+
672
+ code = " class A;\n "
673
+ " void foo() { std::is_rvalue_reference<A&>::value; }" ;
674
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 0 ));
675
+
676
+ code = " class A;\n "
677
+ " void foo() { std::is_rvalue_reference<A&&>::value; }" ;
678
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 1 ));
679
+
680
+ code = " class A;\n "
681
+ " void foo() { std::is_reference<A>::value; }" ;
682
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 0 ));
683
+
684
+ code = " class A;\n "
685
+ " void foo() { std::is_reference<A&>::value; }" ;
686
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 1 ));
687
+
688
+ code = " class A;\n "
689
+ " void foo() { std::is_reference<A&&>::value; }" ;
690
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 1 ));
691
+
692
+ code = " void foo() {\n "
693
+ " int bar;\n "
694
+ " std::is_void<decltype(bar)>::value;\n "
695
+ " }\n " ;
696
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 0 ));
697
+
698
+ code = " void foo(int bar) {\n "
699
+ " std::is_lvalue_reference<decltype(bar)>::value;\n "
700
+ " }\n " ;
701
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 0 ));
702
+
703
+ code = " void foo(int& bar) {\n "
704
+ " std::is_lvalue_reference<decltype(bar)>::value;\n "
705
+ " }\n " ;
706
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 1 ));
707
+
708
+ code = " void foo(int&& bar) {\n "
709
+ " std::is_lvalue_reference<decltype(bar)>::value;\n "
710
+ " }\n " ;
711
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 0 ));
712
+
713
+ code = " void foo(int bar) {\n "
714
+ " std::is_rvalue_reference<decltype(bar)>::value;\n "
715
+ " }\n " ;
716
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 0 ));
717
+
718
+ code = " void foo(int& bar) {\n "
719
+ " std::is_rvalue_reference<decltype(bar)>::value;\n "
720
+ " }\n " ;
721
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 0 ));
722
+
723
+ code = " void foo(int&& bar) {\n "
724
+ " std::is_rvalue_reference<decltype(bar)>::value;\n "
725
+ " }\n " ;
726
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 1 ));
727
+
728
+ code = " void foo(int bar) {\n "
729
+ " std::is_reference<decltype(bar)>::value;\n "
730
+ " }\n " ;
731
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 0 ));
732
+
733
+ code = " void foo(int& bar) {\n "
734
+ " std::is_reference<decltype(bar)>::value;\n "
735
+ " }\n " ;
736
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 1 ));
737
+
738
+ code = " void foo(int&& bar) {\n "
739
+ " std::is_reference<decltype(bar)>::value;\n "
740
+ " }\n " ;
741
+ ASSERT_EQUALS (true , testKnownValueOfTok (code, " :: value" , 1 ));
742
+ }
743
+ }
744
+
599
745
void valueFlowPointerAlias () {
600
746
const char *code;
601
747
std::list<ValueFlow::Value> values;
0 commit comments