brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.2 KiB · 554ed34 Raw
414 lines · cpp
1// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,deadcode,debug.ExprInspection -analyzer-config inline-lambdas=true -verify %s2// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core -analyzer-config inline-lambdas=false -DNO_INLINING=1 -verify %s3// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,debug.DumpCFG -analyzer-config inline-lambdas=true %s > %t 2>&14// RUN: FileCheck --input-file=%t %s5 6#include "Inputs/system-header-simulator-cxx.h"7 8void clang_analyzer_warnIfReached();9void clang_analyzer_eval(int);10 11#ifdef NO_INLINING12 13// expected-no-diagnostics14 15int& invalidate_static_on_unknown_lambda() {16  static int* z;17  auto f = [] {18    z = nullptr;19  }; // should invalidate "z" when inlining is disabled.20  f();21  return *z; // no-warning22}23 24#else25 26struct X { X(const X&); };27void f(X x) { (void) [x]{}; }28 29 30// Lambda semantics tests.31 32void basicCapture() {33  int i = 5;34  [i]() mutable {35    // clang_analyzer_eval does nothing in inlined functions.36    if (i != 5)37      clang_analyzer_warnIfReached();38    ++i;39  }();40  [&i] {41    if (i != 5)42      clang_analyzer_warnIfReached();43  }();44  [&i] {45    if (i != 5)46      clang_analyzer_warnIfReached();47    i++;48  }();49  clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}50}51 52void deferredLambdaCall() {53  int i = 5;54  auto l1 = [i]() mutable {55    if (i != 5)56      clang_analyzer_warnIfReached();57    ++i;58  };59  auto l2 = [&i] {60    if (i != 5)61      clang_analyzer_warnIfReached();62  };63  auto l3 = [&i] {64    if (i != 5)65      clang_analyzer_warnIfReached();66    i++;67  };68  l1();69  l2();70  l3();71  clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}72}73 74void multipleCaptures() {75  int i = 5, j = 5;76  [i, &j]() mutable {77    if (i != 5 && j != 5)78      clang_analyzer_warnIfReached();79    ++i;80    ++j;81  }();82  clang_analyzer_eval(i == 5); // expected-warning{{TRUE}}83  clang_analyzer_eval(j == 6); // expected-warning{{TRUE}}84  [=]() mutable {85    if (i != 5 && j != 6)86      clang_analyzer_warnIfReached();87    ++i;88    ++j;89  }();90  clang_analyzer_eval(i == 5); // expected-warning{{TRUE}}91  clang_analyzer_eval(j == 6); // expected-warning{{TRUE}}92  [&]() mutable {93    if (i != 5 && j != 6)94      clang_analyzer_warnIfReached();95    ++i;96    ++j;97  }();98  clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}99  clang_analyzer_eval(j == 7); // expected-warning{{TRUE}}100}101 102void testReturnValue() {103  int i = 5;104  auto l = [i] (int a) {105    return i + a;106  };107  int b = l(3);108  clang_analyzer_eval(b == 8); // expected-warning{{TRUE}}109}110 111void testAliasingBetweenParameterAndCapture() {112  int i = 5;113 114  auto l = [&i](int &p) {115    i++;116    p++;117  };118  l(i);119  clang_analyzer_eval(i == 7); // expected-warning{{TRUE}}120}121 122// Nested lambdas.123 124void testNestedLambdas() {125  int i = 5;126  auto l = [i]() mutable {127    [&i]() {128      ++i;129    }();130    if (i != 6)131      clang_analyzer_warnIfReached();132  };133  l();134  clang_analyzer_eval(i == 5); // expected-warning{{TRUE}}135}136 137// Captured this.138 139class RandomClass {140  int i;141 142  void captureFields() {143    i = 5;144    [this]() {145      // clang_analyzer_eval does nothing in inlined functions.146      if (i != 5)147        clang_analyzer_warnIfReached();148      ++i;149    }();150    clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}151  }152};153 154 155// Nested this capture.156 157class RandomClass2 {158  int i;159 160  void captureFields() {161    i = 5;162    [this]() {163      // clang_analyzer_eval does nothing in inlined functions.164      if (i != 5)165        clang_analyzer_warnIfReached();166      ++i;167      [this]() {168        // clang_analyzer_eval does nothing in inlined functions.169        if (i != 6)170          clang_analyzer_warnIfReached();171        ++i;172      }();173    }();174    clang_analyzer_eval(i == 7); // expected-warning{{TRUE}}175  }176};177 178 179// Captured function pointers.180 181void inc(int &x) {182  ++x;183}184 185void testFunctionPointerCapture() {186  void (*func)(int &) = inc;187  int i = 5;188  [&i, func] {189    func(i);190  }();191  clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}192}193 194// Captured variable-length array.195 196void testVariableLengthArrayCaptured() {197  int n = 2;     // expected-note {{declared here}}198  int array[n];  // expected-warning {{variable length arrays in C++ are a Clang extension}} \199                    expected-note {{read of non-const variable 'n' is not allowed in a constant expression}}200  array[0] = 7;201 202  int i = [&]{203    return array[0];204  }();205 206  clang_analyzer_eval(i == 7); // expected-warning{{TRUE}}207}208 209// Test inline defensive checks210int getNum();211 212void inlineDefensiveChecks() {213  int i = getNum();214  [=]() {215    if (i == 0)216      ;217  }();218  int p = 5/i;219  (void)p;220}221 222 223template<typename T>224void callLambda(T t) {225  t();226}227 228struct DontCrash {229  int x;230  void f() {231    callLambda([&](){ ++x; });232    callLambdaFromStatic([&](){ ++x; });233  }234 235  template<typename T>236  static void callLambdaFromStatic(T t) {237    t();238  }239};240 241 242// Capture constants243 244void captureConstants() {245  const int i = 5;246  [=]() {247    if (i != 5)248      clang_analyzer_warnIfReached();249  }();250  [&] {251    if (i != 5)252      clang_analyzer_warnIfReached();253  }();254}255 256void captureReferenceByCopy(int &p) {257  int v = 7;258  p = 8;259 260  // p is a reference captured by copy261  [&v,p]() mutable {262    v = p;263    p = 22;264  }();265 266  clang_analyzer_eval(v == 8); // expected-warning{{TRUE}}267  clang_analyzer_eval(p == 8); // expected-warning{{TRUE}}268}269 270void captureReferenceByReference(int &p) {271  int v = 7;272  p = 8;273 274  // p is a reference captured by reference275  [&v,&p]() {276    v = p;277    p = 22;278  }();279 280  clang_analyzer_eval(v == 8); // expected-warning{{TRUE}}281  clang_analyzer_eval(p == 22); // expected-warning{{TRUE}}282}283 284void callMutableLambdaMultipleTimes(int &p) {285  int v = 0;286  p = 8;287 288  auto l = [&v, p]() mutable {289    v = p;290    p++;291  };292 293  l();294 295  clang_analyzer_eval(v == 8); // expected-warning{{TRUE}}296  clang_analyzer_eval(p == 8); // expected-warning{{TRUE}}297 298  l();299 300  clang_analyzer_eval(v == 9); // expected-warning{{TRUE}}301  clang_analyzer_eval(p == 8); // expected-warning{{TRUE}}302}303 304// PR 24914305struct StructPR24914{306  int x;307};308 309void takesConstStructArgument(const StructPR24914&);310void captureStructReference(const StructPR24914& s) {311  [s]() {312    takesConstStructArgument(s);313  }();314}315 316// Lambda capture counts as use for dead-store checking.317 318int returnsValue();319 320void captureByCopyCausesUse() {321  int local1 = returnsValue(); // no-warning322  int local2 = returnsValue(); // no-warning323  int local3 = returnsValue(); // expected-warning{{Value stored to 'local3' during its initialization is never read}}324 325  (void)[local1, local2]() { }; // Explicit capture by copy counts as use.326 327  int local4 = returnsValue(); // no-warning328  int local5 = returnsValue(); // expected-warning{{Value stored to 'local5' during its initialization is never read}}329 330  (void)[=]() {331    (void)local4; // Implicit capture by copy counts as use332  };333}334 335void captureByReference() {336  int local1 = returnsValue(); // no-warning337 338  auto lambda1 = [&local1]() { // Explicit capture by reference339    local1++;340  };341 342  // Don't treat as a dead store because local1 was captured by reference.343  local1 = 7; // no-warning344 345  lambda1();346 347  int local2 = returnsValue(); // no-warning348 349  auto lambda2 = [&]() {350    local2++; // Implicit capture by reference351  };352 353  // Don't treat as a dead store because local2 was captured by reference.354  local2 = 7; // no-warning355 356  lambda2();357}358 359void testCapturedConstExprFloat() {360  constexpr float localConstant = 4.0;361  auto lambda = []{362    // Don't treat localConstant as containing a garbage value363    float copy = localConstant; // no-warning364    (void)copy;365  };366 367  lambda();368}369 370void escape(void*);371 372int& invalidate_static_on_unknown_lambda() {373  static int* z;374  auto lambda = [] {375    static float zz;376    z = new int(120);377  };378  escape(&lambda);379  return *z; // no-warning380}381 382 383static int b = 0;384 385int f() {386  b = 0;387  auto &bm = b;388  [&] {389    bm++;390    bm++;391  }();392  if (bm != 2) {393    int *y = 0;394    return *y; // no-warning395  }396  return 0;397}398 399#endif400 401// CHECK: [B2 (ENTRY)]402// CHECK:   Succs (1): B1403// CHECK: [B1]404// CHECK:   1: x405// CHECK:   2: [B1.1] (ImplicitCastExpr, NoOp, const X)406// CHECK:   3: [B1.2] (CXXConstructExpr[B1.4]+0, X)407// CHECK:   4: [x]     {408// CHECK:    }409// CHECK:   5: (void)[B1.4] (CStyleCastExpr, ToVoid, void)410// CHECK:   Preds (1): B2411// CHECK:   Succs (1): B0412// CHECK: [B0 (EXIT)]413// CHECK:   Preds (1): B1414