]> granicus.if.org Git - clang/commitdiff
Assignments to reference variables shouldn't kill the variable.
authorJordy Rose <jediknil@belkadan.com>
Fri, 4 Jun 2010 01:14:56 +0000 (01:14 +0000)
committerJordy Rose <jediknil@belkadan.com>
Fri, 4 Jun 2010 01:14:56 +0000 (01:14 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@105452 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/LiveVariables.cpp
test/Analysis/reference.cpp

index 01a36a1074e8f54dde56684be86194c876becd28..4efe25ea1e0e9d72522cac4bde2f1e4efb901637 100644 (file)
@@ -256,17 +256,21 @@ void TransferFuncs::VisitAssign(BinaryOperator* B) {
 
   // Assigning to a variable?
   if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS->IgnoreParens())) {
+    // Assignments to references don't kill the ref's address
+    if (DR->getDecl()->getType()->isReferenceType()) {
+      VisitDeclRefExpr(DR);
+    } else {
+      // Update liveness inforamtion.
+      unsigned bit = AD.getIdx(DR->getDecl());
+      LiveState.getDeclBit(bit) = Dead | AD.AlwaysLive.getDeclBit(bit);
 
-    // Update liveness inforamtion.
-    unsigned bit = AD.getIdx(DR->getDecl());
-    LiveState.getDeclBit(bit) = Dead | AD.AlwaysLive.getDeclBit(bit);
-
-    if (AD.Observer) { AD.Observer->ObserverKill(DR); }
+      if (AD.Observer) { AD.Observer->ObserverKill(DR); }
 
-    // Handle things like +=, etc., which also generate "uses"
-    // of a variable.  Do this just by visiting the subexpression.
-    if (B->getOpcode() != BinaryOperator::Assign)
-      VisitDeclRefExpr(DR);
+      // Handle things like +=, etc., which also generate "uses"
+      // of a variable.  Do this just by visiting the subexpression.
+      if (B->getOpcode() != BinaryOperator::Assign)
+        VisitDeclRefExpr(DR);
+    }
   }
   else // Not assigning to a variable.  Process LHS as usual.
     Visit(LHS);
index 6b962157da73840c321d6e5c7bbce22ea49b10c1..f1694163a20c983915ce498da31a7039d020c408 100644 (file)
@@ -1,4 +1,6 @@
 // RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s
+typedef typeof(sizeof(int)) size_t;
+void malloc (size_t);
 
 void f1() {
   int const &i = 3;
@@ -24,3 +26,31 @@ char t2 () {
   *ptr() = 'c';
   return '0';
 }
+
+// Each of the tests below is repeated with pointers as well as references.
+// This is mostly a sanity check, but then again, both should work!
+char t3 () {
+  char& r = ref();
+  r = 'c'; // no-warning
+  if (r) return r;
+  return *(char*)0; // no-warning
+}
+
+char t4 () {
+  char* p = ptr();
+  *p = 'c'; // no-warning
+  if (*p) return *p;
+  return *(char*)0; // no-warning
+}
+
+char t5 (char& r) {
+  r = 'c'; // no-warning
+  if (r) return r;
+  return *(char*)0; // no-warning
+}
+
+char t6 (char* p) {
+  *p = 'c'; // no-warning
+  if (*p) return *p;
+  return *(char*)0; // no-warning
+}