Pass the InitializedEntity to Sema::CheckConstructorAccess and use it to report different diagnostics depending on which entity is being initialized.
llvm-svn: 102010
This commit is contained in:
parent
4c7f50afb8
commit
a01874bf44
|
@ -459,6 +459,9 @@ def err_access :
|
|||
def err_access_ctor :
|
||||
Error<"calling a %select{private|protected}0 constructor of class %2">,
|
||||
NoSFINAE;
|
||||
def err_access_ctor_base :
|
||||
Error<"base class %0 has %select{private|protected}1 constructor">,
|
||||
NoSFINAE;
|
||||
def err_access_dtor_base :
|
||||
Error<"base class %0 has %select{private|protected}1 destructor">,
|
||||
NoSFINAE;
|
||||
|
|
|
@ -2644,6 +2644,7 @@ public:
|
|||
DeclAccessPair FoundDecl);
|
||||
AccessResult CheckConstructorAccess(SourceLocation Loc,
|
||||
CXXConstructorDecl *D,
|
||||
const InitializedEntity &Entity,
|
||||
AccessSpecifier Access);
|
||||
AccessResult CheckDestructorAccess(SourceLocation Loc,
|
||||
CXXDestructorDecl *Dtor,
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Sema.h"
|
||||
#include "SemaInit.h"
|
||||
#include "Lookup.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/CXXInheritance.h"
|
||||
|
@ -1127,18 +1128,28 @@ Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
|
|||
/// Checks access to a constructor.
|
||||
Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
|
||||
CXXConstructorDecl *Constructor,
|
||||
const InitializedEntity &Entity,
|
||||
AccessSpecifier Access) {
|
||||
if (!getLangOptions().AccessControl ||
|
||||
Access == AS_public)
|
||||
return AR_accessible;
|
||||
|
||||
CXXRecordDecl *NamingClass = Constructor->getParent();
|
||||
AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
|
||||
DeclAccessPair::make(Constructor, Access),
|
||||
QualType());
|
||||
Entity.setDiag(diag::err_access_ctor);
|
||||
AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass,
|
||||
DeclAccessPair::make(Constructor, Access),
|
||||
QualType());
|
||||
switch (Entity.getKind()) {
|
||||
default:
|
||||
AccessEntity.setDiag(diag::err_access_ctor);
|
||||
break;
|
||||
|
||||
return CheckAccess(*this, UseLoc, Entity);
|
||||
case InitializedEntity::EK_Base:
|
||||
AccessEntity.setDiag(PDiag(diag::err_access_ctor_base)
|
||||
<< Entity.getBaseSpecifier()->getType());
|
||||
break;
|
||||
}
|
||||
|
||||
return CheckAccess(*this, UseLoc, AccessEntity);
|
||||
}
|
||||
|
||||
/// Checks direct (i.e. non-inherited) access to an arbitrary class
|
||||
|
|
|
@ -3258,7 +3258,7 @@ static Sema::OwningExprResult CopyObject(Sema &S,
|
|||
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S);
|
||||
CurInit.release(); // Ownership transferred into MultiExprArg, below.
|
||||
|
||||
S.CheckConstructorAccess(Loc, Constructor,
|
||||
S.CheckConstructorAccess(Loc, Constructor, Entity,
|
||||
Best->FoundDecl.getAccess());
|
||||
|
||||
if (IsExtraneousCopy) {
|
||||
|
@ -3521,7 +3521,7 @@ InitializationSequence::Perform(Sema &S,
|
|||
if (CurInit.isInvalid())
|
||||
return S.ExprError();
|
||||
|
||||
S.CheckConstructorAccess(Kind.getLocation(), Constructor,
|
||||
S.CheckConstructorAccess(Kind.getLocation(), Constructor, Entity,
|
||||
FoundFn.getAccess());
|
||||
|
||||
CastKind = CastExpr::CK_ConstructorConversion;
|
||||
|
@ -3647,7 +3647,7 @@ InitializationSequence::Perform(Sema &S,
|
|||
return S.ExprError();
|
||||
|
||||
// Only check access if all of that succeeded.
|
||||
S.CheckConstructorAccess(Loc, Constructor,
|
||||
S.CheckConstructorAccess(Loc, Constructor, Entity,
|
||||
Step->Function.FoundDecl.getAccess());
|
||||
|
||||
if (shouldBindAsTemporary(Entity))
|
||||
|
|
|
@ -88,13 +88,25 @@ namespace test1 {
|
|||
namespace test2 {
|
||||
class A {
|
||||
private:
|
||||
A(); // expected-note {{declared private here}}
|
||||
A(); // expected-note 3 {{declared private here}}
|
||||
|
||||
static A foo;
|
||||
};
|
||||
|
||||
A a; // expected-error {{calling a private constructor}}
|
||||
A A::foo; // okay
|
||||
|
||||
class B : A { }; // expected-error {{base class 'test2::A' has private constructor}}
|
||||
B b;
|
||||
|
||||
class C : virtual A {
|
||||
public:
|
||||
C();
|
||||
};
|
||||
|
||||
// FIXME: It would be better if this said something about A being an inherited virtual base.
|
||||
class D : C { }; // expected-error {{base class 'test2::A' has private constructor}}
|
||||
D d;
|
||||
}
|
||||
|
||||
// Implicit destructor calls.
|
||||
|
|
Loading…
Reference in New Issue