teach FormatDiagnostic to aggregate previously formatted arguments and

pass them down into the ArgToStringFn implementation.  This allows 
redundancy across operands to a diagnostic to be eliminated.

This isn't used yet, so no functionality change.

llvm-svn: 84602
This commit is contained in:
Chris Lattner 2009-10-20 05:25:22 +00:00
parent 2f9876cf7c
commit c243f299ce
3 changed files with 41 additions and 5 deletions

View File

@ -164,6 +164,10 @@ public:
ak_nestednamespec, // NestedNameSpecifier *
ak_declcontext // DeclContext *
};
/// ArgumentValue - This typedef represents on argument value, which is a
/// union discriminated by ArgumentKind, with a value.
typedef std::pair<ArgumentKind, intptr_t> ArgumentValue;
private:
unsigned char AllExtensionsSilenced; // Used by __extension__
@ -203,10 +207,17 @@ private:
/// ArgToStringFn - A function pointer that converts an opaque diagnostic
/// argument to a strings. This takes the modifiers and argument that was
/// present in the diagnostic.
///
/// The PrevArgs array (whose length is NumPrevArgs) indicates the previous
/// arguments formatted for this diagnostic. Implementations of this function
/// can use this information to avoid redundancy across arguments.
///
/// This is a hack to avoid a layering violation between libbasic and libsema.
typedef void (*ArgToStringFnTy)(ArgumentKind Kind, intptr_t Val,
const char *Modifier, unsigned ModifierLen,
const char *Argument, unsigned ArgumentLen,
const ArgumentValue *PrevArgs,
unsigned NumPrevArgs,
llvm::SmallVectorImpl<char> &Output,
void *Cookie);
void *ArgToStringCookie;
@ -311,9 +322,10 @@ public:
void ConvertArgToString(ArgumentKind Kind, intptr_t Val,
const char *Modifier, unsigned ModLen,
const char *Argument, unsigned ArgLen,
const ArgumentValue *PrevArgs, unsigned NumPrevArgs,
llvm::SmallVectorImpl<char> &Output) const {
ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen, Output,
ArgToStringCookie);
ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen,
PrevArgs, NumPrevArgs, Output, ArgToStringCookie);
}
void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) {

View File

@ -190,6 +190,8 @@ namespace clang {
static void DummyArgToStringFn(Diagnostic::ArgumentKind AK, intptr_t QT,
const char *Modifier, unsigned ML,
const char *Argument, unsigned ArgLen,
const Diagnostic::ArgumentValue *PrevArgs,
unsigned NumPrevArgs,
llvm::SmallVectorImpl<char> &Output,
void *Cookie) {
const char *Str = "<can't format argument>";
@ -685,6 +687,12 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
const char *DiagStr = getDiags()->getDescription(getID());
const char *DiagEnd = DiagStr+strlen(DiagStr);
/// FormattedArgs - Keep track of all of the arguments formatted by
/// ConvertArgToString and pass them into subsequent calls to
/// ConvertArgToString, allowing the implementation to avoid redundancies in
/// obvious cases.
llvm::SmallVector<Diagnostic::ArgumentValue, 8> FormattedArgs;
while (DiagStr != DiagEnd) {
if (DiagStr[0] != '%') {
// Append non-%0 substrings to Str if we have one.
@ -732,7 +740,9 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
assert(isdigit(*DiagStr) && "Invalid format for argument in diagnostic");
unsigned ArgNo = *DiagStr++ - '0';
switch (getArgKind(ArgNo)) {
Diagnostic::ArgumentKind Kind = getArgKind(ArgNo);
switch (Kind) {
// ---- STRINGS ----
case Diagnostic::ak_std_string: {
const std::string &S = getArgStdStr(ArgNo);
@ -802,11 +812,23 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
case Diagnostic::ak_nameddecl:
case Diagnostic::ak_nestednamespec:
case Diagnostic::ak_declcontext:
getDiags()->ConvertArgToString(getArgKind(ArgNo), getRawArg(ArgNo),
getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo),
Modifier, ModifierLen,
Argument, ArgumentLen, OutStr);
Argument, ArgumentLen,
FormattedArgs.data(), FormattedArgs.size(),
OutStr);
break;
}
// Remember this argument info for subsequent formatting operations. Turn
// std::strings into a null terminated string to make it be the same case as
// all the other ones.
if (Kind != Diagnostic::ak_std_string)
FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo)));
else
FormattedArgs.push_back(std::make_pair(Diagnostic::ak_c_string,
(intptr_t)getArgStdStr(ArgNo).c_str()));
}
}

View File

@ -148,6 +148,8 @@ static std::string ConvertTypeToDiagnosticString(ASTContext &Context,
static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
const char *Modifier, unsigned ModLen,
const char *Argument, unsigned ArgLen,
const Diagnostic::ArgumentValue *PrevArgs,
unsigned NumPrevArgs,
llvm::SmallVectorImpl<char> &Output,
void *Cookie) {
ASTContext &Context = *static_cast<ASTContext*>(Cookie);