[cfe-commits] r99389 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaAccess.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplate.cpp test/CXX/temp/temp.decls/temp.friend/p1.cpp test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp

John McCall rjmccall at apple.com
Wed Mar 24 00:46:06 PDT 2010


Author: rjmccall
Date: Wed Mar 24 02:46:06 2010
New Revision: 99389

URL: http://llvm.org/viewvc/llvm-project?rev=99389&view=rev
Log:
Support friend function specializations.


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaAccess.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp
    cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=99389&r1=99388&r2=99389&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Mar 24 02:46:06 2010
@@ -1256,6 +1256,8 @@
   "explicit specialization of %0 in function scope">;
 def err_template_spec_decl_class_scope : Error<
   "explicit specialization of %0 in class scope">;
+def err_template_spec_decl_friend : Error<
+  "cannot declare an explicit specialization in a friend">;
 def err_template_spec_decl_out_of_scope_global : Error<
   "%select{class template|class template partial|function template|member "
   "function|static data member|member class}0 specialization of %1 must "

Modified: cfe/trunk/lib/Sema/SemaAccess.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAccess.cpp?rev=99389&r1=99388&r2=99389&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaAccess.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAccess.cpp Wed Mar 24 02:46:06 2010
@@ -53,10 +53,11 @@
 
 namespace {
 struct EffectiveContext {
-  EffectiveContext() : Function(0), Dependent(false) {}
+  EffectiveContext() : Inner(0), Function(0), Dependent(false) {}
 
-  explicit EffectiveContext(DeclContext *DC) {
-    Dependent = DC->isDependentContext();
+  explicit EffectiveContext(DeclContext *DC)
+    : Inner(DC),
+      Dependent(DC->isDependentContext()) {
 
     if (isa<FunctionDecl>(DC)) {
       Function = cast<FunctionDecl>(DC)->getCanonicalDecl();
@@ -86,14 +87,15 @@
              != Records.end();
   }
 
-  DeclContext *getPrimaryContext() const {
-    assert((Function || !Records.empty()) && "context has no primary context");
-    if (Function) return Function;
-    return Records[0];
+  /// Retrieves the innermost "useful" context.  Can be null if we're
+  /// doing access-control without privileges.
+  DeclContext *getInnerContext() const {
+    return Inner;
   }
 
   typedef llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator;
 
+  DeclContext *Inner;
   llvm::SmallVector<CXXRecordDecl*, 4> Records;
   FunctionDecl *Function;
   bool Dependent;
@@ -636,7 +638,7 @@
                         SourceLocation Loc,
                         const Sema::AccessedEntity &Entity) {
   assert(EC.isDependent() && "delaying non-dependent access");
-  DeclContext *DC = EC.getPrimaryContext();
+  DeclContext *DC = EC.getInnerContext();
   assert(DC->isDependentContext() && "delaying non-dependent access");
   DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access,
                               Loc,

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=99389&r1=99388&r2=99389&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Mar 24 02:46:06 2010
@@ -2918,6 +2918,13 @@
     } else {
       // This is a function template specialization.
       isFunctionTemplateSpecialization = true;
+
+      // C++0x [temp.expl.spec]p20 forbids "template<> void foo(int);".
+      if (isFriend && isFunctionTemplateSpecialization) {
+        SourceRange Range = TemplateParams->getSourceRange();
+        Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend)
+          << Name << Range << CodeModificationHint::CreateRemoval(Range);
+      }
     }
 
     // FIXME: Free this memory properly.
@@ -3101,6 +3108,9 @@
                                    D.getDeclSpec().getSourceRange().getBegin(),
                                                  "template<> ");
       isFunctionTemplateSpecialization = true;
+    } else {
+      // "friend void foo<>(int);" is an implicit specialization decl.
+      isFunctionTemplateSpecialization = true;
     }
   }
 

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=99389&r1=99388&r2=99389&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Mar 24 02:46:06 2010
@@ -3961,9 +3961,14 @@
   
   // FIXME: Check if the prior specialization has a point of instantiation.
   // If so, we have run afoul of .
+
+  // If this is a friend declaration, then we're not really declaring
+  // an explicit specialization.
+  bool isFriend = (FD->getFriendObjectKind() != Decl::FOK_None);
   
   // Check the scope of this explicit specialization.
-  if (CheckTemplateSpecializationScope(*this, 
+  if (!isFriend &&
+      CheckTemplateSpecializationScope(*this, 
                                        Specialization->getPrimaryTemplate(),
                                        Specialization, FD->getLocation(), 
                                        false))
@@ -3980,7 +3985,8 @@
   assert(SpecInfo && "Function template specialization info missing?");
 
   bool SuppressNew = false;
-  if (CheckSpecializationInstantiationRedecl(FD->getLocation(),
+  if (!isFriend &&
+      CheckSpecializationInstantiationRedecl(FD->getLocation(),
                                              TSK_ExplicitSpecialization,
                                              Specialization,
                                    SpecInfo->getTemplateSpecializationKind(),
@@ -3990,7 +3996,8 @@
   
   // Mark the prior declaration as an explicit specialization, so that later
   // clients know that this is an explicit specialization.
-  SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
+  if (!isFriend)
+    SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
   
   // Turn the given function declaration into a function template
   // specialization, with the template arguments from the previous
@@ -3999,7 +4006,7 @@
                          new (Context) TemplateArgumentList(
                              *Specialization->getTemplateSpecializationArgs()), 
                                         /*InsertPos=*/0, 
-                                        TSK_ExplicitSpecialization);
+                                    SpecInfo->getTemplateSpecializationKind());
   
   // The "previous declaration" for this function template specialization is
   // the prior function template specialization.

Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp?rev=99389&r1=99388&r2=99389&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp Wed Mar 24 02:46:06 2010
@@ -95,7 +95,7 @@
     friend class User<bool>;
     friend bool transform<>(Bool, bool);
 
-    bool value; // expected-note {{declared private here}}
+    bool value; // expected-note 2 {{declared private here}}
   };
 
   template <class T> class User {
@@ -105,13 +105,13 @@
   };
 
   template <class T> T transform(Bool b, T value) {
-    if (b.value)
+    if (b.value) // expected-error {{'value' is a private member of 'test3::Bool'}}
       return value;
     return value + 1;
   }
 
   template bool transform(Bool, bool);
-  template int transform(Bool, int);
+  template int transform(Bool, int); // expected-note {{requested here}}
 
   template class User<bool>;
   template class User<int>; // expected-note {{requested here}}

Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp?rev=99389&r1=99388&r2=99389&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp Wed Mar 24 02:46:06 2010
@@ -6,7 +6,7 @@
 struct A { };
 
 struct X {
-  template<> friend void f<int>(int); // expected-error{{in class scope}}
+  template<> friend void f<int>(int); // expected-error{{in a friend}}
   template<> friend class A<int>; // expected-error{{cannot be a friend}}
   
   friend void f<float>(float); // okay





More information about the cfe-commits mailing list