1 // RUN: %clang_analyze_cc1 \ 2 // RUN: -analyzer-checker=core,apiModeling.llvm.ReturnValue \ 3 // RUN: -analyzer-output=text -verify=class %s 4 5 struct Foo { int Field; }; 6 bool problem(); 7 void doSomething(); 8 9 // We predefined the return value of 'MCAsmParser::Error' as true and we cannot 10 // take the false-branches which leads to a "garbage value" false positive. 11 namespace test_classes { 12 struct MCAsmParser { 13 static bool Error(); 14 }; 15 16 bool parseFoo(Foo &F) { 17 if (problem()) { 18 // class-note@-1 {{Assuming the condition is false}} 19 // class-note@-2 {{Taking false branch}} 20 return MCAsmParser::Error(); 21 } 22 23 F.Field = 0; 24 // class-note@-1 {{The value 0 is assigned to 'F.Field'}} 25 return !MCAsmParser::Error(); 26 // class-note@-1 {{'MCAsmParser::Error' returns true}} 27 // class-note@-2 {{Returning zero, which participates in a condition later}} 28 } 29 30 bool parseFile() { 31 Foo F; 32 if (parseFoo(F)) { 33 // class-note@-1 {{Calling 'parseFoo'}} 34 // class-note@-2 {{Returning from 'parseFoo'}} 35 // class-note@-3 {{Taking false branch}} 36 return true; 37 } 38 39 if (F.Field == 0) { 40 // class-note@-1 {{Field 'Field' is equal to 0}} 41 // class-note@-2 {{Taking true branch}} 42 43 // no-warning: "The left operand of '==' is a garbage value" was here. 44 doSomething(); 45 } 46 47 (void)(1 / F.Field); 48 // class-warning@-1 {{Division by zero}} 49 // class-note@-2 {{Division by zero}} 50 return false; 51 } 52 } // namespace test_classes 53 54 55 // We predefined 'MCAsmParser::Error' as returning true, but now it returns 56 // false, which breaks our invariant. Test the notes. 57 namespace test_break { 58 struct MCAsmParser { 59 static bool Error() { 60 return false; // class-note {{'MCAsmParser::Error' returns false}} 61 // class-note@-1 {{Returning zero, which participates in a condition later}} 62 } 63 }; 64 65 bool parseFoo(Foo &F) { 66 if (problem()) { 67 // class-note@-1 {{Assuming the condition is false}} 68 // class-note@-2 {{Taking false branch}} 69 return !MCAsmParser::Error(); 70 } 71 72 F.Field = 0; 73 // class-note@-1 {{The value 0 is assigned to 'F.Field'}} 74 return MCAsmParser::Error(); 75 // class-note@-1 {{Calling 'MCAsmParser::Error'}} 76 // class-note@-2 {{Returning from 'MCAsmParser::Error'}} 77 // class-note@-3 {{Returning zero, which participates in a condition later}} 78 } 79 80 bool parseFile() { 81 Foo F; 82 if (parseFoo(F)) { 83 // class-note@-1 {{Calling 'parseFoo'}} 84 // class-note@-2 {{Returning from 'parseFoo'}} 85 // class-note@-3 {{Taking false branch}} 86 return true; 87 } 88 89 (void)(1 / F.Field); 90 // class-warning@-1 {{Division by zero}} 91 // class-note@-2 {{Division by zero}} 92 return false; 93 } 94 } // namespace test_classes 95