From: Anders Carlsson Date: Wed, 21 Apr 2010 18:47:17 +0000 (+0000) Subject: Pass the InitializedEntity to Sema::CheckConstructorAccess and use it to report diffe... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9a68a67c6ae4982001815cc04f69b8781058263a;p=clang Pass the InitializedEntity to Sema::CheckConstructorAccess and use it to report different diagnostics depending on which entity is being initialized. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102010 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index bbabb46c11..9a2a388bc0 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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; diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 636bb6a3d3..1506d8c2dc 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2644,6 +2644,7 @@ public: DeclAccessPair FoundDecl); AccessResult CheckConstructorAccess(SourceLocation Loc, CXXConstructorDecl *D, + const InitializedEntity &Entity, AccessSpecifier Access); AccessResult CheckDestructorAccess(SourceLocation Loc, CXXDestructorDecl *Dtor, diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index 352477b859..1658b699c6 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -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; + + case InitializedEntity::EK_Base: + AccessEntity.setDiag(PDiag(diag::err_access_ctor_base) + << Entity.getBaseSpecifier()->getType()); + break; + } - return CheckAccess(*this, UseLoc, Entity); + return CheckAccess(*this, UseLoc, AccessEntity); } /// Checks direct (i.e. non-inherited) access to an arbitrary class diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index a99f513609..fe7f79f9c5 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -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)) diff --git a/test/CXX/class.access/p4.cpp b/test/CXX/class.access/p4.cpp index 9bed7cd8fe..3d1578a4fc 100644 --- a/test/CXX/class.access/p4.cpp +++ b/test/CXX/class.access/p4.cpp @@ -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.