Centralize error reporting of improper uses of incomplete types in the
new DiagnoseIncompleteType. It provides additional information about
struct/class/union/enum types when possible, either by pointing to the
forward declaration of that type or by pointing to the definition (if
we're in the process of defining that type). 
Fixes <rdar://problem/6500531>.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62521 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index be87ee9..fb83cab 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1021,10 +1021,11 @@
   else if (exprType->isVoidType())
     Diag(OpLoc, diag::ext_sizeof_void_type)
       << (isSizeof ? "sizeof" : "__alignof") << ExprRange;
-  else if (exprType->isIncompleteType())
-    return Diag(OpLoc, isSizeof ? diag::err_sizeof_incomplete_type : 
-                                  diag::err_alignof_incomplete_type)
-      << exprType << ExprRange;
+  else 
+    return DiagnoseIncompleteType(OpLoc, exprType,
+                                  isSizeof ? diag::err_sizeof_incomplete_type : 
+                                             diag::err_alignof_incomplete_type,
+                                  ExprRange);
 
   return false;
 }
@@ -1466,9 +1467,11 @@
   // of the ObjC 'id' struct.
   if (const RecordType *RTy = BaseType->getAsRecordType()) {
     RecordDecl *RDecl = RTy->getDecl();
-    if (RTy->isIncompleteType())
-      return ExprError(Diag(OpLoc, diag::err_typecheck_incomplete_tag)
-               << RDecl->getDeclName() << BaseExpr->getSourceRange());
+    if (DiagnoseIncompleteType(OpLoc, BaseType, 
+                               diag::err_typecheck_incomplete_tag,
+                               BaseExpr->getSourceRange()))
+      return ExprError();
+
     // The record definition is complete, now make sure the member is valid.
     // FIXME: Qualified name lookup for C++ is a bit more complicated
     // than this.
@@ -1906,11 +1909,10 @@
     if (literalType->isVariableArrayType())
       return Diag(LParenLoc, diag::err_variable_object_no_init)
         << SourceRange(LParenLoc, literalExpr->getSourceRange().getEnd());
-  } else if (literalType->isIncompleteType()) {
-    return Diag(LParenLoc, diag::err_typecheck_decl_incomplete_type)
-      << literalType
-      << SourceRange(LParenLoc, literalExpr->getSourceRange().getEnd());
-  }
+  } else if (DiagnoseIncompleteType(LParenLoc, literalType,
+                                    diag::err_typecheck_decl_incomplete_type,
+                SourceRange(LParenLoc, literalExpr->getSourceRange().getEnd())))
+    return true;
 
   if (CheckInitializerTypes(literalExpr, literalType, LParenLoc, 
                             DeclarationName(), /*FIXME:DirectInit=*/false))
@@ -2643,10 +2645,16 @@
         if (PTy->getPointeeType()->isVoidType()) {
           Diag(Loc, diag::ext_gnu_void_ptr)
             << lex->getSourceRange() << rex->getSourceRange();
-        } else {
-          Diag(Loc, diag::err_typecheck_arithmetic_incomplete_type)
+        } else if (PTy->getPointeeType()->isFunctionType()) {
+          Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
             << lex->getType() << lex->getSourceRange();
           return QualType();
+        } else {
+          DiagnoseIncompleteType(Loc, PTy->getPointeeType(), 
+                                 diag::err_typecheck_arithmetic_incomplete_type,
+                                 lex->getSourceRange(), SourceRange(),
+                                 lex->getType());
+          return QualType();
         }
       }
       return PExp->getType();
@@ -3038,9 +3046,9 @@
     break;
   case Expr::MLV_IncompleteType:
   case Expr::MLV_IncompleteVoidType:
-    Diag = diag::err_typecheck_incomplete_type_not_modifiable_lvalue;
-    NeedType = true;
-    break;
+    return S.DiagnoseIncompleteType(Loc, E->getType(), 
+                      diag::err_typecheck_incomplete_type_not_modifiable_lvalue,
+                                    E->getSourceRange());
   case Expr::MLV_DuplicateVectorComponents:
     Diag = diag::err_typecheck_duplicate_vector_components_not_mlvalue;
     break;
@@ -3155,10 +3163,16 @@
     } else if (PT->getPointeeType()->isVoidType()) {
       // Pointer to void is extension.
       Diag(OpLoc, diag::ext_gnu_void_ptr) << Op->getSourceRange();
-    } else {
-      Diag(OpLoc, diag::err_typecheck_arithmetic_incomplete_type)
+    } else if (PT->getPointeeType()->isFunctionType()) {
+      Diag(OpLoc, diag::err_typecheck_pointer_arith_function_type)
         << ResType << Op->getSourceRange();
       return QualType();
+    } else {
+      DiagnoseIncompleteType(OpLoc, PT->getPointeeType(), 
+                             diag::err_typecheck_arithmetic_incomplete_type,
+                             Op->getSourceRange(), SourceRange(),
+                             ResType);
+      return QualType();
     }
   } else if (ResType->isComplexType()) {
     // C99 does not support ++/-- on complex types, we allow as an extension.