<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>