summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-10-09 21:11:42 +0000
committerDouglas Gregor <dgregor@apple.com>2009-10-09 21:11:42 +0000
commit7f34baeb4b28f5d96c2b60113cb5e7808ecf7963 (patch)
treec54f7088e07b4564e8b960b5087c38be209d9429
parente19c1810d72d4d23b216595f30aaec867f024399 (diff)
downloadbcm5719-llvm-7f34baeb4b28f5d96c2b60113cb5e7808ecf7963.tar.gz
bcm5719-llvm-7f34baeb4b28f5d96c2b60113cb5e7808ecf7963.zip
When declaring a friend class template, we may end up finding an
injected-class-name (e.g., when we're referring to other specializations of the current class template). Make sure that we see the template rather than the injected-class-name. Fixes PR4768. llvm-svn: 83672
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp16
-rw-r--r--clang/test/SemaTemplate/friend-template.cpp16
2 files changed, 32 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 219d73146ea..3ee257a94eb 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -616,6 +616,22 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// whether this is a valid redeclaration.
ClassTemplateDecl *PrevClassTemplate
= dyn_cast_or_null<ClassTemplateDecl>(PrevDecl);
+
+ // We may have found the injected-class-name of a class template,
+ // class template partial specialization, or class template specialization.
+ // In these cases, grab the template that is being defined or specialized.
+ if (!PrevClassTemplate && PrevDecl && isa<CXXRecordDecl>(PrevDecl) &&
+ cast<CXXRecordDecl>(PrevDecl)->isInjectedClassName()) {
+ PrevDecl = cast<CXXRecordDecl>(PrevDecl->getDeclContext());
+ PrevClassTemplate
+ = cast<CXXRecordDecl>(PrevDecl)->getDescribedClassTemplate();
+ if (!PrevClassTemplate && isa<ClassTemplateSpecializationDecl>(PrevDecl)) {
+ PrevClassTemplate
+ = cast<ClassTemplateSpecializationDecl>(PrevDecl)
+ ->getSpecializedTemplate();
+ }
+ }
+
if (PrevClassTemplate) {
// Ensure that the template parameter lists are compatible.
if (!TemplateParameterListsAreEqual(TemplateParams,
diff --git a/clang/test/SemaTemplate/friend-template.cpp b/clang/test/SemaTemplate/friend-template.cpp
index df27c920b7b..9a483aeb5b1 100644
--- a/clang/test/SemaTemplate/friend-template.cpp
+++ b/clang/test/SemaTemplate/friend-template.cpp
@@ -28,3 +28,19 @@ namespace N {
template<typename T> void f0(T) { }
template<typename T> void f1(T) { } // expected-error{{redefinition}}
}
+
+// PR4768
+template<typename T>
+struct X0 {
+ template<typename U> friend struct X0;
+};
+
+template<typename T>
+struct X0<T*> {
+ template<typename U> friend struct X0;
+};
+
+template<>
+struct X0<int> {
+ template<typename U> friend struct X0;
+};
OpenPOWER on IntegriCloud