summaryrefslogtreecommitdiffstats
path: root/clang/test/CXX/basic/basic.def.odr
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-06-13 19:00:16 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-06-13 19:00:16 +0000
commit17965d42f420a0ca6d7bd5b9a0d7d472dfc5689d (patch)
treed4b3f16ca1e33d6a0f70eab45704213457617e5c /clang/test/CXX/basic/basic.def.odr
parent4244dd5e3f9e423db39dc8d1d235f67edf9b1875 (diff)
downloadbcm5719-llvm-17965d42f420a0ca6d7bd5b9a0d7d472dfc5689d.tar.gz
bcm5719-llvm-17965d42f420a0ca6d7bd5b9a0d7d472dfc5689d.zip
C++ DR712 and others: handle non-odr-use resulting from an lvalue-to-rvalue conversion applied to a member access or similar not-quite-trivial lvalue expression.
Summary: When a variable is named in a context where we can't directly emit a reference to it (because we don't know for sure that it's going to be defined, or it's from an enclosing function and not captured, or the reference might not "work" for some reason), we emit a copy of the variable as a global and use that for the known-to-be-read-only access. Reviewers: rjmccall Subscribers: jdoerfert, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D63157 llvm-svn: 363295
Diffstat (limited to 'clang/test/CXX/basic/basic.def.odr')
-rw-r--r--clang/test/CXX/basic/basic.def.odr/p2.cpp80
1 files changed, 80 insertions, 0 deletions
diff --git a/clang/test/CXX/basic/basic.def.odr/p2.cpp b/clang/test/CXX/basic/basic.def.odr/p2.cpp
new file mode 100644
index 00000000000..0ffd08c924f
--- /dev/null
+++ b/clang/test/CXX/basic/basic.def.odr/p2.cpp
@@ -0,0 +1,80 @@
+// RUN: %clang_cc1 -std=c++98 %s -Wno-unused -verify
+// RUN: %clang_cc1 -std=c++11 %s -Wno-unused -verify
+// RUN: %clang_cc1 -std=c++2a %s -Wno-unused -verify
+
+void use(int);
+
+void f() {
+ const int a = 1; // expected-note {{here}}
+
+#if __cplusplus >= 201103L
+ constexpr int arr[3] = {1, 2, 3}; // expected-note 2{{here}}
+
+ struct S { int x; int f() const; };
+ constexpr S s = {0}; // expected-note 3{{here}}
+ constexpr S *ps = nullptr;
+ S *const &psr = ps; // expected-note 2{{here}}
+#endif
+
+ struct Inner {
+ void test(int i) {
+ // id-expression
+ use(a);
+
+#if __cplusplus >= 201103L
+ // subscripting operation with an array operand
+ use(arr[i]);
+ use(i[arr]);
+ use((+arr)[i]); // expected-error {{reference to local variable}}
+ use(i[+arr]); // expected-error {{reference to local variable}}
+
+ // class member access naming non-static data member
+ use(s.x);
+ use(s.f()); // expected-error {{reference to local variable}}
+ use((&s)->x); // expected-error {{reference to local variable}}
+ use(ps->x); // ok (lvalue-to-rvalue conversion applied to id-expression)
+ use(psr->x); // expected-error {{reference to local variable}}
+
+ // class member access naming a static data member
+ // FIXME: How to test this?
+
+ // pointer-to-member expression
+ use(s.*&S::x);
+ use((s.*&S::f)()); // expected-error {{reference to local variable}}
+ use(ps->*&S::x); // ok (lvalue-to-rvalue conversion applied to id-expression)
+ use(psr->*&S::x); // expected-error {{reference to local variable}}
+#endif
+
+ // parentheses
+ use((a));
+#if __cplusplus >= 201103L
+ use((s.x));
+#endif
+
+ // glvalue conditional expression
+ use(i ? a : a);
+ use(i ? i : a);
+
+ // comma expression
+ use((i, a));
+ // FIXME: This is not an odr-use because it is a discarded-value
+ // expression applied to an expression whose potential result is 'a'.
+ use((a, a)); // expected-error {{reference to local variable}}
+
+ // (and combinations thereof)
+ use(a ? (i, a) : a);
+#if __cplusplus >= 201103L
+ use(a ? (i, a) : arr[a ? s.x : arr[a]]);
+#endif
+ }
+ };
+}
+
+// FIXME: Test that this behaves properly.
+namespace std_example {
+ struct S { static const int x = 0, y = 0; };
+ const int &f(const int &r);
+ bool b;
+ int n = b ? (1, S::x)
+ : f(S::y);
+}
OpenPOWER on IntegriCloud