aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-02-01 02:39:43 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-02-01 02:39:43 +0000
commitb04035a7b1a3c9b93cea72ae56dd2ea6e787bae9 (patch)
tree72d05deb2369a6fd6bfc370f45037bcfc3314184
parentb02e4629f78a0c0c0adf9d66b644e5932a781c7e (diff)
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
-rw-r--r--include/clang/Basic/DiagnosticASTKinds.td6
-rw-r--r--lib/AST/ExprConstant.cpp6
-rw-r--r--test/CXX/expr/expr.const/p2-0x.cpp9
3 files changed, 18 insertions, 3 deletions
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!
}
}