diff options
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 74 |
1 files changed, 54 insertions, 20 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index db81e48f1d..1361318854 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -720,7 +720,7 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) { /// if there is an error. bool Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, - AccessDiagnosticsKind ADK, + unsigned InaccessibleBaseID, unsigned AmbigiousBaseConvID, SourceLocation Loc, SourceRange Range, DeclarationName Name) { @@ -736,15 +736,12 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, (void)DerivationOkay; if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) { - if (ADK == ADK_quiet) + if (!InaccessibleBaseID) return false; // Check that the base class can be accessed. - switch (CheckBaseClassAccess(Loc, /*IsBaseToDerived*/ false, - Base, Derived, Paths.front(), - /*force*/ false, - /*unprivileged*/ false, - ADK)) { + switch (CheckBaseClassAccess(Loc, Base, Derived, Paths.front(), + InaccessibleBaseID)) { case AR_accessible: return false; case AR_inaccessible: return true; case AR_dependent: return false; @@ -780,7 +777,8 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, SourceLocation Loc, SourceRange Range, bool IgnoreAccess) { return CheckDerivedToBaseConversion(Derived, Base, - IgnoreAccess ? ADK_quiet : ADK_normal, + IgnoreAccess ? 0 + : diag::err_upcast_to_inaccessible_base, diag::err_ambiguous_derived_to_base_conv, Loc, Range, DeclarationName()); } @@ -1854,6 +1852,11 @@ Sema::MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor) { // Ignore dependent destructors. if (Destructor->isDependentContext()) return; + + // FIXME: all the access-control diagnostics are positioned on the + // field/base declaration. That's probably good; that said, the + // user might reasonably want to know why the destructor is being + // emitted, and we currently don't say. CXXRecordDecl *ClassDecl = Destructor->getParent(); @@ -1872,25 +1875,41 @@ Sema::MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor) { if (FieldClassDecl->hasTrivialDestructor()) continue; - const CXXDestructorDecl *Dtor = FieldClassDecl->getDestructor(Context); + CXXDestructorDecl *Dtor = FieldClassDecl->getDestructor(Context); + CheckDestructorAccess(Field->getLocation(), Dtor, + PartialDiagnostic(diag::err_access_dtor_field) + << Field->getDeclName() + << FieldType); + MarkDeclarationReferenced(Destructor->getLocation(), const_cast<CXXDestructorDecl*>(Dtor)); } + llvm::SmallPtrSet<const RecordType *, 8> DirectVirtualBases; + // Bases. for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), E = ClassDecl->bases_end(); Base != E; ++Base) { - // Ignore virtual bases. + // Bases are always records in a well-formed non-dependent class. + const RecordType *RT = Base->getType()->getAs<RecordType>(); + + // Remember direct virtual bases. if (Base->isVirtual()) - continue; + DirectVirtualBases.insert(RT); // Ignore trivial destructors. - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl()); if (BaseClassDecl->hasTrivialDestructor()) continue; + + CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context); + + // FIXME: caret should be on the start of the class name + CheckDestructorAccess(Base->getSourceRange().getBegin(), Dtor, + PartialDiagnostic(diag::err_access_dtor_base) + << Base->getType() + << Base->getSourceRange()); - const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context); MarkDeclarationReferenced(Destructor->getLocation(), const_cast<CXXDestructorDecl*>(Dtor)); } @@ -1898,13 +1917,24 @@ Sema::MarkBaseAndMemberDestructorsReferenced(CXXDestructorDecl *Destructor) { // Virtual bases. for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(), E = ClassDecl->vbases_end(); VBase != E; ++VBase) { + + // Bases are always records in a well-formed non-dependent class. + const RecordType *RT = VBase->getType()->getAs<RecordType>(); + + // Ignore direct virtual bases. + if (DirectVirtualBases.count(RT)) + continue; + // Ignore trivial destructors. - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl()); + CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl()); if (BaseClassDecl->hasTrivialDestructor()) continue; - - const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context); + + CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context); + CheckDestructorAccess(ClassDecl->getLocation(), Dtor, + PartialDiagnostic(diag::err_access_dtor_vbase) + << VBase->getType()); + MarkDeclarationReferenced(Destructor->getLocation(), const_cast<CXXDestructorDecl*>(Dtor)); } @@ -4062,7 +4092,10 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { !ClassDecl->hasTrivialDestructor()) { CXXDestructorDecl *Destructor = ClassDecl->getDestructor(Context); MarkDeclarationReferenced(VD->getLocation(), Destructor); - CheckDestructorAccess(VD->getLocation(), Record); + CheckDestructorAccess(VD->getLocation(), Destructor, + PartialDiagnostic(diag::err_access_dtor_var) + << VD->getDeclName() + << VD->getType()); } } @@ -5725,7 +5758,8 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, } // Check if we the conversion from derived to base is valid. - if (CheckDerivedToBaseConversion(NewClassTy, OldClassTy, ADK_covariance, + if (CheckDerivedToBaseConversion(NewClassTy, OldClassTy, + diag::err_covariant_return_inaccessible_base, diag::err_covariant_return_ambiguous_derived_to_base_conv, // FIXME: Should this point to the return type? New->getLocation(), SourceRange(), New->getDeclName())) { |