diff options
author | John McCall <rjmccall@apple.com> | 2012-05-07 06:16:41 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2012-05-07 06:16:41 +0000 |
commit | 9257664568bf375b7790131a84d9a4fa30a5b7e3 (patch) | |
tree | b2134311ce2830aca55c9fe352cbd7877ee72179 /lib/Sema | |
parent | 667fd80de4c3b7b143ba98a3b73e9b9b200f6af0 (diff) |
Refactor DelayedDiagnostics so that it keeps diagnostics in
separate pools owned by the RAII objects that keep pushing
decl state. This gives us quite a bit more flexibility.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156289 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 89 |
2 files changed, 32 insertions, 62 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 5853f7f394..ca3e233cb7 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/APFloat.h" +#include "llvm/Support/CrashRecoveryContext.h" #include "clang/Sema/CXXFieldCollector.h" #include "clang/Sema/TemplateDeduction.h" #include "clang/Sema/ExternalSemaSource.h" @@ -201,7 +202,6 @@ Sema::~Sema() { ExternalSema->ForgetSema(); } - /// makeUnavailableInSystemHeader - There is an error in the current /// context. If we're still in a system header, and we can plausibly /// make the relevant declaration unavailable instead of erroring, do @@ -426,6 +426,9 @@ void Sema::LoadExternalWeakUndeclaredIdentifiers() { /// translation unit when EOF is reached and all but the top-level scope is /// popped. void Sema::ActOnEndOfTranslationUnit() { + assert(DelayedDiagnostics.getCurrentPool() == NULL + && "reached end of translation unit with a pool attached?"); + // Only complete translation units define vtables and perform implicit // instantiations. if (TUKind == TU_Complete) { diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index c0bc369012..e3a21694ac 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -4198,57 +4198,30 @@ static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag, diag.Triggered = true; } -// This duplicates a vector push_back but hides the need to know the -// size of the type. -void Sema::DelayedDiagnostics::add(const DelayedDiagnostic &diag) { - assert(StackSize <= StackCapacity); - - // Grow the stack if necessary. - if (StackSize == StackCapacity) { - unsigned newCapacity = 2 * StackCapacity + 2; - char *newBuffer = new char[newCapacity * sizeof(DelayedDiagnostic)]; - const char *oldBuffer = (const char*) Stack; - - if (StackCapacity) - memcpy(newBuffer, oldBuffer, StackCapacity * sizeof(DelayedDiagnostic)); - - delete[] oldBuffer; - Stack = reinterpret_cast<sema::DelayedDiagnostic*>(newBuffer); - StackCapacity = newCapacity; - } - - assert(StackSize < StackCapacity); - new (&Stack[StackSize++]) DelayedDiagnostic(diag); -} - -void Sema::DelayedDiagnostics::popParsingDecl(Sema &S, ParsingDeclState state, - Decl *decl) { - DelayedDiagnostics &DD = S.DelayedDiagnostics; - - // Check the invariants. - assert(DD.StackSize >= state.SavedStackSize); - assert(state.SavedStackSize >= DD.ActiveStackBase); - assert(DD.ParsingDepth > 0); - - // Drop the parsing depth. - DD.ParsingDepth--; - - // If there are no active diagnostics, we're done. - if (DD.StackSize == DD.ActiveStackBase) - return; - - // We only want to actually emit delayed diagnostics when we - // successfully parsed a decl. - if (decl) { - // We emit all the active diagnostics, not just those starting - // from the saved state. The idea is this: we get one push for a - // decl spec and another for each declarator; in a decl group like: - // deprecated_typedef foo, *bar, baz(); - // only the declarator pops will be passed decls. This is correct; - // we really do need to consider delayed diagnostics from the decl spec - // for each of the different declarations. - for (unsigned i = DD.ActiveStackBase, e = DD.StackSize; i != e; ++i) { - DelayedDiagnostic &diag = DD.Stack[i]; +void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) { + assert(DelayedDiagnostics.getCurrentPool()); + sema::DelayedDiagnosticPool &poppedPool = + *DelayedDiagnostics.getCurrentPool(); + DelayedDiagnostics.popWithoutEmitting(state); + + // When delaying diagnostics to run in the context of a parsed + // declaration, we only want to actually emit anything if parsing + // succeeds. + if (!decl) return; + + // We emit all the active diagnostics in this pool or any of its + // parents. In general, we'll get one pool for the decl spec + // and a child pool for each declarator; in a decl group like: + // deprecated_typedef foo, *bar, baz(); + // only the declarator pops will be passed decls. This is correct; + // we really do need to consider delayed diagnostics from the decl spec + // for each of the different declarations. + const sema::DelayedDiagnosticPool *pool = &poppedPool; + do { + for (sema::DelayedDiagnosticPool::pool_iterator + i = pool->pool_begin(), e = pool->pool_end(); i != e; ++i) { + // This const_cast is a bit lame. Really, Triggered should be mutable. + DelayedDiagnostic &diag = const_cast<DelayedDiagnostic&>(*i); if (diag.Triggered) continue; @@ -4256,25 +4229,19 @@ void Sema::DelayedDiagnostics::popParsingDecl(Sema &S, ParsingDeclState state, case DelayedDiagnostic::Deprecation: // Don't bother giving deprecation diagnostics if the decl is invalid. if (!decl->isInvalidDecl()) - S.HandleDelayedDeprecationCheck(diag, decl); + HandleDelayedDeprecationCheck(diag, decl); break; case DelayedDiagnostic::Access: - S.HandleDelayedAccessCheck(diag, decl); + HandleDelayedAccessCheck(diag, decl); break; case DelayedDiagnostic::ForbiddenType: - handleDelayedForbiddenType(S, diag, decl); + handleDelayedForbiddenType(*this, diag, decl); break; } } - } - - // Destroy all the delayed diagnostics we're about to pop off. - for (unsigned i = state.SavedStackSize, e = DD.StackSize; i != e; ++i) - DD.Stack[i].Destroy(); - - DD.StackSize = state.SavedStackSize; + } while ((pool = pool->getParent())); } static bool isDeclDeprecated(Decl *D) { |