[cfe-commits] r141768 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/AST/DeclCXX.cpp lib/Sema/SemaType.cpp test/CXX/basic/basic.types/p10.cpp

Richard Smith richard-llvm at metafoo.co.uk
Tue Oct 11 22:08:15 PDT 2011


Author: rsmith
Date: Wed Oct 12 00:08:15 2011
New Revision: 141768

URL: http://llvm.org/viewvc/llvm-project?rev=141768&view=rev
Log:
constexpr: don't consider class types with mutable members to be literal types.

The standard doesn't allow this, but mutable constexpr variables break the
semantics so badly that we can't reasonably accept them.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/test/CXX/basic/basic.types/p10.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=141768&r1=141767&r2=141768&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Oct 12 00:08:15 2011
@@ -1266,6 +1266,8 @@
   "%0 is not literal because it has a user-provided destructor">;
 def note_non_literal_nontrivial_dtor : Note<
   "%0 is not literal because it has a non-trivial destructor">;
+def note_non_literal_mutable_field : Note<
+  "%0 is not literal because it has a mutable data member">;
  
 // Objective-C++
 def err_objc_decls_may_only_appear_in_global_scope : Error<

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=141768&r1=141767&r2=141768&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Wed Oct 12 00:08:15 2011
@@ -719,7 +719,11 @@
     }
 
     // Record if this field is the first non-literal field or base.
-    if (!hasNonLiteralTypeFieldsOrBases() && !T->isLiteralType())
+    // As a slight variation on the standard, we regard mutable members as being
+    // non-literal, since mutating a constexpr variable would break C++11
+    // constant expression semantics.
+    if ((!hasNonLiteralTypeFieldsOrBases() && !T->isLiteralType()) ||
+        Field->isMutable())
       data().HasNonLiteralTypeFieldsOrBases = true;
 
     if (Field->hasInClassInitializer()) {

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=141768&r1=141767&r2=141768&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Wed Oct 12 00:08:15 2011
@@ -4127,6 +4127,9 @@
         Diag((*I)->getLocation(), diag::note_non_literal_field)
           << RD << (*I) << (*I)->getType();
         return true;
+      } else if ((*I)->isMutable()) {
+        Diag((*I)->getLocation(), diag::note_non_literal_mutable_field) << RD;
+        return true;
       }
     }
   } else if (!RD->hasTrivialDestructor()) {

Modified: cfe/trunk/test/CXX/basic/basic.types/p10.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.types/p10.cpp?rev=141768&r1=141767&r2=141768&view=diff
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.types/p10.cpp (original)
+++ cfe/trunk/test/CXX/basic/basic.types/p10.cpp Wed Oct 12 00:08:15 2011
@@ -106,3 +106,22 @@
   S s[3]; // expected-note {{data member 's' of non-literal type 'S [3]'}}
 };
 constexpr int f(ArrBad); // expected-error {{1st parameter type 'ArrBad' is not a literal type}}
+
+
+// As a non-conforming tweak to the standard, we do not allow a literal type to
+// have any mutable data members.
+namespace MutableMembers {
+  struct MM {
+    mutable int n; // expected-note {{'MM' is not literal because it has a mutable data member}}
+  };
+  constexpr int f(MM); // expected-error {{not a literal type}}
+
+  // Here's one reason why allowing this would be a disaster...
+  template<int n> struct Id { int k = n; };
+  int f() {
+    // FIXME: correctly check whether the initializer is a constant expression.
+    constexpr MM m = { 0 }; // desired-error {{must be a constant expression}}
+    ++m.n;
+    return Id<m.n>().k; // expected-error {{not an integral constant expression}}
+  }
+}





More information about the cfe-commits mailing list