<div class="gmail_quote">Comments inline.</div><div class="gmail_quote"><br></div><div class="gmail_quote">On Fri, Jun 3, 2011 at 11:36 AM, Sean Hunt <span dir="ltr"><<a href="mailto:scshunt@csclub.uwaterloo.ca">scshunt@csclub.uwaterloo.ca</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">Author: coppro<br>
Date: Fri Jun  3 13:36:49 2011<br>
New Revision: 132572<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=132572&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=132572&view=rev</a><br>
Log:<br>
Begin implementing a cache of special member lookups. Currently only<br>
destructors are implemented but other special members are on the way,<br>
which is where the real benefits of this will be visible.<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/AST/Type.h<br>
    cfe/trunk/include/clang/Sema/Sema.h<br>
    cfe/trunk/lib/Sema/SemaLookup.cpp<br>
<br>
Modified: cfe/trunk/include/clang/AST/Type.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=132572&r1=132571&r2=132572&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=132572&r1=132571&r2=132572&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/AST/Type.h (original)<br>
+++ cfe/trunk/include/clang/AST/Type.h Fri Jun  3 13:36:49 2011<br>
@@ -538,6 +538,14 @@<br>
     return withFastQualifiers(Qualifiers::Const);<br>
   }<br>
<br>
+  /// addVolatile - add the specified type qualifier to this QualType.<br>
+  void addVolatile() {<br>
+    addFastQualifiers(Qualifiers::Volatile);<br>
+  }<br></blockquote><div><br></div><div>I didn't think we wanted to keep adding setters to the AST nodes... But maybe this one isn't so bad.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

+  QualType withVolatile() const {<br>
+    return withFastQualifiers(Qualifiers::Volatile);<br>
+  }<br>
+<br>
   void addFastQualifiers(unsigned TQs) {<br>
     assert(!(TQs & ~Qualifiers::FastMask)<br>
            && "non-fast qualifier bits set in mask!");<br>
<br>
Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=132572&r1=132571&r2=132572&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=132572&r1=132571&r2=132572&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Jun  3 13:36:49 2011<br>
@@ -198,6 +198,52 @@<br>
 typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType*, NamedDecl*>,<br>
                   SourceLocation> UnexpandedParameterPack;<br>
<br>
+// Holds some information about special member function overloads<br>
+// Defined outside Sema so it can be used as a key in a DenseMap.<br>
+struct SpecialMemberID {<br>
+  CXXRecordDecl *D;<br>
+  unsigned SM : 3; //CXXSpecialMember<br></blockquote><div><br></div><div>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"?</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
+  bool ConstArg : 1;<br>
+  bool VolatileArg : 1;<br>
+  bool RValueThis : 1;<br>
+  bool ConstThis : 1;<br>
+  bool VolatileThis : 1;<br>
+};<br>
+<br>
+} // namespace clang<br>
+<br>
+namespace llvm {<br>
+template <> struct DenseMapInfo<clang::SpecialMemberID> {<br>
+  static inline clang::SpecialMemberID getEmptyKey() {<br>
+    clang::SpecialMemberID SMI =<br>
+      {DenseMapInfo<clang::CXXRecordDecl*>::getEmptyKey(), 0,0,0,0,0,0};<br>
+    return SMI;<br>
+  }<br>
+  static inline clang::SpecialMemberID getTombstoneKey() {<br>
+    clang::SpecialMemberID SMI =<br>
+      {DenseMapInfo<clang::CXXRecordDecl*>::getTombstoneKey(), 0,0,0,0,0,0};<br>
+    return SMI;<br>
+  }<br>
+  static unsigned getHashValue (const clang::SpecialMemberID SMI) {<br>
+    // Vary higher bits of the pointer for hashing. Attempt to match the<br>
+    // bit-field representation to reduce masking if the optimizer is awake.<br>
+    // Note that the LLVM optimizer sleeps through this one.<br>
+    return (uintptr_t)SMI.D ^<br>
+      ((<a href="http://SMI.SM" target="_blank">SMI.SM</a> << 24) + (SMI.ConstArg << 27) + (SMI.VolatileArg << 28) +<br>
+       (SMI.RValueThis << 29) + (SMI.ConstThis << 30) +<br>
+       (SMI.VolatileThis << 31));<br>
+  }<br>
+  static bool isEqual(const clang::SpecialMemberID LHS,<br>
+                      const clang::SpecialMemberID RHS) {<br>
+    return LHS.D == RHS.D && <a href="http://LHS.SM" target="_blank">LHS.SM</a> == <a href="http://RHS.SM" target="_blank">RHS.SM</a> && LHS.ConstArg == RHS.ConstArg &&<br>
+           LHS.VolatileArg == RHS.VolatileArg &&<br>
+           LHS.RValueThis == RHS.RValueThis && LHS.ConstThis == RHS.ConstThis &&<br>
+           LHS.VolatileThis == RHS.VolatileThis;<br>
+  }<br>
+};<br>
+} // namespace llvm<br>
+<br>
+namespace clang {<br>
 /// Sema - This implements semantic analysis and AST building for C.<br>
 class Sema {<br>
   Sema(const Sema&);           // DO NOT IMPLEMENT<br>
@@ -600,6 +646,47 @@<br>
   /// A stack of expression evaluation contexts.<br>
   llvm::SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;<br>
<br>
+  /// SpecialMemberOverloadResult - The overloading result for a special member<br>
+  /// function.<br>
+  ///<br>
+  /// This is basically a wrapper around PointerIntPair. The lowest bit of the<br>
+  /// integer is used to determine whether we have a parameter qualification<br>
+  /// match, the second-lowest is whether we had success in resolving the<br>
+  /// overload to a unique non-deleted function.<br>
+  ///<br>
+  /// The ConstParamMatch bit represents whether, when looking up a copy<br>
+  /// constructor or assignment operator, we found a potential copy<br>
+  /// constructor/assignment operator whose first parameter is const-qualified.<br>
+  /// This is used for determining parameter types of other objects and is<br>
+  /// utterly meaningless on other types of special members.<br>
+  class SpecialMemberOverloadResult {<br>
+    llvm::PointerIntPair<CXXMethodDecl*, 2> Pair;<br>
+  public:<br>
+    SpecialMemberOverloadResult(CXXMethodDecl *MD, bool Success,<br>
+                                bool ConstParamMatch)<br>
+      : Pair(MD, Success | ConstParamMatch << 1)<br>
+    {}<br>
+    SpecialMemberOverloadResult() {}<br>
+<br>
+    CXXMethodDecl *getMethod() const { return Pair.getPointer(); }<br>
+    void setMethod(CXXMethodDecl *MD) { Pair.setPointer(MD); }<br>
+<br>
+    bool hasSuccess() const { return Pair.getInt() & 0x1; }<br>
+    void setSuccess(bool B) { Pair.setInt(B | hasConstParamMatch() << 1); }<br>
+<br>
+    bool hasConstParamMatch() const { return Pair.getInt() & 0x2; }<br>
+    void setConstParamMatch(bool B) { Pair.setInt(B << 1 | hasSuccess()); }<br>
+  };<br>
+<br>
+  /// \brief A cache of special member function overload resolution results<br>
+  /// for C++ records.<br>
+  ///<br>
+  /// In C++, special member functions of records (such as the copy constructor)<br>
+  /// are used a lot. As a result, we cache the lookups here so as to make the<br>
+  /// lookups far easier to perform.<br>
+  llvm::DenseMap<SpecialMemberID, SpecialMemberOverloadResult><br>
+    SpecialMemberCache;<br>
+<br>
   /// \brief Whether the code handled by Sema should be considered a<br>
   /// complete translation unit or not.<br>
   ///<br>
@@ -1594,6 +1681,14 @@<br>
 private:<br>
   bool CppLookupName(LookupResult &R, Scope *S);<br>
<br>
+  SpecialMemberOverloadResult LookupSpecialMember(CXXRecordDecl *D,<br>
+                                                  CXXSpecialMember SM,<br>
+                                                  bool ConstArg,<br>
+                                                  bool VolatileArg,<br>
+                                                  bool RValueThis,<br>
+                                                  bool ConstThis,<br>
+                                                  bool VolatileThis);<br>
+<br>
 public:<br>
   /// \brief Look up a name, looking for a single declaration.  Return<br>
   /// null if the results were absent, ambiguous, or overloaded.<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaLookup.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=132572&r1=132571&r2=132572&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=132572&r1=132571&r2=132572&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Fri Jun  3 13:36:49 2011<br>
@@ -14,6 +14,7 @@<br>
 #include "clang/Sema/Sema.h"<br>
 #include "clang/Sema/SemaInternal.h"<br>
 #include "clang/Sema/Lookup.h"<br>
+#include "clang/Sema/Overload.h"<br>
 #include "clang/Sema/DeclSpec.h"<br>
 #include "clang/Sema/Scope.h"<br>
 #include "clang/Sema/ScopeInfo.h"<br>
@@ -2136,6 +2137,51 @@<br>
   }<br>
 }<br>
<br>
+Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *D,<br>
+                                                            CXXSpecialMember SM,<br>
+                                                            bool ConstArg,<br>
+                                                            bool VolatileArg,<br>
+                                                            bool RValueThis,<br>
+                                                            bool ConstThis,<br>
+                                                            bool VolatileThis) {<br>
+  D = D->getDefinition();<br>
+  assert((D && !D->isBeingDefined()) &&<br>
+         "doing special member lookup into record that isn't fully complete");<br>
+  if (RValueThis || ConstThis || VolatileThis)<br>
+    assert((SM == CXXCopyAssignment || SM == CXXMoveAssignment) &&<br>
+           "constructors and destructors always have unqualified lvalue this");<br>
+  if (ConstArg || VolatileArg)<br>
+    assert((SM != CXXDefaultConstructor && SM != CXXDestructor) &&<br>
+           "parameter-less special members can't have qualified arguments");<br>
+<br>
+  // Check the cache for this member<br>
+  SpecialMemberID ID = {D, SM, ConstArg, VolatileArg, RValueThis, ConstThis,<br>
+                        VolatileThis};<br>
+  SpecialMemberOverloadResult Blank;<br>
+  llvm::DenseMap<SpecialMemberID, SpecialMemberOverloadResult>::iterator It;<br>
+  bool New;<br>
+<br>
+  llvm::tie(It, New) = SpecialMemberCache.insert(std::make_pair(ID, Blank));<br>
+  SpecialMemberOverloadResult &Result = It->second;<br>
+<br>
+  // This was already cached<br>
+  if (!New)<br>
+    return Result;<br>
+<br>
+  if (SM == CXXDestructor) {<br>
+    if (!D->hasDeclaredDestructor())<br>
+      DeclareImplicitDestructor(D);<br>
+    CXXDestructorDecl *DD = D->getDestructor();<br>
+    assert(DD && "record without a destructor");<br>
+    Result.setMethod(DD);<br>
+    Result.setSuccess(DD->isDeleted());<br>
+    Result.setConstParamMatch(false);<br>
+    return Result;<br>
+  }<br>
+<br>
+  llvm_unreachable("haven't implemented this for non-destructors yet");<br>
+}<br>
+<br>
 /// \brief Look up the constructors for the given class.<br>
 DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {<br>
   // If the copy constructor has not yet been declared, do so now.<br>
@@ -2153,17 +2199,13 @@<br>
<br>
 /// \brief Look for the destructor of the given class.<br>
 ///<br>
-/// During semantic analysis, this routine should be used in lieu of<br>
-/// CXXRecordDecl::getDestructor().<br>
+/// The destructor will be declared if necessary.<br>
 ///<br>
 /// \returns The destructor for this class.<br>
 CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) {<br>
-  // If the destructor has not yet been declared, do so now.<br>
-  if (CanDeclareSpecialMemberFunction(Context, Class) &&<br>
-      !Class->hasDeclaredDestructor())<br>
-    DeclareImplicitDestructor(Class);<br>
-<br>
-  return Class->getDestructor();<br>
+  return cast<CXXDestructorDecl>(LookupSpecialMember(Class, CXXDestructor,<br>
+                                                     false, false, false,<br>
+                                                     false, false).getMethod());<br>
 }<br>
<br>
 void ADLResult::insert(NamedDecl *New) {<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br>