]> granicus.if.org Git - clang/commitdiff
constexpr: require 'this' to point to an object in a constexpr method call.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 1 Feb 2012 02:39:43 +0000 (02:39 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 1 Feb 2012 02:39:43 +0000 (02:39 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149467 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticASTKinds.td
lib/AST/ExprConstant.cpp
test/CXX/expr/expr.const/p2-0x.cpp

index 090126362408cfcdbd8a3fb1360e64378a8f12c2..7bca36de0b3efdc32ef74f5515072ebd5421363a 100644 (file)
@@ -45,11 +45,13 @@ def note_constexpr_past_end : Note<
   "dereferenced pointer past the end of %select{|subobject of }0"
   "%select{temporary|%2}1 is not a constant expression">;
 def note_constexpr_past_end_subobject : Note<
-  "cannot access %select{base class|derived class|field|array element}0 of "
+  "cannot %select{access base class of|access derived class of|access field of|"
+  "access array element of|ERROR|call member function on}0 "
   "pointer past the end of object">;
 def note_constexpr_null_subobject : Note<
   "cannot %select{access base class of|access derived class of|access field of|"
-  "access array element of|perform pointer arithmetic on}0 null pointer">;
+  "access array element of|perform pointer arithmetic on|"
+  "call member function on}0 null pointer">;
 def note_constexpr_var_init_non_constant : Note<
   "initializer of %0 is not a constant expression">;
 def note_constexpr_typeid_polymorphic : Note<
index 8897667592b07293ac986e75053dd54f57564fdc..0f8de63bba1d0858d6683da9b03bb504b8af5b3d 100644 (file)
@@ -127,7 +127,8 @@ namespace {
 
   // The order of this enum is important for diagnostics.
   enum CheckSubobjectKind {
-    CSK_Base, CSK_Derived, CSK_Field, CSK_ArrayToPointer, CSK_ArrayIndex
+    CSK_Base, CSK_Derived, CSK_Field, CSK_ArrayToPointer, CSK_ArrayIndex,
+    CSK_This
   };
 
   /// A path from a glvalue to a subobject of that glvalue.
@@ -2362,6 +2363,9 @@ public:
     } else
       return Error(E);
 
+    if (This && !This->checkSubobject(Info, E, CSK_This))
+      return false;
+
     const FunctionDecl *Definition = 0;
     Stmt *Body = FD->getBody(Definition);
     APValue Result;
index 390364df635f5eccd642628f4362be7843b3b936..1355bbb7c23dd4bc7119438ec665409729e19d81 100644 (file)
@@ -186,6 +186,15 @@ namespace UndefinedBehavior {
     static_assert((B*)na == 0, "");
     constexpr const int &nf = nb->n; // expected-error {{constant expression}} expected-note {{cannot access field of null pointer}}
     constexpr const int &np = (*(int(*)[4])nullptr)[2]; // expected-error {{constant expression}} expected-note {{cannot access array element of null pointer}}
+
+    struct C {
+      constexpr int f() { return 0; }
+    } constexpr c = C();
+    constexpr int k1 = c.f(); // ok
+    constexpr int k2 = ((C*)nullptr)->f(); // expected-error {{constant expression}} expected-note {{cannot call member function on null pointer}}
+    constexpr int k3 = (&c)[1].f(); // expected-error {{constant expression}} expected-note {{cannot call member function on pointer past the end of object}}
+    C c2;
+    constexpr int k4 = c2.f(); // ok!
   }
 }