[cfe-commits] r100633 - in /cfe/trunk/lib/Sema: Sema.h SemaDeclCXX.cpp

Douglas Gregor dgregor at apple.com
Wed Apr 7 09:53:43 PDT 2010


Author: dgregor
Date: Wed Apr  7 11:53:43 2010
New Revision: 100633

URL: http://llvm.org/viewvc/llvm-project?rev=100633&view=rev
Log:
Split Sema::ActOnFriendTypeDecl into Sema::CheckFriendTypeDecl (for
semantic analysis) and Sema::ActOnFriendTypeDecl (the action
callback). This is a prerequisite for improving template instantiation
of friend type declarations.

Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=100633&r1=100632&r2=100633&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Apr  7 11:53:43 2010
@@ -2530,6 +2530,8 @@
                                                  ExprArg AssertExpr,
                                                  ExprArg AssertMessageExpr);
 
+  FriendDecl *CheckFriendTypeDecl(SourceLocation FriendLoc, 
+                                  TypeSourceInfo *TSInfo);
   DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
                                 MultiTemplateParamsArg TemplateParams);
   DeclPtrTy ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition,

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=100633&r1=100632&r2=100633&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Apr  7 11:53:43 2010
@@ -5318,6 +5318,53 @@
   return DeclPtrTy::make(Decl);
 }
 
+/// \brief Perform semantic analysis of the given friend type declaration.
+///
+/// \returns A friend declaration that.
+FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation FriendLoc, 
+                                      TypeSourceInfo *TSInfo) {
+  assert(TSInfo && "NULL TypeSourceInfo for friend type declaration");
+  
+  QualType T = TSInfo->getType();
+  SourceRange TypeRange = TSInfo->getTypeLoc().getSourceRange();
+  
+  // C++03 [class.friend]p2:
+  //   An elaborated-type-specifier shall be used in a friend declaration
+  //   for a class.*
+  //
+  //   * The class-key of the elaborated-type-specifier is required.
+  if (!getLangOptions().CPlusPlus0x && !T->isElaboratedTypeSpecifier()) {
+    // If we evaluated the type to a record type, suggest putting
+    // a tag in front.
+    if (const RecordType *RT = T->getAs<RecordType>()) {
+      RecordDecl *RD = RT->getDecl();
+      
+      std::string InsertionText = std::string(" ") + RD->getKindName();
+      
+      Diag(FriendLoc, diag::err_unelaborated_friend_type)
+        << (unsigned) RD->getTagKind()
+        << T
+        << SourceRange(FriendLoc)
+        << FixItHint::CreateInsertion(TypeRange.getBegin(),
+                                      InsertionText);
+      return 0; 
+    } else {
+      Diag(FriendLoc, diag::err_unexpected_friend)
+        << SourceRange(FriendLoc, TypeRange.getEnd());
+      return 0;
+    }
+  }
+  
+  // Enum types cannot be friends.
+  if (T->getAs<EnumType>()) {
+    Diag(FriendLoc, diag::err_enum_friend)
+      << SourceRange(FriendLoc, TypeRange.getEnd());
+    return 0;
+  }  
+  
+  return FriendDecl::Create(Context, CurContext, FriendLoc, TSInfo, FriendLoc);
+}
+
 /// Handle a friend type declaration.  This works in tandem with
 /// ActOnTag.
 ///
@@ -5351,6 +5398,9 @@
   if (TheDeclarator.isInvalidType())
     return DeclPtrTy();
 
+  if (!TSI)
+    TSI = Context.getTrivialTypeSourceInfo(T, DS.getSourceRange().getBegin());
+  
   // This is definitely an error in C++98.  It's probably meant to
   // be forbidden in C++0x, too, but the specification is just
   // poorly written.
@@ -5370,38 +5420,11 @@
       << DS.getSourceRange();
     return DeclPtrTy();
   }
-
-  // C++ [class.friend]p2:
-  //   An elaborated-type-specifier shall be used in a friend declaration
-  //   for a class.*
-  //   * The class-key of the elaborated-type-specifier is required.
-  // This is one of the rare places in Clang where it's legitimate to
-  // ask about the "spelling" of the type.
-  if (!getLangOptions().CPlusPlus0x && !T->isElaboratedTypeSpecifier()) {
-    // If we evaluated the type to a record type, suggest putting
-    // a tag in front.
-    if (const RecordType *RT = T->getAs<RecordType>()) {
-      RecordDecl *RD = RT->getDecl();
-
-      std::string InsertionText = std::string(" ") + RD->getKindName();
-
-      Diag(DS.getTypeSpecTypeLoc(), diag::err_unelaborated_friend_type)
-        << (unsigned) RD->getTagKind()
-        << T
-        << SourceRange(DS.getFriendSpecLoc())
-        << FixItHint::CreateInsertion(DS.getTypeSpecTypeLoc(), InsertionText);
-      return DeclPtrTy();
-    }else {
-      Diag(DS.getFriendSpecLoc(), diag::err_unexpected_friend)
-          << DS.getSourceRange();
-      return DeclPtrTy();
-    }
-  }
-
-  // Enum types cannot be friends.
-  if (T->getAs<EnumType>()) {
+  
+  // Enum templates cannot be friends.
+  if (TempParams.size() && T->getAs<EnumType>()) {
     Diag(DS.getTypeSpecTypeLoc(), diag::err_enum_friend)
-      << SourceRange(DS.getFriendSpecLoc());
+    << SourceRange(DS.getFriendSpecLoc());
     return DeclPtrTy();
   }
 
@@ -5417,15 +5440,18 @@
   // friend a member of an arbitrary specialization of your template).
 
   Decl *D;
-  if (TempParams.size())
+  if (unsigned NumTempParamLists = TempParams.size())
     D = FriendTemplateDecl::Create(Context, CurContext, Loc,
-                                   TempParams.size(),
+                                   NumTempParamLists,
                                  (TemplateParameterList**) TempParams.release(),
                                    TSI,
                                    DS.getFriendSpecLoc());
   else
-    D = FriendDecl::Create(Context, CurContext, Loc, TSI,
-                           DS.getFriendSpecLoc());
+    D = CheckFriendTypeDecl(DS.getFriendSpecLoc(), TSI);
+  
+  if (!D)
+    return DeclPtrTy();
+  
   D->setAccess(AS_public);
   CurContext->addDecl(D);
 





More information about the cfe-commits mailing list