Comments inline. On Fri, Jun 3, 2011 at 11:36 AM, Sean Hunt <[email protected]>wrote:
> Author: coppro > Date: Fri Jun 3 13:36:49 2011 > New Revision: 132572 > > URL: http://llvm.org/viewvc/llvm-project?rev=132572&view=rev > Log: > Begin implementing a cache of special member lookups. Currently only > destructors are implemented but other special members are on the way, > which is where the real benefits of this will be visible. > > Modified: > cfe/trunk/include/clang/AST/Type.h > cfe/trunk/include/clang/Sema/Sema.h > cfe/trunk/lib/Sema/SemaLookup.cpp > > Modified: cfe/trunk/include/clang/AST/Type.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=132572&r1=132571&r2=132572&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/AST/Type.h (original) > +++ cfe/trunk/include/clang/AST/Type.h Fri Jun 3 13:36:49 2011 > @@ -538,6 +538,14 @@ > return withFastQualifiers(Qualifiers::Const); > } > > + /// addVolatile - add the specified type qualifier to this QualType. > + void addVolatile() { > + addFastQualifiers(Qualifiers::Volatile); > + } > I didn't think we wanted to keep adding setters to the AST nodes... But maybe this one isn't so bad. + QualType withVolatile() const { > + return withFastQualifiers(Qualifiers::Volatile); > + } > + > void addFastQualifiers(unsigned TQs) { > assert(!(TQs & ~Qualifiers::FastMask) > && "non-fast qualifier bits set in mask!"); > > Modified: cfe/trunk/include/clang/Sema/Sema.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=132572&r1=132571&r2=132572&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Sema/Sema.h (original) > +++ cfe/trunk/include/clang/Sema/Sema.h Fri Jun 3 13:36:49 2011 > @@ -198,6 +198,52 @@ > typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType*, > NamedDecl*>, > SourceLocation> UnexpandedParameterPack; > > +// Holds some information about special member function overloads > +// Defined outside Sema so it can be used as a key in a DenseMap. > +struct SpecialMemberID { > + CXXRecordDecl *D; > + unsigned SM : 3; //CXXSpecialMember > SM seems like a really unfortunate name here, and the comment doesn't help much. SM usually refers to the Source Manager. Is this maybe the "MemberKind"? > + bool ConstArg : 1; > + bool VolatileArg : 1; > + bool RValueThis : 1; > + bool ConstThis : 1; > + bool VolatileThis : 1; > +}; > + > +} // namespace clang > + > +namespace llvm { > +template <> struct DenseMapInfo<clang::SpecialMemberID> { > + static inline clang::SpecialMemberID getEmptyKey() { > + clang::SpecialMemberID SMI = > + {DenseMapInfo<clang::CXXRecordDecl*>::getEmptyKey(), 0,0,0,0,0,0}; > + return SMI; > + } > + static inline clang::SpecialMemberID getTombstoneKey() { > + clang::SpecialMemberID SMI = > + {DenseMapInfo<clang::CXXRecordDecl*>::getTombstoneKey(), > 0,0,0,0,0,0}; > + return SMI; > + } > + static unsigned getHashValue (const clang::SpecialMemberID SMI) { > + // Vary higher bits of the pointer for hashing. Attempt to match the > + // bit-field representation to reduce masking if the optimizer is > awake. > + // Note that the LLVM optimizer sleeps through this one. > + return (uintptr_t)SMI.D ^ > + ((SMI.SM << 24) + (SMI.ConstArg << 27) + (SMI.VolatileArg << 28) + > + (SMI.RValueThis << 29) + (SMI.ConstThis << 30) + > + (SMI.VolatileThis << 31)); > + } > + static bool isEqual(const clang::SpecialMemberID LHS, > + const clang::SpecialMemberID RHS) { > + return LHS.D == RHS.D && LHS.SM == RHS.SM && LHS.ConstArg == > RHS.ConstArg && > + LHS.VolatileArg == RHS.VolatileArg && > + LHS.RValueThis == RHS.RValueThis && LHS.ConstThis == > RHS.ConstThis && > + LHS.VolatileThis == RHS.VolatileThis; > + } > +}; > +} // namespace llvm > + > +namespace clang { > /// Sema - This implements semantic analysis and AST building for C. > class Sema { > Sema(const Sema&); // DO NOT IMPLEMENT > @@ -600,6 +646,47 @@ > /// A stack of expression evaluation contexts. > llvm::SmallVector<ExpressionEvaluationContextRecord, 8> 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 { > + llvm::PointerIntPair<CXXMethodDecl*, 2> Pair; > + public: > + SpecialMemberOverloadResult(CXXMethodDecl *MD, bool Success, > + bool ConstParamMatch) > + : Pair(MD, Success | ConstParamMatch << 1) > + {} > + SpecialMemberOverloadResult() {} > + > + 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. > + /// > + /// In C++, special member functions of records (such as the copy > constructor) > + /// are used a lot. As a result, we cache the lookups here so as to make > the > + /// lookups far easier to perform. > + llvm::DenseMap<SpecialMemberID, SpecialMemberOverloadResult> > + SpecialMemberCache; > + > /// \brief Whether the code handled by Sema should be considered a > /// complete translation unit or not. > /// > @@ -1594,6 +1681,14 @@ > 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. > > Modified: cfe/trunk/lib/Sema/SemaLookup.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=132572&r1=132571&r2=132572&view=diff > > ============================================================================== > --- cfe/trunk/lib/Sema/SemaLookup.cpp (original) > +++ cfe/trunk/lib/Sema/SemaLookup.cpp Fri Jun 3 13:36:49 2011 > @@ -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,51 @@ > } > } > > +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"); > + > + // Check the cache for this member > + SpecialMemberID ID = {D, SM, ConstArg, VolatileArg, RValueThis, > ConstThis, > + VolatileThis}; > + SpecialMemberOverloadResult Blank; > + llvm::DenseMap<SpecialMemberID, SpecialMemberOverloadResult>::iterator > It; > + bool New; > + > + llvm::tie(It, New) = SpecialMemberCache.insert(std::make_pair(ID, > Blank)); > + SpecialMemberOverloadResult &Result = It->second; > + > + // This was already cached > + if (!New) > + return Result; > + > + 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. > @@ -2153,17 +2199,13 @@ > > /// \brief Look for the destructor of the given class. > /// > -/// During semantic analysis, this routine should be used in lieu of > -/// CXXRecordDecl::getDestructor(). > +/// The destructor will be declared if necessary. > /// > /// \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<CXXDestructorDecl>(LookupSpecialMember(Class, CXXDestructor, > + false, false, false, > + false, > false).getMethod()); > } > > void ADLResult::insert(NamedDecl *New) { > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
