diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 1e26a1fcfe..c9941fe90c 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -856,6 +856,8 @@ class CXXTempObjectRegion : public TypedValueRegion { Expr const *E, const MemRegion *sReg); public: + const Expr *getExpr() const { return Ex; } + QualType getValueType() const { return Ex->getType(); } diff --git a/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp index b004aa9c64..c63603ae69 100644 --- a/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp @@ -76,6 +76,11 @@ SourceRange StackAddrEscapeChecker::GenName(raw_ostream &os, << VR->getString() << '\''; range = VR->getDecl()->getSourceRange(); } + else if (const CXXTempObjectRegion *TOR = dyn_cast(R)) { + os << "stack memory associated with temporary object of type '" + << TOR->getValueType().getAsString() << '\''; + range = TOR->getExpr()->getSourceRange(); + } else { assert(false && "Invalid region in ReturnStackAddressChecker."); } diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp index 160935dde5..e4afe43290 100644 --- a/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -424,7 +424,8 @@ void CompoundLiteralRegion::dumpToStream(raw_ostream &os) const { } void CXXTempObjectRegion::dumpToStream(raw_ostream &os) const { - os << "temp_object"; + os << "temp_object{" << getValueType().getAsString() << ',' + << (void*) Ex << '}'; } void CXXBaseObjectRegion::dumpToStream(raw_ostream &os) const { diff --git a/test/Analysis/stack-addr-ps.cpp b/test/Analysis/stack-addr-ps.cpp index 0c1ffba4f8..d6140002fd 100644 --- a/test/Analysis/stack-addr-ps.cpp +++ b/test/Analysis/stack-addr-ps.cpp @@ -1,38 +1,38 @@ -// RUN: %clang_cc1 -fsyntax-only -fblocks -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store=region -verify %s // FIXME: Only the stack-address checking in Sema catches this right now, and // the stack analyzer doesn't handle the ImplicitCastExpr (lvalue). const int& g() { int s; - return s; // expected-warning{{reference to stack memory associated with local variable 's' returned}} + return s; // expected-warning{{Address of stack memory associated with local variable 's' returned}} expected-warning{{reference to stack memory associated with local variable 's' returned}} } const int& g2() { int s1; int &s2 = s1; // expected-note {{binding reference variable 's2' here}} - return s2; // expected-warning {{reference to stack memory associated with local variable 's1' returned}} + return s2; // expected-warning{{Address of stack memory associated with local variable 's1' returned}} expected-warning {{reference to stack memory associated with local variable 's1' returned}} } const int& g3() { int s1; int &s2 = s1; // expected-note {{binding reference variable 's2' here}} int &s3 = s2; // expected-note {{binding reference variable 's3' here}} - return s3; // expected-warning {{reference to stack memory associated with local variable 's1' returned}} + return s3; // expected-warning{{Address of stack memory associated with local variable 's1' returned}} expected-warning {{reference to stack memory associated with local variable 's1' returned}} } int get_value(); -const int &get_reference1() { return get_value(); } // expected-warning {{returning reference to local temporary}} +const int &get_reference1() { return get_value(); } // expected-warning{{Address of stack memory associated with temporary object of type 'const int' returned}} expected-warning {{returning reference to local temporary}} const int &get_reference2() { const int &x = get_value(); // expected-note {{binding reference variable 'x' here}} - return x; // expected-warning {{returning reference to local temporary}} + return x; // expected-warning{{Address of stack memory associated with temporary object of type 'const int' returned}} expected-warning {{returning reference to local temporary}} } const int &get_reference3() { const int &x1 = get_value(); // expected-note {{binding reference variable 'x1' here}} const int &x2 = x1; // expected-note {{binding reference variable 'x2' here}} - return x2; // expected-warning {{returning reference to local temporary}} + return x2; // expected-warning{{Address of stack memory associated with temporary object of type 'const int' returned}} expected-warning {{returning reference to local temporary}} } int global_var; @@ -44,7 +44,7 @@ int *f1() { int *f2() { int x1; int &x2 = x1; // expected-note {{binding reference variable 'x2' here}} - return &x2; // expected-warning {{address of stack memory associated with local variable 'x1' returned}} + return &x2; // expected-warning{{Address of stack memory associated with local variable 'x1' returned}} expected-warning {{address of stack memory associated with local variable 'x1' returned}} } int *f3() { @@ -56,7 +56,7 @@ int *f3() { const int *f4() { const int &x1 = get_value(); // expected-note {{binding reference variable 'x1' here}} const int &x2 = x1; // expected-note {{binding reference variable 'x2' here}} - return &x2; // expected-warning {{returning address of local temporary}} + return &x2; // expected-warning{{Address of stack memory associated with temporary object of type 'const int' returned}} expected-warning {{returning address of local temporary}} } struct S { @@ -67,7 +67,7 @@ int *mf() { S s1; S &s2 = s1; // expected-note {{binding reference variable 's2' here}} int &x = s2.x; // expected-note {{binding reference variable 'x' here}} - return &x; // expected-warning {{address of stack memory associated with local variable 's1' returned}} + return &x; // expected-warning{{Address of stack memory associated with local variable 's1' returned}} expected-warning {{address of stack memory associated with local variable 's1' returned}} } void *lf() { @@ -76,14 +76,6 @@ void *lf() { return x; // expected-warning {{returning address of label, which is local}} } -typedef void (^bptr)(void); - -bptr bf(int j) { - __block int i; - const bptr &qq = ^{ i=0; }; // expected-note {{binding reference variable 'qq' here}} - return qq; // expected-error {{returning block that lives on the local stack}} -} - template struct TS { int *get(); diff --git a/test/Analysis/stack-block-returned.cpp b/test/Analysis/stack-block-returned.cpp new file mode 100644 index 0000000000..af2cec7766 --- /dev/null +++ b/test/Analysis/stack-block-returned.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store=region -fblocks -verify %s + +typedef void (^bptr)(void); + +bptr bf(int j) { + __block int i; + const bptr &qq = ^{ i=0; }; // expected-note {{binding reference variable 'qq' here}} + return qq; // expected-error {{returning block that lives on the local stack}} +}