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