Patch over yet more problems with friend declarations which were provoking
problems on LLVM-Code-Syntax. This proved remarkably easy to "fix" once
I settled on how I was going to approach it.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91633 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index ac1b1ec..c1d828f 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -691,37 +691,6 @@
if (Previous.begin() != Previous.end())
PrevDecl = *Previous.begin();
- if (PrevDecl && TUK == TUK_Friend) {
- // C++ [namespace.memdef]p3:
- // [...] When looking for a prior declaration of a class or a function
- // declared as a friend, and when the name of the friend class or
- // function is neither a qualified name nor a template-id, scopes outside
- // the innermost enclosing namespace scope are not considered.
- DeclContext *OutermostContext = CurContext;
- while (!OutermostContext->isFileContext())
- OutermostContext = OutermostContext->getLookupParent();
-
- if (OutermostContext->Equals(PrevDecl->getDeclContext()) ||
- OutermostContext->Encloses(PrevDecl->getDeclContext())) {
- SemanticContext = PrevDecl->getDeclContext();
- } else {
- // Declarations in outer scopes don't matter. However, the outermost
- // context we computed is the semantic context for our new
- // declaration.
- PrevDecl = 0;
- SemanticContext = OutermostContext;
- }
-
- if (CurContext->isDependentContext()) {
- // If this is a dependent context, we don't want to link the friend
- // class template to the template in scope, because that would perform
- // checking of the template parameter lists that can't be performed
- // until the outer context is instantiated.
- PrevDecl = 0;
- }
- } else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S))
- PrevDecl = 0;
-
// If there is a previous declaration with the same name, check
// whether this is a valid redeclaration.
ClassTemplateDecl *PrevClassTemplate
@@ -742,6 +711,37 @@
}
}
+ if (PrevDecl && TUK == TUK_Friend) {
+ // C++ [namespace.memdef]p3:
+ // [...] When looking for a prior declaration of a class or a function
+ // declared as a friend, and when the name of the friend class or
+ // function is neither a qualified name nor a template-id, scopes outside
+ // the innermost enclosing namespace scope are not considered.
+ DeclContext *OutermostContext = CurContext;
+ while (!OutermostContext->isFileContext())
+ OutermostContext = OutermostContext->getLookupParent();
+
+ if (OutermostContext->Equals(PrevDecl->getDeclContext()) ||
+ OutermostContext->Encloses(PrevDecl->getDeclContext())) {
+ SemanticContext = PrevDecl->getDeclContext();
+ } else {
+ // Declarations in outer scopes don't matter. However, the outermost
+ // context we computed is the semantic context for our new
+ // declaration.
+ PrevDecl = PrevClassTemplate = 0;
+ SemanticContext = OutermostContext;
+ }
+
+ if (CurContext->isDependentContext()) {
+ // If this is a dependent context, we don't want to link the friend
+ // class template to the template in scope, because that would perform
+ // checking of the template parameter lists that can't be performed
+ // until the outer context is instantiated.
+ PrevDecl = PrevClassTemplate = 0;
+ }
+ } else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S))
+ PrevDecl = PrevClassTemplate = 0;
+
if (PrevClassTemplate) {
// Ensure that the template parameter lists are compatible.
if (!TemplateParameterListsAreEqual(TemplateParams,
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 69982be..2ca4810 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -396,7 +396,13 @@
// FIXME: We have a problem here, because the nested call to Visit(ND)
// will inject the thing that the friend references into the current
// owner, which is wrong.
- Decl *NewND = Visit(ND);
+ Decl *NewND;
+
+ // Hack to make this work almost well pending a rewrite.
+ if (ND->getDeclContext()->isRecord())
+ NewND = SemaRef.FindInstantiatedDecl(ND, TemplateArgs);
+ else
+ NewND = Visit(ND);
if (!NewND) return 0;
FU = cast<NamedDecl>(NewND);