diff options
author | John McCall <rjmccall@apple.com> | 2010-03-19 07:35:19 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-03-19 07:35:19 +0000 |
commit | 9aa472c45d2bd81b7b52c225e8acc560d716db97 (patch) | |
tree | 9707af8aa3f84c899e0588d40aec11738ac6d9a3 | |
parent | 5de65721bd31e57f883634d9f10b1bff75c4ffc2 (diff) |
Remember the "found declaration" for an overload candidate, which is the
entity (if applicable) which was actually looked up. If a candidate was found
via a using declaration, this is the UsingShadowDecl; otherwise, if
the candidate is template specialization, this is the template; otherwise,
this is the function.
The point of this exercise is that "found declarations" are the entities
we do access control for, not their underlying declarations. Broadly speaking,
this patch fixes access control for using declarations.
There is a *lot* of redundant code calling into the overload-resolution APIs;
we really ought to clean that up.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98945 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/UnresolvedSet.h | 1 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 39 | ||||
-rw-r--r-- | lib/Sema/SemaAccess.cpp | 44 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 11 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 25 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 96 | ||||
-rw-r--r-- | lib/Sema/SemaInit.h | 7 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 186 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.h | 14 |
10 files changed, 225 insertions, 201 deletions
diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h index 9c59229e31..553f04d76a 100644 --- a/include/clang/AST/UnresolvedSet.h +++ b/include/clang/AST/UnresolvedSet.h @@ -94,6 +94,7 @@ public: NamedDecl *getDecl() const { return ir->getDecl(); } AccessSpecifier getAccess() const { return ir->getAccess(); } + DeclAccessPair getPair() const { return *ir; } NamedDecl *operator*() const { return getDecl(); } diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 6c655e55b4..747fd88978 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -321,6 +321,14 @@ public: Diag(0) { } + AccessedEntity(MemberNonce _, + CXXRecordDecl *NamingClass, + DeclAccessPair FoundDecl) + : Access(FoundDecl.getAccess()), IsMember(true), + Target(FoundDecl.getDecl()), NamingClass(NamingClass), + Diag(0) { + } + AccessedEntity(BaseNonce _, CXXRecordDecl *BaseClass, CXXRecordDecl *DerivedClass, @@ -1131,12 +1139,12 @@ public: typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet; void AddOverloadCandidate(NamedDecl *Function, - AccessSpecifier Access, + DeclAccessPair FoundDecl, Expr **Args, unsigned NumArgs, OverloadCandidateSet &CandidateSet); void AddOverloadCandidate(FunctionDecl *Function, - AccessSpecifier Access, + DeclAccessPair FoundDecl, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, @@ -1146,20 +1154,21 @@ public: Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false); - void AddMethodCandidate(NamedDecl *Decl, AccessSpecifier Access, + void AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversion = false, bool ForceRValue = false); - void AddMethodCandidate(CXXMethodDecl *Method, AccessSpecifier Access, + void AddMethodCandidate(CXXMethodDecl *Method, + DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, QualType ObjectType, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, bool ForceRValue = false); void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, - AccessSpecifier Access, + DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, const TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, @@ -1168,24 +1177,24 @@ public: bool SuppressUserConversions = false, bool ForceRValue = false); void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, - AccessSpecifier Access, + DeclAccessPair FoundDecl, const TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, bool ForceRValue = false); void AddConversionCandidate(CXXConversionDecl *Conversion, - AccessSpecifier Access, + DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, OverloadCandidateSet& CandidateSet); void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, - AccessSpecifier Access, + DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, OverloadCandidateSet &CandidateSet); void AddSurrogateCandidate(CXXConversionDecl *Conversion, - AccessSpecifier Access, + DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, const FunctionProtoType *Proto, QualType ObjectTy, Expr **Args, unsigned NumArgs, @@ -2623,16 +2632,13 @@ public: AccessSpecifier LexicalAS); AccessResult CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, - NamedDecl *D, - AccessSpecifier Access); + DeclAccessPair FoundDecl); AccessResult CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, - NamedDecl *D, - AccessSpecifier Access); + DeclAccessPair FoundDecl); AccessResult CheckAllocationAccess(SourceLocation OperatorLoc, SourceRange PlacementRange, CXXRecordDecl *NamingClass, - NamedDecl *Allocator, - AccessSpecifier Access); + DeclAccessPair FoundDecl); AccessResult CheckConstructorAccess(SourceLocation Loc, CXXConstructorDecl *D, AccessSpecifier Access); @@ -2645,8 +2651,7 @@ public: AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr, Expr *ArgExpr, - NamedDecl *D, - AccessSpecifier Access); + DeclAccessPair FoundDecl); AccessResult CheckBaseClassAccess(SourceLocation AccessLoc, QualType Base, QualType Derived, const CXXBasePath &Path, diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index 171ed3783e..40b320c1be 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -527,15 +527,13 @@ void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx) { } Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, - NamedDecl *D, - AccessSpecifier Access) { + DeclAccessPair Found) { if (!getLangOptions().AccessControl || !E->getNamingClass() || - Access == AS_public) + Found.getAccess() == AS_public) return AR_accessible; - AccessedEntity Entity(AccessedEntity::Member, - E->getNamingClass(), Access, D); + AccessedEntity Entity(AccessedEntity::Member, E->getNamingClass(), Found); Entity.setDiag(diag::err_access) << E->getSourceRange(); return CheckAccess(*this, E->getNameLoc(), Entity); @@ -544,14 +542,12 @@ Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, /// Perform access-control checking on a previously-unresolved member /// access which has now been resolved to a member. Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, - NamedDecl *D, - AccessSpecifier Access) { + DeclAccessPair Found) { if (!getLangOptions().AccessControl || - Access == AS_public) + Found.getAccess() == AS_public) return AR_accessible; - AccessedEntity Entity(AccessedEntity::Member, - E->getNamingClass(), Access, D); + AccessedEntity Entity(AccessedEntity::Member, E->getNamingClass(), Found); Entity.setDiag(diag::err_access) << E->getSourceRange(); return CheckAccess(*this, E->getMemberLoc(), Entity); @@ -569,7 +565,8 @@ Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc, return AR_accessible; CXXRecordDecl *NamingClass = Dtor->getParent(); - AccessedEntity Entity(AccessedEntity::Member, NamingClass, Access, Dtor); + AccessedEntity Entity(AccessedEntity::Member, NamingClass, + DeclAccessPair::make(Dtor, Access)); Entity.setDiag(PDiag); // TODO: avoid copy return CheckAccess(*this, Loc, Entity); @@ -584,8 +581,8 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, return AR_accessible; CXXRecordDecl *NamingClass = Constructor->getParent(); - AccessedEntity Entity(AccessedEntity::Member, - NamingClass, Access, Constructor); + AccessedEntity Entity(AccessedEntity::Member, NamingClass, + DeclAccessPair::make(Constructor, Access)); Entity.setDiag(diag::err_access_ctor); return CheckAccess(*this, UseLoc, Entity); @@ -602,7 +599,8 @@ Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc, return AR_accessible; CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext()); - AccessedEntity Entity(AccessedEntity::Member, NamingClass, Access, Target); + AccessedEntity Entity(AccessedEntity::Member, NamingClass, + DeclAccessPair::make(Target, Access)); Entity.setDiag(Diag); return CheckAccess(*this, UseLoc, Entity); } @@ -612,14 +610,13 @@ Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc, Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc, SourceRange PlacementRange, CXXRecordDecl *NamingClass, - NamedDecl *Fn, - AccessSpecifier Access) { + DeclAccessPair Found) { if (!getLangOptions().AccessControl || !NamingClass || - Access == AS_public) + Found.getAccess() == AS_public) return AR_accessible; - AccessedEntity Entity(AccessedEntity::Member, NamingClass, Access, Fn); + AccessedEntity Entity(AccessedEntity::Member, NamingClass, Found); Entity.setDiag(diag::err_access) << PlacementRange; @@ -631,18 +628,16 @@ Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc, Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, Expr *ObjectExpr, Expr *ArgExpr, - NamedDecl *MemberOperator, - AccessSpecifier Access) { + DeclAccessPair Found) { if (!getLangOptions().AccessControl || - Access == AS_public) + Found.getAccess() == AS_public) return AR_accessible; const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>(); assert(RT && "found member operator but object expr not of record type"); CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl()); - AccessedEntity Entity(AccessedEntity::Member, - NamingClass, Access, MemberOperator); + AccessedEntity Entity(AccessedEntity::Member, NamingClass, Found); Entity.setDiag(diag::err_access) << ObjectExpr->getSourceRange() << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange()); @@ -694,7 +689,8 @@ void Sema::CheckLookupAccess(const LookupResult &R) { for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { if (I.getAccess() != AS_public) { AccessedEntity Entity(AccessedEntity::Member, - R.getNamingClass(), I.getAccess(), *I); + R.getNamingClass(), + I.getPair()); Entity.setDiag(diag::err_access); CheckAccess(*this, R.getNameLoc(), Entity); diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 4693fa974e..317eef8d60 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -2253,7 +2253,8 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, Results.push_back(ResultCandidate(FDecl)); else // FIXME: access? - AddOverloadCandidate(FDecl, AS_none, Args, NumArgs, CandidateSet, + AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), + Args, NumArgs, CandidateSet, false, false, /*PartialOverloading*/ true); } } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index c0b699a518..13a7ead76b 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4204,6 +4204,8 @@ static void AddConstructorInitializationCandidates(Sema &SemaRef, DeclContext::lookup_const_iterator Con, ConEnd; for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(ConstructorName); Con != ConEnd; ++Con) { + DeclAccessPair FoundDecl = DeclAccessPair::make(*Con, (*Con)->getAccess()); + // Find the constructor (which may be a template). CXXConstructorDecl *Constructor = 0; FunctionTemplateDecl *ConstructorTmpl= dyn_cast<FunctionTemplateDecl>(*Con); @@ -4220,12 +4222,11 @@ static void AddConstructorInitializationCandidates(Sema &SemaRef, ((Kind.getKind() == InitializationKind::IK_Default) && Constructor->isDefaultConstructor())) { if (ConstructorTmpl) - SemaRef.AddTemplateOverloadCandidate(ConstructorTmpl, - ConstructorTmpl->getAccess(), + SemaRef.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, /*ExplicitArgs*/ 0, Args, NumArgs, CandidateSet); else - SemaRef.AddOverloadCandidate(Constructor, Constructor->getAccess(), + SemaRef.AddOverloadCandidate(Constructor, FoundDecl, Args, NumArgs, CandidateSet); } } @@ -4535,10 +4536,10 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, if (Conv->getConversionType()->isLValueReferenceType() && (AllowExplicit || !Conv->isExplicit())) { if (ConvTemplate) - AddTemplateConversionCandidate(ConvTemplate, I.getAccess(), ActingDC, + AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, Init, DeclType, CandidateSet); else - AddConversionCandidate(Conv, I.getAccess(), ActingDC, Init, + AddConversionCandidate(Conv, I.getPair(), ActingDC, Init, DeclType, CandidateSet); } } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 2a55894f22..366089f2ab 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -921,7 +921,9 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, } FoundDelete.suppressDiagnostics(); - UnresolvedSet<4> Matches; + + llvm::SmallVector<std::pair<DeclAccessPair,FunctionDecl*>, 2> Matches; + if (NumPlaceArgs > 0) { // C++ [expr.new]p20: // A declaration of a placement deallocation function matches the @@ -964,7 +966,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, Fn = cast<FunctionDecl>((*D)->getUnderlyingDecl()); if (Context.hasSameType(Fn->getType(), ExpectedFunctionType)) - Matches.addDecl(Fn, D.getAccess()); + Matches.push_back(std::make_pair(D.getPair(), Fn)); } } else { // C++ [expr.new]p20: @@ -975,7 +977,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, D != DEnd; ++D) { if (FunctionDecl *Fn = dyn_cast<FunctionDecl>((*D)->getUnderlyingDecl())) if (isNonPlacementDeallocationFunction(Fn)) - Matches.addDecl(D.getDecl(), D.getAccess()); + Matches.push_back(std::make_pair(D.getPair(), Fn)); } } @@ -984,7 +986,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // function, that function will be called; otherwise, no // deallocation function will be called. if (Matches.size() == 1) { - OperatorDelete = cast<FunctionDecl>(Matches[0]->getUnderlyingDecl()); + OperatorDelete = Matches[0].second; // C++0x [expr.new]p20: // If the lookup finds the two-parameter form of a usual @@ -1001,7 +1003,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, << DeleteName; } else { CheckAllocationAccess(StartLoc, Range, FoundDelete.getNamingClass(), - Matches[0].getDecl(), Matches[0].getAccess()); + Matches[0].first); } } @@ -1033,18 +1035,18 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, Alloc != AllocEnd; ++Alloc) { // Even member operator new/delete are implicitly treated as // static, so don't use AddMemberCandidate. + NamedDecl *D = (*Alloc)->getUnderlyingDecl(); - if (FunctionTemplateDecl *FnTemplate = - dyn_cast<FunctionTemplateDecl>((*Alloc)->getUnderlyingDecl())) { - AddTemplateOverloadCandidate(FnTemplate, Alloc.getAccess(), + if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl>(D)) { + AddTemplateOverloadCandidate(FnTemplate, Alloc.getPair(), /*ExplicitTemplateArgs=*/0, Args, NumArgs, Candidates, /*SuppressUserConversions=*/false); continue; } - FunctionDecl *Fn = cast<FunctionDecl>((*Alloc)->getUnderlyingDecl()); - AddOverloadCandidate(Fn, Alloc.getAccess(), Args, NumArgs, Candidates, + FunctionDecl *Fn = cast<FunctionDecl>(D); + AddOverloadCandidate(Fn, Alloc.getPair(), Args, NumArgs, Candidates, /*SuppressUserConversions=*/false); } @@ -1066,8 +1068,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, return true; } Operator = FnDecl; - CheckAllocationAccess(StartLoc, Range, R.getNamingClass(), - FnDecl, Best->getAccess()); + CheckAllocationAccess(StartLoc, Range, R.getNamingClass(), Best->FoundDecl); return false; } diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 98a7eec232..f86ae51c28 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -2007,7 +2007,8 @@ void InitializationSequence::AddAddressOverloadResolutionStep( S.Kind = SK_ResolveAddressOfOverloadedFunction; S.Type = Function->getType(); // Access is currently ignored for these. - S.Function = DeclAccessPair::make(Function, AccessSpecifier(0)); + S.Function.Function = Function; + S.Function.FoundDecl = DeclAccessPair::make(Function, AS_none); Steps.push_back(S); } @@ -2028,12 +2029,13 @@ void InitializationSequence::AddReferenceBindingStep(QualType T, } void InitializationSequence::AddUserConversionStep(FunctionDecl *Function, - AccessSpecifier Access, + DeclAccessPair FoundDecl, QualType T) { Step S; S.Kind = SK_UserConversion; S.Type = T; - S.Function = DeclAccessPair::make(Function, Access); + S.Function.Function = Function; + S.Function.FoundDecl = FoundDecl; Steps.push_back(S); } @@ -2071,7 +2073,8 @@ InitializationSequence::AddConstructorInitializationStep( Step S; S.Kind = SK_ConstructorInitialization; S.Type = T; - S.Function = DeclAccessPair::make(Constructor, Access); + S.Function.Function = Constructor; + S.Function.FoundDecl = DeclAccessPair::make(Constructor, Access); Steps.push_back(S); } @@ -2198,25 +2201,26 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, DeclContext::lookup_iterator Con, ConEnd; for (llvm::tie(Con, ConEnd) = T1RecordDecl->lookup(ConstructorName); Con != ConEnd; ++Con) { + NamedDecl *D = *Con; + DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); + // Find the constructor (which may be a template). CXXConstructorDecl *Constructor = 0; - FunctionTemplateDecl *ConstructorTmpl - = dyn_cast<FunctionTemplateDecl>(*Con); + FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D); if (ConstructorTmpl) Constructor = cast<CXXConstructorDecl>( ConstructorTmpl->getTemplatedDecl()); else - Constructor = cast<CXXConstructorDecl>(*Con); + Constructor = cast<CXXConstructorDecl>(D); if (!Constructor->isInvalidDecl() && Constructor->isConvertingConstructor(AllowExplicit)) { if (ConstructorTmpl) - S.AddTemplateOverloadCandidate(ConstructorTmpl, - ConstructorTmpl->getAccess(), + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, /*ExplicitArgs*/ 0, &Initializer, 1, CandidateSet); else - S.AddOverloadCandidate(Constructor, Constructor->getAccess(), + S.AddOverloadCandidate(Constructor, FoundDecl, &Initializer, 1, CandidateSet); } } @@ -2257,11 +2261,11 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, if ((AllowExplicit || !Conv->isExplicit()) && (AllowRValues || Conv->getConversionType()->isLValueReferenceType())){ if (ConvTemplate) - S.AddTemplateConversionCandidate(ConvTemplate, I.getAccess(), + S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, Initializer, ToType, CandidateSet); else - S.AddConversionCandidate(Conv, I.getAccess(), ActingDC, + S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer, ToType, CandidateSet); } } @@ -2284,7 +2288,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, T2 = cv1T1; // Add the user-defined conversion step. - Sequence.AddUserConversionStep(Function, Best->getAccess(), + Sequence.AddUserConversionStep(Function, Best->FoundDecl, T2.getNonReferenceType()); // Determine whether we need to perform derived-to-base or @@ -2574,25 +2578,26 @@ static void TryConstructorInitialization(Sema &S, DeclContext::lookup_iterator Con, ConEnd; for (llvm::tie(Con, ConEnd) = DestRecordDecl->lookup(ConstructorName); Con != ConEnd; ++Con) { + NamedDecl *D = *Con; + DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); + // Find the constructor (which may be a template). CXXConstructorDecl *Constructor = 0; - FunctionTemplateDecl *ConstructorTmpl - = dyn_cast<FunctionTemplateDecl>(*Con); + FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D); if (ConstructorTmpl) Constructor = cast<CXXConstructorDecl>( ConstructorTmpl->getTemplatedDecl()); else - Constructor = cast<CXXConstructorDecl>(*Con); + Constructor = cast<CXXConstructorDecl>(D); if (!Constructor->isInvalidDecl() && (AllowExplicit || !Constructor->isExplicit())) { if (ConstructorTmpl) - S.AddTemplateOverloadCandidate(ConstructorTmpl, - ConstructorTmpl->getAccess(), + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, /*ExplicitArgs*/ 0, Args, NumArgs, CandidateSet); else - S.AddOverloadCandidate(Constructor, Constructor->getAccess(), + S.AddOverloadCandidate(Constructor, FoundDecl, Args, NumArgs, CandidateSet); } } @@ -2623,11 +2628,11 @@ static void TryConstructorInitialization(Sema &S, // Add the constructor initialization step. Any cv-qualification conversion is // subsumed by the initialization. if (Kind.getKind() == InitializationKind::IK_Copy) { - Sequence.AddUserConversionStep(Best->Function, Best->getAccess(), DestType); + Sequence.AddUserConversionStep(Best->Function, Best->FoundDecl, DestType); } else { Sequence.AddConstructorInitializationStep( cast<CXXConstructorDecl>(Best->Function), - Best->getAccess(), + Best->FoundDecl.getAccess(), DestType); } } @@ -2744,25 +2749,27 @@ static void TryUserDefinedConversion(Sema &S, DeclContext::lookup_iterator Con, ConEnd; for (llvm::tie(Con, ConEnd) = DestRecordDecl->lookup(ConstructorName); Con != ConEnd; ++Con) { + NamedDecl *D = *Con; + DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); + // Find the constructor (which may be a template). CXXConstructorDecl *Constructor = 0; FunctionTemplateDecl *ConstructorTmpl - = dyn_cast<FunctionTemplateDecl>(*Con); + = dyn_cast<FunctionTemplateDecl>(D); if (ConstructorTmpl) Constructor = cast<CXXConstructorDecl>( ConstructorTmpl->getTemplatedDecl()); else - Constructor = cast<CXXConstructorDecl>(*Con); + Constructor = cast<CXXConstructorDecl>(D); if (!Constructor->isInvalidDecl() && Constructor->isConvertingConstructor(AllowExplicit)) { if (ConstructorTmpl) - S.AddTemplateOverloadCandidate(ConstructorTmpl, - ConstructorTmpl->getAccess(), + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, /*ExplicitArgs*/ 0, &Initializer, 1, CandidateSet); else - S.AddOverloadCandidate(Constructor, Constructor->getAccess(), + S.AddOverloadCandidate(Constructor, FoundDecl, &Initializer, 1, CandidateSet); } } @@ -2799,11 +2806,11 @@ static void TryUserDefinedConversion(Sema &S, if (AllowExplicit || !Conv->isExplicit()) { if (ConvTemplate) - S.AddTemplateConversionCandidate(ConvTemplate, I.getAccess(), + S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, CandidateSet); else - S.AddConversionCandidate(Conv, I.getAccess(), ActingDC, + S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer, DestType, CandidateSet); } } @@ -2825,13 +2832,13 @@ static void TryUserDefinedConversion(Sema &S, if (isa<CXXConstructorDecl>(Function)) { // Add the user-defined conversion step. Any cv-qualification conversion is // subsumed by the initialization. - Sequence.AddUserConversionStep(Function, Best->getAccess(), DestType); + Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType); return; } // Add the user-defined conversion step that calls the conversion function. QualType ConvType = Function->getResultType().getNonReferenceType(); - Sequence.AddUserConversionStep(Function, Best->getAccess(), ConvType); + Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType); // If the conversion following the call to the conversion function is // interesting, add it as a separate step. @@ -3135,8 +3142,10 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S, if (!Constructor || Constructor->isInvalidDecl() || !Constructor->isCopyConstructor()) continue; - - S.AddOverloadCandidate(Constructor, Constructor->getAccess(), + + DeclAccessPair FoundDecl + = DeclAccessPair::make(Constructor, Constructor->getAccess()); + S.AddOverloadCandidate(Constructor, FoundDecl, &CurInitExpr, 1, CandidateSet); } @@ -3170,6 +3179,10 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S, return S.ExprError(); } + S.CheckConstructorAccess(Loc, + cast<CXXConstructorDecl>(Best->Function), + Best->FoundDecl.getAccess()); + CurInit.release(); return S.BuildCXXConstructExpr(Loc, CurInitExpr->getType(), cast<CXXConstructorDecl>(Best->Function), @@ -3303,7 +3316,7 @@ InitializationSequence::Perform(Sema &S, // initializer to reflect that choice. // Access control was done in overload resolution. CurInit = S.FixOverloadedFunctionReference(move(CurInit), - cast<FunctionDecl>(Step->Function.getDecl())); + Step->Function.Function); break; case SK_CastDerivedToBaseRValue: @@ -3367,8 +3380,8 @@ InitializationSequence::Perform(Sema &S, // or a conversion function. CastExpr::CastKind CastKind = CastExpr::CK_Unknown; bool IsCopy = false; - FunctionDecl *Fn = cast<FunctionDecl>(Step->Function.getDecl()); - AccessSpecifier FnAccess = Step->Function.getAccess(); + FunctionDecl *Fn = Step->Function.Function; + DeclAccessPair FoundFn = Step->Function.FoundDecl; if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) { // Build a call to the selected constructor. ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S); @@ -3390,7 +3403,8 @@ InitializationSequence::Perform(Sema &S, if (CurInit.isInvalid()) return S.ExprError(); - S.CheckConstructorAccess(Kind.getLocation(), Constructor, FnAccess); + S.CheckConstructorAccess(Kind.getLocation(), Constructor, + FoundFn.getAccess()); CastKind = CastExpr::CK_ConstructorConversion; QualType Class = S.Context.getTypeDeclType(Constructor->getParent()); @@ -3402,7 +3416,7 @@ InitializationSequence::Perform(Sema &S, CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn); S.CheckMemberOperatorAccess(Kind.getLocation(), CurInitExpr, 0, - Conversion, FnAccess); + FoundFn); // FIXME: Should we move this initialization into a separate // derived-to-base conversion? I believe the answer is "no", because @@ -3469,7 +3483,7 @@ InitializationSequence::Perform(Sema &S, case SK_ConstructorInitialization: { CXXConstructorDecl *Constructor - = cast<CXXConstructorDecl>(Step->Function.getDecl()); + = cast<CXXConstructorDecl>(Step->Function.Function); // Build a call to the selected constructor. ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S); @@ -3506,7 +3520,8 @@ InitializationSequence::Perform(Sema &S, return S.ExprError(); // Only check access if all of that succeeded. - S.CheckConstructorAccess(Loc, Constructor, Step->Function.getAccess()); + S.CheckConstructorAccess(Loc, Constructor, + Step->Function.FoundDecl.getAccess()); bool Elidable = cast<CXXConstructExpr>((Expr *)CurInit.get())->isElidable(); @@ -3972,7 +3987,8 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const { break; case SK_UserConversion: - OS << "user-defined conversion via " << S->Function->getNameAsString(); + OS << "user-defined conversion via " + << S->Function.Function->getNameAsString(); break; case SK_QualificationConversionRValue: diff --git a/lib/Sema/SemaInit.h b/lib/Sema/SemaInit.h index 2b49df28fe..18a0938f7c 100644 --- a/lib/Sema/SemaInit.h +++ b/lib/Sema/SemaInit.h @@ -454,7 +454,10 @@ public: /// Always a FunctionDecl. /// For conversion decls, the naming class is the source type. /// For construct decls, the naming class is the target type. - DeclAccessPair Function; + struct { + FunctionDecl *Function; + DeclAccessPair FoundDecl; + } Function; /// \brief When Kind = SK_ConversionSequence, the implicit conversion /// sequence @@ -622,7 +625,7 @@ public: /// \brief Add a new step invoking a conversion function, which is either /// a constructor or a conversion function. void AddUserConversionStep(FunctionDecl *Function, - AccessSpecifier Access, + DeclAccessPair FoundDecl, QualType T); /// \brief Add a new step that performs a qualification conversion to the diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index f73ec9cb61..410bf9a7c1 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1525,28 +1525,30 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType, for (llvm::tie(Con, ConEnd) = ToRecordDecl->lookup(ConstructorName); Con != ConEnd; ++Con) { + NamedDecl *D = *Con; + DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); + // Find the constructor (which may be a template). CXXConstructorDecl *Constructor = 0; FunctionTemplateDecl *ConstructorTmpl - = dyn_cast<FunctionTemplateDecl>(*Con); + = dyn_cast<FunctionTemplateDecl>(D); if (ConstructorTmpl) Constructor = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl()); else - Constructor = cast<CXXConstructorDecl>(*Con); + Constructor = cast<CXXConstructorDecl>(D); if (!Constructor->isInvalidDecl() && Constructor->isConvertingConstructor(AllowExplicit)) { if (ConstructorTmpl) - AddTemplateOverloadCandidate(ConstructorTmpl, - ConstructorTmpl->getAccess(), + AddTemplateOv |