diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/DeclFriend.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaAccess.cpp | 29 |
3 files changed, 31 insertions, 4 deletions
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 72b7f49dff0..cc743200b12 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -33,7 +33,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true), HasTrivialDestructor(true), ComputedVisibleConversions(false), Bases(0), NumBases(0), VBases(0), NumVBases(0), - Definition(D) { + Definition(D), FirstFriend(0) { } CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, diff --git a/clang/lib/AST/DeclFriend.cpp b/clang/lib/AST/DeclFriend.cpp index 8c7cadfbf74..ab3552db28e 100644 --- a/clang/lib/AST/DeclFriend.cpp +++ b/clang/lib/AST/DeclFriend.cpp @@ -35,5 +35,7 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC, } #endif - return new (C) FriendDecl(DC, L, Friend, FriendL); + FriendDecl *FD = new (C) FriendDecl(DC, L, Friend, FriendL); + cast<CXXRecordDecl>(DC)->pushFriendDecl(FD); + return FD; } diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index eca8bb4c2a9..85c4662846b 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclFriend.h" #include "clang/AST/ExprCXX.h" using namespace clang; @@ -55,7 +56,7 @@ struct EffectiveContext { explicit EffectiveContext(DeclContext *DC) { if (isa<FunctionDecl>(DC)) { - Function = cast<FunctionDecl>(DC); + Function = cast<FunctionDecl>(DC)->getCanonicalDecl(); DC = Function->getDeclContext(); } else Function = 0; @@ -85,10 +86,34 @@ static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) { static Sema::AccessResult GetFriendKind(Sema &S, const EffectiveContext &EC, const CXXRecordDecl *Class) { + // A class always has access to its own members. if (EC.isClass(Class)) return Sema::AR_accessible; - // FIXME: implement + // Okay, check friends. + for (CXXRecordDecl::friend_iterator I = Class->friend_begin(), + E = Class->friend_end(); I != E; ++I) { + FriendDecl *Friend = *I; + + if (Type *T = Friend->getFriendType()) { + if (EC.Record && + S.Context.hasSameType(QualType(T, 0), + S.Context.getTypeDeclType(EC.Record))) + return Sema::AR_accessible; + } else { + NamedDecl *D + = cast<NamedDecl>(Friend->getFriendDecl()->getCanonicalDecl()); + + // The decl pointers in EC have been canonicalized, so pointer + // equality is sufficient. + if (D == EC.Function || D == EC.Record) + return Sema::AR_accessible; + } + + // FIXME: templates! templated contexts! dependent delay! + } + + // That's it, give up. return Sema::AR_inaccessible; } |