r188050 - Implement [class.friend]p11's special name lookup rules for friend declarations

Richard Smith richard-llvm at metafoo.co.uk
Thu Aug 8 21:35:01 PDT 2013


Author: rsmith
Date: Thu Aug  8 23:35:01 2013
New Revision: 188050

URL: http://llvm.org/viewvc/llvm-project?rev=188050&view=rev
Log:
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.

Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/CXX/class.access/class.friend/p11.cpp
    cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp
    cfe/trunk/test/FixIt/typo-crash.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=188050&r1=188049&r2=188050&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Thu Aug  8 23:35:01 2013
@@ -1323,6 +1323,11 @@ public:
     return dyn_cast<FunctionDecl>(getDeclContext());
   }
 
+  FunctionDecl *isLocalClass() {
+    return const_cast<FunctionDecl*>(
+        const_cast<const CXXRecordDecl*>(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;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=188050&r1=188049&r2=188050&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Aug  8 23:35:01 2013
@@ -4304,17 +4304,18 @@ def err_member_redeclared_in_instantiati
 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 :
 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<

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=188050&r1=188049&r2=188050&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Aug  8 23:35:01 2013
@@ -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.

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=188050&r1=188049&r2=188050&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Thu Aug  8 23:35:01 2013
@@ -1390,14 +1390,7 @@ void DeclContext::makeDeclVisibleInConte
   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<FunctionDecl>(D))
+  if (isFunctionOrMethod())
     return;
 
   // Skip declarations which should be invisible to name lookup.

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=188050&r1=188049&r2=188050&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Aug  8 23:35:01 2013
@@ -5033,8 +5033,9 @@ Sema::ActOnVariableDeclarator(Scope *S,
             // 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
 ///
 /// 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<unsigned, 1> MismatchedParams;
   SmallVector<std::pair<FunctionDecl *, unsigned>, 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<CXXMethodDecl>(NewFD);
@@ -5951,9 +5955,9 @@ static NamedDecl* DiagnoseInvalidRedecla
       }
     }
   // 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* DiagnoseInvalidRedecla
       // 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* DiagnoseInvalidRedecla
       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* DiagnoseInvalidRedecla
        NearMatch = NearMatches.begin(), NearMatchEnd = NearMatches.end();
        NearMatch != NearMatchEnd; ++NearMatch) {
     FunctionDecl *FD = NearMatch->first;
-    bool FDisConst = false;
-    if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
-      FDisConst = MD->isConst();
+    CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(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* DiagnoseInvalidRedecla
       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,
           // 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,
         // Unqualified local friend declarations are required to resolve
         // to something.
       } else if (isFriend && cast<CXXRecordDecl>(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;
         }

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=188050&r1=188049&r2=188050&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Aug  8 23:35:01 2013
@@ -11274,28 +11274,60 @@ NamedDecl *Sema::ActOnFriendFunctionDecl
   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<CXXRecordDecl>(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<CXXRecordDecl>(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
     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
     }
 
     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
     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.

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=188050&r1=188049&r2=188050&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Thu Aug  8 23:35:01 2013
@@ -217,6 +217,7 @@ static inline unsigned getIDNS(Sema::Loo
   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
       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(LookupRes
     case LookupOrdinaryName:
     case LookupMemberName:
     case LookupRedeclarationWithLinkage:
+    case LookupLocalFriendName:
       BaseCallback = &CXXRecordDecl::FindOrdinaryMember;
       break;
 

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=188050&r1=188049&r2=188050&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Aug  8 23:35:01 2013
@@ -1050,8 +1050,8 @@ Sema::CheckClassTemplate(Scope *S, unsig
     // 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;
     }
   }

Modified: cfe/trunk/test/CXX/class.access/class.friend/p11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/class.friend/p11.cpp?rev=188050&r1=188049&r2=188050&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class.access/class.friend/p11.cpp (original)
+++ cfe/trunk/test/CXX/class.access/class.friend/p11.cpp Thu Aug  8 23:35:01 2013
@@ -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();
+        };
+      }
+    };
+  }
+}

Modified: cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp?rev=188050&r1=188049&r2=188050&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp (original)
+++ cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp Thu Aug  8 23:35:01 2013
@@ -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}}
   };
 }
 

Modified: cfe/trunk/test/FixIt/typo-crash.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/typo-crash.cpp?rev=188050&r1=188049&r2=188050&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/typo-crash.cpp (original)
+++ cfe/trunk/test/FixIt/typo-crash.cpp Thu Aug  8 23:35:01 2013
@@ -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'?}}
 }





More information about the cfe-commits mailing list