From 53a3234f4bc3fd5c7e2403321bff9c907e1f2de6 Mon Sep 17 00:00:00 2001 From: Steve Naroff Date: Tue, 28 Aug 2007 18:45:29 +0000 Subject: [PATCH] Move the "invalid decl" idiom up to Decl (where we have some bits to steal:-) Converted ParmVarDecl, FileVarDecl, BlockVarDecl, and Sema::ParseIdentifierExpr() to use the idiom. Updated array-constraint.c to make sure we no longer get "undeclared identifier" errors:-) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41552 91177308-0d34-0410-b5e6-96231b3b80d8 --- Sema/SemaDecl.cpp | 25 ++++++++++++++++--------- Sema/SemaExpr.cpp | 6 ++---- include/clang/AST/Decl.h | 20 +++++++++++++------- test/Sema/array-constraint.c | 6 ++++++ 4 files changed, 37 insertions(+), 20 deletions(-) diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index 6ccdf2c396..d91420d16f 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -356,7 +356,9 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init, 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; @@ -381,7 +383,7 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init, 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 @@ -389,13 +391,13 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init, 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 { @@ -405,7 +407,7 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init, if (R->isIncompleteType()) { Diag(D.getIdentifierLoc(), diag::err_typecheck_decl_incomplete_type, R.getAsString()); - return 0; + InvalidDecl = true; } } if (SC == VarDecl::Static) { @@ -413,11 +415,14 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init, // 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()); @@ -507,8 +512,10 @@ Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo, 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()); diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index af0e6d4e8e..bea6e99912 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -75,10 +75,8 @@ Sema::ExprResult Sema::ParseIdentifierExpr(Scope *S, SourceLocation Loc, } } if (ValueDecl *VD = dyn_cast(D)) { - ParmVarDecl *PVD = dyn_cast(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); } diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 7c80593045..563921c572 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -49,8 +49,11 @@ public: }; 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; @@ -70,7 +73,8 @@ private: 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(); @@ -84,6 +88,11 @@ public: 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 @@ -221,13 +230,10 @@ public: /// 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; } diff --git a/test/Sema/array-constraint.c b/test/Sema/array-constraint.c index b1095bdc19..4d1c2f1600 100644 --- a/test/Sema/array-constraint.c +++ b/test/Sema/array-constraint.c @@ -5,6 +5,12 @@ struct s* t (struct s z[]) { // expected-error {{array has incomplete element 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; } -- 2.40.0