temporaries.cpp revision 5e5440ba9c135f523f72e7e7c5da59d390d697c5
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w %s
2
3extern bool clang_analyzer_eval(bool);
4
5struct Trivial {
6  Trivial(int x) : value(x) {}
7  int value;
8};
9
10struct NonTrivial : public Trivial {
11  NonTrivial(int x) : Trivial(x) {}
12  ~NonTrivial();
13};
14
15
16Trivial getTrivial() {
17  return Trivial(42); // no-warning
18}
19
20const Trivial &getTrivialRef() {
21  return Trivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'struct Trivial' returned to caller}}
22}
23
24
25NonTrivial getNonTrivial() {
26  return NonTrivial(42); // no-warning
27}
28
29const NonTrivial &getNonTrivialRef() {
30  return NonTrivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'struct NonTrivial' returned to caller}}
31}
32
33namespace rdar13265460 {
34  struct TrivialSubclass : public Trivial {
35    TrivialSubclass(int x) : Trivial(x), anotherValue(-x) {}
36    int anotherValue;
37  };
38
39  TrivialSubclass getTrivialSub() {
40    TrivialSubclass obj(1);
41    obj.value = 42;
42    obj.anotherValue = -42;
43    return obj;
44  }
45
46  void testImmediate() {
47    TrivialSubclass obj = getTrivialSub();
48
49    clang_analyzer_eval(obj.value == 42); // expected-warning{{TRUE}}
50    clang_analyzer_eval(obj.anotherValue == -42); // expected-warning{{TRUE}}
51
52    clang_analyzer_eval(getTrivialSub().value == 42); // expected-warning{{TRUE}}
53    clang_analyzer_eval(getTrivialSub().anotherValue == -42); // expected-warning{{TRUE}}
54  }
55
56  void testMaterializeTemporaryExpr() {
57    const TrivialSubclass &ref = getTrivialSub();
58    clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}
59
60    const Trivial &baseRef = getTrivialSub();
61    clang_analyzer_eval(baseRef.value == 42); // expected-warning{{TRUE}}
62  }
63}
64
65