When stringizing a NamedDecl for a diagnostic, treat the template

specialization types differently.

llvm-svn: 81512
This commit is contained in:
John McCall 2009-09-11 06:45:03 +00:00
parent 9a7edd6bba
commit e1f2ec28d8
6 changed files with 58 additions and 3 deletions

View File

@ -123,6 +123,24 @@ public:
std::string getQualifiedNameAsString() const;
std::string getQualifiedNameAsString(const PrintingPolicy &Policy) const;
/// getNameForDiagnostic - Appends a human-readable name for this
/// declaration into the given string.
///
/// This is the method invoked by Sema when displaying a NamedDecl
/// in a diagnostic. It does not necessarily produce the same
/// result as getNameAsString(); for example, class template
/// specializations are printed with their template arguments.
///
/// TODO: use an API that doesn't require so many temporary strings
virtual void getNameForDiagnostic(std::string &S,
const PrintingPolicy &Policy,
bool Qualified) const {
if (Qualified)
S += getQualifiedNameAsString(Policy);
else
S += getNameAsString();
}
/// declarationReplaces - Determine whether this declaration, if
/// known to be well-formed within its context, will replace the
/// declaration OldD if introduced into scope. A declaration will
@ -839,6 +857,10 @@ public:
StorageClass S = None, bool isInline = false,
bool hasWrittenPrototype = true);
virtual void getNameForDiagnostic(std::string &S,
const PrintingPolicy &Policy,
bool Qualified) const;
virtual SourceRange getSourceRange() const {
return SourceRange(getLocation(), EndRangeLoc);
}

View File

@ -926,6 +926,10 @@ public:
virtual void Destroy(ASTContext& C);
virtual void getNameForDiagnostic(std::string &S,
const PrintingPolicy &Policy,
bool Qualified) const;
/// \brief Retrieve the template that this specialization specializes.
ClassTemplateDecl *getSpecializedTemplate() const;

View File

@ -404,6 +404,18 @@ void FunctionDecl::Destroy(ASTContext& C) {
Decl::Destroy(C);
}
void FunctionDecl::getNameForDiagnostic(std::string &S,
const PrintingPolicy &Policy,
bool Qualified) const {
NamedDecl::getNameForDiagnostic(S, Policy, Qualified);
const TemplateArgumentList *TemplateArgs = getTemplateSpecializationArgs();
if (TemplateArgs)
S += TemplateSpecializationType::PrintTemplateArgumentList(
TemplateArgs->getFlatArgumentList(),
TemplateArgs->flat_size(),
Policy);
}
Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {

View File

@ -422,6 +422,19 @@ void ClassTemplateSpecializationDecl::Destroy(ASTContext &C) {
CXXRecordDecl::Destroy(C);
}
void
ClassTemplateSpecializationDecl::getNameForDiagnostic(std::string &S,
const PrintingPolicy &Policy,
bool Qualified) const {
NamedDecl::getNameForDiagnostic(S, Policy, Qualified);
const TemplateArgumentList &TemplateArgs = getTemplateArgs();
S += TemplateSpecializationType::PrintTemplateArgumentList(
TemplateArgs.getFlatArgumentList(),
TemplateArgs.flat_size(),
Policy);
}
ClassTemplateDecl *
ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
if (SpecializedPartialSpecialization *PartialSpec

View File

@ -85,13 +85,17 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
assert(ModLen == 0 && ArgLen == 0 &&
"Invalid modifier for DeclarationName argument");
} else if (Kind == Diagnostic::ak_nameddecl) {
bool Qualified;
if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0)
S = reinterpret_cast<NamedDecl*>(Val)->getQualifiedNameAsString();
Qualified = true;
else {
assert(ModLen == 0 && ArgLen == 0 &&
"Invalid modifier for NamedDecl* argument");
S = reinterpret_cast<NamedDecl*>(Val)->getNameAsString();
Qualified = false;
}
reinterpret_cast<NamedDecl*>(Val)->getNameForDiagnostic(S,
Context.PrintingPolicy,
Qualified);
} else {
llvm::raw_string_ostream OS(S);
assert(Kind == Diagnostic::ak_nestednamespec);

View File

@ -53,7 +53,7 @@ void e3(union B<A>::Member);
void e4(enum B<A>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}}
template <class T> struct C {
void foo(class B<T>::Member); // expected-error{{no type named 'Member' in 'B'}}
void foo(class B<T>::Member); // expected-error{{no type named 'Member' in 'B<int>'}}
};
C<float> f1;