[cfe-commits] r83505 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp

John McCall rjmccall at apple.com
Wed Oct 7 16:34:26 PDT 2009


Author: rjmccall
Date: Wed Oct  7 18:34:25 2009
New Revision: 83505

URL: http://llvm.org/viewvc/llvm-project?rev=83505&view=rev
Log:
Refactoring around friend class templates.  Better error message for friend enums.
Don't create a new declaration for friend classes if a declaration already exists.


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=83505&r1=83504&r2=83505&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Oct  7 18:34:25 2009
@@ -311,6 +311,8 @@
 
 def err_unexpected_friend : Error<
   "friends can only be classes or functions">;
+def err_enum_friend : Error<
+  "enum types cannot be friends">;
 def err_friend_is_member : Error<
   "friends cannot be members of the declaring class">;
 def ext_friend_inner_class : Extension<

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=83505&r1=83504&r2=83505&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Oct  7 18:34:25 2009
@@ -1323,71 +1323,29 @@
   // FIXME: Warn on useless const/volatile
   // FIXME: Warn on useless static/extern/typedef/private_extern/mutable
   // FIXME: Warn on useless attributes
+  Decl *TagD = 0;
   TagDecl *Tag = 0;
   if (DS.getTypeSpecType() == DeclSpec::TST_class ||
       DS.getTypeSpecType() == DeclSpec::TST_struct ||
       DS.getTypeSpecType() == DeclSpec::TST_union ||
       DS.getTypeSpecType() == DeclSpec::TST_enum) {
-    if (!DS.getTypeRep()) // We probably had an error
+    TagD = static_cast<Decl *>(DS.getTypeRep());
+
+    if (!TagD) // We probably had an error
       return DeclPtrTy();
 
     // Note that the above type specs guarantee that the
     // type rep is a Decl, whereas in many of the others
     // it's a Type.
-    Tag = dyn_cast<TagDecl>(static_cast<Decl *>(DS.getTypeRep()));
+    Tag = dyn_cast<TagDecl>(TagD);
   }
 
   if (DS.isFriendSpecified()) {
-    // We have a "friend" declaration that does not have a declarator.
-    // Look at the type to see if the friend declaration was handled
-    // elsewhere (e.g., for friend classes and friend class templates).
-    // If not, produce a suitable diagnostic or go try to befriend the
-    // type itself.
-    QualType T;
-    if (DS.getTypeSpecType() == DeclSpec::TST_typename ||
-        DS.getTypeSpecType() == DeclSpec::TST_typeofType)
-      T = QualType::getFromOpaquePtr(DS.getTypeRep());
-    else if (DS.getTypeSpecType() == DeclSpec::TST_typeofExpr ||
-             DS.getTypeSpecType() == DeclSpec::TST_decltype)
-      T = ((Expr *)DS.getTypeRep())->getType();
-    else if (DS.getTypeSpecType() == DeclSpec::TST_class ||
-             DS.getTypeSpecType() == DeclSpec::TST_struct ||
-             DS.getTypeSpecType() == DeclSpec::TST_union)
-      return DeclPtrTy::make(Tag);
-    
-    if (T.isNull()) {
-      // Fall through to diagnose this error, below.
-    } else if (const RecordType *RecordT = T->getAs<RecordType>()) {
-      // C++ [class.friend]p2:
-      //   An elaborated-type-specifier shall be used in a friend declaration
-      //   for a class.
-
-      // We have something like "friend C;", where C is the name of a
-      // class type but is missing an elaborated type specifier. Complain,
-      // but tell the user exactly how to fix the problem.
-      RecordDecl *RecordD = RecordT->getDecl();
-      Diag(DS.getTypeSpecTypeLoc(), diag::err_unelaborated_friend_type)
-        << (unsigned)RecordD->getTagKind()
-        << QualType(RecordT, 0)
-        << SourceRange(DS.getFriendSpecLoc())
-        << CodeModificationHint::CreateInsertion(DS.getTypeSpecTypeLoc(),
-                                  RecordD->getKindName() + std::string(" "));
-      
-      // FIXME: We could go into ActOnTag to actually make the friend
-      // declaration happen at this point.
+    // If we're dealing with a class template decl, assume that the
+    // template routines are handling it.
+    if (TagD && isa<ClassTemplateDecl>(TagD))
       return DeclPtrTy();
-    } 
-    
-    if (!T.isNull() && T->isDependentType()) {
-      // Since T is a dependent type, handle it as a friend type
-      // declaration.
-      return ActOnFriendTypeDecl(S, DS, MultiTemplateParamsArg(*this, 0, 0));
-    } 
-        
-    // Complain about any non-dependent friend type here.
-    Diag(DS.getFriendSpecLoc(), diag::err_unexpected_friend)
-      << DS.getSourceRange();
-    return DeclPtrTy();
+    return ActOnFriendTypeDecl(S, DS, MultiTemplateParamsArg(*this, 0, 0));
   }
          
   if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
@@ -4333,14 +4291,9 @@
           // for the consumer of this Decl to know it doesn't own it.
           // For our current ASTs this shouldn't be a problem, but will
           // need to be changed with DeclGroups.
-          if (TUK == TUK_Reference)
+          if (TUK == TUK_Reference || TUK == TUK_Friend)
             return DeclPtrTy::make(PrevDecl);
 
-          // If this is a friend, make sure we create the new
-          // declaration in the appropriate semantic context.
-          if (TUK == TUK_Friend)
-            SearchDC = PrevDecl->getDeclContext();
-
           // Diagnose attempts to redefine a tag.
           if (TUK == TUK_Definition) {
             if (TagDecl *Def = PrevTagDecl->getDefinition(Context)) {

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=83505&r1=83504&r2=83505&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Oct  7 18:34:25 2009
@@ -4283,8 +4283,10 @@
 
       std::string InsertionText = std::string(" ") + RD->getKindName();
 
-      Diag(DS.getFriendSpecLoc(), diag::err_unelaborated_friend_type)
-        << (RD->isUnion())
+      Diag(DS.getTypeSpecTypeLoc(), diag::err_unelaborated_friend_type)
+        << (unsigned) RD->getTagKind()
+        << T
+        << SourceRange(DS.getFriendSpecLoc())
         << CodeModificationHint::CreateInsertion(DS.getTypeSpecTypeLoc(),
                                                  InsertionText);
       return DeclPtrTy();
@@ -4295,21 +4297,11 @@
     }
   }
 
-  bool IsDefinition = false;
-
-  // We want to do a few things differently if the type was declared with
-  // a tag:  specifically, we want to use the associated RecordDecl as
-  // the object of our friend declaration, and we want to disallow
-  // class definitions.
-  switch (DS.getTypeSpecType()) {
-  default: break;
-  case DeclSpec::TST_class:
-  case DeclSpec::TST_struct:
-  case DeclSpec::TST_union:
-    CXXRecordDecl *RD = cast_or_null<CXXRecordDecl>((Decl*) DS.getTypeRep());
-    if (RD)
-      IsDefinition |= RD->isDefinition();
-    break;
+  // Enum types cannot be friends.
+  if (T->getAs<EnumType>()) {
+    Diag(DS.getTypeSpecTypeLoc(), diag::err_enum_friend)
+      << SourceRange(DS.getFriendSpecLoc());
+    return DeclPtrTy();
   }
 
   // C++98 [class.friend]p1: A friend of a class is a function

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp?rev=83505&r1=83504&r2=83505&view=diff

==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp Wed Oct  7 18:34:25 2009
@@ -12,9 +12,8 @@
   friend class A;
   friend union A; // expected-error {{use of 'A' with tag type that does not match previous declaration}}
 
-  // FIXME: a better error would be something like 'enum types cannot be friends'
   friend enum A; // expected-error {{ISO C++ forbids forward references to 'enum' types}} \
-                // expected-error{{classes or functions}}
+                 // expected-error {{enum types cannot be friends}}
 };
 
 template <class T> struct B { // expected-note {{previous use is here}}





More information about the cfe-commits mailing list