[cfe-commits] r99709 - in /cfe/trunk: lib/Sema/SemaAccess.cpp test/CXX/class.access/p4.cpp

John McCall rjmccall at apple.com
Fri Mar 26 23:55:49 PDT 2010


Author: rjmccall
Date: Sat Mar 27 01:55:49 2010
New Revision: 99709

URL: http://llvm.org/viewvc/llvm-project?rev=99709&view=rev
Log:
Accumulate all functions and classes that the effective context is
nested within, and suddenly local classes start working.  Wouldn't be
necessary if I hadn't used local classes in Clang in the first place.
Or, well, wouldn't be necessary yet. :)


Modified:
    cfe/trunk/lib/Sema/SemaAccess.cpp
    cfe/trunk/test/CXX/class.access/p4.cpp

Modified: cfe/trunk/lib/Sema/SemaAccess.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAccess.cpp?rev=99709&r1=99708&r2=99709&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaAccess.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAccess.cpp Sat Mar 27 01:55:49 2010
@@ -53,32 +53,38 @@
 
 namespace {
 struct EffectiveContext {
-  EffectiveContext() : Inner(0), Function(0), Dependent(false) {}
+  EffectiveContext() : Inner(0), Dependent(false) {}
 
   explicit EffectiveContext(DeclContext *DC)
     : Inner(DC),
       Dependent(DC->isDependentContext()) {
 
-    if (isa<EnumDecl>(DC))
-      DC = cast<EnumDecl>(DC)->getDeclContext();
-
-    if (isa<FunctionDecl>(DC)) {
-      Function = cast<FunctionDecl>(DC)->getCanonicalDecl();
-      DC = Function->getDeclContext();
-    } else
-      Function = 0;
-
     // C++ [class.access.nest]p1:
     //   A nested class is a member and as such has the same access
     //   rights as any other member.
     // C++ [class.access]p2:
     //   A member of a class can also access all the names to which
-    //   the class has access.
-    // This implies that the privileges of nesting are transitive.
-    while (isa<CXXRecordDecl>(DC)) {
-      CXXRecordDecl *Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl();
-      Records.push_back(Record);
-      DC = Record->getDeclContext();
+    //   the class has access.  A local class of a member function
+    //   may access the same names that the member function itself
+    //   may access.
+    // This almost implies that the privileges of nesting are transitive.
+    // Technically it says nothing about the local classes of non-member
+    // functions (which can gain privileges through friendship), but we
+    // take that as an oversight.
+    while (true) {
+      if (isa<CXXRecordDecl>(DC)) {
+        CXXRecordDecl *Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl();
+        Records.push_back(Record);
+        DC = Record->getDeclContext();
+      } else if (isa<FunctionDecl>(DC)) {
+        FunctionDecl *Function = cast<FunctionDecl>(DC)->getCanonicalDecl();
+        Functions.push_back(Function);
+        DC = Function->getDeclContext();
+      } else if (DC->isFileContext()) {
+        break;
+      } else {
+        DC = DC->getParent();
+      }
     }
   }
 
@@ -99,8 +105,8 @@
   typedef llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator;
 
   DeclContext *Inner;
+  llvm::SmallVector<FunctionDecl*, 4> Functions;
   llvm::SmallVector<CXXRecordDecl*, 4> Records;
-  FunctionDecl *Function;
   bool Dependent;
 };
 }
@@ -291,16 +297,18 @@
 static Sema::AccessResult MatchesFriend(Sema &S,
                                         const EffectiveContext &EC,
                                         FunctionDecl *Friend) {
-  if (!EC.Function)
-    return Sema::AR_inaccessible;
+  Sema::AccessResult OnFailure = Sema::AR_inaccessible;
 
-  if (Friend == EC.Function)
-    return Sema::AR_accessible;
+  for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator
+         I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
+    if (Friend == *I)
+      return Sema::AR_accessible;
 
-  if (EC.isDependent() && MightInstantiateTo(S, EC.Function, Friend))
-    return Sema::AR_dependent;
+    if (EC.isDependent() && MightInstantiateTo(S, *I, Friend))
+      OnFailure = Sema::AR_dependent;
+  }
 
-  return Sema::AR_inaccessible;
+  return OnFailure;
 }
 
 /// Determines whether the given friend function template matches
@@ -308,21 +316,29 @@
 static Sema::AccessResult MatchesFriend(Sema &S,
                                         const EffectiveContext &EC,
                                         FunctionTemplateDecl *Friend) {
-  if (!EC.Function) return Sema::AR_inaccessible;
+  if (EC.Functions.empty()) return Sema::AR_inaccessible;
 
-  FunctionTemplateDecl *FTD = EC.Function->getPrimaryTemplate();
-  if (!FTD)
-    FTD = EC.Function->getDescribedFunctionTemplate();
-  if (!FTD)
-    return Sema::AR_inaccessible;
+  Sema::AccessResult OnFailure = Sema::AR_inaccessible;
 
-  if (Friend == FTD->getCanonicalDecl())
-    return Sema::AR_accessible;
+  for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator
+         I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
 
-  if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend))
-    return Sema::AR_dependent;
+    FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate();
+    if (!FTD)
+      FTD = (*I)->getDescribedFunctionTemplate();
+    if (!FTD)
+      continue;
 
-  return Sema::AR_inaccessible;
+    FTD = FTD->getCanonicalDecl();
+
+    if (Friend == FTD)
+      return Sema::AR_accessible;
+
+    if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend))
+      OnFailure = Sema::AR_dependent;
+  }
+
+  return OnFailure;
 }
 
 /// Determines whether the given friend declaration matches anything

Modified: cfe/trunk/test/CXX/class.access/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/p4.cpp?rev=99709&r1=99708&r2=99709&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class.access/p4.cpp (original)
+++ cfe/trunk/test/CXX/class.access/p4.cpp Sat Mar 27 01:55:49 2010
@@ -295,3 +295,17 @@
 
   B::~B() {};
 }
+
+namespace test12 {
+  class A {
+    int x;
+
+    void foo() {
+      class Local {
+        int foo(A *a) {
+          return a->x;
+        }
+      };
+    }
+  };
+}





More information about the cfe-commits mailing list