[cfe-commits] r158228 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/DeclCXX.h lib/AST/Decl.cpp lib/AST/DeclCXX.cpp test/CXX/special/class.copy/p13-0x.cpp test/CXX/special/class.copy/p8-cxx11.cpp

Richard Smith richard-llvm at metafoo.co.uk
Fri Jun 8 14:09:23 PDT 2012


Author: rsmith
Date: Fri Jun  8 16:09:22 2012
New Revision: 158228

URL: http://llvm.org/viewvc/llvm-project?rev=158228&view=rev
Log:
PR13051: If a constructor is explicitly defaulted, it isn't marked as being
constexpr until we get to the end of the class definition. When that happens,
be sure to remember that the class actually does have a constexpr constructor.

This is a stopgap solution, which still doesn't cover the case of a class with
multiple copy constructors (only some of which are constexpr). We should be
performing constructor lookup when implicitly defining a constructor in order
to determine whether all constructors it invokes are constexpr.

Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/test/CXX/special/class.copy/p13-0x.cpp
    cfe/trunk/test/CXX/special/class.copy/p8-cxx11.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=158228&r1=158227&r2=158228&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Fri Jun  8 16:09:22 2012
@@ -1183,7 +1183,7 @@
   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 @@
   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.
   ///

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=158228&r1=158227&r2=158228&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Jun  8 16:09:22 2012
@@ -650,6 +650,9 @@
   void markedVirtualFunctionPure();
   friend void FunctionDecl::setPure(bool);
 
+  void markedConstructorConstexpr(CXXConstructorDecl *CD);
+  friend void FunctionDecl::setConstexpr(bool);
+
   friend class ASTNodeImporter;
 
 protected:
@@ -1119,7 +1122,7 @@
   bool hasConstexprDefaultConstructor() const {
     return data().HasConstexprDefaultConstructor ||
            (!data().UserDeclaredConstructor &&
-            defaultedDefaultConstructorIsConstexpr() && isLiteral());
+            defaultedDefaultConstructorIsConstexpr());
   }
 
   /// hasConstexprCopyConstructor - Whether this class has a constexpr copy
@@ -1127,7 +1130,7 @@
   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 @@
   bool hasConstexprMoveConstructor() const {
     return data().HasConstexprMoveConstructor ||
            (needsImplicitMoveConstructor() &&
-            data().DefaultedMoveConstructorIsConstexpr && isLiteral());
+            data().DefaultedMoveConstructorIsConstexpr);
   }
 
   // hasTrivialCopyConstructor - Whether this class has a trivial copy

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=158228&r1=158227&r2=158228&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Fri Jun  8 16:09:22 2012
@@ -1684,6 +1684,13 @@
       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());

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=158228&r1=158227&r2=158228&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Jun  8 16:09:22 2012
@@ -470,6 +470,18 @@
   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) &&

Modified: cfe/trunk/test/CXX/special/class.copy/p13-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p13-0x.cpp?rev=158228&r1=158227&r2=158228&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.copy/p13-0x.cpp (original)
+++ cfe/trunk/test/CXX/special/class.copy/p13-0x.cpp Fri Jun  8 16:09:22 2012
@@ -58,3 +58,59 @@
 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;
+  };
+}

Modified: cfe/trunk/test/CXX/special/class.copy/p8-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p8-cxx11.cpp?rev=158228&r1=158227&r2=158228&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.copy/p8-cxx11.cpp (original)
+++ cfe/trunk/test/CXX/special/class.copy/p8-cxx11.cpp Fri Jun  8 16:09:22 2012
@@ -43,6 +43,6 @@
   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 &);
 };





More information about the cfe-commits mailing list