diff options
author | John McCall <rjmccall@apple.com> | 2009-08-28 07:59:38 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2009-08-28 07:59:38 +0000 |
commit | 02cace78cf48cc26686bd5b07c78606abca13bcd (patch) | |
tree | 6a631652ec93156bd9ed8b2eafd457d8948a607a /lib/Sema/SemaDecl.cpp | |
parent | 550b14b410eaed037c9b791806194e6cea1ebe90 (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.cpp | 22 |
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); |