diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2012-04-14 14:01:31 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2012-04-14 14:01:31 +0000 |
commit | dbe13110f59f48b4dbb7552b3ac2935acdeece7f (patch) | |
tree | be1815eb79b42ff482a8562b13c2dcbf0c5dcbee /include/clang/Basic/PartialDiagnostic.h | |
parent | 9da628931ebf2609493570f87824ca22402cc65f (diff) | |
download | src-test2-dbe13110f59f48b4dbb7552b3ac2935acdeece7f.tar.gz src-test2-dbe13110f59f48b4dbb7552b3ac2935acdeece7f.zip |
Notes
Diffstat (limited to 'include/clang/Basic/PartialDiagnostic.h')
-rw-r--r-- | include/clang/Basic/PartialDiagnostic.h | 137 |
1 files changed, 72 insertions, 65 deletions
diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h index c6ca98976555..007e6a47603a 100644 --- a/include/clang/Basic/PartialDiagnostic.h +++ b/include/clang/Basic/PartialDiagnostic.h @@ -25,88 +25,90 @@ namespace clang { class PartialDiagnostic { public: + 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 = DiagnosticsEngine::MaxArguments + }; + struct Storage { - Storage() : NumDiagArgs(0), NumDiagRanges(0), NumFixItHints(0) { } + Storage() : NumDiagArgs(0), NumDiagRanges(0) { } enum { - /// MaxArguments - The maximum number of arguments we can hold. We + /// 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 + MaxArguments = PartialDiagnostic::MaxArguments }; - + /// NumDiagArgs - This contains the number of entries in Arguments. unsigned char NumDiagArgs; - + /// NumDiagRanges - This is the number of ranges in the DiagRanges array. unsigned char NumDiagRanges; - /// \brief The number of code modifications hints in the - /// FixItHints array. - unsigned char NumFixItHints; - /// 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]; - - /// DiagArgumentsVal - The values for the various substitution positions. - /// This is used when the argument is not an std::string. The specific value + + /// 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]; - + /// \brief The values for the various substitution positions that have /// string arguments. std::string DiagArgumentsStr[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]; - - enum { MaxFixItHints = DiagnosticsEngine::MaxFixItHints }; - + /// FixItHints - If valid, provides a hint with some code /// to insert, remove, or modify at a particular position. - FixItHint FixItHints[MaxFixItHints]; + SmallVector<FixItHint, 6> FixItHints; }; - /// \brief An allocator for Storage objects, which uses a small cache to + /// \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; - + public: StorageAllocator(); ~StorageAllocator(); - + /// \brief Allocate new storage. Storage *Allocate() { if (NumFreeListEntries == 0) return new Storage; - + Storage *Result = FreeList[--NumFreeListEntries]; Result->NumDiagArgs = 0; Result->NumDiagRanges = 0; - Result->NumFixItHints = 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; } - + delete S; } }; - + private: // NOTE: Sema assumes that PartialDiagnostic is location-invariant // in the sense that its bits can be safely memcpy'ed and destructed @@ -114,18 +116,18 @@ private: /// DiagID - The diagnostic ID. mutable unsigned DiagID; - + /// DiagStorage - Storage for args and ranges. mutable Storage *DiagStorage; /// \brief Allocator used to allocate storage for this diagnostic. StorageAllocator *Allocator; - + /// \brief Retrieve storage for this particular diagnostic. Storage *getStorage() const { if (DiagStorage) return DiagStorage; - + if (Allocator) DiagStorage = Allocator->Allocate(); else { @@ -134,48 +136,53 @@ private: } return DiagStorage; } - - void freeStorage() { + + void freeStorage() { if (!DiagStorage) return; - + + // The hot path for PartialDiagnostic is when we just used it to wrap an ID + // (typically so we have the flexibility of passing a more complex + // diagnostic into the callee, but that does not commonly occur). + // + // Split this out into a slow function for silly compilers (*cough*) which + // can't do decent partial inlining. + freeStorageSlow(); + } + + void freeStorageSlow() { if (Allocator) Allocator->Deallocate(DiagStorage); else if (Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0))) delete DiagStorage; DiagStorage = 0; } - + void AddSourceRange(const CharSourceRange &R) const { if (!DiagStorage) DiagStorage = getStorage(); - assert(DiagStorage->NumDiagRanges < + assert(DiagStorage->NumDiagRanges < llvm::array_lengthof(DiagStorage->DiagRanges) && "Too many arguments to diagnostic!"); DiagStorage->DiagRanges[DiagStorage->NumDiagRanges++] = R; - } + } void AddFixItHint(const FixItHint &Hint) const { if (Hint.isNull()) return; - + if (!DiagStorage) DiagStorage = getStorage(); - assert(DiagStorage->NumFixItHints < Storage::MaxFixItHints && - "Too many code modification hints!"); - if (DiagStorage->NumFixItHints >= Storage::MaxFixItHints) - return; // Don't crash in release builds - DiagStorage->FixItHints[DiagStorage->NumFixItHints++] - = Hint; + DiagStorage->FixItHints.push_back(Hint); } - + public: PartialDiagnostic(unsigned DiagID, StorageAllocator &Allocator) : DiagID(DiagID), DiagStorage(0), Allocator(&Allocator) { } - - PartialDiagnostic(const PartialDiagnostic &Other) + + PartialDiagnostic(const PartialDiagnostic &Other) : DiagID(Other.DiagID), DiagStorage(0), Allocator(Other.Allocator) { if (Other.DiagStorage) { @@ -184,14 +191,14 @@ public: } } - PartialDiagnostic(const PartialDiagnostic &Other, Storage *DiagStorage) - : DiagID(Other.DiagID), DiagStorage(DiagStorage), + PartialDiagnostic(const PartialDiagnostic &Other, Storage *DiagStorage) + : DiagID(Other.DiagID), DiagStorage(DiagStorage), Allocator(reinterpret_cast<StorageAllocator *>(~uintptr_t(0))) { if (Other.DiagStorage) *this->DiagStorage = *Other.DiagStorage; } - + PartialDiagnostic(const Diagnostic &Other, StorageAllocator &Allocator) : DiagID(Other.getID()), DiagStorage(0), Allocator(&Allocator) { @@ -202,22 +209,22 @@ public: else AddTaggedVal(Other.getRawArg(I), Other.getArgKind(I)); } - + // Copy source ranges. for (unsigned I = 0, N = Other.getNumRanges(); I != N; ++I) AddSourceRange(Other.getRange(I)); - + // Copy fix-its. for (unsigned I = 0, N = Other.getNumFixItHints(); I != N; ++I) AddFixItHint(Other.getFixItHint(I)); } - + PartialDiagnostic &operator=(const PartialDiagnostic &Other) { DiagID = Other.DiagID; if (Other.DiagStorage) { if (!DiagStorage) DiagStorage = getStorage(); - + *DiagStorage = *Other.DiagStorage; } else { freeStorage(); @@ -245,7 +252,7 @@ public: void AddString(StringRef V) const { if (!DiagStorage) DiagStorage = getStorage(); - + assert(DiagStorage->NumDiagArgs < Storage::MaxArguments && "Too many arguments to diagnostic!"); DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] @@ -256,7 +263,7 @@ public: void Emit(const DiagnosticBuilder &DB) const { if (!DiagStorage) return; - + // Add all arguments. for (unsigned i = 0, e = DiagStorage->NumDiagArgs; i != e; ++i) { if ((DiagnosticsEngine::ArgumentKind)DiagStorage->DiagArgumentsKind[i] @@ -266,25 +273,25 @@ public: DB.AddTaggedVal(DiagStorage->DiagArgumentsVal[i], (DiagnosticsEngine::ArgumentKind)DiagStorage->DiagArgumentsKind[i]); } - + // Add all ranges. for (unsigned i = 0, e = DiagStorage->NumDiagRanges; i != e; ++i) DB.AddSourceRange(DiagStorage->DiagRanges[i]); - + // Add all fix-its. - for (unsigned i = 0, e = DiagStorage->NumFixItHints; i != e; ++i) + for (unsigned i = 0, e = DiagStorage->FixItHints.size(); i != e; ++i) DB.AddFixItHint(DiagStorage->FixItHints[i]); } - + /// \brief Clear out this partial diagnostic, giving it a new diagnostic ID /// and removing all of its arguments, ranges, and fix-it hints. void Reset(unsigned DiagID = 0) { this->DiagID = DiagID; freeStorage(); } - + bool hasStorage() const { return DiagStorage != 0; } - + friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, unsigned I) { PD.AddTaggedVal(I, DiagnosticsEngine::ak_uint); @@ -306,11 +313,11 @@ public: friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, StringRef S) { - + PD.AddString(S); return PD; } - + friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, const SourceRange &R) { PD.AddSourceRange(CharSourceRange::getTokenRange(R)); @@ -322,13 +329,13 @@ public: PD.AddSourceRange(R); return PD; } - + friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, const FixItHint &Hint) { PD.AddFixItHint(Hint); return PD; } - + }; inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, @@ -336,7 +343,7 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, PD.Emit(DB); return DB; } - + /// \brief A partial diagnostic along with the source location where this /// diagnostic occurs. typedef std::pair<SourceLocation, PartialDiagnostic> PartialDiagnosticAt; |