Implement CWG1170, which makes access-control errors into template

argument deduction failures. Only implemented in C++0x, since this is
a significant change in behavior from C++98/03.

llvm-svn: 131209
This commit is contained in:
Douglas Gregor 2011-05-11 23:45:11 +00:00
parent 7c6c90b35d
commit 347d626cf7
4 changed files with 53 additions and 3 deletions

View File

@ -32,6 +32,7 @@ td {
</ul>
<li><a href="#checking_upcoming_features">Checks for Upcoming Standard Language Features</a></li>
<ul>
<li><a href="#cxx_access_control_sfinae">C++0x SFINAE includes access control</a></li>
<li><a href="#cxx_alias_templates">C++0x alias templates</a></li>
<li><a href="#cxx_attributes">C++0x attributes</a></li>
<li><a href="#cxx_decltype">C++0x <tt>decltype()</tt></a></li>
@ -379,6 +380,10 @@ not yet implemented will be noted.</p>
<p>Use <tt>__has_feature(cxx_decltype)</tt> to determine if support for the
<tt>decltype()</tt> specifier is enabled.</p>
<h3 id="cxx_access_control_sfinae">C++0x SFINAE includes access control</h3>
<p>Use <tt>__has_feature(cxx_access_control_sfinae)</tt> to determine whether access-control errors (e.g., calling a private constructor) are considered to be template argument deduction errors (aka SFINAE errors), per <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1170">C++ DR1170</a>.</p>
<h3 id="cxx_alias_templates">C++0x alias templates</h3>
<p>Use <tt>__has_feature(cxx_alias_templates)</tt> to determine if support for

View File

@ -557,6 +557,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.Case("ownership_returns", true)
.Case("ownership_takes", true)
// C++0x features
.Case("cxx_access_control_sfinae", LangOpts.CPlusPlus0x)
.Case("cxx_alias_templates", LangOpts.CPlusPlus0x)
.Case("cxx_attributes", LangOpts.CPlusPlus0x)
.Case("cxx_auto_type", LangOpts.CPlusPlus0x)

View File

@ -577,9 +577,12 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
break;
case DiagnosticIDs::SFINAE_AccessControl:
// Unless access checking is specifically called out as a SFINAE
// error, report this diagnostic.
if (!SemaRef.AccessCheckingSFINAE)
// 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:

View File

@ -0,0 +1,41 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
#if !__has_feature(cxx_access_control_sfinae)
# error No support for access control as part of SFINAE?
#endif
typedef char yes_type;
typedef char (&no_type)[2];
template<unsigned N> struct unsigned_c { };
template<typename T>
class has_copy_constructor {
static T t;
template<typename U> static yes_type check(unsigned_c<sizeof(U(t))> * = 0);
template<typename U> static no_type check(...);
public:
static const bool value = (sizeof(check<T>(0)) == sizeof(yes_type));
};
struct HasCopy { };
struct HasNonConstCopy {
HasNonConstCopy(HasNonConstCopy&);
};
struct HasDeletedCopy {
HasDeletedCopy(const HasDeletedCopy&) = delete;
};
struct HasPrivateCopy {
private:
HasPrivateCopy(const HasPrivateCopy&);
};
int check0[has_copy_constructor<HasCopy>::value? 1 : -1];
int check1[has_copy_constructor<HasNonConstCopy>::value? 1 : -1];
int check2[has_copy_constructor<HasDeletedCopy>::value? -1 : 1];
int check3[has_copy_constructor<HasPrivateCopy>::value? -1 : 1];