[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