summaryrefslogtreecommitdiffstats
path: root/clang/test/Analysis
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2018-07-31 19:39:37 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2018-07-31 19:39:37 +0000
commitbd880fe1c1235f48d5e537af563362ddc4f8af53 (patch)
tree7a3306948c07a228645b403ec6e1c43deb6d6a39 /clang/test/Analysis
parent959fe03933e5f841f77219d526f88055c081d9a0 (diff)
downloadbcm5719-llvm-bd880fe1c1235f48d5e537af563362ddc4f8af53.tar.gz
bcm5719-llvm-bd880fe1c1235f48d5e537af563362ddc4f8af53.zip
[CFG] [analyzer] Add stubs for constructor and message argument constructors.
CFG now correctly identifies construction context for temporaries constructed for the purpose of passing into a function as an argument. Such context is still not fully implemented because the information it provides is not rich enough: it doens't contain information about argument index. It will be addresssed later. This patch is an extension of r330377 to C++ construct-expressions and Objective-C message expressions which aren't call-expressions but require similar handling. C++ new-expressions with placement arguments still remain to be handled. Differential Revision: https://reviews.llvm.org/D49826 llvm-svn: 338425
Diffstat (limited to 'clang/test/Analysis')
-rw-r--r--clang/test/Analysis/cfg-rich-constructors.cpp31
-rw-r--r--clang/test/Analysis/cfg-rich-constructors.mm41
-rw-r--r--clang/test/Analysis/temporaries.cpp34
-rw-r--r--clang/test/Analysis/temporaries.mm23
4 files changed, 125 insertions, 4 deletions
diff --git a/clang/test/Analysis/cfg-rich-constructors.cpp b/clang/test/Analysis/cfg-rich-constructors.cpp
index 6780cf1a7be..d66c9d31185 100644
--- a/clang/test/Analysis/cfg-rich-constructors.cpp
+++ b/clang/test/Analysis/cfg-rich-constructors.cpp
@@ -817,6 +817,11 @@ public:
~D();
};
+class E {
+public:
+ E(D d);
+};
+
void useC(C c);
void useCByReference(const C &c);
void useD(D d);
@@ -880,6 +885,32 @@ void passArgumentWithDestructor() {
void passArgumentWithDestructorByReference() {
useDByReference(D());
}
+
+// FIXME: Find construction context for the argument.
+// CHECK: void passArgumentIntoAnotherConstructor()
+// CXX11: 1: argument_constructors::D() (CXXConstructExpr, [B1.2], [B1.4], class argument_constructors::D)
+// CXX11-NEXT: 2: [B1.1] (BindTemporary)
+// CXX11-NEXT: 3: [B1.2] (ImplicitCastExpr, NoOp, const class argument_constructors::D)
+// CXX11-NEXT: 4: [B1.3]
+// CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, class argument_constructors::D)
+// CXX11-NEXT: 6: [B1.5] (BindTemporary)
+// CXX11-ELIDE-NEXT: 7: [B1.6] (CXXConstructExpr, [B1.9], [B1.10], class argument_constructors::E)
+// CXX11-NOELIDE-NEXT: 7: [B1.6] (CXXConstructExpr, [B1.9], class argument_constructors::E)
+// CXX11-NEXT: 8: argument_constructors::E([B1.7]) (CXXFunctionalCastExpr, ConstructorConversion, class argument_constructors::E)
+// CXX11-NEXT: 9: [B1.8]
+// CXX11-NEXT: 10: [B1.9] (CXXConstructExpr, [B1.11], class argument_constructors::E)
+// CXX11-NEXT: 11: argument_constructors::E e = argument_constructors::E(argument_constructors::D());
+// CXX11-NEXT: 12: ~argument_constructors::D() (Temporary object destructor)
+// CXX11-NEXT: 13: ~argument_constructors::D() (Temporary object destructor)
+// CXX17: 1: argument_constructors::D() (CXXConstructExpr, class argument_constructors::D)
+// CXX17-NEXT: 2: [B1.1] (BindTemporary)
+// CXX17-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class argument_constructors::E)
+// CXX17-NEXT: 4: argument_constructors::E([B1.3]) (CXXFunctionalCastExpr, ConstructorConversion, class argument_constructors::E)
+// CXX17-NEXT: 5: argument_constructors::E e = argument_constructors::E(argument_constructors::D());
+// CXX17-NEXT: 6: ~argument_constructors::D() (Temporary object destructor)
+void passArgumentIntoAnotherConstructor() {
+ E e = E(D());
+}
} // end namespace argument_constructors
namespace copy_elision_with_extra_arguments {
diff --git a/clang/test/Analysis/cfg-rich-constructors.mm b/clang/test/Analysis/cfg-rich-constructors.mm
new file mode 100644
index 00000000000..31173249e8d
--- /dev/null
+++ b/clang/test/Analysis/cfg-rich-constructors.mm
@@ -0,0 +1,41 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++11 -w %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11,ELIDE,CXX11-ELIDE %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++17 -w %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX17,ELIDE,CXX17-ELIDE %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++11 -w -analyzer-config elide-constructors=false %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11,NOELIDE,CXX11-NOELIDE %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++17 -w -analyzer-config elide-constructors=false %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX17,NOELIDE,CXX17-NOELIDE %s
+
+class D {
+public:
+ D();
+ ~D();
+};
+
+@interface E {}
+-(void) foo: (D) d;
+@end
+
+// FIXME: Find construction context for the argument.
+// CHECK: void passArgumentIntoMessage(E *e)
+// CHECK: 1: e
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, LValueToRValue, E *)
+// CXX11-NEXT: 3: D() (CXXConstructExpr, [B1.4], [B1.6], class D)
+// CXX11-NEXT: 4: [B1.3] (BindTemporary)
+// CXX11-NEXT: 5: [B1.4] (ImplicitCastExpr, NoOp, const class D)
+// CXX11-NEXT: 6: [B1.5]
+// CXX11-NEXT: 7: [B1.6] (CXXConstructExpr, class D)
+// CXX11-NEXT: 8: [B1.7] (BindTemporary)
+// Double brackets trigger FileCheck variables, escape.
+// CXX11-NEXT: 9: {{\[}}[B1.2] foo:[B1.8]]
+// CXX11-NEXT: 10: ~D() (Temporary object destructor)
+// CXX11-NEXT: 11: ~D() (Temporary object destructor)
+// CXX17-NEXT: 3: D() (CXXConstructExpr, class D)
+// CXX17-NEXT: 4: [B1.3] (BindTemporary)
+// Double brackets trigger FileCheck variables, escape.
+// CXX17-NEXT: 5: {{\[}}[B1.2] foo:[B1.4]]
+// CXX17-NEXT: 6: ~D() (Temporary object destructor)
+void passArgumentIntoMessage(E *e) {
+ [e foo: D()];
+}
diff --git a/clang/test/Analysis/temporaries.cpp b/clang/test/Analysis/temporaries.cpp
index de3420e7089..539882f17ea 100644
--- a/clang/test/Analysis/temporaries.cpp
+++ b/clang/test/Analysis/temporaries.cpp
@@ -1,7 +1,7 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=false -verify -w -std=c++03 %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=false -verify -w -std=c++11 %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -DTEMPORARY_DTORS -verify -w -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true %s -std=c++11
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -DTEMPORARY_DTORS -w -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true %s -std=c++17
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus,debug.ExprInspection -analyzer-config cfg-temporary-dtors=false -verify -w -std=c++03 %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus,debug.ExprInspection -analyzer-config cfg-temporary-dtors=false -verify -w -std=c++11 %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus,debug.ExprInspection -DTEMPORARY_DTORS -verify -w -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true %s -std=c++11
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus,debug.ExprInspection -DTEMPORARY_DTORS -w -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true %s -std=c++17
// Note: The C++17 run-line doesn't -verify yet - it is a no-crash test.
@@ -945,3 +945,29 @@ C &&foo2();
const C &bar1() { return foo1(); } // no-crash
C &&bar2() { return foo2(); } // no-crash
} // end namespace pass_references_through
+
+
+namespace ctor_argument {
+// Stripped down unique_ptr<int>
+struct IntPtr {
+ IntPtr(): i(new int) {}
+ IntPtr(IntPtr &&o): i(o.i) { o.i = 0; }
+ ~IntPtr() { delete i; }
+
+ int *i;
+};
+
+struct Foo {
+ Foo(IntPtr);
+ void bar();
+
+ IntPtr i;
+};
+
+void bar() {
+ IntPtr ptr;
+ int *i = ptr.i;
+ Foo f(static_cast<IntPtr &&>(ptr));
+ *i = 99; // no-warning
+}
+} // namespace ctor_argument
diff --git a/clang/test/Analysis/temporaries.mm b/clang/test/Analysis/temporaries.mm
new file mode 100644
index 00000000000..3b6166db6e3
--- /dev/null
+++ b/clang/test/Analysis/temporaries.mm
@@ -0,0 +1,23 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker core,cplusplus -verify %s
+
+// expected-no-diagnostics
+
+// Stripped down unique_ptr<int>
+struct IntPtr {
+ IntPtr(): i(new int) {}
+ IntPtr(IntPtr &&o): i(o.i) { o.i = nullptr; }
+ ~IntPtr() { delete i; }
+
+ int *i;
+};
+
+@interface Foo {}
+ -(void) foo: (IntPtr)arg;
+@end
+
+void bar(Foo *f) {
+ IntPtr ptr;
+ int *i = ptr.i;
+ [f foo: static_cast<IntPtr &&>(ptr)];
+ *i = 99; // no-warning
+}
OpenPOWER on IntegriCloud