diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 30628e692c..a9b948eee5 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -132,7 +132,12 @@ public: /// *introduces* a number of other declarations into the current /// scope, and those declarations use the IDNS of their targets, /// but the actual using declarations go in this namespace. - IDNS_Using = 0x0200 + IDNS_Using = 0x0200, + + /// This declaration is a C++ operator declared in a non-class + /// context. All such operators are also in IDNS_Ordinary. + /// C++ lexical operator lookup looks for these. + IDNS_NonMemberOperator = 0x0400 }; /// ObjCDeclQualifier - Qualifier used on types in method declarations @@ -533,6 +538,14 @@ public: FOK_Declared : FOK_Undeclared); } + /// Specifies that this declaration is a C++ overloaded non-member. + void setNonMemberOperator() { + assert(getKind() == Function || getKind() == FunctionTemplate); + assert((IdentifierNamespace & IDNS_Ordinary) && + "visible non-member operators should be in ordinary namespace"); + IdentifierNamespace |= IDNS_NonMemberOperator; + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *) { return true; } static bool classofKind(Kind K) { return true; } diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 45f7e496ba..53647badff 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -197,6 +197,11 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) { for (unsigned I = 0; I != NumParams; ++I) Params.push_back(cast(Reader.GetDecl(Record[Idx++]))); FD->setParams(Params.data(), NumParams); + + // FIXME: order this properly w.r.t. friendness + // FIXME: this same thing needs to happen for function templates + if (FD->isOverloadedOperator() && !FD->getDeclContext()->isRecord()) + FD->setNonMemberOperator(); } void PCHDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h index 97bc4f25a5..0961299587 100644 --- a/lib/Sema/Lookup.h +++ b/lib/Sema/Lookup.h @@ -124,7 +124,6 @@ public: }; typedef UnresolvedSetImpl::iterator iterator; - typedef bool (*ResultFilter)(NamedDecl*, unsigned IDNS); LookupResult(Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc, Sema::LookupNameKind LookupKind, @@ -136,7 +135,6 @@ public: Name(Name), NameLoc(NameLoc), LookupKind(LookupKind), - IsAcceptableFn(0), IDNS(0), Redecl(Redecl != Sema::NotForRedeclaration), HideTags(true), @@ -156,7 +154,6 @@ public: Name(Other.Name), NameLoc(Other.NameLoc), LookupKind(Other.LookupKind), - IsAcceptableFn(Other.IsAcceptableFn), IDNS(Other.IDNS), Redecl(Other.Redecl), HideTags(Other.HideTags), @@ -242,8 +239,7 @@ public: /// \brief Tests whether the given declaration is acceptable. bool isAcceptableDecl(NamedDecl *D) const { - assert(IsAcceptableFn); - return IsAcceptableFn(D, IDNS); + return D->isInIdentifierNamespace(IDNS); } /// \brief Returns the identifier namespace mask for this lookup. @@ -575,7 +571,6 @@ private: SourceLocation NameLoc; SourceRange NameContextRange; Sema::LookupNameKind LookupKind; - ResultFilter IsAcceptableFn; // set by configure() unsigned IDNS; // set by configure() bool Redecl; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index cc57bdd5f8..7d2d866828 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3269,6 +3269,12 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, NewFD->setAccess(Access); } + if (NewFD->isOverloadedOperator() && !DC->isRecord() && + NewFD->isInIdentifierNamespace(Decl::IDNS_Ordinary)) { + NewFD->setNonMemberOperator(); + if (FunctionTemplate) FunctionTemplate->setNonMemberOperator(); + } + // If we have a function template, check the template parameter // list. This will check and merge default template arguments. if (FunctionTemplate) { diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index a7a1084d31..0609eef3c9 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -193,37 +193,6 @@ namespace { }; } -static bool IsAcceptableIDNS(NamedDecl *D, unsigned IDNS) { - return D->isInIdentifierNamespace(IDNS); -} - -static bool IsAcceptableOperatorName(NamedDecl *D, unsigned IDNS) { - return D->isInIdentifierNamespace(IDNS) && - !D->getDeclContext()->isRecord(); -} - -/// Gets the default result filter for the given lookup. -static inline -LookupResult::ResultFilter getResultFilter(Sema::LookupNameKind NameKind) { - switch (NameKind) { - case Sema::LookupOrdinaryName: - case Sema::LookupTagName: - case Sema::LookupMemberName: - case Sema::LookupRedeclarationWithLinkage: // FIXME: check linkage, scoping - case Sema::LookupUsingDeclName: - case Sema::LookupObjCProtocolName: - case Sema::LookupNestedNameSpecifierName: - case Sema::LookupNamespaceName: - return &IsAcceptableIDNS; - - case Sema::LookupOperatorName: - return &IsAcceptableOperatorName; - } - - llvm_unreachable("unkknown lookup kind"); - return 0; -} - // Retrieve the set of identifier namespaces that correspond to a // specific kind of name lookup. static inline unsigned getIDNS(Sema::LookupNameKind NameKind, @@ -232,7 +201,6 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind, unsigned IDNS = 0; switch (NameKind) { case Sema::LookupOrdinaryName: - case Sema::LookupOperatorName: case Sema::LookupRedeclarationWithLinkage: IDNS = Decl::IDNS_Ordinary; if (CPlusPlus) { @@ -241,6 +209,13 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind, } break; + case Sema::LookupOperatorName: + // Operator lookup is its own crazy thing; it is not the same + // as (e.g.) looking up an operator name for redeclaration. + assert(!Redeclaration && "cannot do redeclaration operator lookup"); + IDNS = Decl::IDNS_NonMemberOperator; + break; + case Sema::LookupTagName: if (CPlusPlus) { IDNS = Decl::IDNS_Type; @@ -287,7 +262,6 @@ void LookupResult::configure() { IDNS = getIDNS(LookupKind, SemaRef.getLangOptions().CPlusPlus, isForRedeclaration()); - IsAcceptableFn = getResultFilter(LookupKind); // If we're looking for one of the allocation or deallocation // operators, make sure that the implicitly-declared new and delete diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index fe60be062c..8924c7876a 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1140,6 +1140,12 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, DC->makeDeclVisibleInContext(ToFriendD, /*Recoverable=*/ false); } + if (Function->isOverloadedOperator() && !DC->isRecord() && + Function->isInIdentifierNamespace(Decl::IDNS_Ordinary)) { + Function->setNonMemberOperator(); + if (FunctionTemplate) FunctionTemplate->setNonMemberOperator(); + } + return Function; }