From: Richard Smith Date: Fri, 9 Aug 2013 04:35:01 +0000 (+0000) Subject: Implement [class.friend]p11's special name lookup rules for friend declarations X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4e9686b1f9947f1747b4f4316deb2087a7f56282;p=clang Implement [class.friend]p11's special name lookup rules for friend declarations of local classes. We were previously handling this by performing qualified lookup within a function declaration(!!); replace it with the proper scope lookup. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@188050 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 4995812388..f96032c61b 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -1323,6 +1323,11 @@ public: return dyn_cast(getDeclContext()); } + FunctionDecl *isLocalClass() { + return const_cast( + const_cast(this)->isLocalClass()); + } + /// \brief Determine whether this dependent class is a current instantiation, /// when viewed from within the given context. bool isCurrentInstantiation(const DeclContext *CurContext) const; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 57425cb080..d231af330b 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -4304,17 +4304,18 @@ def err_member_redeclared_in_instantiation : Error< def err_member_name_of_class : Error<"member %0 has the same name as its class">; def err_member_def_undefined_record : Error< "out-of-line definition of %0 from class %1 without definition">; -def err_member_def_does_not_match : Error< - "out-of-line definition of %0 does not match any declaration in %1">; +def err_member_decl_does_not_match : Error< + "out-of-line %select{declaration|definition}2 of %0 " + "does not match any declaration in %1">; def err_friend_decl_with_def_arg_must_be_def : Error< "friend declaration specifying a default argument must be a definition">; def err_friend_decl_with_def_arg_redeclared : Error< "friend declaration specifying a default argument must be the only declaration">; def err_friend_decl_does_not_match : Error< "friend declaration of %0 does not match any declaration in %1">; -def err_member_def_does_not_match_suggest : Error< - "out-of-line definition of %0 does not match any declaration in %1; " - "did you mean %2?">; +def err_member_decl_does_not_match_suggest : Error< + "out-of-line %select{declaration|definition}3 of %0 " + "does not match any declaration in %1; did you mean %2?">; def err_member_def_does_not_match_ret_type : Error< "out-of-line definition of %q0 differs from the declaration in the return type">; def err_nonstatic_member_out_of_line : Error< @@ -4339,6 +4340,10 @@ def note_member_def_close_const_match : Note< def note_member_def_close_param_match : Note< "type of %ordinal0 parameter of member declaration does not match definition" "%diff{ ($ vs $)|}1,2">; +def note_local_decl_close_match : Note<"local declaration nearly matches">; +def note_local_decl_close_param_match : Note< + "type of %ordinal0 parameter of local declaration does not match definition" + "%diff{ ($ vs $)|}1,2">; def err_typecheck_ivar_variable_size : Error< "instance variables must have a constant size">; def err_ivar_reference_type : Error< diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 44300176e2..4afa93e330 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2360,6 +2360,9 @@ public: /// are outside of the current scope unless they have linkage. See /// C99 6.2.2p4-5 and C++ [basic.link]p6. LookupRedeclarationWithLinkage, + /// Look up a friend of a local class. This lookup does not look + /// outside the innermost non-class scope. See C++11 [class.friend]p11. + LookupLocalFriendName, /// Look up the name of an Objective-C protocol. LookupObjCProtocolName, /// Look up implicit 'self' parameter of an objective-c method. diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index e99f7ec5b0..e46d671682 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -1390,14 +1390,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal, assert(this == getPrimaryContext() && "expected a primary DC"); // Skip declarations within functions. - // FIXME: We shouldn't need to build lookup tables for function declarations - // ever, and we can't do so correctly because we can't model the nesting of - // scopes which occurs within functions. We use "qualified" lookup into - // function declarations when handling friend declarations inside nested - // classes, and consequently accept the following invalid code: - // - // void f() { void g(); { int g; struct S { friend void g(); }; } } - if (isFunctionOrMethod() && !isa(D)) + if (isFunctionOrMethod()) return; // Skip declarations which should be invisible to name lookup. diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 15e6a49272..330d0cbb58 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5033,8 +5033,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // the template out-of-line. if (!D.getCXXScopeSpec().isInvalid() && !Invalid && !PrevVarTemplate) { - Diag(D.getIdentifierLoc(), diag::err_member_def_does_not_match) - << Name << DC << D.getCXXScopeSpec().getRange(); + Diag(D.getIdentifierLoc(), diag::err_member_decl_does_not_match) + << Name << DC << /*IsDefinition*/true + << D.getCXXScopeSpec().getRange(); Invalid = true; } } @@ -5914,24 +5915,27 @@ class DifferentNameValidatorCCC : public CorrectionCandidateCallback { /// /// Returns a NamedDecl iff typo correction was performed and substituting in /// the new declaration name does not cause new errors. -static NamedDecl* DiagnoseInvalidRedeclaration( +static NamedDecl *DiagnoseInvalidRedeclaration( Sema &SemaRef, LookupResult &Previous, FunctionDecl *NewFD, - ActOnFDArgs &ExtraArgs) { + ActOnFDArgs &ExtraArgs, bool IsLocalFriend, Scope *S) { NamedDecl *Result = NULL; DeclarationName Name = NewFD->getDeclName(); DeclContext *NewDC = NewFD->getDeclContext(); - LookupResult Prev(SemaRef, Name, NewFD->getLocation(), - Sema::LookupOrdinaryName, Sema::ForRedeclaration); SmallVector MismatchedParams; SmallVector, 1> NearMatches; TypoCorrection Correction; - bool isFriendDecl = (SemaRef.getLangOpts().CPlusPlus && - ExtraArgs.D.getDeclSpec().isFriendSpecified()); - unsigned DiagMsg = isFriendDecl ? diag::err_no_matching_local_friend - : diag::err_member_def_does_not_match; + unsigned DiagMsg = IsLocalFriend ? diag::err_no_matching_local_friend + : diag::err_member_decl_does_not_match; + LookupResult Prev(SemaRef, Name, NewFD->getLocation(), + IsLocalFriend ? Sema::LookupLocalFriendName + : Sema::LookupOrdinaryName, + Sema::ForRedeclaration); NewFD->setInvalidDecl(); - SemaRef.LookupQualifiedName(Prev, NewDC); + if (IsLocalFriend) + SemaRef.LookupName(Prev, S); + else + SemaRef.LookupQualifiedName(Prev, NewDC); assert(!Prev.isAmbiguous() && "Cannot have an ambiguity in previous-declaration lookup"); CXXMethodDecl *MD = dyn_cast(NewFD); @@ -5951,9 +5955,9 @@ static NamedDecl* DiagnoseInvalidRedeclaration( } } // If the qualified name lookup yielded nothing, try typo correction - } else if ((Correction = SemaRef.CorrectTypo(Prev.getLookupNameInfo(), - Prev.getLookupKind(), 0, 0, - Validator, NewDC))) { + } else if ((Correction = SemaRef.CorrectTypo( + Prev.getLookupNameInfo(), Prev.getLookupKind(), S, 0, + Validator, IsLocalFriend ? 0 : NewDC))) { // Trap errors. Sema::SFINAETrap Trap(SemaRef); @@ -6000,11 +6004,12 @@ static NamedDecl* DiagnoseInvalidRedeclaration( // Ignore the correction if it didn't yield any close FunctionDecl matches Correction = TypoCorrection(); } else { - DiagMsg = isFriendDecl ? diag::err_no_matching_local_friend_suggest - : diag::err_member_def_does_not_match_suggest; + DiagMsg = IsLocalFriend ? diag::err_no_matching_local_friend_suggest + : diag::err_member_decl_does_not_match_suggest; } } + bool IsDefinition = ExtraArgs.D.isFunctionDefinition(); if (Correction) { // FIXME: use Correction.getCorrectionRange() instead of computing the range // here. This requires passing in the CXXScopeSpec to CorrectTypo which in @@ -6016,11 +6021,12 @@ static NamedDecl* DiagnoseInvalidRedeclaration( FixItLoc.setBegin(SS.getBeginLoc()); SemaRef.Diag(NewFD->getLocStart(), DiagMsg) << Name << NewDC << Correction.getQuoted(SemaRef.getLangOpts()) + << IsDefinition << FixItHint::CreateReplacement( FixItLoc, Correction.getAsString(SemaRef.getLangOpts())); } else { SemaRef.Diag(NewFD->getLocation(), DiagMsg) - << Name << NewDC << NewFD->getLocation(); + << Name << NewDC << IsDefinition << NewFD->getLocation(); } bool NewFDisConst = false; @@ -6031,16 +6037,18 @@ static NamedDecl* DiagnoseInvalidRedeclaration( NearMatch = NearMatches.begin(), NearMatchEnd = NearMatches.end(); NearMatch != NearMatchEnd; ++NearMatch) { FunctionDecl *FD = NearMatch->first; - bool FDisConst = false; - if (CXXMethodDecl *MD = dyn_cast(FD)) - FDisConst = MD->isConst(); + CXXMethodDecl *MD = dyn_cast(FD); + bool FDisConst = MD && MD->isConst(); + bool IsMember = MD || !IsLocalFriend; if (unsigned Idx = NearMatch->second) { ParmVarDecl *FDParam = FD->getParamDecl(Idx-1); SourceLocation Loc = FDParam->getTypeSpecStartLoc(); if (Loc.isInvalid()) Loc = FD->getLocation(); - SemaRef.Diag(Loc, diag::note_member_def_close_param_match) - << Idx << FDParam->getType() << NewFD->getParamDecl(Idx-1)->getType(); + SemaRef.Diag(Loc, IsMember ? diag::note_member_def_close_param_match + : diag::note_local_decl_close_param_match) + << Idx << FDParam->getType() + << NewFD->getParamDecl(Idx - 1)->getType(); } else if (Correction) { SemaRef.Diag(FD->getLocation(), diag::note_previous_decl) << Correction.getQuoted(SemaRef.getLangOpts()); @@ -6048,7 +6056,9 @@ static NamedDecl* DiagnoseInvalidRedeclaration( SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) << NewFDisConst << FD->getSourceRange().getEnd(); } else - SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_match); + SemaRef.Diag(FD->getLocation(), + IsMember ? diag::note_member_def_close_match + : diag::note_local_decl_close_match); } return Result; } @@ -7063,9 +7073,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // matches (e.g., those that differ only in cv-qualifiers and // whether the parameter types are references). - if (NamedDecl *Result = DiagnoseInvalidRedeclaration(*this, Previous, - NewFD, - ExtraArgs)) { + if (NamedDecl *Result = DiagnoseInvalidRedeclaration( + *this, Previous, NewFD, ExtraArgs, false, 0)) { AddToScope = ExtraArgs.AddToScope; return Result; } @@ -7074,9 +7083,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Unqualified local friend declarations are required to resolve // to something. } else if (isFriend && cast(CurContext)->isLocalClass()) { - if (NamedDecl *Result = DiagnoseInvalidRedeclaration(*this, Previous, - NewFD, - ExtraArgs)) { + if (NamedDecl *Result = DiagnoseInvalidRedeclaration( + *this, Previous, NewFD, ExtraArgs, true, S)) { AddToScope = ExtraArgs.AddToScope; return Result; } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 31be93b171..e67719000c 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -11274,28 +11274,60 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); - // FIXME: there are different rules in local classes + // There are five cases here. + // - There's no scope specifier and we're in a local class. Only look + // for functions declared in the immediately-enclosing block scope. + // We recover from invalid scope qualifiers as if they just weren't there. + FunctionDecl *FunctionContainingLocalClass = 0; + if ((SS.isInvalid() || !SS.isSet()) && + (FunctionContainingLocalClass = + cast(CurContext)->isLocalClass())) { + // C++11 [class.friend]p11: + // If a friend declaration appears in a local class and the name + // specified is an unqualified name, a prior declaration is + // looked up without considering scopes that are outside the + // innermost enclosing non-class scope. For a friend function + // declaration, if there is no prior declaration, the program is + // ill-formed. + + // Find the innermost enclosing non-class scope. This is the block + // scope containing the local class definition (or for a nested class, + // the outer local class). + DCScope = S->getFnParent(); + + // Look up the function name in the scope. + Previous.clear(LookupLocalFriendName); + LookupName(Previous, S, /*AllowBuiltinCreation*/false); + + if (!Previous.empty()) { + // All possible previous declarations must have the same context: + // either they were declared at block scope or they are members of + // one of the enclosing local classes. + DC = Previous.getRepresentativeDecl()->getDeclContext(); + } else { + // This is ill-formed, but provide the context that we would have + // declared the function in, if we were permitted to, for error recovery. + DC = FunctionContainingLocalClass; + } + + // C++ [class.friend]p6: + // A function can be defined in a friend declaration of a class if and + // only if the class is a non-local class (9.8), the function name is + // unqualified, and the function has namespace scope. + if (D.isFunctionDefinition()) { + Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class); + } - // There are four cases here. // - There's no scope specifier, in which case we just go to the // appropriate scope and look for a function or function template // there as appropriate. - // Recover from invalid scope qualifiers as if they just weren't there. - if (SS.isInvalid() || !SS.isSet()) { - // C++0x [namespace.memdef]p3: + } else if (SS.isInvalid() || !SS.isSet()) { + // C++11 [namespace.memdef]p3: // If the name in a friend declaration is neither qualified nor // a template-id and the declaration is a function or an // elaborated-type-specifier, the lookup to determine whether // the entity has been previously declared shall not consider // any scopes outside the innermost enclosing namespace. - // C++0x [class.friend]p11: - // If a friend declaration appears in a local class and the name - // specified is an unqualified name, a prior declaration is - // looked up without considering scopes that are outside the - // innermost enclosing non-class scope. For a friend function - // declaration, if there is no prior declaration, the program is - // ill-formed. - bool isLocal = cast(CurContext)->isLocalClass(); bool isTemplateId = D.getName().getKind() == UnqualifiedId::IK_TemplateId; // Find the appropriate context according to the above. @@ -11318,10 +11350,6 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, while (true) { LookupQualifiedName(Previous, LookupDC); - // TODO: decide what we think about using declarations. - if (isLocal) - break; - if (!Previous.empty()) { DC = LookupDC; break; @@ -11336,15 +11364,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, } DCScope = getScopeForDeclContext(S, DC); - - // C++ [class.friend]p6: - // A function can be defined in a friend declaration of a class if and - // only if the class is a non-local class (9.8), the function name is - // unqualified, and the function has namespace scope. - if (isLocal && D.isFunctionDefinition()) { - Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class); - } - + // - There's a non-dependent scope specifier, in which case we // compute it and do a previous lookup there for a function // or function template. @@ -11436,15 +11456,18 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, FakeDCScope.setEntity(DC); DCScope = &FakeDCScope; } - + bool AddToScope = true; NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous, TemplateParams, AddToScope); if (!ND) return 0; - assert(ND->getDeclContext() == DC); assert(ND->getLexicalDeclContext() == CurContext); + // If we performed typo correction, we might have added a scope specifier + // and changed the decl context. + DC = ND->getDeclContext(); + // Add the function declaration to the appropriate lookup tables, // adjusting the redeclarations list as necessary. We don't // want to do this yet if the friending class is dependent. diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 82f404f1f2..fc8b6b9c09 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -217,6 +217,7 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind, case Sema::LookupObjCImplicitSelfParam: case Sema::LookupOrdinaryName: case Sema::LookupRedeclarationWithLinkage: + case Sema::LookupLocalFriendName: IDNS = Decl::IDNS_Ordinary; if (CPlusPlus) { IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Namespace; @@ -908,6 +909,15 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { return true; } + if (R.getLookupKind() == LookupLocalFriendName && !S->isClassScope()) { + // C++11 [class.friend]p11: + // If a friend declaration appears in a local class and the name + // specified is an unqualified name, a prior declaration is + // looked up without considering scopes that are outside the + // innermost enclosing non-class scope. + return false; + } + if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC && S->getParent() && !S->getParent()->isTemplateParamScope()) { // We've just searched the last template parameter scope and @@ -1594,6 +1604,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, case LookupOrdinaryName: case LookupMemberName: case LookupRedeclarationWithLinkage: + case LookupLocalFriendName: BaseCallback = &CXXRecordDecl::FindOrdinaryMember; break; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 50cca0d94a..bd2936b614 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1050,8 +1050,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // template out-of-line. if (!SS.isInvalid() && !Invalid && !PrevClassTemplate) { Diag(NameLoc, TUK == TUK_Friend ? diag::err_friend_decl_does_not_match - : diag::err_member_def_does_not_match) - << Name << SemanticContext << SS.getRange(); + : diag::err_member_decl_does_not_match) + << Name << SemanticContext << /*IsDefinition*/true << SS.getRange(); Invalid = true; } } diff --git a/test/CXX/class.access/class.friend/p11.cpp b/test/CXX/class.access/class.friend/p11.cpp index a05b2d2875..ba44a0d492 100644 --- a/test/CXX/class.access/class.friend/p11.cpp +++ b/test/CXX/class.access/class.friend/p11.cpp @@ -17,3 +17,83 @@ namespace test1 { }; } } + +namespace test2 { + void bar(); // expected-note {{'::test2::bar' declared here}} + + void foo() { // expected-note {{'::test2::foo' declared here}} + struct S1 { + friend void foo(); // expected-error {{no matching function 'foo' found in local scope; did you mean '::test2::foo'?}} + }; + + void foo(); // expected-note {{local declaration nearly matches}} + struct S2 { + friend void foo(); + }; + + { + struct S2 { + friend void foo(); // expected-error {{no matching function found in local scope}} + }; + } + + { + int foo; + struct S3 { + friend void foo(); // expected-error {{no matching function found in local scope}} + }; + } + + struct S4 { + friend void bar(); // expected-error {{no matching function 'bar' found in local scope; did you mean '::test2::bar'?}} + }; + + { void bar(); } + struct S5 { + friend void bar(); // expected-error {{no matching function found in local scope}} + }; + + { + void bar(); + struct S6 { + friend void bar(); + }; + } + + struct S7 { + void bar() { Inner::f(); } + struct Inner { + friend void bar(); + static void f() {} + }; + }; + + void bar(); // expected-note {{'bar' declared here}} + struct S8 { + struct Inner { + friend void bar(); + }; + }; + + struct S9 { + struct Inner { + friend void baz(); // expected-error {{no matching function 'baz' found in local scope; did you mean 'bar'?}} + }; + }; + + struct S10 { + void quux() {} + void foo() { + struct Inner1 { + friend void bar(); // expected-error {{no matching function found in local scope}} + friend void quux(); // expected-error {{no matching function found in local scope}} + }; + + void bar(); + struct Inner2 { + friend void bar(); + }; + } + }; + } +} diff --git a/test/CXX/special/class.copy/implicit-move.cpp b/test/CXX/special/class.copy/implicit-move.cpp index 33374129f7..1941da7e8a 100644 --- a/test/CXX/special/class.copy/implicit-move.cpp +++ b/test/CXX/special/class.copy/implicit-move.cpp @@ -209,29 +209,29 @@ namespace DR1402 { struct NoMove11 : NonTrivialMoveAssignVBase {}; // expected-note {{'const DR1402::NoMove11 &'}} struct Test { - friend NoMove1::NoMove1(NoMove1 &&); // expected-error {{no matching function}} - friend NoMove2::NoMove2(NoMove2 &&); // expected-error {{no matching function}} - friend NoMove3::NoMove3(NoMove3 &&); // expected-error {{no matching function}} - friend NoMove4::NoMove4(NoMove4 &&); // expected-error {{no matching function}} - friend NoMove5::NoMove5(NoMove5 &&); // expected-error {{no matching function}} - friend NoMove6::NoMove6(NoMove6 &&); // expected-error {{no matching function}} - friend NoMove7::NoMove7(NoMove7 &&); // expected-error {{no matching function}} - friend NoMove8::NoMove8(NoMove8 &&); // expected-error {{no matching function}} + friend NoMove1::NoMove1(NoMove1 &&); // expected-error {{does not match}} + friend NoMove2::NoMove2(NoMove2 &&); // expected-error {{does not match}} + friend NoMove3::NoMove3(NoMove3 &&); // expected-error {{does not match}} + friend NoMove4::NoMove4(NoMove4 &&); // expected-error {{does not match}} + friend NoMove5::NoMove5(NoMove5 &&); // expected-error {{does not match}} + friend NoMove6::NoMove6(NoMove6 &&); // expected-error {{does not match}} + friend NoMove7::NoMove7(NoMove7 &&); // expected-error {{does not match}} + friend NoMove8::NoMove8(NoMove8 &&); // expected-error {{does not match}} friend NoMove9::NoMove9(NoMove9 &&); friend NoMove10::NoMove10(NoMove10 &&); friend NoMove11::NoMove11(NoMove11 &&); - friend NoMove1 &NoMove1::operator=(NoMove1 &&); // expected-error {{no matching function}} - friend NoMove2 &NoMove2::operator=(NoMove2 &&); // expected-error {{no matching function}} - friend NoMove3 &NoMove3::operator=(NoMove3 &&); // expected-error {{no matching function}} - friend NoMove4 &NoMove4::operator=(NoMove4 &&); // expected-error {{no matching function}} - friend NoMove5 &NoMove5::operator=(NoMove5 &&); // expected-error {{no matching function}} - friend NoMove6 &NoMove6::operator=(NoMove6 &&); // expected-error {{no matching function}} - friend NoMove7 &NoMove7::operator=(NoMove7 &&); // expected-error {{no matching function}} - friend NoMove8 &NoMove8::operator=(NoMove8 &&); // expected-error {{no matching function}} + friend NoMove1 &NoMove1::operator=(NoMove1 &&); // expected-error {{does not match}} + friend NoMove2 &NoMove2::operator=(NoMove2 &&); // expected-error {{does not match}} + friend NoMove3 &NoMove3::operator=(NoMove3 &&); // expected-error {{does not match}} + friend NoMove4 &NoMove4::operator=(NoMove4 &&); // expected-error {{does not match}} + friend NoMove5 &NoMove5::operator=(NoMove5 &&); // expected-error {{does not match}} + friend NoMove6 &NoMove6::operator=(NoMove6 &&); // expected-error {{does not match}} + friend NoMove7 &NoMove7::operator=(NoMove7 &&); // expected-error {{does not match}} + friend NoMove8 &NoMove8::operator=(NoMove8 &&); // expected-error {{does not match}} friend NoMove9 &NoMove9::operator=(NoMove9 &&); - friend NoMove10 &NoMove10::operator=(NoMove10 &&); // expected-error {{no matching function}} - friend NoMove11 &NoMove11::operator=(NoMove11 &&); // expected-error {{no matching function}} + friend NoMove10 &NoMove10::operator=(NoMove10 &&); // expected-error {{does not match}} + friend NoMove11 &NoMove11::operator=(NoMove11 &&); // expected-error {{does not match}} }; } diff --git a/test/FixIt/typo-crash.cpp b/test/FixIt/typo-crash.cpp index 0ff160e448..4ea63c542a 100644 --- a/test/FixIt/typo-crash.cpp +++ b/test/FixIt/typo-crash.cpp @@ -26,5 +26,5 @@ namespace PR12297 { using namespace A::B; // FIXME: Adding '::PR12297::' is not needed as removing 'A::' is sufficient - T A::global(); // expected-error {{out-of-line definition of 'global' does not match any declaration in namespace 'PR12297::A'; did you mean '::PR12297::global'?}} + T A::global(); // expected-error {{out-of-line declaration of 'global' does not match any declaration in namespace 'PR12297::A'; did you mean '::PR12297::global'?}} }