зеркало из https://github.com/microsoft/clang-1.git
-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:
Родитель
b224343723
Коммит
77faa365cb
|
@ -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());
|
||||
|
|
Загрузка…
Ссылка в новой задаче