-Wc++98-compat: warn if a SFINAE substitution in C++11 suppresses an access

control diagnostic.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142463 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Richard Smith 2011-10-19 00:07:01 +00:00
Родитель b224343723
Коммит 77faa365cb
4 изменённых файлов: 45 добавлений и 10 удалений

Просмотреть файл

@ -740,6 +740,11 @@ public:
assert(isActive() && "DiagnosticsEngine is inactive");
return DiagObj->CurDiagID;
}
/// \brief Retrieve the active diagnostic's location.
///
/// \pre \c isActive()
SourceLocation getLocation() const { return DiagObj->CurDiagLoc; }
/// \brief Clear out the current diagnostic.
void Clear() { DiagObj = 0; }

Просмотреть файл

@ -808,6 +808,9 @@ def note_access_constrained_by_path : Note<
" inheritance here">;
def note_access_protected_restricted : Note<
"object type %select{|%1 }0must derive from context type %2">;
def warn_cxx98_compat_sfinae_access_control : Warning<
"substitution failure due to access control is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore, NoSFINAE;
// C++ name lookup
def err_incomplete_nested_name_spec : Error<

Просмотреть файл

@ -625,18 +625,9 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
if (llvm::Optional<TemplateDeductionInfo*> Info = SemaRef.isSFINAEContext()) {
switch (DiagnosticIDs::getDiagnosticSFINAEResponse(getDiagID())) {
case DiagnosticIDs::SFINAE_Report:
// Fall through; we'll report the diagnostic below.
// We'll report the diagnostic below.
break;
case DiagnosticIDs::SFINAE_AccessControl:
// Per C++ Core Issue 1170, access control is part of SFINAE.
// Additionally, the AccessCheckingSFINAE flag can be used to temporary
// make access control a part of SFINAE for the purposes of checking
// type traits.
if (!SemaRef.AccessCheckingSFINAE &&
!SemaRef.getLangOptions().CPlusPlus0x)
break;
case DiagnosticIDs::SFINAE_SubstitutionFailure:
// Count this failure so that we know that template argument deduction
// has failed.
@ -646,6 +637,33 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
Clear();
return;
case DiagnosticIDs::SFINAE_AccessControl: {
// Per C++ Core Issue 1170, access control is part of SFINAE.
// Additionally, the AccessCheckingSFINAE flag can be used to temporary
// make access control a part of SFINAE for the purposes of checking
// type traits.
if (!SemaRef.AccessCheckingSFINAE &&
!SemaRef.getLangOptions().CPlusPlus0x)
break;
SourceLocation Loc = getLocation();
// Suppress this diagnostic.
++SemaRef.NumSFINAEErrors;
SemaRef.Diags.setLastDiagnosticIgnored();
SemaRef.Diags.Clear();
Clear();
// Now the diagnostic state is clear, produce a C++98 compatibility
// warning.
SemaRef.Diag(Loc, diag::warn_cxx98_compat_sfinae_access_control);
// The last diagnostic which Sema produced was ignored. Suppress any
// notes attached to it.
SemaRef.Diags.setLastDiagnosticIgnored();
return;
}
case DiagnosticIDs::SFINAE_Suppress:
// Make a copy of this suppressed diagnostic and store it with the
// template-deduction information;

Просмотреть файл

@ -170,3 +170,12 @@ struct BadFriends {
};
int n = {}; // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}}
class PrivateMember {
struct ImPrivate {};
};
template<typename T> typename T::ImPrivate SFINAEAccessControl(T t) { // expected-warning {{substitution failure due to access control is incompatible with C++98}} expected-note {{while substituting deduced template arguments into function template 'SFINAEAccessControl' [with T = PrivateMember]}}
return typename T::ImPrivate();
}
int SFINAEAccessControl(...) { return 0; }
int CheckSFINAEAccessControl = SFINAEAccessControl(PrivateMember());