From: Richard Smith Date: Wed, 1 Feb 2012 02:39:43 +0000 (+0000) Subject: constexpr: require 'this' to point to an object in a constexpr method call. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b04035a7b1a3c9b93cea72ae56dd2ea6e787bae9;p=clang constexpr: require 'this' to point to an object in a constexpr method call. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149467 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td index 0901263624..7bca36de0b 100644 --- a/include/clang/Basic/DiagnosticASTKinds.td +++ b/include/clang/Basic/DiagnosticASTKinds.td @@ -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< diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 8897667592..0f8de63bba 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -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; diff --git a/test/CXX/expr/expr.const/p2-0x.cpp b/test/CXX/expr/expr.const/p2-0x.cpp index 390364df63..1355bbb7c2 100644 --- a/test/CXX/expr/expr.const/p2-0x.cpp +++ b/test/CXX/expr/expr.const/p2-0x.cpp @@ -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! } }