diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-03-09 20:10:30 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-03-09 20:10:30 +0000 |
commit | 216f78b7333dbc89f58fa69066396ae3237da6da (patch) | |
tree | c5582df83664ec9d2d9c37f028dc8121124229ad /lib/Sema/SemaDecl.cpp | |
parent | f9ff5876289d5228c299b57416a62c8c3b848287 (diff) |
Improve our semantic error recovery.
When an error made a record member invalid, the record would stay as "isBeingDefined" and
not "completeDefinition". Even easily recoverable errors ended up propagating records in
such "beingDefined" state, for example:
struct A {
~A() const; // expected-error {{'const' qualifier is not allowed on a destructor}}
};
struct B : A {}; // A & B would stay as "not complete definition" and "being defined".
This weird state was impending lookups in the records and hitting assertion in the ASTWriter.
Part of rdar://11007039
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152432 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 6c25a20e24..5febad616c 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2378,8 +2378,11 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, Tag = CTD->getTemplatedDecl(); } - if (Tag) + if (Tag) { Tag->setFreeStanding(); + if (Tag->isInvalidDecl()) + return Tag; + } if (unsigned TypeQuals = DS.getTypeQualifiers()) { // Enforce C99 6.7.3p2: "Types other than pointer types derived from object @@ -8601,6 +8604,13 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD, TagDecl *Tag = cast<TagDecl>(TagD); Tag->setRBraceLoc(RBraceLoc); + // Make sure we "complete" the definition even it is invalid. + if (Tag->isBeingDefined()) { + assert(Tag->isInvalidDecl() && "We should already have completed it"); + if (RecordDecl *RD = dyn_cast<RecordDecl>(Tag)) + RD->completeDefinition(); + } + if (isa<CXXRecordDecl>(Tag)) FieldCollector->FinishClass(); @@ -8632,6 +8642,12 @@ void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) { TagDecl *Tag = cast<TagDecl>(TagD); Tag->setInvalidDecl(); + // Make sure we "complete" the definition even it is invalid. + if (Tag->isBeingDefined()) { + if (RecordDecl *RD = dyn_cast<RecordDecl>(Tag)) + RD->completeDefinition(); + } + // We're undoing ActOnTagStartDefinition here, not // ActOnStartCXXMemberDeclarations, so we don't have to mess with // the FieldCollector. @@ -8840,11 +8856,19 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, } QualType EltTy = Context.getBaseElementType(T); - if (!EltTy->isDependentType() && - RequireCompleteType(Loc, EltTy, diag::err_field_incomplete)) { - // Fields of incomplete type force their record to be invalid. - Record->setInvalidDecl(); - InvalidDecl = true; + if (!EltTy->isDependentType()) { + if (RequireCompleteType(Loc, EltTy, diag::err_field_incomplete)) { + // Fields of incomplete type force their record to be invalid. + Record->setInvalidDecl(); + InvalidDecl = true; + } else { + NamedDecl *Def; + EltTy->isIncompleteType(&Def); + if (Def && Def->isInvalidDecl()) { + Record->setInvalidDecl(); + InvalidDecl = true; + } + } } // C99 6.7.2.1p8: A member of a structure or union may have any type other |