diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 6a7b7d90e57a..870c8bb04052 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -49,6 +49,7 @@ namespace clang { class ExternalASTSource; class ASTMutationListener; class IdentifierTable; + class PartialDiagnosticStorageAllocator; class SelectorTable; class SourceManager; class TargetInfo; @@ -346,7 +347,7 @@ class ASTContext : public llvm::RefCountedBase { mutable llvm::BumpPtrAllocator BumpAlloc; /// \brief Allocator for partial diagnostics. - PartialDiagnostic::StorageAllocator DiagAllocator; + PartialDiagnosticStorageAllocator *DiagAllocator; /// \brief The current C++ ABI. llvm::OwningPtr ABI; @@ -391,8 +392,8 @@ public: /// Return the total memory used for various side tables. size_t getSideTableAllocatedMemory() const; - PartialDiagnostic::StorageAllocator &getDiagAllocator() { - return DiagAllocator; + PartialDiagnosticStorageAllocator &getDiagAllocator() { + return *DiagAllocator; } const TargetInfo &getTargetInfo() const { return *Target; } diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h index 8cb1e19940bf..e5dff5ad099e 100644 --- a/clang/include/clang/Basic/Diagnostic.h +++ b/clang/include/clang/Basic/Diagnostic.h @@ -593,6 +593,7 @@ private: friend class DiagnosticBuilder; friend class Diagnostic; friend class PartialDiagnostic; + friend struct PartialDiagnosticStorage; friend class DiagnosticErrorTrap; /// CurDiagLoc - This is the location of the current diagnostic that is in diff --git a/clang/include/clang/Basic/PartialDiagnostic.h b/clang/include/clang/Basic/PartialDiagnostic.h index f6092e685819..7bc9f546557b 100644 --- a/clang/include/clang/Basic/PartialDiagnostic.h +++ b/clang/include/clang/Basic/PartialDiagnostic.h @@ -23,91 +23,87 @@ namespace clang { -class PartialDiagnostic { -public: +struct PartialDiagnosticStorage { + PartialDiagnosticStorage() : NumDiagArgs(0), NumDiagRanges(0) { } + enum { - // The MaxArguments and MaxFixItHints member enum values from - // DiagnosticsEngine are private but DiagnosticsEngine declares - // PartialDiagnostic a friend. These enum values are redeclared - // here so that the nested Storage class below can access them. + /// MaxArguments - The maximum number of arguments we can hold. We + /// currently only support up to 10 arguments (%0-%9). + /// A single diagnostic with more than that almost certainly has to + /// be simplified anyway. MaxArguments = DiagnosticsEngine::MaxArguments }; - struct Storage { - Storage() : NumDiagArgs(0), NumDiagRanges(0) { } + /// NumDiagArgs - This contains the number of entries in Arguments. + unsigned char NumDiagArgs; - enum { - /// MaxArguments - The maximum number of arguments we can hold. We - /// currently only support up to 10 arguments (%0-%9). - /// A single diagnostic with more than that almost certainly has to - /// be simplified anyway. - MaxArguments = PartialDiagnostic::MaxArguments - }; + /// NumDiagRanges - This is the number of ranges in the DiagRanges array. + unsigned char NumDiagRanges; - /// NumDiagArgs - This contains the number of entries in Arguments. - unsigned char NumDiagArgs; + /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum + /// values, with one for each argument. This specifies whether the argument + /// is in DiagArgumentsStr or in DiagArguments. + unsigned char DiagArgumentsKind[MaxArguments]; - /// NumDiagRanges - This is the number of ranges in the DiagRanges array. - unsigned char NumDiagRanges; + /// DiagArgumentsVal - The values for the various substitution positions. + /// This is used when the argument is not an std::string. The specific value + /// is mangled into an intptr_t and the interpretation depends on exactly + /// what sort of argument kind it is. + intptr_t DiagArgumentsVal[MaxArguments]; - /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum - /// values, with one for each argument. This specifies whether the argument - /// is in DiagArgumentsStr or in DiagArguments. - unsigned char DiagArgumentsKind[MaxArguments]; + /// \brief The values for the various substitution positions that have + /// string arguments. + std::string DiagArgumentsStr[MaxArguments]; - /// DiagArgumentsVal - The values for the various substitution positions. - /// This is used when the argument is not an std::string. The specific value - /// is mangled into an intptr_t and the interpretation depends on exactly - /// what sort of argument kind it is. - intptr_t DiagArgumentsVal[MaxArguments]; + /// DiagRanges - The list of ranges added to this diagnostic. It currently + /// only support 10 ranges, could easily be extended if needed. + CharSourceRange DiagRanges[10]; - /// \brief The values for the various substitution positions that have - /// string arguments. - std::string DiagArgumentsStr[MaxArguments]; + /// FixItHints - If valid, provides a hint with some code + /// to insert, remove, or modify at a particular position. + SmallVector FixItHints; +}; - /// DiagRanges - The list of ranges added to this diagnostic. It currently - /// only support 10 ranges, could easily be extended if needed. - CharSourceRange DiagRanges[10]; +/// \brief An allocator for Storage objects, which uses a small cache to +/// objects, used to reduce malloc()/free() traffic for partial diagnostics. +class PartialDiagnosticStorageAllocator { + static const unsigned NumCached = 16; + typedef PartialDiagnosticStorage Storage; + Storage Cached[NumCached]; + Storage *FreeList[NumCached]; + unsigned NumFreeListEntries; - /// FixItHints - If valid, provides a hint with some code - /// to insert, remove, or modify at a particular position. - SmallVector FixItHints; - }; +public: + PartialDiagnosticStorageAllocator(); + ~PartialDiagnosticStorageAllocator(); - /// \brief An allocator for Storage objects, which uses a small cache to - /// objects, used to reduce malloc()/free() traffic for partial diagnostics. - class StorageAllocator { - static const unsigned NumCached = 16; - Storage Cached[NumCached]; - Storage *FreeList[NumCached]; - unsigned NumFreeListEntries; + /// \brief Allocate new storage. + Storage *Allocate() { + if (NumFreeListEntries == 0) + return new Storage; - public: - StorageAllocator(); - ~StorageAllocator(); + Storage *Result = FreeList[--NumFreeListEntries]; + Result->NumDiagArgs = 0; + Result->NumDiagRanges = 0; + Result->FixItHints.clear(); + return Result; + } - /// \brief Allocate new storage. - Storage *Allocate() { - if (NumFreeListEntries == 0) - return new Storage; - - Storage *Result = FreeList[--NumFreeListEntries]; - Result->NumDiagArgs = 0; - Result->NumDiagRanges = 0; - Result->FixItHints.clear(); - return Result; + /// \brief Free the given storage object. + void Deallocate(Storage *S) { + if (S >= Cached && S <= Cached + NumCached) { + FreeList[NumFreeListEntries++] = S; + return; } - /// \brief Free the given storage object. - void Deallocate(Storage *S) { - if (S >= Cached && S <= Cached + NumCached) { - FreeList[NumFreeListEntries++] = S; - return; - } + delete S; + } +}; - delete S; - } - }; +class PartialDiagnostic { +public: + typedef PartialDiagnosticStorage Storage; + typedef PartialDiagnosticStorageAllocator StorageAllocator; private: // NOTE: Sema assumes that PartialDiagnostic is location-invariant diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index c9af67c8b6fe..8f9ab719b95f 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -241,6 +241,9 @@ ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM, LastSDM(0, 0), UniqueBlockByRefTypeID(0) { + // Create a new allocator for partial diagnostics. + DiagAllocator = new (BumpAlloc) PartialDiagnosticStorageAllocator; + if (size_reserve > 0) Types.reserve(size_reserve); TUDecl = TranslationUnitDecl::Create(*this); @@ -285,6 +288,9 @@ ASTContext::~ASTContext() { AEnd = DeclAttrs.end(); A != AEnd; ++A) A->second->~AttrVec(); + + // Destroy the partial diagnostic allocator. + DiagAllocator->~PartialDiagnosticStorageAllocator(); } void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) { diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp index c330215db1aa..fc7aaebc59a9 100644 --- a/clang/lib/Basic/Diagnostic.cpp +++ b/clang/lib/Basic/Diagnostic.cpp @@ -842,13 +842,13 @@ bool DiagnosticConsumer::IncludeInDiagnosticCounts() const { return true; } void IgnoringDiagConsumer::anchor() { } -PartialDiagnostic::StorageAllocator::StorageAllocator() { +PartialDiagnosticStorageAllocator::PartialDiagnosticStorageAllocator() { for (unsigned I = 0; I != NumCached; ++I) FreeList[I] = Cached + I; NumFreeListEntries = NumCached; } -PartialDiagnostic::StorageAllocator::~StorageAllocator() { +PartialDiagnosticStorageAllocator::~PartialDiagnosticStorageAllocator() { // Don't assert if we are in a CrashRecovery context, as this // invariant may be invalidated during a crash. assert((NumFreeListEntries == NumCached || llvm::CrashRecoveryContext::isRecoveringFromCrash()) && "A partial is on the lamb");