aboutsummaryrefslogtreecommitdiff
path: root/clang/test
diff options
context:
space:
mode:
authorTimm Baeder <tbaeder@redhat.com>2025-01-09 11:42:35 +0100
committerGitHub <noreply@github.com>2025-01-09 11:42:35 +0100
commitfd6baa477fa13a4b893aeeba7fce92eb6a1f4962 (patch)
tree24dd2bba87b0a8afe7b364b9a1666a47510c4f92 /clang/test
parentb79ed8729b3d6d5482481c41a7de2cd75b0f61df (diff)
downloadllvm-fd6baa477fa13a4b893aeeba7fce92eb6a1f4962.zip
llvm-fd6baa477fa13a4b893aeeba7fce92eb6a1f4962.tar.gz
llvm-fd6baa477fa13a4b893aeeba7fce92eb6a1f4962.tar.bz2
[clang][ExprConst] Add diagnostics for invalid binary arithmetic (#118475)
... between unrelated declarations or literals. Leaving this small (I haven't run the whole test suite locally) to get some feedback on the wording and implementation first. The output of the sample in https://github.com/llvm/llvm-project/issues/117409 is now: ```console ./array.cpp:57:6: warning: expression result unused [-Wunused-value] 57 | am - aj.af(); | ~~ ^ ~~~~~~~ ./array.cpp:70:8: error: call to consteval function 'L::L<bx>' is not a constant expression 70 | q(0, [] { | ^ ./array.cpp:57:6: note: arithmetic on addresses of literals has unspecified value 57 | am - aj.af(); | ^ ./array.cpp:62:5: note: in call to 'al(&""[0], {&""[0]})' 62 | al(bp.af(), k); | ^~~~~~~~~~~~~~ ./array.cpp:70:8: note: in call to 'L<bx>({})' 70 | q(0, [] { | ^~~~ 71 | struct bx { | ~~~~~~~~~~~ 72 | constexpr operator ab<g<l<decltype(""[0])>::e>::e>() { return t(""); } | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 73 | }; | ~~ 74 | return bx(); | ~~~~~~~~~~~~ 75 | }()); | ~~~ ``` The output for ```c++ int a, b; constexpr int n = &b - &a ``` is now: ```console ./array.cpp:80:15: error: constexpr variable 'n' must be initialized by a constant expression 80 | constexpr int n = &b - &a; | ^ ~~~~~~~ ./array.cpp:80:22: note: arithmetic involving '&b' and '&a' has unspecified value 80 | constexpr int n = &b - &a; | ^ 1 error generated. ```
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/AST/ByteCode/builtin-functions.cpp2
-rw-r--r--clang/test/AST/ByteCode/cxx20.cpp2
-rw-r--r--clang/test/AST/ByteCode/functions.cpp4
-rw-r--r--clang/test/AST/ByteCode/literals.cpp4
-rw-r--r--clang/test/CXX/expr/expr.const/p2-0x.cpp30
-rw-r--r--clang/test/SemaCXX/constant-expression-cxx11.cpp26
-rw-r--r--clang/test/SemaCXX/constant-expression-cxx14.cpp2
7 files changed, 43 insertions, 27 deletions
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp
index 7237640..7034e8c 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -1010,7 +1010,7 @@ namespace FunctionStart {
void a(void) {}
static_assert(__builtin_function_start(a) == a, ""); // both-error {{not an integral constant expression}} \
// ref-note {{comparison against opaque constant address '&__builtin_function_start(a)'}} \
- // expected-note {{comparison of addresses of literals has unspecified value}}
+ // expected-note {{comparison of addresses of potentially overlapping literals has unspecified value}}
}
namespace BuiltinInImplicitCtor {
diff --git a/clang/test/AST/ByteCode/cxx20.cpp b/clang/test/AST/ByteCode/cxx20.cpp
index dea4055..268362c 100644
--- a/clang/test/AST/ByteCode/cxx20.cpp
+++ b/clang/test/AST/ByteCode/cxx20.cpp
@@ -115,7 +115,7 @@ constexpr auto name1() { return "name1"; }
constexpr auto name2() { return "name2"; }
constexpr auto b3 = name1() == name1(); // ref-error {{must be initialized by a constant expression}} \
- // ref-note {{comparison of addresses of literals}}
+ // ref-note {{comparison of addresses of potentially overlapping literals}}
constexpr auto b4 = name1() == name2();
static_assert(!b4);
diff --git a/clang/test/AST/ByteCode/functions.cpp b/clang/test/AST/ByteCode/functions.cpp
index 10bea3a..66693a1 100644
--- a/clang/test/AST/ByteCode/functions.cpp
+++ b/clang/test/AST/ByteCode/functions.cpp
@@ -208,11 +208,11 @@ namespace Comparison {
constexpr bool u13 = pf < pg; // both-warning {{ordered comparison of function pointers}} \
// both-error {{must be initialized by a constant expression}} \
- // both-note {{comparison between '&f' and '&g' has unspecified value}}
+ // both-note {{comparison between pointers to unrelated objects '&f' and '&g' has unspecified value}}
constexpr bool u14 = pf < (void(*)())nullptr; // both-warning {{ordered comparison of function pointers}} \
// both-error {{must be initialized by a constant expression}} \
- // both-note {{comparison between '&f' and 'nullptr' has unspecified value}}
+ // both-note {{comparison between pointers to unrelated objects '&f' and 'nullptr' has unspecified value}}
diff --git a/clang/test/AST/ByteCode/literals.cpp b/clang/test/AST/ByteCode/literals.cpp
index 662823c..3d415a9 100644
--- a/clang/test/AST/ByteCode/literals.cpp
+++ b/clang/test/AST/ByteCode/literals.cpp
@@ -194,7 +194,7 @@ namespace PointerComparison {
constexpr void *qv = (void*)&s.b;
constexpr bool v1 = null < (int*)0;
constexpr bool v2 = null < pv; // both-error {{must be initialized by a constant expression}} \
- // both-note {{comparison between 'nullptr' and '&s.a' has unspecified value}}
+ // both-note {{comparison between pointers to unrelated objects 'nullptr' and '&s.a' has unspecified value}}
constexpr bool v3 = null == pv; // ok
constexpr bool v4 = qv == pv; // ok
@@ -202,7 +202,7 @@ namespace PointerComparison {
constexpr bool v5 = qv >= pv;
constexpr bool v8 = qv > (void*)&s.a;
constexpr bool v6 = qv > null; // both-error {{must be initialized by a constant expression}} \
- // both-note {{comparison between '&s.b' and 'nullptr' has unspecified value}}
+ // both-note {{comparison between pointers to unrelated objects '&s.b' and 'nullptr' has unspecified value}}
constexpr bool v7 = qv <= (void*)&s.b; // ok
diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp
index 67160ba..df5ce10 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -510,22 +510,22 @@ namespace UnspecifiedRelations {
// different objects that are not members of the same array or to different
// functions, or if only one of them is null, the results of p<q, p>q, p<=q,
// and p>=q are unspecified.
- constexpr bool u1 = p < q; // expected-error {{constant expression}} expected-note {{comparison between '&a' and '&b' has unspecified value}}
- constexpr bool u2 = p > q; // expected-error {{constant expression}} expected-note {{comparison between '&a' and '&b' has unspecified value}}
- constexpr bool u3 = p <= q; // expected-error {{constant expression}} expected-note {{comparison between '&a' and '&b' has unspecified value}}
- constexpr bool u4 = p >= q; // expected-error {{constant expression}} expected-note {{comparison between '&a' and '&b' has unspecified value}}
- constexpr bool u5 = p < (int*)0; // expected-error {{constant expression}} expected-note {{comparison between '&a' and 'nullptr' has unspecified value}}
- constexpr bool u6 = p <= (int*)0; // expected-error {{constant expression}} expected-note {{comparison between '&a' and 'nullptr' has unspecified value}}
- constexpr bool u7 = p > (int*)0; // expected-error {{constant expression}} expected-note {{comparison between '&a' and 'nullptr' has unspecified value}}
- constexpr bool u8 = p >= (int*)0; // expected-error {{constant expression}} expected-note {{comparison between '&a' and 'nullptr' has unspecified value}}
- constexpr bool u9 = (int*)0 < q; // expected-error {{constant expression}} expected-note {{comparison between 'nullptr' and '&b' has unspecified value}}
- constexpr bool u10 = (int*)0 <= q; // expected-error {{constant expression}} expected-note {{comparison between 'nullptr' and '&b' has unspecified value}}
- constexpr bool u11 = (int*)0 > q; // expected-error {{constant expression}} expected-note {{comparison between 'nullptr' and '&b' has unspecified value}}
- constexpr bool u12 = (int*)0 >= q; // expected-error {{constant expression}} expected-note {{comparison between 'nullptr' and '&b' has unspecified value}}
+ constexpr bool u1 = p < q; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&a' and '&b' has unspecified value}}
+ constexpr bool u2 = p > q; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&a' and '&b' has unspecified value}}
+ constexpr bool u3 = p <= q; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&a' and '&b' has unspecified value}}
+ constexpr bool u4 = p >= q; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&a' and '&b' has unspecified value}}
+ constexpr bool u5 = p < (int*)0; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&a' and 'nullptr' has unspecified value}}
+ constexpr bool u6 = p <= (int*)0; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&a' and 'nullptr' has unspecified value}}
+ constexpr bool u7 = p > (int*)0; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&a' and 'nullptr' has unspecified value}}
+ constexpr bool u8 = p >= (int*)0; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&a' and 'nullptr' has unspecified value}}
+ constexpr bool u9 = (int*)0 < q; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects 'nullptr' and '&b' has unspecified value}}
+ constexpr bool u10 = (int*)0 <= q; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects 'nullptr' and '&b' has unspecified value}}
+ constexpr bool u11 = (int*)0 > q; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects 'nullptr' and '&b' has unspecified value}}
+ constexpr bool u12 = (int*)0 >= q; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects 'nullptr' and '&b' has unspecified value}}
void f(), g();
constexpr void (*pf)() = &f, (*pg)() = &g;
- constexpr bool u13 = pf < pg; // expected-error {{constant expression}} expected-note {{comparison between '&f' and '&g' has unspecified value}}
+ constexpr bool u13 = pf < pg; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&f' and '&g' has unspecified value}}
// expected-warning@-1 {{ordered comparison of function pointers}}
constexpr bool u14 = pf == pg;
@@ -578,11 +578,11 @@ namespace UnspecifiedRelations {
constexpr void *pv = (void*)&s.a;
constexpr void *qv = (void*)&s.b;
constexpr bool v1 = null < (int*)0;
- constexpr bool v2 = null < pv; // expected-error {{constant expression}} expected-note {{comparison between 'nullptr' and '&s.a' has unspecified value}}
+ constexpr bool v2 = null < pv; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects 'nullptr' and '&s.a' has unspecified value}}
constexpr bool v3 = null == pv;
constexpr bool v4 = qv == pv;
constexpr bool v5 = qv >= pv;
- constexpr bool v6 = qv > null; // expected-error {{constant expression}} expected-note {{comparison between '&s.b' and 'nullptr' has unspecified value}}
+ constexpr bool v6 = qv > null; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&s.b' and 'nullptr' has unspecified value}}
constexpr bool v7 = qv <= (void*)&s.b;
constexpr bool v8 = qv > (void*)&s.a;
}
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 0c34933..c990dc7 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -380,20 +380,36 @@ static_assert(string == string, "");
static_assert(string == also_string, "");
// These strings may overlap, and so the result of the comparison is unknown.
-constexpr bool may_overlap_1 = +"foo" == +"foo"; // expected-error {{}} expected-note {{addresses of literals}}
-constexpr bool may_overlap_2 = +"foo" == +"foo\0bar"; // expected-error {{}} expected-note {{addresses of literals}}
-constexpr bool may_overlap_3 = +"foo" == "bar\0foo" + 4; // expected-error {{}} expected-note {{addresses of literals}}
-constexpr bool may_overlap_4 = "xfoo" + 1 == "xfoo" + 1; // expected-error {{}} expected-note {{addresses of literals}}
+constexpr bool may_overlap_1 = +"foo" == +"foo"; // expected-error {{}} expected-note {{addresses of potentially overlapping literals}}
+constexpr bool may_overlap_2 = +"foo" == +"foo\0bar"; // expected-error {{}} expected-note {{addresses of potentially overlapping literals}}
+constexpr bool may_overlap_3 = +"foo" == "bar\0foo" + 4; // expected-error {{}} expected-note {{addresses of potentially overlapping literals}}
+constexpr bool may_overlap_4 = "xfoo" + 1 == "xfoo" + 1; // expected-error {{}} expected-note {{addresses of potentially overlapping literals}}
// These may overlap even though they have different encodings.
// One of these two comparisons is non-constant, but due to endianness we don't
// know which one.
constexpr bool may_overlap_different_encoding[] =
{fold((const char*)u"A" != (const char*)"xA\0\0\0x" + 1), fold((const char*)u"A" != (const char*)"x\0A\0\0x" + 1)};
- // expected-error@-2 {{}} expected-note@-1 {{addresses of literals}}
+ // expected-error@-2 {{}} expected-note@-1 {{addresses of potentially overlapping literals}}
}
+constexpr const char *getStr() {
+ return "abc"; // expected-note {{repeated evaluation of the same literal expression can produce different objects}}
+}
+constexpr int strMinus() {
+ (void)(getStr() - getStr()); // expected-note {{arithmetic on addresses of potentially overlapping literals has unspecified value}} \
+ // cxx11-warning {{C++14 extension}}
+ return 0;
+}
+static_assert(strMinus() == 0, ""); // expected-error {{not an integral constant expression}} \
+ // expected-note {{in call to}}
+
+constexpr int a = 0;
+constexpr int b = 1;
+constexpr int n = &b - &a; // expected-error {{must be initialized by a constant expression}} \
+ // expected-note {{arithmetic involving unrelated objects '&b' and '&a' has unspecified value}}
+
namespace MaterializeTemporary {
constexpr int f(const int &r) { return r; }
diff --git a/clang/test/SemaCXX/constant-expression-cxx14.cpp b/clang/test/SemaCXX/constant-expression-cxx14.cpp
index 936d360..579883a 100644
--- a/clang/test/SemaCXX/constant-expression-cxx14.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx14.cpp
@@ -1315,7 +1315,7 @@ constexpr bool different_in_loop(bool b = false) {
const char *p[2] = {};
for (const char *&r : p)
r = "hello";
- return p[0] == p[1]; // expected-note {{addresses of literals}}
+ return p[0] == p[1]; // expected-note {{addresses of potentially overlapping literals}}
}
constexpr bool check = different_in_loop();
// expected-error@-1 {{}} expected-note@-1 {{in call}}