//===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides Sema routines for C++ access control semantics.
//
//===----------------------------------------------------------------------===//
#include "Sema.h"
#include "SemaInit.h"
#include "Lookup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DependentDiagnostic.h"
#include "clang/AST/ExprCXX.h"
using namespace clang;
/// A copy of Sema's enum without AR_delayed.
enum AccessResult {
AR_accessible,
AR_inaccessible,
AR_dependent
};
/// SetMemberAccessSpecifier - Set the access specifier of a member.
/// Returns true on error (when the previous member decl access specifier
/// is different from the new member decl access specifier).
bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
NamedDecl *PrevMemberDecl,
AccessSpecifier LexicalAS) {
if (!PrevMemberDecl) {
// Use the lexical access specifier.
MemberDecl->setAccess(LexicalAS);
return false;
}
// C++ [class.access.spec]p3: When a member is redeclared its access
// specifier must be same as its initial declaration.
if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {
Diag(MemberDecl->getLocation(),
diag::err_class_redeclared_with_different_access)
<< MemberDecl << LexicalAS;
Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)
<< PrevMemberDecl << PrevMemberDecl->getAccess();
MemberDecl->setAccess(LexicalAS);
return true;
}
MemberDecl->setAccess(PrevMemberDecl->getAccess());
return false;
}
static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {
DeclContext *DC = D->getDeclContext();
// This can only happen at top: enum decls only "publish" their
// immediate members.
if (isa<EnumDecl>(DC))
DC = cast<EnumDecl>(DC)->getDeclContext();
CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC);
while (DeclaringClass->isAnonymousStructOrUnion())
DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext());
return DeclaringClass;
}
namespace {
struct EffectiveContext {
EffectiveContext() : Inner(0), Dependent(false) {}
explicit EffectiveContext(DeclContext *DC)
: Inner(DC),
Dependent