brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.6 KiB · 4458ad2 Raw
173 lines · cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\2// RUN:                    -analyzer-checker=debug.ExprInspection\3// RUN:                    -Wno-dangling -Wno-c++1z-extensions\4// RUN:                    -verify=expected,cpp14\5// RUN:                    -x c++ -std=c++14 %s6// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\7// RUN:                    -analyzer-checker=debug.ExprInspection\8// RUN:                    -analyzer-config elide-constructors=false\9// RUN:                    -Wno-dangling -Wno-c++1z-extensions\10// RUN:                    -verify=expected,cpp14\11// RUN:                    -x c++ -std=c++14 %s12// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\13// RUN:                    -analyzer-checker=debug.ExprInspection\14// RUN:                    -Wno-dangling -verify=expected,cpp17\15// RUN:                    -x c++ -std=c++17 %s16 17template<typename T>18void clang_analyzer_dump(T&&) {}19 20template<typename T>21T create() { return T{}; }22 23template<typename T>24T const& select(bool cond, T const& t, T const& u) { return cond ? t : u; }25 26struct Composite {27  int x;28  int y;29};30 31struct Derived : Composite {32  int z;33};34 35template<typename T>36struct Array {37  T array[20];38 39  T&& front() && { return static_cast<T&&>(array[0]); }40};41 42void whole_object() {43  int const& i = 10; // extends `int`44  clang_analyzer_dump(i); // expected-warning-re {{&lifetime_extended_object{int, i, S{{[0-9]+}}} }}45  Composite&& c = Composite{}; // extends `Composite`46  clang_analyzer_dump(c); // expected-warning-re {{&lifetime_extended_object{Composite, c, S{{[0-9]+}}} }}47  auto&& a = Array<int>{}; // extends `Array<int>`48  clang_analyzer_dump(a); // expected-warning-re {{&lifetime_extended_object{Array<int>, a, S{{[0-9]+}}} }}49  Composite&& d = Derived{}; // extends `Derived`50  clang_analyzer_dump(d); // expected-warning-re {{&Base{lifetime_extended_object{Derived, d, S{{[0-9]+}}},Composite} }}51}52 53void member_access() {54  int&& x = Composite{}.x;  // extends `Composite`55  clang_analyzer_dump(x); // expected-warning-re {{&lifetime_extended_object{Composite, x, S{{[0-9]+}}}.x }}56  int&& y = create<Composite>().y; // extends `Composite`57  clang_analyzer_dump(y); // expected-warning-re {{&lifetime_extended_object{struct Composite, y, S{{[0-9]+}}}.y }}58  int&& d = Array<int>{}.front(); // dangles `Array<int>`59  clang_analyzer_dump(d); // expected-warning-re {{&Element{temp_object{Array<int>, S{{[0-9]+}}}.array,0 S64b,int} }}60}61 62void array_subscript() {63  int&& i = Array<int>{}.array[0]; // extends `Array<int>`64  clang_analyzer_dump(i); // expected-warning-re {{&Element{lifetime_extended_object{Array<int>, i, S{{[0-9]+}}}.array,0 S64b,int} }}65  auto&& c = Array<Composite>{}.array[0]; // extends `Array<int>`66  clang_analyzer_dump(c); // expected-warning-re {{&Element{lifetime_extended_object{Array<Composite>, c, S{{[0-9]+}}}.array,0 S64b,struct Composite} }}67  auto&& x = Array<Composite>{}.array[0].x; // extends `Array<Composite>`68  clang_analyzer_dump(x); // expected-warning-re {{&Element{lifetime_extended_object{Array<Composite>, x, S{{[0-9]+}}}.array,0 S64b,struct Composite}.x }}69}70 71void ternary(bool cond) {72  Composite cc;73  // Value category mismatch of the operands (lvalue and xvalue), ternary produces prvalue74  auto&& ternaryProducesPRvalue = cond ? Composite{}.x : cc.x; // extends prvalue of 'int', `Composite` in true branch is destroyed75  clang_analyzer_dump(ternaryProducesPRvalue); // expected-warning-re {{&lifetime_extended_object{int, ternaryProducesPRvalue, S{{[0-9]+}}} }}76 77  // Value category agrees (xvalues), lifetime extension is triggered78  auto&& branchesExtended = cond ? Composite{}.x : static_cast<Composite&&>(cc).x; // extends `Composite` in true branch79  clang_analyzer_dump(branchesExtended);80  // expected-warning-re@-1 {{&lifetime_extended_object{Composite, branchesExtended, S{{[0-9]+}}}.x }}81  // expected-warning@-2 {{&cc.x }}82 83  // Object of different types in branches are lifetime extended84  auto&& extendingDifferentTypes = cond ? Composite{}.x : Array<int>{}.array[0]; // extends `Composite` or `Array<int>`85  clang_analyzer_dump(extendingDifferentTypes);86  // expected-warning-re@-1 {{&lifetime_extended_object{Composite, extendingDifferentTypes, S{{[0-9]+}}}.x }}87  // expected-warning-re@-2 {{&Element{lifetime_extended_object{Array<int>, extendingDifferentTypes, S{{[0-9]+}}}.array,0 S64b,int} }}88 89  Composite const& variableAndExtended = cond ? static_cast<Composite&&>(cc) : Array<Composite>{}.array[0]; // extends `Array<Composite>` in false branch90  clang_analyzer_dump(variableAndExtended);91  // expected-warning@-1 {{&cc }}92  // expected-warning-re@-2 {{&Element{lifetime_extended_object{Array<Composite>, variableAndExtended, S{{[0-9]+}}}.array,0 S64b,struct Composite} }}93 94  int const& extendAndDangling = cond ? Array<int>{}.array[0] : Array<int>{}.front(); // extends `Array<int>` only in true branch, false branch dangles95  clang_analyzer_dump(extendAndDangling);96  // expected-warning-re@-1 {{&Element{lifetime_extended_object{Array<int>, extendAndDangling, S{{[0-9]+}}}.array,0 S64b,int} }}97  // expected-warning-re@-2 {{&Element{temp_object{Array<int>, S{{[0-9]+}}}.array,0 S64b,int} }}98}99 100struct RefAggregate {101  int const& rx;102  Composite&& ry = Composite{};103};104 105void aggregateWithReferences() {106  RefAggregate multipleExtensions = {10, Composite{}}; // extends `int` and `Composite`107  clang_analyzer_dump(multipleExtensions.rx); // expected-warning-re {{&lifetime_extended_object{int, multipleExtensions, S{{[0-9]+}}} }}108  clang_analyzer_dump(multipleExtensions.ry); // expected-warning-re {{&lifetime_extended_object{Composite, multipleExtensions, S{{[0-9]+}}} }}109 110  RefAggregate danglingAndExtended{Array<int>{}.front(), Composite{}}; // extends only `Composite`, `Array<int>` dangles111  clang_analyzer_dump(danglingAndExtended.rx); // expected-warning-re {{&Element{temp_object{Array<int>, S{{[0-9]+}}}.array,0 S64b,int} }}112  clang_analyzer_dump(danglingAndExtended.ry); // expected-warning-re {{&lifetime_extended_object{Composite, danglingAndExtended, S{{[0-9]+}}} }}113 114  int i = 10;115  RefAggregate varAndExtended{i, Composite{}};  // extends `Composite`116  clang_analyzer_dump(varAndExtended.rx); // expected-warning {{&i }}117  clang_analyzer_dump(varAndExtended.ry); // expected-warning-re {{&lifetime_extended_object{Composite, varAndExtended, S{{[0-9]+}}} }}118 119  auto const& viaReference = RefAggregate{10, Composite{}}; // extends `int`, `Composite`, and `RefAggregate`120  clang_analyzer_dump(viaReference);    // expected-warning-re {{&lifetime_extended_object{RefAggregate, viaReference, S{{[0-9]+}}} }}121  clang_analyzer_dump(viaReference.rx); // expected-warning-re {{&lifetime_extended_object{int, viaReference, S{{[0-9]+}}} }}122  clang_analyzer_dump(viaReference.ry); // expected-warning-re {{&lifetime_extended_object{Composite, viaReference, S{{[0-9]+}}} }}123  124  // FIXME: clang currently support extending lifetime of object bound to reference members of aggregates,125  // that are created from default member initializer. But CFG and ExprEngine need to be updated to address this change.126  // The following expect warning: {{&lifetime_extended_object{Composite, defaultInitExtended, S{{[0-9]+}}} }}127  RefAggregate defaultInitExtended{i};128  clang_analyzer_dump(defaultInitExtended.ry); // expected-warning {{Unknown }}129}130 131void lambda() {132  auto const& lambdaRef = [capture = create<Composite>()] {};133  clang_analyzer_dump(lambdaRef); // expected-warning-re {{lifetime_extended_object{class (lambda at {{[^)]+}}), lambdaRef, S{{[0-9]+}}} }}134 135  // The capture [&refCapture = create<Composite const>()] { ... } per [expr.prim.lambda.capture] p6 equivalent to:136  //   auto& refCapture = create<Composite const>(); // Well-formed, deduces auto = Composite const, and performs lifetime extension137  //   [&refCapture] { ... }138  // Where 'refCapture' has the same lifetime as the lambda itself.139  // However, compilers differ: Clang lifetime-extends from C++17, GCC rejects the code, and MSVC dangles140  // See also CWG2737 (https://cplusplus.github.io/CWG/issues/2737.html)141  auto const refExtendingCapture = [&refCapture = create<Composite const>()] {142     clang_analyzer_dump(refCapture);143     // cpp14-warning-re@-1 {{&temp_object{const struct Composite, S{{[0-9]+}}} }}144     // cpp17-warning-re@-2 {{&lifetime_extended_object{const struct Composite, refExtendingCapture, S{{[0-9]+}}} }}145  };146  refExtendingCapture();147}148 149void viaStructuredBinding() {150  auto&& [x, y] = Composite{}; // extends `Composite` and binds it to unnamed decomposed object151  clang_analyzer_dump(x); // expected-warning-re {{&lifetime_extended_object{Composite, D{{[0-9]+}}, S{{[0-9]+}}}.x }}152  clang_analyzer_dump(y); // expected-warning-re {{&lifetime_extended_object{Composite, D{{[0-9]+}}, S{{[0-9]+}}}.y }}153 154  auto&& [rx, ry] = RefAggregate{10, Composite{}}; // extends `int`, `Composite`, and `RefAggregate`, and binds them to unnamed decomposed object155  clang_analyzer_dump(rx); // expected-warning-re {{&lifetime_extended_object{int, D{{[0-9]+}}, S{{[0-9]+}}} }}156  clang_analyzer_dump(ry); // expected-warning-re {{&lifetime_extended_object{Composite, D{{[0-9]+}}, S{{[0-9]+}}} }}157}158 159void propagation(bool cond) {160  int const& le = Composite{}.x;161  // May return lifetime-extended region or dangling temporary162  auto&& oneDangling = select(cond, le, 10); // does not extend lifetime of arguments163  clang_analyzer_dump(oneDangling);164  // expected-warning-re@-1 {{&lifetime_extended_object{Composite, le, S{{[0-9]+}}}.x }}165  // expected-warning-re@-2 {{&temp_object{int, S{{[0-9]+}}} }}166 167  // Always dangles168  auto&& bothDangling = select(cond, 10, 20); // does not extend lifetime of arguments169  clang_analyzer_dump(bothDangling);170  // expected-warning-re@-1 {{&temp_object{int, S{{[0-9]+}}} }}171  // expected-warning-re@-2 {{&temp_object{int, S{{[0-9]+}}} }}172}173