From: Richard Trieu <rtrieu@google.com> Date: Tue, 27 Sep 2016 23:44:07 +0000 (+0000) Subject: Revert r282547 and add test to show correct behavior. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=53874ed2c9a0976df7b8474cd673c0ece8f7bb02;p=clang Revert r282547 and add test to show correct behavior. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@282555 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 91c12d8f5c..eb8c3d2cc8 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -13850,6 +13850,12 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Dcl); if (MD) { + if (MD->getParent()->isDependentType()) { + MD->setDefaulted(); + MD->setExplicitlyDefaulted(); + return; + } + CXXSpecialMember Member = getSpecialMember(MD); if (Member == CXXInvalid) { if (!MD->isInvalidDecl()) @@ -13860,8 +13866,6 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { MD->setDefaulted(); MD->setExplicitlyDefaulted(); - if (MD->getParent()->isDependentType()) return; - // If this definition appears within the record, do the checking when // the record is complete. const FunctionDecl *Primary = MD; diff --git a/test/SemaCXX/cxx0x-defaulted-functions.cpp b/test/SemaCXX/cxx0x-defaulted-functions.cpp index 2bbc73012d..08d5dbd285 100644 --- a/test/SemaCXX/cxx0x-defaulted-functions.cpp +++ b/test/SemaCXX/cxx0x-defaulted-functions.cpp @@ -209,30 +209,29 @@ int fn() { } } -namespace templated_class { -template <typename T> -class X { - X() = default; - X(const X&) = default; - X(X&&) = default; - X &operator=(const X&) = default; - X &operator=(X&&) = default; - ~X() = default; - - X(T) = default; // expected-error {{only special member functions may be defaulted}} - void Run() = default; // expected-error {{only special member functions may be defaulted}} +namespace dependent_classes { +template <bool B, typename X, typename Y> +struct conditional; + +template <typename X, typename Y> +struct conditional<true, X, Y> { typedef X type; }; + +template <typename X, typename Y> +struct conditional<false, X, Y> { typedef Y type; }; + +template<bool B> struct X { + X(); + + // B == false triggers error for = default. + using T = typename conditional<B, const X &, int>::type; + X(T) = default; // expected-error {{only special member functions}} + + // Either value of B creates a constructor that can be default + using U = typename conditional<B, X&&, const X&>::type; + X(U) = default; +}; + +X<true> x1; +X<false> x2; // expected-note {{in instantiation}} - }; - template <typename T> - X<T>::X() = default; // expected-error {{definition of explicitly defaulted}} - template <typename T> - X<T>::X(const X<T>&) = default; // expected-error {{definition of explicitly defaulted}} - template <typename T> - X<T>::X(X<T>&&) = default; // expected-error {{definition of explicitly defaulted}} - template <typename T> - X<T> &X<T>::operator=(const X<T>&) = default; // expected-error {{definition of explicitly defaulted}} - template <typename T> - X<T> &X<T>::operator=(X<T>&&) = default; // expected-error {{definition of explicitly defaulted}} - template <typename T> - X<T>::~X() = default; // expected-error {{definition of explicitly defaulted}} }