From f18bfd44c4fe4ab28c44eecb7aeed618bcf8f627 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Wed, 28 Aug 2013 08:04:08 +0000 Subject: [PATCH] [analyzer] Assume new returns non-null even under -fno-exceptions Summary: -fno-exceptions does not implicitly attach a nothrow specifier to every operator new. Even in this mode, non-nothrow new must not return a null pointer. Failure to allocate memory can be signalled by other means, or just by killing the program. This behaviour is consistent with the compiler - even with -fno-exceptions, the generated code never tests for null (and would segfault if the opeator actually happened to return null). Reviewers: jordan_rose CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D1528 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189452 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 11 +- test/Analysis/NewDelete-path-notes.cpp | 138 ++++++---------------- test/Analysis/new-with-exceptions.cpp | 32 ++--- 3 files changed, 51 insertions(+), 130 deletions(-) diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index c39d779d69..27963ade93 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -367,11 +367,14 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, if (!State) return; - // If we're compiling with exceptions enabled, and this allocation function - // is not declared as non-throwing, failures /must/ be signalled by - // exceptions, and thus the return value will never be NULL. + // If this allocation function is not declared as non-throwing, failures + // /must/ be signalled by exceptions, and thus the return value will never be + // NULL. -fno-exceptions does not influence this semantics. + // FIXME: GCC has a -fcheck-new option, which forces it to consider the case + // where new can return NULL. If we end up supporting that option, we can + // consider adding a check for it here. // C++11 [basic.stc.dynamic.allocation]p3. - if (FD && getContext().getLangOpts().CXXExceptions) { + if (FD) { QualType Ty = FD->getType(); if (const FunctionProtoType *ProtoType = Ty->getAs()) if (!ProtoType->isNothrow(getContext())) diff --git a/test/Analysis/NewDelete-path-notes.cpp b/test/Analysis/NewDelete-path-notes.cpp index d38bdb692f..b420551c3e 100644 --- a/test/Analysis/NewDelete-path-notes.cpp +++ b/test/Analysis/NewDelete-path-notes.cpp @@ -6,8 +6,7 @@ void test() { int *p = new int; // expected-note@-1 {{Memory is allocated}} if (p) - // expected-note@-1 {{Assuming 'p' is non-null}} - // expected-note@-2 {{Taking true branch}} + // expected-note@-1 {{Taking true branch}} delete p; // expected-note@-1 {{Memory is released}} @@ -151,75 +150,12 @@ void test(Odd *odd) { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line8 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line8 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindevent -// CHECK-NEXT: location -// CHECK-NEXT: -// CHECK-NEXT: line8 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: ranges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line8 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line8 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: depth0 -// CHECK-NEXT: extended_message -// CHECK-NEXT: Assuming 'p' is non-null -// CHECK-NEXT: message -// CHECK-NEXT: Assuming 'p' is non-null -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line8 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line8 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line11 +// CHECK-NEXT: line10 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line11 +// CHECK-NEXT: line10 // CHECK-NEXT: col10 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -231,7 +167,7 @@ void test(Odd *odd) { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line11 +// CHECK-NEXT: line10 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -239,12 +175,12 @@ void test(Odd *odd) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line11 +// CHECK-NEXT: line10 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line11 +// CHECK-NEXT: line10 // CHECK-NEXT: col12 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -264,12 +200,12 @@ void test(Odd *odd) { // CHECK-NEXT: start // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line11 +// CHECK-NEXT: line10 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line11 +// CHECK-NEXT: line10 // CHECK-NEXT: col10 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -277,12 +213,12 @@ void test(Odd *odd) { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line14 +// CHECK-NEXT: line13 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line14 +// CHECK-NEXT: line13 // CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -294,7 +230,7 @@ void test(Odd *odd) { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line14 +// CHECK-NEXT: line13 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -302,12 +238,12 @@ void test(Odd *odd) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line14 +// CHECK-NEXT: line13 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line14 +// CHECK-NEXT: line13 // CHECK-NEXT: col10 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -325,10 +261,10 @@ void test(Odd *odd) { // CHECK-NEXT: typeDouble free // CHECK-NEXT: issue_context_kindfunction // CHECK-NEXT: issue_contexttest -// CHECK-NEXT: issue_hash9 +// CHECK-NEXT: issue_hash8 // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line14 +// CHECK-NEXT: line13 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -340,7 +276,7 @@ void test(Odd *odd) { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line25 +// CHECK-NEXT: line24 // CHECK-NEXT: col2 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -348,12 +284,12 @@ void test(Odd *odd) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line25 +// CHECK-NEXT: line24 // CHECK-NEXT: col2 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line25 +// CHECK-NEXT: line24 // CHECK-NEXT: col12 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -369,7 +305,7 @@ void test(Odd *odd) { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line19 +// CHECK-NEXT: line18 // CHECK-NEXT: col2 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -387,12 +323,12 @@ void test(Odd *odd) { // CHECK-NEXT: start // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line19 +// CHECK-NEXT: line18 // CHECK-NEXT: col2 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line19 +// CHECK-NEXT: line18 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -400,12 +336,12 @@ void test(Odd *odd) { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line20 +// CHECK-NEXT: line19 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line20 +// CHECK-NEXT: line19 // CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -417,7 +353,7 @@ void test(Odd *odd) { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line20 +// CHECK-NEXT: line19 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -425,12 +361,12 @@ void test(Odd *odd) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line20 +// CHECK-NEXT: line19 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line20 +// CHECK-NEXT: line19 // CHECK-NEXT: col13 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -446,7 +382,7 @@ void test(Odd *odd) { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line25 +// CHECK-NEXT: line24 // CHECK-NEXT: col2 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -454,12 +390,12 @@ void test(Odd *odd) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line25 +// CHECK-NEXT: line24 // CHECK-NEXT: col2 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line25 +// CHECK-NEXT: line24 // CHECK-NEXT: col12 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -479,12 +415,12 @@ void test(Odd *odd) { // CHECK-NEXT: start // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line25 +// CHECK-NEXT: line24 // CHECK-NEXT: col2 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line25 +// CHECK-NEXT: line24 // CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -492,12 +428,12 @@ void test(Odd *odd) { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line27 +// CHECK-NEXT: line26 // CHECK-NEXT: col2 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line27 +// CHECK-NEXT: line26 // CHECK-NEXT: col7 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -509,7 +445,7 @@ void test(Odd *odd) { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line27 +// CHECK-NEXT: line26 // CHECK-NEXT: col2 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -517,12 +453,12 @@ void test(Odd *odd) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line27 +// CHECK-NEXT: line26 // CHECK-NEXT: col2 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line27 +// CHECK-NEXT: line26 // CHECK-NEXT: col11 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -543,7 +479,7 @@ void test(Odd *odd) { // CHECK-NEXT: issue_hash3 // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line27 +// CHECK-NEXT: line26 // CHECK-NEXT: col2 // CHECK-NEXT: file0 // CHECK-NEXT: diff --git a/test/Analysis/new-with-exceptions.cpp b/test/Analysis/new-with-exceptions.cpp index d909f1fb8b..84d77c2230 100644 --- a/test/Analysis/new-with-exceptions.cpp +++ b/test/Analysis/new-with-exceptions.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-store region -std=c++11 -fexceptions -fcxx-exceptions -verify -DEXCEPTIONS %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-store region -std=c++11 -fexceptions -fcxx-exceptions -verify %s // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-store region -std=c++11 -verify %s void clang_analyzer_eval(bool); @@ -32,33 +32,15 @@ void testNew() { clang_analyzer_eval(new NoThrow); // expected-warning{{UNKNOWN}} clang_analyzer_eval(new NoExcept); // expected-warning{{UNKNOWN}} - clang_analyzer_eval(new DefaultThrow); - clang_analyzer_eval(new ExplicitThrow); -#ifdef EXCEPTIONS - // expected-warning@-3 {{TRUE}} - // expected-warning@-3 {{TRUE}} -#else - // expected-warning@-6 {{UNKNOWN}} - // expected-warning@-6 {{UNKNOWN}} -#endif + clang_analyzer_eval(new DefaultThrow); // expected-warning{{TRUE}} + clang_analyzer_eval(new ExplicitThrow); // expected-warning{{TRUE}} } void testNewArray() { - clang_analyzer_eval(new NoThrow[2]); - clang_analyzer_eval(new NoExcept[2]); - clang_analyzer_eval(new DefaultThrow[2]); - clang_analyzer_eval(new ExplicitThrow[2]); -#ifdef EXCEPTIONS - // expected-warning@-5 {{TRUE}} - // expected-warning@-5 {{TRUE}} - // expected-warning@-5 {{TRUE}} - // expected-warning@-5 {{TRUE}} -#else - // expected-warning@-10 {{UNKNOWN}} - // expected-warning@-10 {{UNKNOWN}} - // expected-warning@-10 {{UNKNOWN}} - // expected-warning@-10 {{UNKNOWN}} -#endif + clang_analyzer_eval(new NoThrow[2]); // expected-warning{{TRUE}} + clang_analyzer_eval(new NoExcept[2]); // expected-warning{{TRUE}} + clang_analyzer_eval(new DefaultThrow[2]); // expected-warning{{TRUE}} + clang_analyzer_eval(new ExplicitThrow[2]); // expected-warning{{TRUE}} } extern void *operator new[](size_t, int) noexcept; -- 2.50.1