New = NewFD;
} else {
QualType R = GetTypeForDeclarator(D, S);
- if (R.isNull()) return 0;
+
+ assert(!R.isNull() && "GetTypeForDeclarator() returned null type");
+ bool InvalidDecl = false;
VarDecl *NewVD;
VarDecl::StorageClass SC;
if (R->isIncompleteType()) {
Diag(D.getIdentifierLoc(), diag::err_typecheck_decl_incomplete_type,
R.getAsString());
- return 0;
+ InvalidDecl = true;
}
}
// C99 6.9p2: The storage-class specifiers auto and register shall not
if (SC == VarDecl::Auto || SC == VarDecl::Register) {
Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope,
R.getAsString());
- return 0;
+ InvalidDecl = true;
}
// C99 6.7.5.2p2: If an identifier is declared to be an object with
// static storage duration, it shall not have a variable length array.
if (const ArrayType *ary = R->getAsArrayType()) {
if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
- return 0;
+ InvalidDecl = true;
}
NewVD = new FileVarDecl(D.getIdentifierLoc(), II, R, SC, LastDeclarator);
} else {
if (R->isIncompleteType()) {
Diag(D.getIdentifierLoc(), diag::err_typecheck_decl_incomplete_type,
R.getAsString());
- return 0;
+ InvalidDecl = true;
}
}
if (SC == VarDecl::Static) {
// static storage duration, it shall not have a variable length array.
if (const ArrayType *ary = R->getAsArrayType()) {
if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
- return 0;
+ InvalidDecl = true;
}
}
NewVD = new BlockVarDecl(D.getIdentifierLoc(), II, R, SC, LastDeclarator);
- }
+ }
+ if (InvalidDecl)
+ NewVD->setInvalidDecl();
+
// Handle attributes prior to checking for duplicates in MergeVarDecl
HandleDeclAttributes(NewVD, D.getDeclSpec().getAttributes(),
D.getAttributes());
parmDeclType = Context.getPointerType(parmDeclType);
ParmVarDecl *New = new ParmVarDecl(PI.IdentLoc, II, parmDeclType,
- VarDecl::None, 0, PI.InvalidType);
-
+ VarDecl::None, 0);
+ if (PI.InvalidType)
+ New->setInvalidDecl();
+
// If this has an identifier, add it to the scope stack.
if (II) {
New->setNext(II->getFETokenInfo<Decl>());
}
}
if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
- ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(VD);
-
- // FIXME: generalize this for all decls.
- if (PVD && PVD->getInvalidType())
+ // Only create DeclRefExpr's for valid Decl's.
+ if (VD->getInvalidDecl())
return true;
return new DeclRefExpr(VD, VD->getType(), Loc);
}
};
private:
/// DeclKind - This indicates which class this is.
- Kind DeclKind;
+ Kind DeclKind : 8;
+ /// InvalidDecl - This indicates a semantic error occurred.
+ int InvalidDecl : 1;
+
/// Loc - The location that this decl.
SourceLocation Loc;
protected:
Decl(Kind DK, SourceLocation L, IdentifierInfo *Id, Decl *NextDecl)
- : DeclKind(DK), Loc(L), Identifier(Id), Next(0), NextDeclarator(NextDecl) {
+ : DeclKind(DK), InvalidDecl(0), Loc(L), Identifier(Id), Next(0),
+ NextDeclarator(NextDecl) {
if (Decl::CollectingStats()) addDeclKind(DK);
}
virtual ~Decl();
Kind getKind() const { return DeclKind; }
Decl *getNext() const { return Next; }
void setNext(Decl *N) { Next = N; }
+
+ /// setInvalidDecl - Indicates the Decl had a semantic error. This
+ /// allows for graceful error recovery.
+ void setInvalidDecl() { InvalidDecl = 1; }
+ int getInvalidDecl() const { return InvalidDecl; }
/// getNextDeclarator - If this decl was part of a multi-declarator
/// declaration, such as "int X, Y, *Z;" this returns the decl for the next
/// ParmVarDecl - Represent a parameter to a function.
class ParmVarDecl : public VarDecl {
- bool InvalidType;
public:
ParmVarDecl(SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S,
- Decl *PrevDecl, bool flag)
- : VarDecl(ParmVariable, L, Id, T, S, PrevDecl), InvalidType(flag) {}
-
- bool getInvalidType() const { return InvalidType; }
+ Decl *PrevDecl)
+ : VarDecl(ParmVariable, L, Id, T, S, PrevDecl) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == ParmVariable; }
return z;
}
+void ff() {
+ struct s v, *p; // expected-error {{variable has incomplete type 'struct s'}}
+
+ p = &v;
+}
+
void *k (void l[2]) { // expected-error {{array has incomplete element type}}
return l;
}