<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Sean,<div>This looks to be breaking one of our internal buildbots (x86_64 Snow Leopard 10.6 Release Build) with the following errors:</div><div><span class="Apple-style-span" style="font-family: 'Courier New', courier, monotype; white-space: pre; "><br></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', courier, monotype; white-space: pre; ">llvm[4]: Compiling ScratchBuffer.cpp for Release build</span></div><div><span class="Apple-style-span" style="font-family: Times; "><pre style="font-family: 'Courier New', courier, monotype; "><span class="stdout" style="font-family: 'Courier New', courier, monotype; color: black; ">0  clang             0x0000000100e98942 PrintStackTrace(void*) + 34
1  clang             0x0000000100e98e49 SignalHandler(int) + 697
2  libSystem.B.dylib 0x00007fff806fd66a _sigtramp + 26
3  libSystem.B.dylib 0x00000001021be8d0 _sigtramp + 2175537792
4  clang             0x00000001006973c2 clang::FunctionDecl::getMinRequiredArguments() const + 18
5  clang             0x00000001003db57a clang::Sema::DeduceTemplateArguments(clang::FunctionTemplateDecl*, clang::TemplateArgumentListInfo*, clang::Expr**, unsigned int, clang::FunctionDecl*&, clang::sema::TemplateDeductionInfo&) + 74
6  clang             0x0000000100380e7d clang::Sema::AddTemplateOverloadCandidate(clang::FunctionTemplateDecl*, clang::DeclAccessPair, clang::TemplateArgumentListInfo*, clang::Expr**, unsigned int, clang::OverloadCandidateSet&, bool) + 253
7  clang             0x000000010036841c clang::Sema::LookupSpecialMember(clang::CXXRecordDecl*, clang::Sema::CXXSpecialMember, bool, bool, bool, bool, bool) + 2028
8  clang             0x00000001003686d1 clang::Sema::LookupCopyingAssignment(clang::CXXRecordDecl*, unsigned int, bool, unsigned int, bool*) + 65
9  clang             0x00000001002e69a2 clang::Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(clang::CXXRecordDecl*) + 690
10 clang             0x00000001002df233 clang::Sema::DeclareImplicitCopyAssignment(clang::CXXRecordDecl*) + 211
11 clang             0x0000000100364917 DeclareImplicitMemberFunctionsWithName(clang::Sema&, clang::DeclarationName, clang::DeclContext const*) + 375
12 clang             0x0000000100364260 clang::Sema::CppLookupName(clang::LookupResult&, clang::Scope*) + 1248
13 clang             0x0000000100365daa clang::Sema::LookupName(clang::LookupResult&, clang::Scope*, bool) + 922
14 clang             0x0000000100367875 clang::Sema::LookupOverloadedOperatorName(clang::OverloadedOperatorKind, clang::Scope*, clang::QualType, clang::QualType, clang::UnresolvedSetImpl&) + 245
15 clang             0x0000000100320313 clang::Sema::BuildBinOp(clang::Scope*, clang::SourceLocation, clang::BinaryOperatorKind, clang::Expr*, clang::Expr*) + 371
16 clang             0x0000000100301fc3 clang::Sema::ActOnBinOp(clang::Scope*, clang::SourceLocation, clang::tok::TokenKind, clang::Expr*, clang::Expr*) + 2019
17 clang             0x0000000100200423 clang::Parser::ParseRHSOfBinaryExpression(clang::ActionResult<clang::Expr*, true>, clang::prec::Level) + 1459
18 clang             0x00000001001ffe65 clang::Parser::ParseAssignmentExpression() + 165
19 clang             0x00000001001ffda4 clang::Parser::ParseExpression() + 20
20 clang             0x0000000100217dde clang::Parser::ParseExprStatement(clang::ParsedAttributes&) + 62
21 clang             0x0000000100217860 clang::Parser::ParseStatementOrDeclaration(clang::ASTOwningVector<clang::Stmt*, 32u>&, bool) + 1552
22 clang             0x000000010021b58f clang::Parser::ParseCompoundStatementBody(bool) + 351
23 clang             0x000000010021c4a6 clang::Parser::ParseFunctionStatementBody(clang::Decl*, clang::Parser::ParseScope&) + 166
24 clang             0x00000001001e994c clang::Parser::ParseLexedMethodDef(clang::Parser::LexedMeth</span><span class="stdout" style="font-family: 'Courier New', courier, monotype; color: black; ">od&) + 460
25 clang             0x00000001001e93fd clang::Parser::ParseLexedMethodDefs(clang::Parser::ParsingClass&) + 141
26 clang             0x00000001001fbf75 clang::Parser::ParseCXXMemberSpecification(clang::SourceLocation, unsigned int, clang::Decl*) + 1909
27 clang             0x00000001001fb431 clang::Parser::ParseClassSpecifier(clang::tok::TokenKind, clang::SourceLocation, clang::DeclSpec&, clang::Parser::ParsedTemplateInfo const&, clang::AccessSpecifier, bool) + 4497
28 clang             0x00000001001edce5 clang::Parser::ParseDeclarationSpecifiers(clang::DeclSpec&, clang::Parser::ParsedTemplateInfo const&, clang::AccessSpecifier, clang::Parser::DeclSpecContext) + 2053
29 clang             0x000000010022551b clang::Parser::ParseDeclarationOrFunctionDefinition(clang::Parser::ParsingDeclSpec&, clang::AccessSpecifier) + 75
30 clang             0x0000000100225914 clang::Parser::ParseDeclarationOrFunctionDefinition(clang::ParsedAttributes&, clang::AccessSpecifier) + 388
31 clang             0x0000000100224faf clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange&, clang::Parser::ParsingDeclSpec*) + 2511
32 clang             0x00000001001f863e clang::Parser::ParseInnerNamespace(std::vector<clang::SourceLocation, std::allocator<clang::SourceLocation> >&, std::vector<clang::IdentifierInfo*, std::allocator<clang::IdentifierInfo*> >&, std::vector<clang::SourceLocation, std::allocator<clang::SourceLocation> >&, unsigned int, clang::SourceLocation&, clang::SourceLocation&, clang::ParsedAttributes&, clang::SourceLocation&) + 206
33 clang             0x00000001001f832b clang::Parser::ParseNamespace(unsigned int, clang::SourceLocation&, clang::SourceLocation) + 3195
34 clang             0x00000001001ed086 clang::Parser::ParseDeclaration(clang::ASTOwningVector<clang::Stmt*, 32u>&, unsigned int, clang::SourceLocation&, clang::Parser::ParsedAttributesWithRange&) + 646
35 clang             0x0000000100224b55 clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange&, clang::Parser::ParsingDeclSpec*) + 1397
36 clang             0x00000001002245b1 clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&) + 241
37 clang             0x00000001001e837d clang::ParseAST(clang::Sema&, bool) + 589
38 clang             0x00000001001cac1e clang::CodeGenAction::ExecuteAction() + 686
39 clang             0x000000010002c0ba clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 858
40 clang             0x000000010000a0b8 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) + 2648
41 clang             0x0000000100002abb cc1_main(char const**, char const**, char const*, void*) + 5755
42 clang             0x00000001000066c7 main + 679
43 clang             0x0000000100001434 start + 52
44 clang             0x0000000000000054 start + 4294962260</span></pre></span></div><div>Similar errors for:</div><div><br></div><div><span class="Apple-style-span" style="font-family: 'Courier New', courier, monotype; white-space: pre; ">llvm[4]: Compiling ParsePragma.cpp for Release build</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', courier, monotype; white-space: pre; ">llvm[4]: Compiling SemaAttr.cpp for Release build</span></div><div><br></div><div>Please try and resolve these issues (by reverting or otherwise) in a timely manner. </div><div><br></div><div> Regards,</div><div>  Chad</div><div><br></div><div><br><div><div>On Jun 21, 2011, at 4:42 PM, Sean Hunt wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>Author: coppro<br>Date: Tue Jun 21 18:42:56 2011<br>New Revision: 133581<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=133581&view=rev">http://llvm.org/viewvc/llvm-project?rev=133581&view=rev</a><br>Log:<br>Attempt to reapply this patch for caching copy assignment operator<br>lookup. Previously, it was breaking self-host, but it's been a week and<br>a half and I can't reproduce, so I need to see if it's still failing.<br><br>Modified:<br>    cfe/trunk/include/clang/Sema/Sema.h<br>    cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>    cfe/trunk/lib/Sema/SemaLookup.cpp<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=133581&r1=133580&r2=133581&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=133581&r1=133580&r2=133581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/include/clang/Sema/Sema.h (original)<br>+++ cfe/trunk/include/clang/Sema/Sema.h Tue Jun 21 18:42:56 2011<br>@@ -1683,9 +1683,12 @@<br><br>   DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class);<br>   CXXConstructorDecl *LookupDefaultConstructor(CXXRecordDecl *Class);<br>-  CXXConstructorDecl *LookupCopyConstructor(CXXRecordDecl *Class,<br>-                                            unsigned Quals,<br>-                                            bool *ConstParam = 0);<br>+  CXXConstructorDecl *LookupCopyingConstructor(CXXRecordDecl *Class,<br>+                                               unsigned Quals,<br>+                                               bool *ConstParam = 0);<br>+  CXXMethodDecl *LookupCopyingAssignment(CXXRecordDecl *Class, unsigned Quals,<br>+                                         bool RValueThis, unsigned ThisQuals,<br>+                                         bool *ConstParam = 0);<br>   CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);<br><br>   void ArgumentDependentLookup(DeclarationName Name, bool Operator,<br><br>Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=133581&r1=133580&r2=133581&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=133581&r1=133580&r2=133581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Jun 21 18:42:56 2011<br>@@ -3637,7 +3637,7 @@<br>     //    resolution, as applied to B's [copy] constructor, results in an<br>     //    ambiguity or a function that is deleted or inaccessible from the<br>     //    defaulted constructor<br>-    CXXConstructorDecl *BaseCtor = LookupCopyConstructor(BaseDecl, ArgQuals);<br>+    CXXConstructorDecl *BaseCtor = LookupCopyingConstructor(BaseDecl, ArgQuals);<br>     if (!BaseCtor || BaseCtor->isDeleted())<br>       return true;<br>     if (CheckConstructorAccess(Loc, BaseCtor, BaseCtor->getAccess(), PDiag()) !=<br>@@ -3665,7 +3665,7 @@<br>     //    resolution, as applied to B's [copy] constructor, results in an<br>     //    ambiguity or a function that is deleted or inaccessible from the<br>     //    defaulted constructor<br>-    CXXConstructorDecl *BaseCtor = LookupCopyConstructor(BaseDecl, ArgQuals);<br>+    CXXConstructorDecl *BaseCtor = LookupCopyingConstructor(BaseDecl, ArgQuals);<br>     if (!BaseCtor || BaseCtor->isDeleted())<br>       return true;<br>     if (CheckConstructorAccess(Loc, BaseCtor, BaseCtor->getAccess(), PDiag()) !=<br>@@ -3727,8 +3727,8 @@<br>     //    cannot be [copied] because overload resolution, as applied to B's<br>     //    [copy] constructor, results in an ambiguity or a function that is<br>     //    deleted or inaccessible from the defaulted constructor<br>-      CXXConstructorDecl *FieldCtor = LookupCopyConstructor(FieldRecord,<br>-                                                            ArgQuals);<br>+      CXXConstructorDecl *FieldCtor = LookupCopyingConstructor(FieldRecord,<br>+                                                               ArgQuals);<br>       if (!FieldCtor || FieldCtor->isDeleted())<br>         return true;<br>       if (CheckConstructorAccess(Loc, FieldCtor, FieldCtor->getAccess(),<br>@@ -3753,19 +3753,15 @@<br><br>   bool Union = RD->isUnion();<br><br>-  bool ConstArg =<br>-    MD->getParamDecl(0)->getType()->getPointeeType().isConstQualified();<br>+  unsigned ArgQuals =<br>+    MD->getParamDecl(0)->getType()->getPointeeType().isConstQualified() ?<br>+      Qualifiers::Const : 0;<br><br>   // We do this because we should never actually use an anonymous<br>   // union's constructor.<br>   if (Union && RD->isAnonymousStructOrUnion())<br>     return false;<br><br>-  DeclarationName OperatorName =<br>-    Context.DeclarationNames.getCXXOperatorName(OO_Equal);<br>-  LookupResult R(*this, OperatorName, Loc, LookupOrdinaryName);<br>-  R.suppressDiagnostics();<br>-<br>   // FIXME: We should put some diagnostic logic right into this function.<br><br>   // C++0x [class.copy]/11<br>@@ -3787,37 +3783,11 @@<br>     //    resolution, as applied to B's [copy] assignment operator, results in<br>     //    an ambiguity or a function that is deleted or inaccessible from the<br>     //    assignment operator<br>-<br>-    LookupQualifiedName(R, BaseDecl, false);<br>-<br>-    // Filter out any result that isn't a copy-assignment operator.<br>-    LookupResult::Filter F = R.makeFilter();<br>-    while (F.hasNext()) {<br>-      NamedDecl *D = F.next();<br>-      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))<br>-        if (Method->isCopyAssignmentOperator())<br>-          continue;<br>-      <br>-      F.erase();<br>-    }<br>-    F.done();<br>- <br>-    // Build a fake argument expression<br>-    QualType ArgType = BaseType;<br>-    QualType ThisType = BaseType;<br>-    if (ConstArg)<br>-      ArgType.addConst();<br>-    Expr *Args[] = { new (Context) OpaqueValueExpr(Loc, ThisType, VK_LValue)<br>-                   , new (Context) OpaqueValueExpr(Loc, ArgType, VK_LValue)<br>-                   };<br>-<br>-    OverloadCandidateSet OCS((Loc));<br>-    OverloadCandidateSet::iterator Best;<br>-<br>-    AddFunctionCandidates(R.asUnresolvedSet(), Args, 2, OCS);<br>-<br>-    if (OCS.BestViableFunction(*this, Loc, Best, false) !=<br>-        OR_Success)<br>+    CXXMethodDecl *CopyOper = LookupCopyingAssignment(BaseDecl, ArgQuals, false,<br>+                                                      0);<br>+    if (!CopyOper || CopyOper->isDeleted())<br>+      return true;<br>+    if (CheckDirectMemberAccess(Loc, CopyOper, PDiag()) != AR_accessible)<br>       return true;<br>   }<br><br>@@ -3832,37 +3802,11 @@<br>     //    resolution, as applied to B's [copy] assignment operator, results in<br>     //    an ambiguity or a function that is deleted or inaccessible from the<br>     //    assignment operator<br>-<br>-    LookupQualifiedName(R, BaseDecl, false);<br>-<br>-    // Filter out any result that isn't a copy-assignment operator.<br>-    LookupResult::Filter F = R.makeFilter();<br>-    while (F.hasNext()) {<br>-      NamedDecl *D = F.next();<br>-      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))<br>-        if (Method->isCopyAssignmentOperator())<br>-          continue;<br>-      <br>-      F.erase();<br>-    }<br>-    F.done();<br>- <br>-    // Build a fake argument expression<br>-    QualType ArgType = BaseType;<br>-    QualType ThisType = BaseType;<br>-    if (ConstArg)<br>-      ArgType.addConst();<br>-    Expr *Args[] = { new (Context) OpaqueValueExpr(Loc, ThisType, VK_LValue)<br>-                   , new (Context) OpaqueValueExpr(Loc, ArgType, VK_LValue)<br>-                   };<br>-<br>-    OverloadCandidateSet OCS((Loc));<br>-    OverloadCandidateSet::iterator Best;<br>-<br>-    AddFunctionCandidates(R.asUnresolvedSet(), Args, 2, OCS);<br>-<br>-    if (OCS.BestViableFunction(*this, Loc, Best, false) !=<br>-        OR_Success)<br>+    CXXMethodDecl *CopyOper = LookupCopyingAssignment(BaseDecl, ArgQuals, false,<br>+                                                      0);<br>+    if (!CopyOper || CopyOper->isDeleted())<br>+      return true;<br>+    if (CheckDirectMemberAccess(Loc, CopyOper, PDiag()) != AR_accessible)<br>       return true;<br>   }<br><br>@@ -3909,37 +3853,12 @@<br>           return true;<br>       }<br><br>-      LookupQualifiedName(R, FieldRecord, false);<br>-<br>-      // Filter out any result that isn't a copy-assignment operator.<br>-      LookupResult::Filter F = R.makeFilter();<br>-      while (F.hasNext()) {<br>-        NamedDecl *D = F.next();<br>-        if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))<br>-          if (Method->isCopyAssignmentOperator())<br>-            continue;<br>-        <br>-        F.erase();<br>-      }<br>-      F.done();<br>-   <br>-      // Build a fake argument expression<br>-      QualType ArgType = FieldType;<br>-      QualType ThisType = FieldType;<br>-      if (ConstArg)<br>-        ArgType.addConst();<br>-      Expr *Args[] = { new (Context) OpaqueValueExpr(Loc, ThisType, VK_LValue)<br>-                     , new (Context) OpaqueValueExpr(Loc, ArgType, VK_LValue)<br>-                     };<br>-<br>-      OverloadCandidateSet OCS((Loc));<br>-      OverloadCandidateSet::iterator Best;<br>-<br>-      AddFunctionCandidates(R.asUnresolvedSet(), Args, 2, OCS);<br>-<br>-      if (OCS.BestViableFunction(*this, Loc, Best, false) !=<br>-          OR_Success)<br>-        return true;<br>+      CXXMethodDecl *CopyOper = LookupCopyingAssignment(FieldRecord, ArgQuals,<br>+                                                        false, 0);<br>+      if (!CopyOper || CopyOper->isDeleted())<br>+        return false;<br>+      if (CheckDirectMemberAccess(Loc, CopyOper, PDiag()) != AR_accessible)<br>+        return false;<br>     }<br>   }<br><br>@@ -6688,58 +6607,6 @@<br>                         Loc, Copy.take());<br> }<br><br>-/// \brief Determine whether the given class has a copy assignment operator <br>-/// that accepts a const-qualified argument.<br>-static bool hasConstCopyAssignment(Sema &S, const CXXRecordDecl *CClass) {<br>-  CXXRecordDecl *Class = const_cast<CXXRecordDecl *>(CClass);<br>-  <br>-  if (!Class->hasDeclaredCopyAssignment())<br>-    S.DeclareImplicitCopyAssignment(Class);<br>-  <br>-  QualType ClassType = S.Context.getCanonicalType(S.Context.getTypeDeclType(Class));<br>-  DeclarationName OpName <br>-    = S.Context.DeclarationNames.getCXXOperatorName(OO_Equal);<br>-    <br>-  DeclContext::lookup_const_iterator Op, OpEnd;<br>-  for (llvm::tie(Op, OpEnd) = Class->lookup(OpName); Op != OpEnd; ++Op) {<br>-    // C++ [class.copy]p9:<br>-    //   A user-declared copy assignment operator is a non-static non-template<br>-    //   member function of class X with exactly one parameter of type X, X&,<br>-    //   const X&, volatile X& or const volatile X&.<br>-    const CXXMethodDecl* Method = dyn_cast<CXXMethodDecl>(*Op);<br>-    if (!Method)<br>-      continue;<br>-    <br>-    if (Method->isStatic())<br>-      continue;<br>-    if (Method->getPrimaryTemplate())<br>-      continue;<br>-    const FunctionProtoType *FnType =<br>-    Method->getType()->getAs<FunctionProtoType>();<br>-    assert(FnType && "Overloaded operator has no prototype.");<br>-    // Don't assert on this; an invalid decl might have been left in the AST.<br>-    if (FnType->getNumArgs() != 1 || FnType->isVariadic())<br>-      continue;<br>-    bool AcceptsConst = true;<br>-    QualType ArgType = FnType->getArgType(0);<br>-    if (const LValueReferenceType *Ref = ArgType->getAs<LValueReferenceType>()){<br>-      ArgType = Ref->getPointeeType();<br>-      // Is it a non-const lvalue reference?<br>-      if (!ArgType.isConstQualified())<br>-        AcceptsConst = false;<br>-    }<br>-    if (!S.Context.hasSameUnqualifiedType(ArgType, ClassType))<br>-      continue;<br>-    <br>-    // We have a single argument of type cv X or cv X&, i.e. we've found the<br>-    // copy assignment operator. Return whether it accepts const arguments.<br>-    return AcceptsConst;<br>-  }<br>-  assert(Class->isInvalidDecl() &&<br>-         "No copy assignment operator declared in valid code.");<br>-  return false;  <br>-}<br>-<br> std::pair<Sema::ImplicitExceptionSpecification, bool><br> Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(<br>                                                    CXXRecordDecl *ClassDecl) {<br>@@ -6760,11 +6627,28 @@<br>   for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),<br>                                        BaseEnd = ClassDecl->bases_end();<br>        HasConstCopyAssignment && Base != BaseEnd; ++Base) {<br>+    // We'll handle this below<br>+    if (LangOpts.CPlusPlus0x && Base->isVirtual())<br>+      continue;<br>+<br>     assert(!Base->getType()->isDependentType() &&<br>            "Cannot generate implicit members for class with dependent bases.");<br>-    const CXXRecordDecl *BaseClassDecl<br>-      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());<br>-    HasConstCopyAssignment = hasConstCopyAssignment(*this, BaseClassDecl);<br>+    CXXRecordDecl *BaseClassDecl = Base->getType()->getAsCXXRecordDecl();<br>+    LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const, false, 0,<br>+                            &HasConstCopyAssignment);<br>+  }<br>+<br>+  // In C++0x, the above citation has "or virtual added"<br>+  if (LangOpts.CPlusPlus0x) {<br>+    for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),<br>+                                         BaseEnd = ClassDecl->vbases_end();<br>+         HasConstCopyAssignment && Base != BaseEnd; ++Base) {<br>+      assert(!Base->getType()->isDependentType() &&<br>+             "Cannot generate implicit members for class with dependent bases.");<br>+      CXXRecordDecl *BaseClassDecl = Base->getType()->getAsCXXRecordDecl();<br>+      LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const, false, 0,<br>+                              &HasConstCopyAssignment);<br>+    }<br>   }<br><br>   //       -- for all the nonstatic data members of X that are of a class<br>@@ -6776,10 +6660,9 @@<br>        HasConstCopyAssignment && Field != FieldEnd;<br>        ++Field) {<br>     QualType FieldType = Context.getBaseElementType((*Field)->getType());<br>-    if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {<br>-      const CXXRecordDecl *FieldClassDecl<br>-        = cast<CXXRecordDecl>(FieldClassType->getDecl());<br>-      HasConstCopyAssignment = hasConstCopyAssignment(*this, FieldClassDecl);<br>+    if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {<br>+      LookupCopyingAssignment(FieldClassDecl, Qualifiers::Const, false, 0,<br>+                              &HasConstCopyAssignment);<br>     }<br>   }<br><br>@@ -6791,35 +6674,47 @@<br>   // C++ [except.spec]p14:<br>   //   An implicitly declared special member function (Clause 12) shall have an <br>   //   exception-specification. [...]<br>+<br>+  // It is unspecified whether or not an implicit copy assignment operator<br>+  // attempts to deduplicate calls to assignment operators of virtual bases are<br>+  // made. As such, this exception specification is effectively unspecified.<br>+  // Based on a similar decision made for constness in C++0x, we're erring on<br>+  // the side of assuming such calls to be made regardless of whether they<br>+  // actually happen.<br>   ImplicitExceptionSpecification ExceptSpec(Context);<br>+  unsigned ArgQuals = HasConstCopyAssignment ? Qualifiers::Const : 0;<br>   for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),<br>                                        BaseEnd = ClassDecl->bases_end();<br>        Base != BaseEnd; ++Base) {<br>+    if (Base->isVirtual())<br>+      continue;<br>+<br>     CXXRecordDecl *BaseClassDecl<br>       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());<br>-    <br>-    if (!BaseClassDecl->hasDeclaredCopyAssignment())<br>-      DeclareImplicitCopyAssignment(BaseClassDecl);<br>+    if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl,<br>+                                                            ArgQuals, false, 0))<br>+      ExceptSpec.CalledDecl(CopyAssign);<br>+  }<br><br>-    if (CXXMethodDecl *CopyAssign<br>-           = BaseClassDecl->getCopyAssignmentOperator(HasConstCopyAssignment))<br>+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),<br>+                                       BaseEnd = ClassDecl->vbases_end();<br>+       Base != BaseEnd; ++Base) {<br>+    CXXRecordDecl *BaseClassDecl<br>+      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());<br>+    if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl,<br>+                                                            ArgQuals, false, 0))<br>       ExceptSpec.CalledDecl(CopyAssign);<br>   }<br>+<br>   for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),<br>                                   FieldEnd = ClassDecl->field_end();<br>        Field != FieldEnd;<br>        ++Field) {<br>     QualType FieldType = Context.getBaseElementType((*Field)->getType());<br>-    if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {<br>-      CXXRecordDecl *FieldClassDecl<br>-        = cast<CXXRecordDecl>(FieldClassType->getDecl());<br>-      <br>-      if (!FieldClassDecl->hasDeclaredCopyAssignment())<br>-        DeclareImplicitCopyAssignment(FieldClassDecl);<br>-<br>-      if (CXXMethodDecl *CopyAssign<br>-            = FieldClassDecl->getCopyAssignmentOperator(HasConstCopyAssignment))<br>-        ExceptSpec.CalledDecl(CopyAssign);      <br>+    if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {<br>+      if (CXXMethodDecl *CopyAssign =<br>+          LookupCopyingAssignment(FieldClassDecl, ArgQuals, false, 0))<br>+        ExceptSpec.CalledDecl(CopyAssign);<br>     }      <br>   }<br><br>@@ -7206,8 +7101,8 @@<br><br>     CXXRecordDecl *BaseClassDecl<br>       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());<br>-    LookupCopyConstructor(BaseClassDecl, Qualifiers::Const,<br>-                          &HasConstCopyConstructor);<br>+    LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const,<br>+                             &HasConstCopyConstructor);<br>   }<br><br>   for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),<br>@@ -7216,8 +7111,8 @@<br>        ++Base) {<br>     CXXRecordDecl *BaseClassDecl<br>       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());<br>-    LookupCopyConstructor(BaseClassDecl, Qualifiers::Const,<br>-                          &HasConstCopyConstructor);<br>+    LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const,<br>+                             &HasConstCopyConstructor);<br>   }<br><br>   //     -- for all the nonstatic data members of X that are of a<br>@@ -7230,8 +7125,8 @@<br>        ++Field) {<br>     QualType FieldType = Context.getBaseElementType((*Field)->getType());<br>     if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {<br>-      LookupCopyConstructor(FieldClassDecl, Qualifiers::Const,<br>-                            &HasConstCopyConstructor);<br>+      LookupCopyingConstructor(FieldClassDecl, Qualifiers::Const,<br>+                               &HasConstCopyConstructor);<br>     }<br>   }<br>   //   Otherwise, the implicitly declared copy constructor will have<br>@@ -7255,7 +7150,7 @@<br>     CXXRecordDecl *BaseClassDecl<br>       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());<br>     if (CXXConstructorDecl *CopyConstructor =<br>-          LookupCopyConstructor(BaseClassDecl, Quals))<br>+          LookupCopyingConstructor(BaseClassDecl, Quals))<br>       ExceptSpec.CalledDecl(CopyConstructor);<br>   }<br>   for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),<br>@@ -7265,7 +7160,7 @@<br>     CXXRecordDecl *BaseClassDecl<br>       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());<br>     if (CXXConstructorDecl *CopyConstructor =<br>-          LookupCopyConstructor(BaseClassDecl, Quals))<br>+          LookupCopyingConstructor(BaseClassDecl, Quals))<br>       ExceptSpec.CalledDecl(CopyConstructor);<br>   }<br>   for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),<br>@@ -7275,7 +7170,7 @@<br>     QualType FieldType = Context.getBaseElementType((*Field)->getType());<br>     if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {<br>       if (CXXConstructorDecl *CopyConstructor =<br>-        LookupCopyConstructor(FieldClassDecl, Quals))<br>+        LookupCopyingConstructor(FieldClassDecl, Quals))<br>       ExceptSpec.CalledDecl(CopyConstructor);<br>     }<br>   }<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=133581&r1=133580&r2=133581&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=133581&r1=133580&r2=133581&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaLookup.cpp Tue Jun 21 18:42:56 2011<br>@@ -2269,7 +2269,8 @@<br>           (SM == CXXCopyConstructor &&<br>             cast<CXXConstructorDecl>(M)->isCopyConstructor())) {<br>         QualType ArgType = M->getType()->getAs<FunctionProtoType>()->getArgType(0);<br>-        if (ArgType->getPointeeType().isConstQualified())<br>+        if (!ArgType->isReferenceType() ||<br>+            ArgType->getPointeeType().isConstQualified())<br>           Result->setConstParamMatch(true);<br>       }<br>     } else {<br>@@ -2310,10 +2311,10 @@<br>   return cast_or_null<CXXConstructorDecl>(Result->getMethod());<br> }<br><br>-/// \brief Look up the copy constructor for the given class.<br>-CXXConstructorDecl *Sema::LookupCopyConstructor(CXXRecordDecl *Class,<br>-                                                unsigned Quals,<br>-                                                bool *ConstParamMatch) {<br>+/// \brief Look up the copying constructor for the given class.<br>+CXXConstructorDecl *Sema::LookupCopyingConstructor(CXXRecordDecl *Class,<br>+                                                   unsigned Quals,<br>+                                                   bool *ConstParamMatch) {<br>   assert(!(Quals & ~(Qualifiers::Const | Qualifiers::Volatile)) &&<br>          "non-const, non-volatile qualifiers for copy ctor arg");<br>   SpecialMemberOverloadResult *Result =<br>@@ -2341,6 +2342,27 @@<br>   return Class->lookup(Name);<br> }<br><br>+/// \brief Look up the copying assignment operator for the given class.<br>+CXXMethodDecl *Sema::LookupCopyingAssignment(CXXRecordDecl *Class,<br>+                                             unsigned Quals, bool RValueThis,<br>+                                             unsigned ThisQuals,<br>+                                             bool *ConstParamMatch) {<br>+  assert(!(Quals & ~(Qualifiers::Const | Qualifiers::Volatile)) &&<br>+         "non-const, non-volatile qualifiers for copy assignment arg");<br>+  assert(!(ThisQuals & ~(Qualifiers::Const | Qualifiers::Volatile)) &&<br>+         "non-const, non-volatile qualifiers for copy assignment this");<br>+  SpecialMemberOverloadResult *Result =<br>+    LookupSpecialMember(Class, CXXCopyAssignment, Quals & Qualifiers::Const,<br>+                        Quals & Qualifiers::Volatile, RValueThis,<br>+                        ThisQuals & Qualifiers::Const,<br>+                        ThisQuals & Qualifiers::Volatile);<br>+<br>+  if (ConstParamMatch)<br>+    *ConstParamMatch = Result->hasConstParamMatch();<br>+<br>+  return Result->getMethod();<br>+}<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><br><br>_______________________________________________<br>cfe-commits mailing list<br><a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits<br></div></blockquote></div><br></div></body></html>