Add include needed for MSVC.
[clang/acc.git] / lib / Sema / SemaAccess.cpp
blob31d8a3f5ab0750075d432b38535df1e0c5f781d1
1 //===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file provides Sema routines for C++ access control semantics.
12 //===----------------------------------------------------------------------===//
14 #include "SemaInherit.h"
15 #include "Sema.h"
16 #include "clang/AST/ASTContext.h"
17 using namespace clang;
19 /// SetMemberAccessSpecifier - Set the access specifier of a member.
20 /// Returns true on error (when the previous member decl access specifier
21 /// is different from the new member decl access specifier).
22 bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
23 NamedDecl *PrevMemberDecl,
24 AccessSpecifier LexicalAS) {
25 if (!PrevMemberDecl) {
26 // Use the lexical access specifier.
27 MemberDecl->setAccess(LexicalAS);
28 return false;
31 // C++ [class.access.spec]p3: When a member is redeclared its access
32 // specifier must be same as its initial declaration.
33 if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {
34 Diag(MemberDecl->getLocation(),
35 diag::err_class_redeclared_with_different_access)
36 << MemberDecl << LexicalAS;
37 Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)
38 << PrevMemberDecl << PrevMemberDecl->getAccess();
39 return true;
42 MemberDecl->setAccess(PrevMemberDecl->getAccess());
43 return false;
46 /// Find a class on the derivation path between Derived and Base that is
47 /// inaccessible. If @p NoPrivileges is true, special access rights (members
48 /// and friends) are not considered.
49 const CXXBaseSpecifier *Sema::FindInaccessibleBase(
50 QualType Derived, QualType Base, BasePaths &Paths, bool NoPrivileges)
52 Base = Context.getCanonicalType(Base).getUnqualifiedType();
53 assert(!Paths.isAmbiguous(Base) &&
54 "Can't check base class access if set of paths is ambiguous");
55 assert(Paths.isRecordingPaths() &&
56 "Can't check base class access without recorded paths");
59 const CXXBaseSpecifier *InaccessibleBase = 0;
61 const CXXRecordDecl *CurrentClassDecl = 0;
62 if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(getCurFunctionDecl()))
63 CurrentClassDecl = MD->getParent();
65 for (BasePaths::paths_iterator Path = Paths.begin(), PathsEnd = Paths.end();
66 Path != PathsEnd; ++Path) {
68 bool FoundInaccessibleBase = false;
70 for (BasePath::const_iterator Element = Path->begin(),
71 ElementEnd = Path->end(); Element != ElementEnd; ++Element) {
72 const CXXBaseSpecifier *Base = Element->Base;
74 switch (Base->getAccessSpecifier()) {
75 default:
76 assert(0 && "invalid access specifier");
77 case AS_public:
78 // Nothing to do.
79 break;
80 case AS_private:
81 // FIXME: Check if the current function/class is a friend.
82 if (NoPrivileges || CurrentClassDecl != Element->Class)
83 FoundInaccessibleBase = true;
84 break;
85 case AS_protected:
86 // FIXME: Implement
87 break;
90 if (FoundInaccessibleBase) {
91 InaccessibleBase = Base;
92 break;
96 if (!FoundInaccessibleBase) {
97 // We found a path to the base, our work here is done.
98 return 0;
102 assert(InaccessibleBase && "no path found, but no inaccessible base");
103 return InaccessibleBase;
106 /// CheckBaseClassAccess - Check that a derived class can access its base class
107 /// and report an error if it can't. [class.access.base]
108 bool Sema::CheckBaseClassAccess(QualType Derived, QualType Base,
109 unsigned InaccessibleBaseID,
110 BasePaths &Paths, SourceLocation AccessLoc,
111 DeclarationName Name) {
113 if (!getLangOptions().AccessControl)
114 return false;
115 const CXXBaseSpecifier *InaccessibleBase = FindInaccessibleBase(
116 Derived, Base, Paths);
118 if (InaccessibleBase) {
119 Diag(AccessLoc, InaccessibleBaseID)
120 << Derived << Base << Name;
122 AccessSpecifier AS = InaccessibleBase->getAccessSpecifierAsWritten();
124 // If there's no written access specifier, then the inheritance specifier
125 // is implicitly private.
126 if (AS == AS_none)
127 Diag(InaccessibleBase->getSourceRange().getBegin(),
128 diag::note_inheritance_implicitly_private_here);
129 else
130 Diag(InaccessibleBase->getSourceRange().getBegin(),
131 diag::note_inheritance_specifier_here) << AS;
133 return true;
136 return false;