182 lines · cpp
1// RUN: %clang_analyze_cc1 -std=c++14 \2// RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\3// RUN: -verify %s4 5#include "Inputs/llvm.h"6 7void clang_analyzer_numTimesReached();8void clang_analyzer_warnIfReached();9void clang_analyzer_eval(bool);10 11namespace clang {12struct Shape {13 template <typename T>14 const T *castAs() const;15 16 template <typename T>17 const T *getAs() const;18 19 virtual double area();20};21class Triangle : public Shape {};22class Rectangle : public Shape {};23class Hexagon : public Shape {};24class Circle : public Shape {25public:26 ~Circle();27};28class SuspiciouslySpecificCircle : public Circle {};29} // namespace clang30 31using namespace llvm;32using namespace clang;33 34void test_regions_dyn_cast(const Shape *A, const Shape *B) {35 if (dyn_cast<Circle>(A) && !dyn_cast<Circle>(B))36 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}37}38 39void test_regions_isa(const Shape *A, const Shape *B) {40 if (isa<Circle>(A) && !isa<Circle>(B))41 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}42}43 44void test_regions_isa_variadic(const Shape *A, const Shape *B) {45 if (isa<Triangle, Rectangle, Hexagon>(A) &&46 !isa<Rectangle, Hexagon, Circle>(B))47 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}48}49 50void test_regions_isa_and_nonnull(const Shape *A, const Shape *B) {51 if (isa_and_nonnull<Circle>(A) && !isa_and_nonnull<Circle>(B))52 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}53}54 55void test_regions_isa_and_nonnull_variadic(const Shape *A, const Shape *B) {56 if (isa_and_nonnull<Triangle, Rectangle, Hexagon>(A) &&57 !isa_and_nonnull<Rectangle, Hexagon, Circle>(B))58 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}59}60 61namespace test_cast {62void evalLogic(const Shape *S) {63 const Circle *C = cast<Circle>(S);64 clang_analyzer_numTimesReached(); // expected-warning {{1}}65 66 if (S && C)67 clang_analyzer_eval(C == S); // expected-warning {{TRUE}}68 69 if (S && !C)70 clang_analyzer_warnIfReached(); // no-warning71 72 if (!S)73 clang_analyzer_warnIfReached(); // no-warning74}75} // namespace test_cast76 77namespace test_dyn_cast {78void evalLogic(const Shape *S) {79 const Circle *C = dyn_cast<Circle>(S);80 clang_analyzer_numTimesReached(); // expected-warning {{2}}81 82 if (S && C)83 clang_analyzer_eval(C == S); // expected-warning {{TRUE}}84 85 if (S && !C)86 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}87 88 if (!S)89 clang_analyzer_warnIfReached(); // no-warning90}91} // namespace test_dyn_cast92 93namespace test_cast_or_null {94void evalLogic(const Shape *S) {95 const Circle *C = cast_or_null<Circle>(S);96 clang_analyzer_numTimesReached(); // expected-warning {{2}}97 98 if (S && C)99 clang_analyzer_eval(C == S); // expected-warning {{TRUE}}100 101 if (S && !C)102 clang_analyzer_warnIfReached(); // no-warning103 104 if (!S)105 clang_analyzer_eval(!C); // expected-warning {{TRUE}}106}107} // namespace test_cast_or_null108 109namespace test_dyn_cast_or_null {110void evalLogic(const Shape *S) {111 const Circle *C = dyn_cast_or_null<Circle>(S);112 clang_analyzer_numTimesReached(); // expected-warning {{3}}113 114 if (S && C)115 clang_analyzer_eval(C == S); // expected-warning {{TRUE}}116 117 if (S && !C)118 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}119 120 if (!S)121 clang_analyzer_eval(!C); // expected-warning {{TRUE}}122}123} // namespace test_dyn_cast_or_null124 125namespace test_cast_as {126void evalLogic(const Shape *S) {127 const Circle *C = S->castAs<Circle>();128 clang_analyzer_numTimesReached(); // expected-warning {{1}}129 130 if (S && C)131 clang_analyzer_eval(C == S);132 // expected-warning@-1 {{TRUE}}133 134 if (S && !C)135 clang_analyzer_warnIfReached(); // no-warning136 137 if (!S)138 clang_analyzer_warnIfReached(); // no-warning139}140} // namespace test_cast_as141 142namespace test_get_as {143void evalLogic(const Shape *S) {144 const Circle *C = S->getAs<Circle>();145 clang_analyzer_numTimesReached(); // expected-warning {{2}}146 147 if (S && C)148 clang_analyzer_eval(C == S);149 // expected-warning@-1 {{TRUE}}150 151 if (S && !C)152 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}153 154 if (!S)155 clang_analyzer_warnIfReached(); // no-warning156}157} // namespace test_get_as158 159namespace crashes {160void test_non_reference_null_region_crash(Shape s) {161 cast<Circle>(s); // no-crash162}163 164void test_non_reference_temporary_crash() {165 extern std::unique_ptr<Shape> foo();166 auto P = foo();167 auto Q = cast<Circle>(std::move(P)); // no-crash168}169 170double test_virtual_method_after_call(Shape *S) {171 if (isa<Circle>(S))172 return S->area();173 return S->area() / 2;174}175 176void test_delete_crash() {177 extern Circle *makeCircle();178 Shape *S = makeCircle();179 delete cast<SuspiciouslySpecificCircle>(S);180}181} // namespace crashes182