White-listing templated-scope friend decls is a good idea, but doing it
by marking the decl invalid isn't.  Make some steps towards supporting these
and then hastily shut them down at the last second by marking them as
unsupported.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116661 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index ea6481b..c3a1e75 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -516,8 +516,9 @@
 static AccessResult MatchesFriend(Sema &S,
                                   const EffectiveContext &EC,
                                   FriendDecl *FriendD) {
-  // Whitelist accesses if there's an invalid friend declaration.
-  if (FriendD->isInvalidDecl())
+  // Whitelist accesses if there's an invalid or unsupported friend
+  // declaration.
+  if (FriendD->isInvalidDecl() || FriendD->isUnsupportedFriend())
     return AR_accessible;
 
   if (TypeSourceInfo *T = FriendD->getFriendType())
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index e771452..d118194 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -3410,11 +3410,11 @@
         = MatchTemplateParametersToScopeSpecifier(
                                   D.getDeclSpec().getSourceRange().getBegin(),
                                   D.getCXXScopeSpec(),
-                           (TemplateParameterList**)TemplateParamLists.get(),
-                                                  TemplateParamLists.size(),
-                                                  isFriend,
-                                                  isExplicitSpecialization,
-                                                  Invalid)) {
+                                  TemplateParamLists.get(),
+                                  TemplateParamLists.size(),
+                                  isFriend,
+                                  isExplicitSpecialization,
+                                  Invalid)) {
     // All but one template parameter lists have been matching.
     --NumMatchedTemplateParamLists;
 
@@ -3462,7 +3462,7 @@
   if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) {
     NewFD->setTemplateParameterListsInfo(Context,
                                          NumMatchedTemplateParamLists,
-                        (TemplateParameterList**)TemplateParamLists.release());
+                                         TemplateParamLists.release());
   }
 
   if (Invalid) {
@@ -3732,14 +3732,20 @@
 
     // Qualified decls generally require a previous declaration.
     if (D.getCXXScopeSpec().isSet()) {
-      // ...with the major exception of dependent friend declarations.
-      // In theory, this condition could be whether the qualifier
-      // is dependent;  in practice, the way we nest template parameters
-      // prevents this sort of matching from working, so we have to base it
-      // on the general dependence of the context.
-      if (isFriend && CurContext->isDependentContext()) {
-        // ignore these
+      // ...with the major exception of templated-scope or
+      // dependent-scope friend declarations.
 
+      // TODO: we currently also suppress this check in dependent
+      // contexts because (1) the parameter depth will be off when
+      // matching friend templates and (2) we might actually be
+      // selecting a friend based on a dependent factor.  But there
+      // are situations where these conditions don't apply and we
+      // can actually do this check immediately.
+      if (isFriend &&
+          (NumMatchedTemplateParamLists ||
+           D.getCXXScopeSpec().getScopeRep()->isDependent() ||
+           CurContext->isDependentContext())) {
+        // ignore these
       } else {
         // The user tried to provide an out-of-line definition for a
         // function that is a member of a class or namespace, but there
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index be1ee35..583f7c5 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -6532,6 +6532,17 @@
 
   if (ND->isInvalidDecl())
     FrD->setInvalidDecl();
+  else {
+    FunctionDecl *FD;
+    if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
+      FD = FTD->getTemplatedDecl();
+    else
+      FD = cast<FunctionDecl>(ND);
+
+    // Mark templated-scope function declarations as unsupported.
+    if (FD->getNumTemplateParameterLists())
+      FrD->setUnsupportedFriend(true);
+  }
 
   return ND;
 }
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index f85c3f0..66ded48 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -1375,13 +1375,8 @@
   // If there were at least as many template-ids as there were template
   // parameter lists, then there are no template parameter lists remaining for
   // the declaration itself.
-  if (Idx >= NumParamLists) {
-    // Silently drop template member friend declarations.
-    // TODO: implement these
-    if (IsFriend && NumParamLists) Invalid = true;
-
+  if (Idx >= NumParamLists)
     return 0;
-  }
 
   // If there were too many template parameter lists, complain about that now.
   if (Idx != NumParamLists - 1) {
@@ -1410,11 +1405,6 @@
     }
   }
 
-  // Silently drop template member template friend declarations.
-  // TODO: implement these
-  if (IsFriend && NumParamLists > 1)
-    Invalid = true;
-
   // Return the last template parameter list, which corresponds to the
   // entity being declared.
   return ParamLists[NumParamLists - 1];
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index c892735..05ade63 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -908,6 +908,7 @@
   else
     D->Friend = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
   D->NextFriend = cast_or_null<FriendDecl>(Reader.GetDecl(Record[Idx++]));
+  D->UnsupportedFriend = (Record[Idx++] != 0);
   D->FriendLoc = ReadSourceLocation(Record, Idx);
 }
 
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 0dcc822..bf7c259 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -835,6 +835,7 @@
   else
     Writer.AddDeclRef(D->Friend.get<NamedDecl*>(), Record);
   Writer.AddDeclRef(D->NextFriend, Record);
+  Record.push_back(D->UnsupportedFriend);
   Writer.AddSourceLocation(D->FriendLoc, Record);
   Code = serialization::DECL_FRIEND;
 }