diff options
-rw-r--r-- | include/clang/AST/Decl.h | 6 | ||||
-rw-r--r-- | include/clang/AST/DeclCXX.h | 9 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 7 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 12 | ||||
-rw-r--r-- | test/CXX/special/class.copy/p13-0x.cpp | 56 | ||||
-rw-r--r-- | test/CXX/special/class.copy/p8-cxx11.cpp | 2 |
6 files changed, 85 insertions, 7 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 8ec69b43f0..a7bf599636 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -1183,7 +1183,7 @@ public: bool isARCPseudoStrong() const { return VarDeclBits.ARCPseudoStrong; } void setARCPseudoStrong(bool ps) { VarDeclBits.ARCPseudoStrong = ps; } - /// Whether this variable is (C++0x) constexpr. + /// Whether this variable is (C++11) constexpr. bool isConstexpr() const { return VarDeclBits.IsConstexpr; } void setConstexpr(bool IC) { VarDeclBits.IsConstexpr = IC; } @@ -1736,9 +1736,9 @@ public: bool hasInheritedPrototype() const { return HasInheritedPrototype; } void setHasInheritedPrototype(bool P = true) { HasInheritedPrototype = P; } - /// Whether this is a (C++0x) constexpr function or constexpr constructor. + /// Whether this is a (C++11) constexpr function or constexpr constructor. bool isConstexpr() const { return IsConstexpr; } - void setConstexpr(bool IC) { IsConstexpr = IC; } + void setConstexpr(bool IC); /// \brief Whether this function has been deleted. /// diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 6b44f777bb..21e8a98bef 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -650,6 +650,9 @@ class CXXRecordDecl : public RecordDecl { void markedVirtualFunctionPure(); friend void FunctionDecl::setPure(bool); + void markedConstructorConstexpr(CXXConstructorDecl *CD); + friend void FunctionDecl::setConstexpr(bool); + friend class ASTNodeImporter; protected: @@ -1119,7 +1122,7 @@ public: bool hasConstexprDefaultConstructor() const { return data().HasConstexprDefaultConstructor || (!data().UserDeclaredConstructor && - defaultedDefaultConstructorIsConstexpr() && isLiteral()); + defaultedDefaultConstructorIsConstexpr()); } /// hasConstexprCopyConstructor - Whether this class has a constexpr copy @@ -1127,7 +1130,7 @@ public: bool hasConstexprCopyConstructor() const { return data().HasConstexprCopyConstructor || (!data().DeclaredCopyConstructor && - data().DefaultedCopyConstructorIsConstexpr && isLiteral()); + data().DefaultedCopyConstructorIsConstexpr); } /// hasConstexprMoveConstructor - Whether this class has a constexpr move @@ -1135,7 +1138,7 @@ public: bool hasConstexprMoveConstructor() const { return data().HasConstexprMoveConstructor || (needsImplicitMoveConstructor() && - data().DefaultedMoveConstructorIsConstexpr && isLiteral()); + data().DefaultedMoveConstructorIsConstexpr); } // hasTrivialCopyConstructor - Whether this class has a trivial copy diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 1d5ff10f7b..ee90b23e5c 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1684,6 +1684,13 @@ void FunctionDecl::setPure(bool P) { Parent->markedVirtualFunctionPure(); } +void FunctionDecl::setConstexpr(bool IC) { + IsConstexpr = IC; + CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(this); + if (IC && CD) + CD->getParent()->markedConstructorConstexpr(CD); +} + bool FunctionDecl::isMain() const { const TranslationUnitDecl *tunit = dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext()); diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 1c0316db71..84aa7c5c88 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -470,6 +470,18 @@ void CXXRecordDecl::markedVirtualFunctionPure() { data().Abstract = true; } +void CXXRecordDecl::markedConstructorConstexpr(CXXConstructorDecl *CD) { + if (CD->isCopyConstructor()) + data().HasConstexprCopyConstructor = true; + else if (CD->isMoveConstructor()) + data().HasConstexprMoveConstructor = true; + else + data().HasConstexprNonCopyMoveConstructor = true; + + if (CD->isDefaultConstructor()) + data().HasConstexprDefaultConstructor = true; +} + void CXXRecordDecl::addedMember(Decl *D) { if (!D->isImplicit() && !isa<FieldDecl>(D) && diff --git a/test/CXX/special/class.copy/p13-0x.cpp b/test/CXX/special/class.copy/p13-0x.cpp index 0a9aa62145..5d436016a0 100644 --- a/test/CXX/special/class.copy/p13-0x.cpp +++ b/test/CXX/special/class.copy/p13-0x.cpp @@ -58,3 +58,59 @@ struct Constexpr5Base {}; struct Constexpr5 : Constexpr5Base { constexpr Constexpr5() {} }; constexpr Constexpr5 ce5move = Constexpr5(); constexpr Constexpr5 ce5copy = ce5move; + +// An explicitly-defaulted constructor doesn't become constexpr until the end of +// its class. Make sure we note that the class has a constexpr constructor when +// that happens. +namespace PR13052 { + template<typename T> struct S { + S() = default; // expected-note 2{{here}} + S(S&&) = default; + S(const S&) = default; + T t; + }; + + struct U { + U() = default; + U(U&&) = default; + U(const U&) = default; + }; + + struct V { + V(); // expected-note {{here}} + V(V&&) = default; + V(const V&) = default; + }; + + struct W { + W(); // expected-note {{here}} + }; + + static_assert(__is_literal_type(U), ""); + static_assert(!__is_literal_type(V), ""); + static_assert(!__is_literal_type(W), ""); + static_assert(__is_literal_type(S<U>), ""); + static_assert(!__is_literal_type(S<V>), ""); + static_assert(!__is_literal_type(S<W>), ""); + + struct X { + friend constexpr U::U() noexcept; + friend constexpr U::U(U&&) noexcept; + friend constexpr U::U(const U&) noexcept; + friend constexpr V::V(); // expected-error {{follows non-constexpr declaration}} + friend constexpr V::V(V&&) noexcept; + friend constexpr V::V(const V&) noexcept; + friend constexpr W::W(); // expected-error {{follows non-constexpr declaration}} + friend constexpr W::W(W&&) noexcept; + friend constexpr W::W(const W&) noexcept; + friend constexpr S<U>::S() noexcept; + friend constexpr S<U>::S(S<U>&&) noexcept; + friend constexpr S<U>::S(const S<U>&) noexcept; + friend constexpr S<V>::S(); // expected-error {{follows non-constexpr declaration}} + friend constexpr S<V>::S(S<V>&&) noexcept; + friend constexpr S<V>::S(const S<V>&) noexcept; + friend constexpr S<W>::S(); // expected-error {{follows non-constexpr declaration}} + friend constexpr S<W>::S(S<W>&&) noexcept; + friend constexpr S<W>::S(const S<W>&) noexcept; + }; +} diff --git a/test/CXX/special/class.copy/p8-cxx11.cpp b/test/CXX/special/class.copy/p8-cxx11.cpp index 02e6cd1c9a..a2613f4612 100644 --- a/test/CXX/special/class.copy/p8-cxx11.cpp +++ b/test/CXX/special/class.copy/p8-cxx11.cpp @@ -43,6 +43,6 @@ struct Test { friend C::C(C &); friend D::D(const D &); friend E::E(E &); - friend F::F(const F &); + constexpr friend F::F(const F &); friend G::G(G &); }; |