clang API Documentation

Enumerations | Functions
SemaAccess.cpp File Reference
#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DependentDiagnostic.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
Include dependency graph for SemaAccess.cpp:

Go to the source code of this file.

Enumerations

enum  AccessResult { AR_accessible, AR_inaccessible, AR_dependent }
 A copy of Sema's enum without AR_delayed. More...

Functions

static CXXRecordDeclFindDeclaringClass (NamedDecl *D)
static bool MightInstantiateTo (const CXXRecordDecl *From, const CXXRecordDecl *To)
 Checks whether one class might instantiate to the other.
static AccessResult IsDerivedFromInclusive (const CXXRecordDecl *Derived, const CXXRecordDecl *Target)
static bool MightInstantiateTo (Sema &S, DeclContext *Context, DeclContext *Friend)
static bool MightInstantiateTo (Sema &S, CanQualType Context, CanQualType Friend)
static bool MightInstantiateTo (Sema &S, FunctionDecl *Context, FunctionDecl *Friend)
static bool MightInstantiateTo (Sema &S, FunctionTemplateDecl *Context, FunctionTemplateDecl *Friend)
static AccessResult MatchesFriend (Sema &S, const EffectiveContext &EC, const CXXRecordDecl *Friend)
static AccessResult MatchesFriend (Sema &S, const EffectiveContext &EC, CanQualType Friend)
static AccessResult MatchesFriend (Sema &S, const EffectiveContext &EC, ClassTemplateDecl *Friend)
static AccessResult MatchesFriend (Sema &S, const EffectiveContext &EC, FunctionDecl *Friend)
static AccessResult MatchesFriend (Sema &S, const EffectiveContext &EC, FunctionTemplateDecl *Friend)
static AccessResult MatchesFriend (Sema &S, const EffectiveContext &EC, FriendDecl *FriendD)
static AccessResult GetFriendKind (Sema &S, const EffectiveContext &EC, const CXXRecordDecl *Class)
static AccessResult GetProtectedFriendKind (Sema &S, const EffectiveContext &EC, const CXXRecordDecl *InstanceContext, const CXXRecordDecl *NamingClass)
static AccessResult HasAccess (Sema &S, const EffectiveContext &EC, const CXXRecordDecl *NamingClass, AccessSpecifier Access, const AccessTarget &Target)
static CXXBasePathFindBestPath (Sema &S, const EffectiveContext &EC, AccessTarget &Target, AccessSpecifier FinalAccess, CXXBasePaths &Paths)
static bool TryDiagnoseProtectedAccess (Sema &S, const EffectiveContext &EC, AccessTarget &Target)
static void diagnoseBadDirectAccess (Sema &S, const EffectiveContext &EC, AccessTarget &entity)
static void DiagnoseAccessPath (Sema &S, const EffectiveContext &EC, AccessTarget &entity)
static void DiagnoseBadAccess (Sema &S, SourceLocation Loc, const EffectiveContext &EC, AccessTarget &Entity)
static bool IsMicrosoftUsingDeclarationAccessBug (Sema &S, SourceLocation AccessLoc, AccessTarget &Entity)
static AccessResult IsAccessible (Sema &S, const EffectiveContext &EC, AccessTarget &Entity)
static void DelayDependentAccess (Sema &S, const EffectiveContext &EC, SourceLocation Loc, const AccessTarget &Entity)
static AccessResult CheckEffectiveAccess (Sema &S, const EffectiveContext &EC, SourceLocation Loc, AccessTarget &Entity)
 Checks access to an entity from the given effective context.
static Sema::AccessResult CheckAccess (Sema &S, SourceLocation Loc, AccessTarget &Entity)

Enumeration Type Documentation

A copy of Sema's enum without AR_delayed.

Enumerator:
AR_accessible 
AR_inaccessible 
AR_dependent 

Definition at line 30 of file SemaAccess.cpp.


Function Documentation

static Sema::AccessResult CheckAccess ( Sema S,
SourceLocation  Loc,
AccessTarget &  Entity 
) [static]
static AccessResult CheckEffectiveAccess ( Sema S,
const EffectiveContext &  EC,
SourceLocation  Loc,
AccessTarget &  Entity 
) [static]
static void DelayDependentAccess ( Sema S,
const EffectiveContext &  EC,
SourceLocation  Loc,
const AccessTarget &  Entity 
) [static]
static void DiagnoseAccessPath ( Sema S,
const EffectiveContext &  EC,
AccessTarget &  entity 
) [static]
static void DiagnoseBadAccess ( Sema S,
SourceLocation  Loc,
const EffectiveContext &  EC,
AccessTarget &  Entity 
) [static]
static void diagnoseBadDirectAccess ( Sema S,
const EffectiveContext &  EC,
AccessTarget &  entity 
) [static]

We are unable to access a given declaration due to its direct access control; diagnose that.

Definition at line 1093 of file SemaAccess.cpp.

References clang::AS_protected, clang::DeclContext::decls(), clang::Sema::Diag(), FindDeclaringClass(), clang::DeclContext::getParent(), clang::Decl::getPreviousDecl(), and TryDiagnoseProtectedAccess().

Referenced by DiagnoseAccessPath().

static CXXBasePath* FindBestPath ( Sema S,
const EffectiveContext &  EC,
AccessTarget &  Target,
AccessSpecifier  FinalAccess,
CXXBasePaths Paths 
) [static]

Finds the best path from the naming class to the declaring class, taking friend declarations into account.

C++0x [class.access.base]p5: A member m is accessible at the point R when named in class N if [M1] m as a member of N is public, or [M2] m as a member of N is private, and R occurs in a member or friend of class N, or [M3] m as a member of N is protected, and R occurs in a member or friend of class N, or in a member or friend of a class P derived from N, where m as a member of P is public, private, or protected, or [M4] there exists a base class B of N that is accessible at R, and m is accessible at R when named in class B.

C++0x [class.access.base]p4: A base class B of N is accessible at R, if [B1] an invented public member of B would be a public member of N, or [B2] R occurs in a member or friend of class N, and an invented public member of B would be a private or protected member of N, or [B3] R occurs in a member or friend of a class P derived from N, and an invented public member of B would be a private or protected member of P, or [B4] there exists a class S such that B is a base class of S accessible at R and S is a base class of N accessible at R.

Along a single inheritance path we can restate both of these iteratively:

First, we note that M1-4 are equivalent to B1-4 if the member is treated as a notional base of its declaring class with inheritance access equivalent to the member's access. Therefore we need only ask whether a class B is accessible from a class N in context R.

Let B_1 .. B_n be the inheritance path in question (i.e. where B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of B_i). For i in 1..n, we will calculate ACAB(i), the access to the closest accessible base in the path: Access(a, b) = (* access on the base specifier from a to b *) Merge(a, forbidden) = forbidden Merge(a, private) = forbidden Merge(a, b) = min(a,b) Accessible(c, forbidden) = false Accessible(c, private) = (R is c) || IsFriend(c, R) Accessible(c, protected) = (R derived from c) || IsFriend(c, R) Accessible(c, public) = true ACAB(n) = public ACAB(i) = let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in if Accessible(B_i, AccessToBase) then public else AccessToBase

B is an accessible base of N at R iff ACAB(1) = public.

Parameters:
FinalAccessthe access of the "final step", or AS_public if there is no final step.
Returns:
null if friendship is dependent

Definition at line 926 of file SemaAccess.cpp.

References clang::CXXBasePath::Access, AR_accessible, AR_dependent, AR_inaccessible, clang::AS_none, clang::AS_private, clang::AS_public, clang::CXXBasePaths::begin(), clang::CXXBasePaths::end(), clang::CXXRecordDecl::getCanonicalDecl(), HasAccess(), and clang::CXXRecordDecl::isDerivedFrom().

Referenced by DiagnoseAccessPath(), and IsAccessible().

static CXXRecordDecl* FindDeclaringClass ( NamedDecl D) [static]
static AccessResult GetFriendKind ( Sema S,
const EffectiveContext &  EC,
const CXXRecordDecl Class 
) [static]
static AccessResult GetProtectedFriendKind ( Sema S,
const EffectiveContext &  EC,
const CXXRecordDecl InstanceContext,
const CXXRecordDecl NamingClass 
) [static]

Search for a class P that EC is a friend of, under the constraint InstanceContext <= P if InstanceContext exists, or else NamingClass <= P and with the additional restriction that a protected member of NamingClass would have some natural access in P, which implicitly imposes the constraint that P <= NamingClass.

This isn't quite the condition laid out in the standard. Instead of saying that a notional protected member of NamingClass would have to have some natural access in P, it says the actual target has to have some natural access in P, which opens up the possibility that the target (which is not necessarily a member of NamingClass) might be more accessible along some path not passing through it. That's really a bad idea, though, because it introduces two problems:

  • Most importantly, it breaks encapsulation because you can access a forbidden base class's members by directly subclassing it elsewhere.
  • It also makes access substantially harder to compute because it breaks the hill-climbing algorithm: knowing that the target is accessible in some base class would no longer let you change the question solely to whether the base class is accessible, because the original target might have been more accessible because of crazy subclassing. So we don't implement that.

Definition at line 710 of file SemaAccess.cpp.

References AR_accessible, AR_dependent, AR_inaccessible, clang::CXXRecordDecl::getCanonicalDecl(), and GetFriendKind().

Referenced by HasAccess().

static AccessResult HasAccess ( Sema S,
const EffectiveContext &  EC,
const CXXRecordDecl NamingClass,
AccessSpecifier  Access,
const AccessTarget &  Target 
) [static]
static AccessResult IsAccessible ( Sema S,
const EffectiveContext &  EC,
AccessTarget &  Entity 
) [static]

Determines whether the accessed entity is accessible. Public members have been weeded out by this point.

Definition at line 1314 of file SemaAccess.cpp.

References clang::CXXBasePath::Access, AR_accessible, AR_dependent, AR_inaccessible, clang::AS_none, clang::AS_public, FindBestPath(), clang::Decl::getAccess(), and HasAccess().

Referenced by CheckEffectiveAccess(), and clang::Sema::IsSimplyAccessible().

static AccessResult IsDerivedFromInclusive ( const CXXRecordDecl Derived,
const CXXRecordDecl Target 
) [static]

Checks whether one class is derived from another, inclusively. Properly indicates when it couldn't be determined due to dependence.

This should probably be donated to AST or at least Sema.

Definition at line 274 of file SemaAccess.cpp.

References AR_accessible, AR_dependent, AR_inaccessible, clang::CXXRecordDecl::bases(), clang::Type::getAs(), clang::CXXRecordDecl::getCanonicalDecl(), clang::CXXRecordDecl::hasDefinition(), clang::DeclContext::isDependentContext(), clang::Type::isDependentType(), and MightInstantiateTo().

Referenced by HasAccess(), and TryDiagnoseProtectedAccess().

static bool IsMicrosoftUsingDeclarationAccessBug ( Sema S,
SourceLocation  AccessLoc,
AccessTarget &  Entity 
) [static]

MSVC has a bug where if during an using declaration name lookup, the declaration found is unaccessible (private) and that declaration was bring into scope via another using declaration whose target declaration is accessible (public) then no error is generated. Example: class A { public: int f(); }; class B : public A { private: using A::f; }; class C : public B { private: using B::f; };

Here, B::f is private so this should fail in Standard C++, but because B::f refers to A::f which is public MSVC accepts it.

Definition at line 1294 of file SemaAccess.cpp.

References clang::AS_private, clang::AS_protected, clang::AS_public, clang::Sema::Diag(), clang::Decl::getAccess(), and clang::NamedDecl::getQualifiedNameAsString().

Referenced by CheckEffectiveAccess().

static AccessResult MatchesFriend ( Sema S,
const EffectiveContext &  EC,
const CXXRecordDecl Friend 
) [static]
static AccessResult MatchesFriend ( Sema S,
const EffectiveContext &  EC,
CanQualType  Friend 
) [static]
static AccessResult MatchesFriend ( Sema S,
const EffectiveContext &  EC,
ClassTemplateDecl Friend 
) [static]

Determines whether the given friend class template matches anything in the effective context.

Definition at line 438 of file SemaAccess.cpp.

References AR_accessible, AR_dependent, AR_inaccessible, clang::ClassTemplateDecl::getCanonicalDecl(), clang::Decl::getDeclContext(), clang::NamedDecl::getDeclName(), clang::CXXRecordDecl::getDescribedClassTemplate(), MightInstantiateTo(), and Record.

static AccessResult MatchesFriend ( Sema S,
const EffectiveContext &  EC,
FunctionDecl Friend 
) [static]

Determines whether the given friend function matches anything in the effective context.

Definition at line 491 of file SemaAccess.cpp.

References AR_accessible, AR_dependent, AR_inaccessible, and MightInstantiateTo().

static AccessResult MatchesFriend ( Sema S,
const EffectiveContext &  EC,
FunctionTemplateDecl Friend 
) [static]

Determines whether the given friend function template matches anything in the effective context.

Definition at line 510 of file SemaAccess.cpp.

References AR_accessible, AR_dependent, AR_inaccessible, clang::FunctionTemplateDecl::getCanonicalDecl(), and MightInstantiateTo().

static AccessResult MatchesFriend ( Sema S,
const EffectiveContext &  EC,
FriendDecl FriendD 
) [static]

Determines whether the given friend declaration matches anything in the effective context.

Definition at line 540 of file SemaAccess.cpp.

References AR_accessible, clang::Decl::getCanonicalDecl(), clang::FriendDecl::getFriendDecl(), clang::FriendDecl::getFriendType(), clang::Decl::isInvalidDecl(), clang::FriendDecl::isUnsupportedFriend(), and MatchesFriend().

static bool MightInstantiateTo ( const CXXRecordDecl From,
const CXXRecordDecl To 
) [static]
static bool MightInstantiateTo ( Sema S,
DeclContext Context,
DeclContext Friend 
) [static]
static bool MightInstantiateTo ( Sema S,
CanQualType  Context,
CanQualType  Friend 
) [static]

Definition at line 344 of file SemaAccess.cpp.

static bool MightInstantiateTo ( Sema S,
FunctionDecl Context,
FunctionDecl Friend 
) [static]
static bool MightInstantiateTo ( Sema S,
FunctionTemplateDecl Context,
FunctionTemplateDecl Friend 
) [static]
static bool TryDiagnoseProtectedAccess ( Sema S,
const EffectiveContext &  EC,
AccessTarget &  Target 
) [static]

Given that an entity has protected natural access, check whether access might be denied because of the protected member access restriction.

Returns:
true if a note was emitted

Definition at line 1018 of file SemaAccess.cpp.

References AR_accessible, AR_dependent, AR_inaccessible, clang::Sema::Context, clang::Sema::Diag(), clang::Decl::getAsFunction(), clang::Decl::getLocation(), clang::ASTContext::getTypeDeclType(), and IsDerivedFromInclusive().

Referenced by diagnoseBadDirectAccess().