[cfe-commits] r82950 - in /cfe/trunk: lib/Sema/SemaDeclCXX.cpp test/SemaTemplate/friend-template.cpp
Douglas Gregor
dgregor at apple.com
Sun Sep 27 17:08:27 PDT 2009
Author: dgregor
Date: Sun Sep 27 19:08:27 2009
New Revision: 82950
URL: http://llvm.org/viewvc/llvm-project?rev=82950&view=rev
Log:
Improve handling of friend function templates somewhat
Modified:
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/test/SemaTemplate/friend-template.cpp
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=82950&r1=82949&r2=82950&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Sep 27 19:08:27 2009
@@ -4220,9 +4220,6 @@
DeclarationName Name = GetNameForDeclarator(D);
assert(Name);
- // The existing declaration we found.
- FunctionDecl *FD = NULL;
-
// The context we found the declaration in, or in which we should
// create the declaration.
DeclContext *DC;
@@ -4230,19 +4227,20 @@
// FIXME: handle local classes
// Recover from invalid scope qualifiers as if they just weren't there.
+ NamedDecl *PrevDecl = 0;
if (!ScopeQual.isInvalid() && ScopeQual.isSet()) {
DC = computeDeclContext(ScopeQual);
// FIXME: handle dependent contexts
if (!DC) return DeclPtrTy();
- Decl *Dec = LookupQualifiedNameWithType(DC, Name, T);
+ PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName, true);
// If searching in that context implicitly found a declaration in
// a different context, treat it like it wasn't found at all.
// TODO: better diagnostics for this case. Suggesting the right
// qualified scope would be nice...
- if (!Dec || Dec->getDeclContext() != DC) {
+ if (!PrevDecl || !PrevDecl->getDeclContext()->Equals(DC)) {
D.setInvalidType();
Diag(Loc, diag::err_qualified_friend_not_found) << Name << T;
return DeclPtrTy();
@@ -4250,11 +4248,9 @@
// C++ [class.friend]p1: A friend of a class is a function or
// class that is not a member of the class . . .
- if (DC == CurContext)
+ if (DC->Equals(CurContext))
Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
- FD = cast<FunctionDecl>(Dec);
-
// Otherwise walk out to the nearest namespace scope looking for matches.
} else {
// TODO: handle local class contexts.
@@ -4268,15 +4264,15 @@
// declarations should stop at the nearest enclosing namespace,
// not that they should only consider the nearest enclosing
// namespace.
- while (DC->isRecord()) DC = DC->getParent();
+ while (DC->isRecord())
+ DC = DC->getParent();
- Decl *Dec = LookupQualifiedNameWithType(DC, Name, T);
+ PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName, true);
// TODO: decide what we think about using declarations.
- if (Dec) {
- FD = cast<FunctionDecl>(Dec);
+ if (PrevDecl)
break;
- }
+
if (DC->isFileContext()) break;
DC = DC->getParent();
}
@@ -4286,24 +4282,11 @@
// C++0x changes this for both friend types and functions.
// Most C++ 98 compilers do seem to give an error here, so
// we do, too.
- if (FD && DC == CurContext && !getLangOptions().CPlusPlus0x)
+ if (PrevDecl && DC->Equals(CurContext) && !getLangOptions().CPlusPlus0x)
Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
}
- bool Redeclaration = (FD != 0);
-
- // If we found a match, create a friend function declaration with
- // that function as the previous declaration.
- if (Redeclaration) {
- // Create it in the semantic context of the original declaration.
- DC = FD->getDeclContext();
-
- // If we didn't find something matching the type exactly, create
- // a declaration. This declaration should only be findable via
- // argument-dependent lookup.
- } else {
- assert(DC->isFileContext());
-
+ if (DC->isFileContext()) {
// This implies that it has to be an operator or function.
if (D.getKind() == Declarator::DK_Constructor ||
D.getKind() == Declarator::DK_Destructor ||
@@ -4315,20 +4298,15 @@
}
}
- NamedDecl *ND = ActOnFunctionDeclarator(S, D, DC, T, DInfo,
- /* PrevDecl = */ FD,
+ bool Redeclaration = false;
+ NamedDecl *ND = ActOnFunctionDeclarator(S, D, DC, T, DInfo, PrevDecl,
MultiTemplateParamsArg(*this),
IsDefinition,
Redeclaration);
if (!ND) return DeclPtrTy();
- assert(cast<FunctionDecl>(ND)->getPreviousDeclaration() == FD &&
- "lost reference to previous declaration");
-
- FD = cast<FunctionDecl>(ND);
-
- assert(FD->getDeclContext() == DC);
- assert(FD->getLexicalDeclContext() == CurContext);
+ assert(ND->getDeclContext() == DC);
+ assert(ND->getLexicalDeclContext() == CurContext);
// Add the function declaration to the appropriate lookup tables,
// adjusting the redeclarations list as necessary. We don't
@@ -4338,18 +4316,18 @@
// lookup context is in lexical scope.
if (!CurContext->isDependentContext()) {
DC = DC->getLookupContext();
- DC->makeDeclVisibleInContext(FD, /* Recoverable=*/ false);
+ DC->makeDeclVisibleInContext(ND, /* Recoverable=*/ false);
if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
- PushOnScopeChains(FD, EnclosingScope, /*AddToContext=*/ false);
+ PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false);
}
FriendDecl *FrD = FriendDecl::Create(Context, CurContext,
- D.getIdentifierLoc(), FD,
+ D.getIdentifierLoc(), ND,
DS.getFriendSpecLoc());
FrD->setAccess(AS_public);
CurContext->addDecl(FrD);
- return DeclPtrTy::make(FD);
+ return DeclPtrTy::make(ND);
}
void Sema::SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc) {
Modified: cfe/trunk/test/SemaTemplate/friend-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/friend-template.cpp?rev=82950&r1=82949&r2=82950&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/friend-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/friend-template.cpp Sun Sep 27 19:08:27 2009
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only %s
+// RUN: clang-cc -fsyntax-only -verify %s
// PR5057
namespace std {
@@ -15,3 +15,16 @@
{
};
}
+
+
+namespace N {
+ template<typename T> void f1(T) { } // expected-note{{here}}
+
+ class X {
+ template<typename T> friend void f0(T);
+ template<typename T> friend void f1(T);
+ };
+
+ template<typename T> void f0(T) { }
+ template<typename T> void f1(T) { } // expected-error{{redefinition}}
+}
More information about the cfe-commits
mailing list