aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-09-11 06:45:03 +0000
committerJohn McCall <rjmccall@apple.com>2009-09-11 06:45:03 +0000
commit136a6988960ac3aeb96f298da7a1a182db7217cd (patch)
tree09fb77402986a09d43cc27f50893bfa28496c44a
parenta4d3282683b22608b05a3d4566c96af269d99c5c (diff)
When stringizing a NamedDecl for a diagnostic, treat the template
specialization types differently. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81512 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Decl.h22
-rw-r--r--include/clang/AST/DeclTemplate.h4
-rw-r--r--lib/AST/Decl.cpp12
-rw-r--r--lib/AST/DeclTemplate.cpp13
-rw-r--r--lib/Sema/Sema.cpp8
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp2
6 files changed, 58 insertions, 3 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index c4c7d26c51..70edcbb222 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -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);
}
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 0232d9382e..ced7639f87 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -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;
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 776a26595b..16936428f3 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -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) {
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index b46f6275d3..77c2a21507 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -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
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index b158c85414..080266c75f 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -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);
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp
index 0c9f294d2b..b76cb91a75 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp
@@ -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;