From 308742c87e2311c3f349092e5b823c3821e61b10 Mon Sep 17 00:00:00 2001 From: Sean Hunt Date: Sat, 4 Jun 2011 04:32:43 +0000 Subject: [PATCH] Reimplement r132572 on top of a FoldingSet, thus hopefully solving both the self-host failures and Chandler's concerns. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132622 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Type.h | 8 +++++ include/clang/Sema/Sema.h | 42 +++++++++++++++++++++++++++ lib/Sema/SemaLookup.cpp | 61 +++++++++++++++++++++++++++++++++++---- 3 files changed, 105 insertions(+), 6 deletions(-) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index b6c6b5616c..7dc672a41a 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -538,6 +538,14 @@ public: return withFastQualifiers(Qualifiers::Const); } + /// addVolatile - add the specified type qualifier to this QualType. + void addVolatile() { + addFastQualifiers(Qualifiers::Volatile); + } + QualType withVolatile() const { + return withFastQualifiers(Qualifiers::Volatile); + } + void addFastQualifiers(unsigned TQs) { assert(!(TQs & ~Qualifiers::FastMask) && "non-fast qualifier bits set in mask!"); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 0b32d5d905..4156d6704e 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -600,6 +600,40 @@ public: /// A stack of expression evaluation contexts. llvm::SmallVector ExprEvalContexts; + /// SpecialMemberOverloadResult - The overloading result for a special member + /// function. + /// + /// This is basically a wrapper around PointerIntPair. The lowest bit of the + /// integer is used to determine whether we have a parameter qualification + /// match, the second-lowest is whether we had success in resolving the + /// overload to a unique non-deleted function. + /// + /// The ConstParamMatch bit represents whether, when looking up a copy + /// constructor or assignment operator, we found a potential copy + /// constructor/assignment operator whose first parameter is const-qualified. + /// This is used for determining parameter types of other objects and is + /// utterly meaningless on other types of special members. + class SpecialMemberOverloadResult : public llvm::FastFoldingSetNode { + llvm::PointerIntPair Pair; + public: + SpecialMemberOverloadResult(const llvm::FoldingSetNodeID &ID) + : FastFoldingSetNode(ID) + {} + + CXXMethodDecl *getMethod() const { return Pair.getPointer(); } + void setMethod(CXXMethodDecl *MD) { Pair.setPointer(MD); } + + bool hasSuccess() const { return Pair.getInt() & 0x1; } + void setSuccess(bool B) { Pair.setInt(B | hasConstParamMatch() << 1); } + + bool hasConstParamMatch() const { return Pair.getInt() & 0x2; } + void setConstParamMatch(bool B) { Pair.setInt(B << 1 | hasSuccess()); } + }; + + /// \brief A cache of special member function overload resolution results + /// for C++ records. + llvm::FoldingSet SpecialMemberCache; + /// \brief Whether the code handled by Sema should be considered a /// complete translation unit or not. /// @@ -1594,6 +1628,14 @@ public: private: bool CppLookupName(LookupResult &R, Scope *S); + SpecialMemberOverloadResult *LookupSpecialMember(CXXRecordDecl *D, + CXXSpecialMember SM, + bool ConstArg, + bool VolatileArg, + bool RValueThis, + bool ConstThis, + bool VolatileThis); + public: /// \brief Look up a name, looking for a single declaration. Return /// null if the results were absent, ambiguous, or overloaded. diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 2bfa86cb55..d07afa1c02 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -14,6 +14,7 @@ #include "clang/Sema/Sema.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/Overload.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" @@ -2136,6 +2137,57 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, } } +Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *D, + CXXSpecialMember SM, + bool ConstArg, + bool VolatileArg, + bool RValueThis, + bool ConstThis, + bool VolatileThis) { + D = D->getDefinition(); + assert((D && !D->isBeingDefined()) && + "doing special member lookup into record that isn't fully complete"); + if (RValueThis || ConstThis || VolatileThis) + assert((SM == CXXCopyAssignment || SM == CXXMoveAssignment) && + "constructors and destructors always have unqualified lvalue this"); + if (ConstArg || VolatileArg) + assert((SM != CXXDefaultConstructor && SM != CXXDestructor) && + "parameter-less special members can't have qualified arguments"); + + llvm::FoldingSetNodeID ID; + ID.AddPointer(D); + ID.AddInteger(SM); + ID.AddInteger(ConstArg); + ID.AddInteger(VolatileArg); + ID.AddInteger(RValueThis); + ID.AddInteger(ConstThis); + ID.AddInteger(VolatileThis); + + void *InsertPoint; + SpecialMemberOverloadResult *Result = + SpecialMemberCache.FindNodeOrInsertPos(ID, InsertPoint); + + // This was already cached + if (Result) + return Result; + + Result = new SpecialMemberOverloadResult(ID); + SpecialMemberCache.InsertNode(Result, InsertPoint); + + if (SM == CXXDestructor) { + if (!D->hasDeclaredDestructor()) + DeclareImplicitDestructor(D); + CXXDestructorDecl *DD = D->getDestructor(); + assert(DD && "record without a destructor"); + Result->setMethod(DD); + Result->setSuccess(DD->isDeleted()); + Result->setConstParamMatch(false); + return Result; + } + + llvm_unreachable("haven't implemented this for non-destructors yet"); +} + /// \brief Look up the constructors for the given class. DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) { // If the copy constructor has not yet been declared, do so now. @@ -2158,12 +2210,9 @@ DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) { /// /// \returns The destructor for this class. CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) { - // If the destructor has not yet been declared, do so now. - if (CanDeclareSpecialMemberFunction(Context, Class) && - !Class->hasDeclaredDestructor()) - DeclareImplicitDestructor(Class); - - return Class->getDestructor(); + return cast(LookupSpecialMember(Class, CXXDestructor, + false, false, false, + false, false)->getMethod()); } void ADLResult::insert(NamedDecl *New) { -- 2.40.0