Implement more thoughful error recovery when dealing with bogus declarator types.

For example, the following code was resulting in spurious warnings. This was the result of
Sema::GetTypeForDeclarator() synthesizing a type to hand back to the caller (in this case,
"int []", instead of "struct s[]", which is invalid).

struct s; 
struct s* t (struct s z[]) {   // expected-error {{array has incomplete element type}}
  return z;
}

Strategy: Flag the error in Declarator/DeclaratorChunk. This info is later stored in 
the ParmVarDecl. If the decl is referenced, Sema::ParseIdentifierExpr() will check if 
the type is invalid. If so, it quietly returns "true", without instantiating a DeclRefExpr.

This seems to work nicely. If Chris is happy with the approach, I will generalize this to
all VarDecls.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41521 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp
index be61d73..43d2ca9 100644
--- a/Sema/SemaDecl.cpp
+++ b/Sema/SemaDecl.cpp
@@ -463,7 +463,8 @@
   }
   return NewGroup;
 }
-  
+
+// Called from Sema::ParseStartOfFunctionDef().
 ParmVarDecl *
 Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo,
                            Scope *FnScope) {
@@ -505,7 +506,7 @@
     parmDeclType = Context.getPointerType(parmDeclType);
   
   ParmVarDecl *New = new ParmVarDecl(PI.IdentLoc, II, parmDeclType, 
-                                     VarDecl::None, 0);
+                                     VarDecl::None, 0, PI.InvalidType);
 
   // If this has an identifier, add it to the scope stack.
   if (II) {
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index b715556..88a0579 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -74,8 +74,14 @@
       return Diag(Loc, diag::err_undeclared_var_use, II.getName());
     }
   }
-  if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
+  if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
+    ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(VD);
+    
+    // FIXME: generalize this for all decls.
+    if (PVD && PVD->getInvalidType())
+      return true;
     return new DeclRefExpr(VD, VD->getType(), Loc);
+  }
   if (isa<TypedefDecl>(D))
     return Diag(Loc, diag::err_unexpected_typedef, II.getName());
 
diff --git a/Sema/SemaType.cpp b/Sema/SemaType.cpp
index 535b079..17ab64a 100644
--- a/Sema/SemaType.cpp
+++ b/Sema/SemaType.cpp
@@ -123,7 +123,7 @@
 /// instances.
 QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
   QualType T = ConvertDeclSpecToType(D.getDeclSpec(), Context);
-
+  
   // Apply const/volatile/restrict qualifiers to T.
   T = T.getQualifiedType(D.getDeclSpec().getTypeQualifiers());
   
@@ -138,6 +138,7 @@
         // C++ 8.3.2p4: There shall be no ... pointers to references ...
         Diag(D.getIdentifierLoc(), diag::err_illegal_decl_pointer_to_reference,
              D.getIdentifier()->getName());
+        D.setInvalidType(true);
         T = Context.IntTy;
       }
 
@@ -150,6 +151,7 @@
         Diag(D.getIdentifierLoc(),
              diag::err_illegal_decl_reference_to_reference,
              D.getIdentifier()->getName());
+        D.setInvalidType(true);
         T = RT->getReferenceeType();
       }
 
@@ -170,19 +172,27 @@
       if (T->isIncompleteType()) { 
         Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_incomplete_type,
              T.getAsString());
+        T = Context.IntTy;
+        D.setInvalidType(true);
       } else if (T->isFunctionType()) {
         Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_of_functions,
              D.getIdentifier()->getName());
+        T = Context.getPointerType(T);
+        D.setInvalidType(true);
       } else if (const ReferenceType *RT = T->getAsReferenceType()) {
         // C++ 8.3.2p4: There shall be no ... arrays of references ...
         Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_of_references,
              D.getIdentifier()->getName());
+        T = RT->getReferenceeType();
+        D.setInvalidType(true);
       } else if (const RecordType *EltTy = T->getAsRecordType()) {
         // If the element type is a struct or union that contains a variadic
         // array, reject it: C99 6.7.2.1p2.
         if (EltTy->getDecl()->hasFlexibleArrayMember()) {
           Diag(DeclType.Loc, diag::err_flexible_array_in_array,
                T.getAsString());
+          T = Context.IntTy;
+          D.setInvalidType(true);
         }
       }
       T = Context.getArrayType(T, ASM, ATI.TypeQuals, 
@@ -264,6 +274,7 @@
   return T.getAsOpaquePtr();
 }
 
+// Called from Parser::ParseParenDeclarator().
 Sema::TypeResult Sema::ParseParamDeclaratorType(Scope *S, Declarator &D) {
   // Note: parameters have identifiers, but we don't care about them here, we
   // just want the type converted.