[cfe-commits] r132572 - in /cfe/trunk: include/clang/AST/Type.h include/clang/Sema/Sema.h lib/Sema/SemaLookup.cpp

Chandler Carruth chandlerc at google.com
Fri Jun 3 13:16:50 PDT 2011


Comments inline.

On Fri, Jun 3, 2011 at 11:36 AM, Sean Hunt <scshunt at csclub.uwaterloo.ca>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
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20110603/7f5a646c/attachment.html>


More information about the cfe-commits mailing list