[cfe-commits] r163681 - in /cfe/trunk: lib/Analysis/UninitializedValues.cpp test/Sema/uninit-variables.c

Ted Kremenek kremenek at apple.com
Tue Sep 11 22:53:43 PDT 2012


Author: kremenek
Date: Wed Sep 12 00:53:43 2012
New Revision: 163681

URL: http://llvm.org/viewvc/llvm-project?rev=163681&view=rev
Log:
Teach -Wuninitialized to recognize __attribute__((analyzer_noreturn))
for halting the propagation of uninitialized value tracking along
a path.  Unlike __attribute__((noreturn)), this attribute (which
is used by clients of the static analyzer) can be used to annotate
functions that essentially never return, but in rare cares may be
allowed to return for (special) debugging purposes.  This attribute
has been shown in reducing false positives in the static analyzer
by pruning false postives, and is equally applicable here.

Handling this attribute in the CFG itself is another option, but
this is not something all clients (e.g., possibly -Wunreachable-code)
would want to see.

Addresses <rdar://problem/12281583>.

Modified:
    cfe/trunk/lib/Analysis/UninitializedValues.cpp
    cfe/trunk/test/Sema/uninit-variables.c

Modified: cfe/trunk/lib/Analysis/UninitializedValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/UninitializedValues.cpp?rev=163681&r1=163680&r2=163681&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/UninitializedValues.cpp (original)
+++ cfe/trunk/lib/Analysis/UninitializedValues.cpp Wed Sep 12 00:53:43 2012
@@ -605,14 +605,26 @@
 }
 
 void TransferFunctions::VisitCallExpr(CallExpr *ce) {
-  // After a call to a function like setjmp or vfork, any variable which is
-  // initialized anywhere within this function may now be initialized. For now,
-  // just assume such a call initializes all variables.
-  // FIXME: Only mark variables as initialized if they have an initializer which
-  // is reachable from here.
-  Decl *Callee = ce->getCalleeDecl();
-  if (Callee && Callee->hasAttr<ReturnsTwiceAttr>())
-    vals.setAllScratchValues(Initialized);
+  if (Decl *Callee = ce->getCalleeDecl()) {
+    if (Callee->hasAttr<ReturnsTwiceAttr>()) {
+      // After a call to a function like setjmp or vfork, any variable which is
+      // initialized anywhere within this function may now be initialized. For
+      // now, just assume such a call initializes all variables.  FIXME: Only
+      // mark variables as initialized if they have an initializer which is
+      // reachable from here.
+      vals.setAllScratchValues(Initialized);
+    }
+    else if (Callee->hasAttr<AnalyzerNoReturnAttr>()) {
+      // Functions labeled like "analyzer_noreturn" are often used to denote
+      // "panic" functions that in special debug situations can still return,
+      // but for the most part should not be treated as returning.  This is a
+      // useful annotation borrowed from the static analyzer that is useful for
+      // suppressing branch-specific false positives when we call one of these
+      // functions but keep pretending the path continues (when in reality the
+      // user doesn't care).
+      vals.setAllScratchValues(Unknown);
+    }
+  }
 }
 
 void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) {

Modified: cfe/trunk/test/Sema/uninit-variables.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/uninit-variables.c?rev=163681&r1=163680&r2=163681&view=diff
==============================================================================
--- cfe/trunk/test/Sema/uninit-variables.c (original)
+++ cfe/trunk/test/Sema/uninit-variables.c Wed Sep 12 00:53:43 2012
@@ -508,3 +508,26 @@
   int n = ((p && (0 || 1)) && (n = *p)) ? n : -1; // ok
   return n;
 }
+
+void test_analyzer_noreturn_aux() __attribute__((analyzer_noreturn));
+
+void test_analyzer_noreturn(int y) {
+  int x; // expected-note {{initialize the variable 'x' to silence this warning}}
+  if (y) {
+    test_analyzer_noreturn_aux();
+	++x; // no-warning
+  }
+  else {
+	++x; // expected-warning {{variable 'x' is uninitialized when used here}}
+  }
+}
+void test_analyzer_noreturn_2(int y) {
+  int x;
+  if (y) {
+    test_analyzer_noreturn_aux();
+  }
+  else {
+	x = 1;
+  }
+  ++x; // no-warning
+}





More information about the cfe-commits mailing list