Implement DR21
A default template-argument shall not be specified in a friend template
declaration.
Interestingly, we properly handled default template arguments on friend
class members but not on just friend classes.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184882 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 82de369..6d8c790 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -4938,6 +4938,7 @@
TPC_ClassTemplate,
TPC_FunctionTemplate,
TPC_ClassTemplateMember,
+ TPC_FriendClassTemplate,
TPC_FriendFunctionTemplate,
TPC_FriendFunctionTemplateDefinition,
TPC_TypeAliasTemplate
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 88b24a1..6c0658f 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -1033,13 +1033,14 @@
// template declaration. Skip this check for a friend in a dependent
// context, because the template parameter list might be dependent.
if (!(TUK == TUK_Friend && CurContext->isDependentContext()) &&
- CheckTemplateParameterList(TemplateParams,
- PrevClassTemplate? PrevClassTemplate->getTemplateParameters() : 0,
- (SS.isSet() && SemanticContext &&
- SemanticContext->isRecord() &&
- SemanticContext->isDependentContext())
- ? TPC_ClassTemplateMember
- : TPC_ClassTemplate))
+ CheckTemplateParameterList(
+ TemplateParams,
+ PrevClassTemplate ? PrevClassTemplate->getTemplateParameters() : 0,
+ (SS.isSet() && SemanticContext && SemanticContext->isRecord() &&
+ SemanticContext->isDependentContext())
+ ? TPC_ClassTemplateMember
+ : TUK == TUK_Friend ? TPC_FriendClassTemplate
+ : TPC_ClassTemplate))
Invalid = true;
if (SS.isSet()) {
@@ -1187,6 +1188,7 @@
<< DefArgRange;
return true;
+ case Sema::TPC_FriendClassTemplate:
case Sema::TPC_FriendFunctionTemplate:
// C++ [temp.param]p9:
// A default template-argument shall not be specified in a
diff --git a/test/CXX/drs/dr0xx.cpp b/test/CXX/drs/dr0xx.cpp
index c51e8c8..e002641 100644
--- a/test/CXX/drs/dr0xx.cpp
+++ b/test/CXX/drs/dr0xx.cpp
@@ -223,12 +223,11 @@
X x = f(); // expected-error {{private}}
}
-namespace dr21 { // dr21: no
+namespace dr21 { // dr21: yes
template<typename T> struct A;
struct X {
- // FIXME: We should reject these, per [temp.param]p9.
- template<typename T = int> friend struct A;
- template<typename T = int> friend struct B;
+ template<typename T = int> friend struct A; // expected-error {{default template argument not permitted on a friend template}}
+ template<typename T = int> friend struct B; // expected-error {{default template argument not permitted on a friend template}}
};
}
diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html
index eda94fb..dd8c7d2 100644
--- a/www/cxx_dr_status.html
+++ b/www/cxx_dr_status.html
@@ -164,7 +164,7 @@
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#21">21</a></td>
<td>TC1</td>
<td>Can a default argument for a template parameter appear in a friend declaration?</td>
- <td class="none" align="center">No</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#22">22</a></td>