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/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.