aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-08-28 07:59:38 +0000
committerJohn McCall <rjmccall@apple.com>2009-08-28 07:59:38 +0000
commit02cace78cf48cc26686bd5b07c78606abca13bcd (patch)
tree6a631652ec93156bd9ed8b2eafd457d8948a607a /lib/Sema/SemaDecl.cpp
parent550b14b410eaed037c9b791806194e6cea1ebe90 (diff)
Omnibus friend decl refactoring. Instead of cloning AST classes for friend
declarations of same, introduce a single AST class and add appropriate bits (encoded in the namespace) for whether a decl is "real" or not. Much hackery about previously-declared / not-previously-declared, but it's essentially mandated by the standard that friends alter lookup, and this is at least fairly non-intrusive. Refactor the Sema methods specific to friends for cleaner flow and less nesting. Incidentally solve a few bugs, but I remain confident that we can put them back. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80353 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp22
1 files changed, 13 insertions, 9 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 045c12aab5..15e8bc3ab8 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -735,7 +735,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
const CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
- if (OldMethod && NewMethod &&
+ if (OldMethod && NewMethod && !NewMethod->getFriendObjectKind() &&
NewMethod->getLexicalDeclContext()->isRecord()) {
// -- Member function declarations with the same name and the
// same parameter types cannot be overloaded if any of them
@@ -2411,6 +2411,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
bool isVirtualOkay = false;
FunctionDecl *NewFD;
+
if (isFriend) {
// DC is the namespace in which the function is being declared.
assert((DC->isFileContext() || PrevDecl) && "previously-undeclared "
@@ -2420,13 +2421,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// A function can be defined in a friend declaration of a
// class . . . . Such a function is implicitly inline.
isInline |= IsFunctionDefinition;
+ }
- NewFD = FriendFunctionDecl::Create(Context, DC,
- D.getIdentifierLoc(), Name, R, DInfo,
- isInline,
- D.getDeclSpec().getFriendSpecLoc());
-
- } else if (D.getKind() == Declarator::DK_Constructor) {
+ if (D.getKind() == Declarator::DK_Constructor) {
// This is a C++ constructor declaration.
assert(DC->isRecord() &&
"Constructors can only be declared in a member context");
@@ -2514,10 +2511,13 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
NewFD->setInvalidDecl();
// Set the lexical context. If the declarator has a C++
- // scope specifier, the lexical context will be different
- // from the semantic context.
+ // scope specifier, or is the object of a friend declaration, the
+ // lexical context will be different from the semantic context.
NewFD->setLexicalDeclContext(CurContext);
+ if (isFriend)
+ NewFD->setObjectOfFriendDecl(/* PreviouslyDeclared= */ PrevDecl != NULL);
+
// Match up the template parameter lists with the scope specifier, then
// determine whether we have a template or a template specialization.
FunctionTemplateDecl *FunctionTemplate = 0;
@@ -4310,6 +4310,10 @@ CreateNewDecl:
// lexical context will be different from the semantic context.
New->setLexicalDeclContext(CurContext);
+ // Mark this as a friend decl if applicable.
+ if (TUK == TUK_Friend)
+ New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ PrevDecl != NULL);
+
// Set the access specifier.
if (!Invalid && TUK != TUK_Friend)
SetMemberAccessSpecifier(New, PrevDecl, AS);