Fix a long standard problem with clang retaining "too much" sugar
information about types. We often print diagnostics where we say
"foo_t" is bad, but the user doesn't know how foo_t is declared
(because it is a typedef). Fix this by expanding sugar when present
in a diagnostic (and not one of a few special cases, like vectors).
Before:
t.m:5:2: error: invalid operands to binary expression ('typeof(P)' and 'typeof(F)')
MAX(P, F);
^~~~~~~~~
t.m:1:78: note: instantiated from:
#define MAX(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __b : __a; })
^
After:
t.m:5:2: error: invalid operands to binary expression ('typeof(P)' (aka 'struct mystruct') and 'typeof(F)' (aka 'float'))
MAX(P, F);
^~~~~~~~~
t.m:1:78: note: instantiated from:
#define MAX(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __b : __a; })
^
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65081 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index 3f94a03..83ccd22 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -648,9 +648,9 @@
}
// ---- NAMES and TYPES ----
case Diagnostic::ak_identifierinfo: {
- OutStr.push_back('\'');
const IdentifierInfo *II = getArgIdentifier(ArgNo);
assert(ModifierLen == 0 && "No modifiers for strings yet");
+ OutStr.push_back('\'');
OutStr.append(II->getName(), II->getName() + II->getLength());
OutStr.push_back('\'');
break;
@@ -658,11 +658,9 @@
case Diagnostic::ak_qualtype:
case Diagnostic::ak_declarationname:
case Diagnostic::ak_nameddecl:
- OutStr.push_back('\'');
getDiags()->ConvertArgToString(getArgKind(ArgNo), getRawArg(ArgNo),
Modifier, ModifierLen,
Argument, ArgumentLen, OutStr);
- OutStr.push_back('\'');
break;
}
}
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 539457f..1ffaf93 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -22,19 +22,39 @@
/// ConvertQualTypeToStringFn - This function is used to pretty print the
/// specified QualType as a string in diagnostics.
static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
- const char *Modifier, unsigned ModLen,
- const char *Argument, unsigned ArgLen,
- llvm::SmallVectorImpl<char> &Output) {
+ const char *Modifier, unsigned ModLen,
+ const char *Argument, unsigned ArgLen,
+ llvm::SmallVectorImpl<char> &Output) {
std::string S;
if (Kind == Diagnostic::ak_qualtype) {
+ assert(ModLen == 0 && ArgLen == 0 &&
+ "Invalid modifier for QualType argument");
+
QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val)));
// FIXME: Playing with std::string is really slow.
S = Ty.getAsString();
+
+ // If this is a sugared type (like a typedef, typeof, etc), then unwrap one
+ // level of the sugar so that the type is more obvious to the user.
+ QualType DesugaredTy = Ty->getDesugaredType();
+ DesugaredTy.setCVRQualifiers(DesugaredTy.getCVRQualifiers() |
+ Ty.getCVRQualifiers());
- assert(ModLen == 0 && ArgLen == 0 &&
- "Invalid modifier for QualType argument");
+ if (Ty != DesugaredTy &&
+ // If the desugared type is a vector type, we don't want to expand it,
+ // it will turn into an attribute mess. People want their "vec4".
+ !isa<VectorType>(DesugaredTy) &&
+
+ // Don't desugar objc types. FIXME: THIS IS A HACK.
+ S != "id" && S != "Class") {
+ S = "'"+S+"' (aka '";
+ S += DesugaredTy.getAsString();
+ S += "')";
+ Output.append(S.begin(), S.end());
+ return;
+ }
} else if (Kind == Diagnostic::ak_declarationname) {
@@ -58,7 +78,10 @@
S = reinterpret_cast<NamedDecl*>(Val)->getNameAsString();
}
}
+
+ Output.push_back('\'');
Output.append(S.begin(), S.end());
+ Output.push_back('\'');
}