[analyzer] Accept references to variables declared "extern void" (C only).

In C, 'void' is treated like any other incomplete type, and though it is
never completed, you can cast the address of a void-typed variable to do
something useful. (In C++ it's illegal to declare a variable with void type.)

Previously we asserted on this code; now we just treat it like any other
incomplete type.

And speaking of incomplete types, we don't know their extent. Actually
check that in TypedValueRegion::getExtent, though that's not being used
by any checkers that are on by default.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182880 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index bfe4e15..627e010 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1613,7 +1613,9 @@
   const LocationContext *LCtx = Pred->getLocationContext();
 
   if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
-    assert(Ex->isGLValue());
+    // C permits "extern void v", and if you cast the address to a valid type,
+    // you can even do things with it. We simply pretend 
+    assert(Ex->isGLValue() || VD->getType()->isVoidType());
     SVal V = state->getLValue(VD, Pred->getLocationContext());
 
     // For references, the 'lvalue' is the pointer address stored in the
diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp
index 31ac86b..0102f92 100644
--- a/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -186,7 +186,7 @@
 
   if (isa<VariableArrayType>(T))
     return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this));
-  if (isa<IncompleteArrayType>(T))
+  if (T->isIncompleteType())
     return UnknownVal();
 
   CharUnits size = Ctx.getTypeSizeInChars(T);
diff --git a/test/Analysis/misc-ps.c b/test/Analysis/misc-ps.c
index b302860..01cad15 100644
--- a/test/Analysis/misc-ps.c
+++ b/test/Analysis/misc-ps.c
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -disable-free -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=deadcode -verify %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -disable-free -analyzer-eagerly-assume -analyzer-checker=core,deadcode,debug.ExprInspection -verify %s
+
+void clang_analyzer_eval(int);
 
 int size_rdar9373039 = 1;
 int foo_rdar9373039(const char *);
@@ -175,3 +177,17 @@
   context->callback(uninitialized); // expected-warning {{uninitialized}}
 }
 
+
+// PR16131: C permits variables to be declared extern void.
+static void PR16131(int x) {
+  extern void v;
+
+  int *ip = (int *)&v;
+  char *cp = (char *)&v;
+  clang_analyzer_eval(ip == cp); // expected-warning{{TRUE}}
+  // expected-warning@-1 {{comparison of distinct pointer types}}
+
+  *ip = 42;
+  clang_analyzer_eval(*ip == 42); // expected-warning{{TRUE}}
+  clang_analyzer_eval(*(int *)&v == 42); // expected-warning{{TRUE}}
+}
diff --git a/test/Analysis/out-of-bounds.c b/test/Analysis/out-of-bounds.c
index dd593c5..d89a239 100644
--- a/test/Analysis/out-of-bounds.c
+++ b/test/Analysis/out-of-bounds.c
@@ -154,3 +154,15 @@
   buf[-1] = 0; // no-warning;
 }
 
+void test_incomplete_struct() {
+  extern struct incomplete incomplete;
+  int *p = (int *)&incomplete;
+  p[1] = 42; // no-warning
+}
+
+void test_extern_void() {
+  extern void v;
+  int *p = (int *)&v;
+  p[1] = 42; // no-warning
+}
+