aboutsummaryrefslogtreecommitdiff
path: root/clang/unittests/AST/StructuralEquivalenceTest.cpp
diff options
context:
space:
mode:
authorBalázs Kéri <balazs.keri@ericsson.com>2024-01-18 09:20:05 +0100
committerGitHub <noreply@github.com>2024-01-18 09:20:05 +0100
commit9ca1a08144a3caea8fd2f45fd4930ca796cf4166 (patch)
tree079ada260eb15e5fa25c63c80f4dbc169d7b4f7e /clang/unittests/AST/StructuralEquivalenceTest.cpp
parentf1226eea52e21b6325cf24cf0d7ccd6a517baee5 (diff)
downloadllvm-9ca1a08144a3caea8fd2f45fd4930ca796cf4166.zip
llvm-9ca1a08144a3caea8fd2f45fd4930ca796cf4166.tar.gz
llvm-9ca1a08144a3caea8fd2f45fd4930ca796cf4166.tar.bz2
[clang][ASTImporter] Improve structural equivalence of overloadable operators. (#72242)
Operators that are overloadable may be parsed as `CXXOperatorCallExpr` or as `UnaryOperator` (or `BinaryOperator`). This depends on the context and can be different if a similar construct is imported into an existing AST. The two "forms" of the operator call AST nodes should be detected as equivalent to allow AST import of these cases. This fix has probably other consequences because if a structure is imported that has `CXXOperatorCallExpr` into an AST with an existing similar structure that has `UnaryOperator` (or binary), the additional data in the `CXXOperatorCallExpr` node is lost at the import (because the existing node will be used). I am not sure if this can cause problems.
Diffstat (limited to 'clang/unittests/AST/StructuralEquivalenceTest.cpp')
-rw-r--r--clang/unittests/AST/StructuralEquivalenceTest.cpp170
1 files changed, 170 insertions, 0 deletions
diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp b/clang/unittests/AST/StructuralEquivalenceTest.cpp
index 22c7b82..91dd717 100644
--- a/clang/unittests/AST/StructuralEquivalenceTest.cpp
+++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp
@@ -2275,6 +2275,176 @@ TEST_F(StructuralEquivalenceStmtTest, UnaryOperatorDifferentOps) {
EXPECT_FALSE(testStructuralMatch(t));
}
+TEST_F(StructuralEquivalenceStmtTest,
+ CXXOperatorCallExprVsUnaryBinaryOperator) {
+ auto t = makeNamedDecls(
+ R"(
+ template <typename T, T x>
+ class A;
+ template <typename T, T x, T y>
+ void foo(
+ A<T, x + y>,
+ A<T, x - y>,
+ A<T, -x>,
+ A<T, x * y>,
+ A<T, *x>,
+ A<T, x / y>,
+ A<T, x % y>,
+ A<T, x ^ y>,
+ A<T, x & y>,
+ A<T, &x>,
+ A<T, x | y>,
+ A<T, ~x>,
+ A<T, !x>,
+ A<T, x < y>,
+ A<T, (x > y)>,
+ A<T, x << y>,
+ A<T, (x >> y)>,
+ A<T, x == y>,
+ A<T, x != y>,
+ A<T, x <= y>,
+ A<T, x >= y>,
+ A<T, x <=> y>,
+ A<T, x && y>,
+ A<T, x || y>,
+ A<T, ++x>,
+ A<T, --x>,
+ A<T, (x , y)>,
+ A<T, x ->* y>,
+ A<T, x -> y>
+ );
+ )",
+ R"(
+ struct Bar {
+ Bar& operator=(Bar&);
+ Bar& operator->();
+ };
+
+ Bar& operator+(Bar&, Bar&);
+ Bar& operator+(Bar&);
+ Bar& operator-(Bar&, Bar&);
+ Bar& operator-(Bar&);
+ Bar& operator*(Bar&, Bar&);
+ Bar& operator*(Bar&);
+ Bar& operator/(Bar&, Bar&);
+ Bar& operator%(Bar&, Bar&);
+ Bar& operator^(Bar&, Bar&);
+ Bar& operator&(Bar&, Bar&);
+ Bar& operator&(Bar&);
+ Bar& operator|(Bar&, Bar&);
+ Bar& operator~(Bar&);
+ Bar& operator!(Bar&);
+ Bar& operator<(Bar&, Bar&);
+ Bar& operator>(Bar&, Bar&);
+ Bar& operator+=(Bar&, Bar&);
+ Bar& operator-=(Bar&, Bar&);
+ Bar& operator*=(Bar&, Bar&);
+ Bar& operator/=(Bar&, Bar&);
+ Bar& operator%=(Bar&, Bar&);
+ Bar& operator^=(Bar&, Bar&);
+ Bar& operator&=(Bar&, Bar&);
+ Bar& operator|=(Bar&, Bar&);
+ Bar& operator<<(Bar&, Bar&);
+ Bar& operator>>(Bar&, Bar&);
+ Bar& operator<<=(Bar&, Bar&);
+ Bar& operator>>=(Bar&, Bar&);
+ Bar& operator==(Bar&, Bar&);
+ Bar& operator!=(Bar&, Bar&);
+ Bar& operator<=(Bar&, Bar&);
+ Bar& operator>=(Bar&, Bar&);
+ Bar& operator<=>(Bar&, Bar&);
+ Bar& operator&&(Bar&, Bar&);
+ Bar& operator||(Bar&, Bar&);
+ Bar& operator++(Bar&);
+ Bar& operator--(Bar&);
+ Bar& operator,(Bar&, Bar&);
+ Bar& operator->*(Bar&, Bar&);
+
+ template <typename T, T x>
+ class A;
+ template <typename T, T x, T y>
+ void foo(
+ A<T, x + y>,
+ A<T, x - y>,
+ A<T, -x>,
+ A<T, x * y>,
+ A<T, *x>,
+ A<T, x / y>,
+ A<T, x % y>,
+ A<T, x ^ y>,
+ A<T, x & y>,
+ A<T, &x>,
+ A<T, x | y>,
+ A<T, ~x>,
+ A<T, !x>,
+ A<T, x < y>,
+ A<T, (x > y)>,
+ A<T, x << y>,
+ A<T, (x >> y)>,
+ A<T, x == y>,
+ A<T, x != y>,
+ A<T, x <= y>,
+ A<T, x >= y>,
+ A<T, x <=> y>,
+ A<T, x && y>,
+ A<T, x || y>,
+ A<T, ++x>,
+ A<T, --x>,
+ A<T, (x , y)>,
+ A<T, x ->* y>,
+ A<T, x -> y>
+ );
+ )",
+ Lang_CXX20);
+ EXPECT_TRUE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceStmtTest,
+ CXXOperatorCallExprVsUnaryBinaryOperatorNe) {
+ auto t = makeNamedDecls(
+ R"(
+ template <typename T, T x>
+ class A;
+ template <typename T, T x, T y>
+ void foo(
+ A<T, x + y>
+ );
+ )",
+ R"(
+ struct Bar;
+
+ Bar& operator-(Bar&, Bar&);
+
+ template <typename T, T x>
+ class A;
+ template <typename T, T x, T y>
+ void foo(
+ A<T, x - y>
+ );
+ )",
+ Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceStmtTest, NonTypeTemplateParm) {
+ auto t = makeNamedDecls(
+ R"(
+ template <typename T, T x>
+ class A;
+ template <typename T, T x, T y>
+ void foo(A<T, x>);
+ )",
+ R"(
+ template <typename T, T x>
+ class A;
+ template <typename T, T x, T y>
+ void foo(A<T, y>);
+ )",
+ Lang_CXX11);
+ // FIXME: These should not match,
+ EXPECT_TRUE(testStructuralMatch(t));
+}
+
TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookupDifferentName) {
auto t = makeStmts(
R"(