aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYang Ni <yangni@google.com>2017-06-13 15:51:50 -0700
committerYang Ni <yangni@google.com>2017-06-22 12:13:04 -0700
commitf6d3e58d364ae3d97a9cf468ca926259193c9018 (patch)
tree62072a1c40ed406195aa10f8fc5aa1545acf7a5b
parent88cd94d5165bf8a266d3f3095946fc25bc4809af (diff)
downloadslang-oreo-dev.tar.gz
Fix crashing in return that references rs objoreo-dev
Bug: 38173182 Since slang adds rsClearObj() calls on local variables and parameters of RS object types at exiting points, a return statement may end up accessing nullptr if it references an RS object. Previously, we handle the special case where the return value itself is an RS object. This CL extends that treatment to the more general case where the return value itself is not an RS object, but it references an RS object. The code transformation is the same as before for the special case, i.e., to create a temporary variable for the return value, and transform the return statement to return the temp instead. Added a slang test for the general case. Test: Slang Test Test: CTS on Sailfish and X86_64 emulator Change-Id: Idf29e648423290d87a428179d1bc38994525d413 (cherry picked from commit f05ee4b89abdaf166e6c42289b99a7b5cf7ee291)
-rw-r--r--lit-tests/P_ref_count/ref_count.rs2
-rw-r--r--lit-tests/P_ref_count/ref_count2.rs17
-rw-r--r--slang_rs_object_ref_count.cpp45
3 files changed, 58 insertions, 6 deletions
diff --git a/lit-tests/P_ref_count/ref_count.rs b/lit-tests/P_ref_count/ref_count.rs
index 081d6d1..7f6dae8 100644
--- a/lit-tests/P_ref_count/ref_count.rs
+++ b/lit-tests/P_ref_count/ref_count.rs
@@ -35,5 +35,3 @@ void entrypoint() {
rsDebug("good objects", 0);
}
}
-
-
diff --git a/lit-tests/P_ref_count/ref_count2.rs b/lit-tests/P_ref_count/ref_count2.rs
new file mode 100644
index 0000000..8ac2d81
--- /dev/null
+++ b/lit-tests/P_ref_count/ref_count2.rs
@@ -0,0 +1,17 @@
+// RUN: %Slang %s
+// RUN: %rs-filecheck-wrapper %s
+
+#pragma version(1)
+#pragma rs java_package_name(ref_count2)
+
+// CHECK: %[[RETVAL:[A-Za-z][A-Za-z0-9]*]] = call i32 @_Z18rsGetElementAt_int13rs_allocationj{{.*}}
+// CHECK: call void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation{{.*}}* {{.*}})
+// CHECK: ret i32 %[[RETVAL]]
+static int goo(rs_allocation a) {
+ return rsGetElementAt_int(a, 0);
+}
+
+void entrypoint() {
+ rs_allocation a = rsCreateAllocation_int(100);
+ rsDebug("val at 0:", goo(a));
+}
diff --git a/slang_rs_object_ref_count.cpp b/slang_rs_object_ref_count.cpp
index 2471473..e1050f4 100644
--- a/slang_rs_object_ref_count.cpp
+++ b/slang_rs_object_ref_count.cpp
@@ -20,6 +20,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/OperationKinds.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtVisitor.h"
@@ -1389,7 +1390,18 @@ clang::DeclRefExpr *RSObjectRefCount::CreateGuard(clang::ASTContext &C,
);
clang::Stmt *UpdatedStmt = nullptr;
- if (!RSExportPrimitiveType::IsRSObjectType(Ty.getTypePtr())) {
+ if (CountRSObjectTypes(Ty.getTypePtr()) == 0) {
+ // The expression E is not an RS object itself. Instead of calling
+ // rsSetObject(), create an assignment statement to set the value of the
+ // temporary "guard" variable to the expression.
+ // This can happen if called from RSObjectRefCount::VisitReturnStmt(),
+ // when the return expression is not an RS object but references one.
+ UpdatedStmt =
+ new(C) clang::BinaryOperator(DRE, E, clang::BO_Assign, Ty,
+ clang::VK_RValue, clang::OK_Ordinary, Loc,
+ false);
+
+ } else if (!RSExportPrimitiveType::IsRSObjectType(Ty.getTypePtr())) {
// By definition, this is a struct assignment if we get here
UpdatedStmt =
CreateStructRSSetObject(C, DRE, E, Loc, Loc);
@@ -1641,6 +1653,28 @@ void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
}
}
+namespace {
+
+class FindRSObjRefVisitor : public clang::RecursiveASTVisitor<FindRSObjRefVisitor> {
+public:
+ explicit FindRSObjRefVisitor() : mRefRSObj(false) {}
+ bool VisitExpr(clang::Expr* Expression) {
+ if (CountRSObjectTypes(Expression->getType().getTypePtr()) > 0) {
+ mRefRSObj = true;
+ // Found a reference to an RS object. Stop the AST traversal.
+ return false;
+ }
+ return true;
+ }
+
+ bool foundRSObjRef() const { return mRefRSObj; }
+
+private:
+ bool mRefRSObj;
+};
+
+} // anonymous namespace
+
void RSObjectRefCount::VisitReturnStmt(clang::ReturnStmt *RS) {
getCurrentScope()->setCurrentStmt(RS);
@@ -1660,11 +1694,14 @@ void RSObjectRefCount::VisitReturnStmt(clang::ReturnStmt *RS) {
return;
}
- // If the return statement does not return anything, or if it does not return
+ FindRSObjRefVisitor visitor;
+
+ visitor.TraverseStmt(RS);
+
+ // If the return statement does not return anything, or if it does not reference
// a rsObject, no need to transform it.
- clang::Expr* RetVal = RS->getRetValue();
- if (!RetVal || CountRSObjectTypes(RetVal->getType().getTypePtr()) == 0) {
+ if (!visitor.foundRSObjRef()) {
return;
}