aboutsummaryrefslogtreecommitdiff
path: root/clang/test/AST/ByteCode/cxx20.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/AST/ByteCode/cxx20.cpp')
-rw-r--r--clang/test/AST/ByteCode/cxx20.cpp85
1 files changed, 84 insertions, 1 deletions
diff --git a/clang/test/AST/ByteCode/cxx20.cpp b/clang/test/AST/ByteCode/cxx20.cpp
index 67bf9a7..1888998 100644
--- a/clang/test/AST/ByteCode/cxx20.cpp
+++ b/clang/test/AST/ByteCode/cxx20.cpp
@@ -1070,9 +1070,30 @@ namespace Virtual {
public:
int a = f();
- virtual constexpr int f() { return 10; }
+ virtual constexpr int f() const { return 10; }
};
+ K k;
+ static_assert(k.f() == 10); // both-error {{not an integral constant expression}} \
+ // both-note {{virtual function called on object 'k' whose dynamic type is not constant}}
+
+ void f() {
+ constexpr K k;
+ static_assert(k.f() == 10);
+ }
+
+ void f2() {
+ K k;
+ static_assert(k.f() == 10); // both-error {{not an integral constant expression}} \
+ // both-note {{virtual function called on object 'k' whose dynamic type is not constant}}
+ }
+
+ static_assert(K().f() == 10);
+
+ void f3() {
+ static_assert(K().f() == 10);
+ }
+
class L : public K {
public:
int b = f();
@@ -1083,6 +1104,42 @@ namespace Virtual {
static_assert(l.a == 10);
static_assert(l.b == 10);
static_assert(l.c == 10);
+ static_assert(l.f() == 10);
+
+ struct M {
+ K& mk = k;
+ };
+ static_assert(M{}.mk.f() == 10); // both-error {{not an integral constant expression}} \
+ // both-note {{virtual function called on object 'k' whose dynamic type is not constant}}
+
+ struct N {
+ K* mk = &k;
+ };
+ static_assert(N{}.mk->f() == 10); // both-error {{not an integral constant expression}} \
+ // both-note {{virtual function called on object 'k' whose dynamic type is not constant}}
+
+ extern K o;
+ static_assert(o.f() == 10); // both-error {{not an integral constant expression}} \
+ // both-note {{virtual function called on object 'o' whose dynamic type is not constant}}
+ static K p;
+ static_assert(p.f() == 10); // both-error {{not an integral constant expression}} \
+ // both-note {{virtual function called on object 'p' whose dynamic type is not constant}}
+
+ void f4() {
+ static K p;
+ static_assert(p.f() == 10); // both-error {{not an integral constant expression}} \
+ // both-note {{virtual function called on object 'p' whose dynamic type is not constant}}
+ }
+
+ const K q;
+ static_assert(q.f() == 10); // both-error {{not an integral constant expression}} \
+ // both-note {{virtual function called on object 'q' whose dynamic type is not constant}}
+
+ void f5() {
+ const K q;
+ static_assert(q.f() == 10); // both-error {{not an integral constant expression}} \
+ // both-note {{virtual function called on object 'q' whose dynamic type is not constant}}
+ }
}
namespace DiscardedTrivialCXXConstructExpr {
@@ -1100,3 +1157,29 @@ namespace DiscardedTrivialCXXConstructExpr {
constexpr int y = foo(12); // both-error {{must be initialized by a constant expression}} \
// both-note {{in call to}}
}
+
+namespace VirtualFunctionCallThroughArrayElem {
+ struct X {
+ constexpr virtual int foo() const {
+ return 3;
+ }
+ };
+ constexpr X xs[5];
+ static_assert(xs[3].foo() == 3);
+
+ constexpr X xs2[1][2];
+ static_assert(xs2[0].foo() == 3); // both-error {{is not a structure or union}}
+ static_assert(xs2[0][0].foo() == 3);
+
+ struct Y: public X {
+ constexpr int foo() const override {
+ return 1;
+ }
+ };
+ constexpr Y ys[20];
+ static_assert(ys[12].foo() == static_cast<const X&>(ys[12]).foo());
+
+ X a[3][4];
+ static_assert(a[2][3].foo()); // both-error {{not an integral constant expression}} \
+ // both-note {{virtual function called on object 'a[2][3]' whose dynamic type is not constant}}
+}