From 73d2a1b05bb04ab0136af374ddaa5d4602d4c939 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 19 Nov 2008 06:04:55 +0000 Subject: [PATCH] implement a transparent optimization with the diagnostics stuff: const char*'s are now not converted to std::strings when the diagnostic is formed, we just hold onto their pointer and format as needed. This commit makes DiagnosticClient::FormatDiagnostic even more of a mess, I'll fix it in the next commit. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59593 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Analysis/PathSensitive/BugReporter.h | 12 +++- include/clang/Basic/Diagnostic.h | 69 ++++++++++++++++--- lib/Basic/Diagnostic.cpp | 3 +- 3 files changed, 71 insertions(+), 13 deletions(-) diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h index 98731e1745..72f83bee34 100644 --- a/include/clang/Analysis/PathSensitive/BugReporter.h +++ b/include/clang/Analysis/PathSensitive/BugReporter.h @@ -315,8 +315,16 @@ public: for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i) R.addRange(Info.getRange(i)); - for (unsigned i = 0, e = Info.getNumArgs(); i != e; ++i) - R.addString(Info.getArgStr(i)); + for (unsigned i = 0, e = Info.getNumArgs(); i != e; ++i) { + switch (Info.getArgKind(i)) { + case DiagnosticInfo::ak_std_string: + R.addString(Info.getArgStdStr(i)); + break; + case DiagnosticInfo::ak_c_string: + R.addString(Info.getArgCStr(i)); + break; + } + } } // Iterators. diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index ca7c100ee9..7742307d47 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -178,9 +178,29 @@ private: // diagnostic is in flight at a time. friend class DiagnosticInfo; - /// DiagArguments - The values for the various substitution positions. It - /// currently only support 10 arguments (%0-%9). - std::string DiagArguments[10]; + 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 = 10 + }; + + /// 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]; + + /// DiagArgumentsStr - This holds the values of each string argument for the + /// current diagnostic. This value is only used when the corresponding + /// ArgumentKind is ak_std_string. + 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 intepretation 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. const SourceRange *DiagRanges[10]; @@ -212,6 +232,12 @@ class DiagnosticInfo { unsigned DiagID; void operator=(const DiagnosticInfo&); // DO NOT IMPLEMENT public: + enum ArgumentKind { + ak_std_string, // std::string + ak_c_string // const char * + }; + + DiagnosticInfo(Diagnostic *diagObj, FullSourceLoc loc, unsigned diagID) : DiagObj(diagObj), Loc(loc), DiagID(diagID) { if (DiagObj == 0) return; @@ -251,11 +277,25 @@ public: unsigned getNumArgs() const { return DiagObj->NumDiagArgs; } - /// getArgStr - Return the provided argument string specified by Idx. - const std::string &getArgStr(unsigned Idx) const { + + /// getArgKind - Return the kind of the specified index. Based on the kind + /// of argument, the accessors below can be used to get the value. + ArgumentKind getArgKind(unsigned Idx) const { assert((signed char)Idx < DiagObj->NumDiagArgs && - "Argument out of range!"); - return DiagObj->DiagArguments[Idx]; + "Argument index out of range!"); + return (ArgumentKind)DiagObj->DiagArgumentsKind[Idx]; + } + + /// getArgStdStr - Return the provided argument string specified by Idx. + const std::string &getArgStdStr(unsigned Idx) const { + assert(getArgKind(Idx) == ak_std_string && "invalid argument accessor!"); + return DiagObj->DiagArgumentsStr[Idx]; + } + + /// getArgCStr - Return the specified C string argument. + const char *getArgCStr(unsigned Idx) const { + assert(getArgKind(Idx) == ak_c_string && "invalid argument accessor!"); + return reinterpret_cast(DiagObj->DiagArgumentsVal[Idx]); } /// getNumRanges - Return the number of source ranges associated with this @@ -270,10 +310,19 @@ public: } DiagnosticInfo &operator<<(const std::string &S) { - assert((unsigned)DiagObj->NumDiagArgs < - sizeof(DiagObj->DiagArguments)/sizeof(DiagObj->DiagArguments[0]) && + assert((unsigned)DiagObj->NumDiagArgs < Diagnostic::MaxArguments && + "Too many arguments to diagnostic!"); + DiagObj->DiagArgumentsKind[DiagObj->NumDiagArgs] = ak_std_string; + DiagObj->DiagArgumentsStr[DiagObj->NumDiagArgs++] = S; + return *this; + } + + DiagnosticInfo &operator<<(const char *Str) { + assert((unsigned)DiagObj->NumDiagArgs < Diagnostic::MaxArguments && "Too many arguments to diagnostic!"); - DiagObj->DiagArguments[DiagObj->NumDiagArgs++] = S; + DiagObj->DiagArgumentsKind[DiagObj->NumDiagArgs] = ak_c_string; + DiagObj->DiagArgumentsVal[DiagObj->NumDiagArgs++] = + reinterpret_cast(Str); return *this; } diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp index a202a55f26..35d454b1b9 100644 --- a/lib/Basic/Diagnostic.cpp +++ b/lib/Basic/Diagnostic.cpp @@ -255,7 +255,8 @@ std::string DiagnosticClient::FormatDiagnostic(const DiagnosticInfo &Info) { if (Msg[i] == '%' && isdigit(Msg[i + 1])) { unsigned StrNo = Msg[i + 1] - '0'; Msg = std::string(Msg.begin(), Msg.begin() + i) + - Info.getArgStr(StrNo) + + (Info.getArgKind(StrNo) == DiagnosticInfo::ak_std_string ? + Info.getArgStdStr(StrNo) : std::string(Info.getArgCStr(StrNo))) + std::string(Msg.begin() + i + 2, Msg.end()); } } -- 2.40.0