[cfe-commits] r91633 - in /cfe/trunk: lib/AST/DeclCXX.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaCXX/friend.cpp
John McCall
rjmccall at apple.com
Thu Dec 17 15:21:11 PST 2009
Author: rjmccall
Date: Thu Dec 17 17:21:11 2009
New Revision: 91633
URL: http://llvm.org/viewvc/llvm-project?rev=91633&view=rev
Log:
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.
Modified:
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/SemaCXX/friend.cpp
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=91633&r1=91632&r2=91633&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Thu Dec 17 17:21:11 2009
@@ -874,7 +874,11 @@
isa<CXXRecordDecl>(D) ||
isa<FunctionTemplateDecl>(D) ||
isa<ClassTemplateDecl>(D));
- assert(D->getFriendObjectKind());
+
+ // As a temporary hack, we permit template instantiation to point
+ // to the original declaration when instantiating members.
+ assert(D->getFriendObjectKind() ||
+ (cast<CXXRecordDecl>(DC)->getTemplateSpecializationKind()));
}
#endif
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=91633&r1=91632&r2=91633&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Dec 17 17:21:11 2009
@@ -691,6 +691,26 @@
if (Previous.begin() != Previous.end())
PrevDecl = *Previous.begin();
+ // If there is a previous declaration with the same name, check
+ // 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 (PrevDecl && TUK == TUK_Friend) {
// C++ [namespace.memdef]p3:
// [...] When looking for a prior declaration of a class or a function
@@ -708,7 +728,7 @@
// Declarations in outer scopes don't matter. However, the outermost
// context we computed is the semantic context for our new
// declaration.
- PrevDecl = 0;
+ PrevDecl = PrevClassTemplate = 0;
SemanticContext = OutermostContext;
}
@@ -717,30 +737,10 @@
// 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;
+ PrevDecl = PrevClassTemplate = 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
- = 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();
- }
- }
+ PrevDecl = PrevClassTemplate = 0;
if (PrevClassTemplate) {
// Ensure that the template parameter lists are compatible.
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=91633&r1=91632&r2=91633&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Dec 17 17:21:11 2009
@@ -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);
Modified: cfe/trunk/test/SemaCXX/friend.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/friend.cpp?rev=91633&r1=91632&r2=91633&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/friend.cpp (original)
+++ cfe/trunk/test/SemaCXX/friend.cpp Thu Dec 17 17:21:11 2009
@@ -15,3 +15,17 @@
friend void ns::f(int a);
};
}
+
+// Test derived from LLVM's Registry.h
+namespace test1 {
+ template <class T> struct Outer {
+ void foo(T);
+ struct Inner {
+ friend void Outer::foo(T);
+ };
+ };
+
+ void test() {
+ (void) Outer<int>::Inner();
+ }
+}
More information about the cfe-commits
mailing list