llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: None (Serafean) <details> <summary>Changes</summary> Currently clang_getCursorBinaryOperatorKind and clang_getCursorUnaryOperatorKind only return valid values for operations on POD and rewritten operators. Extend this to also correctly return for overloaded operators by handling CXXOperatorCallExpr. Note: this is necessary to ever get CXUnaryOperator_Coawait. Depends on https://github.com/llvm/llvm-project/pull/182247, otherwise chaos ensues. --- Full diff: https://github.com/llvm/llvm-project/pull/182303.diff 5 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (+1) - (modified) clang/test/Index/binop.cpp (+146) - (added) clang/test/Index/unaryop.cpp (+70) - (modified) clang/tools/c-index-test/c-index-test.c (+20-1) - (modified) clang/tools/libclang/CIndex.cpp (+39-11) ``````````diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 6e9e5baea2921..4c70305f3d207 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -397,6 +397,7 @@ clang-format libclang -------- +- Return valid CXUnaryOperatorKind and CXBinaryOperatorKind for overloaded operators. Code Completion --------------- diff --git a/clang/test/Index/binop.cpp b/clang/test/Index/binop.cpp index 576fd73cc2abf..0be4f28116fe7 100644 --- a/clang/test/Index/binop.cpp +++ b/clang/test/Index/binop.cpp @@ -58,6 +58,7 @@ void func(void) { #pragma clang diagnostic pop } +// CHECK: CallExpr=C:3:8 BinOp= 0 // CHECK: BinaryOperator=.* BinOp=.* 1 // CHECK: BinaryOperator=->* BinOp=->* 2 // CHECK: BinaryOperator=* BinOp=* 3 @@ -90,3 +91,148 @@ void func(void) { // CHECK: CompoundAssignOperator=^= BinOp=^= 31 // CHECK: CompoundAssignOperator=|= BinOp=|= 32 // CHECK: BinaryOperator=, BinOp=, 33 + +struct D { + D() = default; + D& operator+(){return *this;} + D& operator-(){return *this;} + D& operator*(const D&){return *this;} + D& operator/(const D&){return *this;} + D& operator%(const D&){return *this;} + D& operator+(const D&){return *this;} + D& operator-(const D&){return *this;} + + D& operator<<(const D&){return *this;} + D& operator>>(const D&){return *this;} + + bool operator<(const D&){return true;} + bool operator>(const D&){return true;} + bool operator<=(const D&){return true;} + bool operator>=(const D&){return true;} + bool operator==(const D&){return true;} + bool operator!=(const D&){return true;} + + D& operator|(const D&){return *this;} + D& operator&(const D&){return *this;} + D& operator^(const D&){return *this;} + + bool operator&&(const D&){return true;} + bool operator||(const D&){return true;} + + D& operator+=(const D&){return *this;} + D& operator-=(const D&){return *this;} + D& operator*=(const D&){return *this;} + D& operator/=(const D&){return *this;} + D& operator%=(const D&){return *this;} + D& operator&=(const D&){return *this;} + D& operator|=(const D&){return *this;} + D& operator^=(const D&){return *this;} + D& operator<<=(const D&){return *this;} + D& operator>>=(const D&){return *this;} + D& operator,(const D&){return *this;} + + int& operator->*(int D::*i){return this->i;} + + // Negative test of --/++ + D& operator++(){return *this;}; + D& operator++(int){return *this;}; + D& operator--(){return *this;}; + D& operator--(int){return *this;}; + + int i; +}; + +void func2(void) { + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunused-value" + D a, b; + int D::*p = &D::i; + + D *pc; + a->*p; + + a *b; + a / b; + a % b; + a + b; + a - b; + + a << b; + a >> b; + + a < b; + a > b; + + a <= b; + a >= b; + a == b; + a != b; + + a &b; + a ^ b; + a | b; + + a &&b; + a || b; + + a = b; + + a *= b; + a /= b; + a %= b; + a += b; + a -= b; + + a <<= b; + a >>= b; + + a &= b; + a ^= b; + a |= b; + a, b; + +// Negative test + a++; + ++a; + a--; + --a; + #pragma clang diagnostic pop +} + +// CHECK: CallExpr=D:96:3 BinOp= 0 +// CHECK: CallExpr=D:96:3 BinOp= 0 +// CHECK: CallExpr=operator->*:134:8 BinOp=->* 2 +// CHECK: CallExpr=operator*:99:6 BinOp=* 3 +// CHECK: CallExpr=operator/:100:6 BinOp=/ 4 +// CHECK: CallExpr=operator%:101:6 BinOp=% 5 +// CHECK: CallExpr=operator+:102:6 BinOp=+ 6 +// CHECK: CallExpr=operator-:103:6 BinOp=- 7 +// CHECK: CallExpr=operator<<:105:6 BinOp=<< 8 +// CHECK: CallExpr=operator>>:106:6 BinOp=>> 9 +// CHECK: CallExpr=operator<:108:8 BinOp=< 11 +// CHECK: CallExpr=operator>:109:8 BinOp=> 12 +// CHECK: CallExpr=operator<=:110:8 BinOp=<= 13 +// CHECK: CallExpr=operator>=:111:8 BinOp=>= 14 +// CHECK: CallExpr=operator==:112:8 BinOp=== 15 +// CHECK: CallExpr=operator!=:113:8 BinOp=!= 16 +// CHECK: CallExpr=operator&:116:6 BinOp=& 17 +// CHECK: CallExpr=operator^:117:6 BinOp=^ 18 +// CHECK: CallExpr=operator|:115:6 BinOp=| 19 +// CHECK: CallExpr=operator&&:119:8 BinOp=&& 20 +// CHECK: CallExpr=operator||:120:8 BinOp=|| 21 +// CHECK: CallExpr=operator=:95:8 BinOp== 22 +// CHECK: CallExpr=operator*=:124:6 BinOp=*= 23 +// CHECK: CallExpr=operator/=:125:6 BinOp=/= 24 +// CHECK: CallExpr=operator%=:126:6 BinOp=%= 25 +// CHECK: CallExpr=operator+=:122:6 BinOp=+= 26 +// CHECK: CallExpr=operator-=:123:6 BinOp=-= 27 +// CHECK: CallExpr=operator<<=:130:6 BinOp=<<= 28 +// CHECK: CallExpr=operator>>=:131:6 BinOp=>>= 29 +// CHECK: CallExpr=operator&=:127:6 BinOp=&= 30 +// CHECK: CallExpr=operator^=:129:6 BinOp=^= 31 +// CHECK: CallExpr=operator|=:128:6 BinOp=|= 32 +// CHECK: CallExpr=operator,:132:6 BinOp=, 33 +// CHECK: CallExpr=operator++:138:6 BinOp= 0 +// CHECK: CallExpr=operator++:137:6 BinOp= 0 +// CHECK: CallExpr=operator--:140:6 BinOp= 0 +// CHECK: CallExpr=operator--:139:6 BinOp= 0 diff --git a/clang/test/Index/unaryop.cpp b/clang/test/Index/unaryop.cpp new file mode 100644 index 0000000000000..bd0cbae598817 --- /dev/null +++ b/clang/test/Index/unaryop.cpp @@ -0,0 +1,70 @@ +// RUN: c-index-test -test-print-unops %s | FileCheck %s + +void func(){ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-value" + int i; + + i++; + ++i; + i--; + --i; + int *p = &i; + *p; + int c= +i; + int d= -i; + + ~i; + !i; + +#pragma clang diagnostic pop +} + + +struct C{ + C() = default; + C& operator++(); + C& operator++(int); + C& operator--(); + C& operator--(int); + C& operator*(); + C* operator&(); + C& operator+(); + C& operator-(); + C& operator!(); + C& operator~(); +}; + +void func2(){ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-value" + C i; + i++; + ++i; + i--; + --i; + C *p = &i; + *i; + +i; + C n = +i; + -i; + C m = -i; + + ~i; + !i; + +#pragma clang diagnostic pop +} + +// CHECK: CallExpr=C:25:5CallExpr=operator++:27:8 UnOp=++ 1 +// CHECK: CallExpr=operator++:26:8 UnOp=++ 3 +// CHECK: CallExpr=operator--:29:8 UnOp=-- 2 +// CHECK: CallExpr=operator--:28:8 UnOp=-- 4 +// CHECK: CallExpr=operator&:31:8 UnOp=& 5 +// CHECK: CallExpr=operator*:30:8 UnOp=* 6 +// CHECK: CallExpr=operator+:32:8 UnOp=+ 7 +// CHECK: CallExpr=C:24:8CallExpr=operator+:32:8 UnOp=+ 7 +// CHECK: CallExpr=operator-:33:8 UnOp=- 8 +// CHECK: CallExpr=C:24:8CallExpr=operator-:33:8 UnOp=- 8 +// CHECK: CallExpr=operator~:35:8 UnOp=~ 9 +// CHECK: CallExpr=operator!:34:8 UnOp=! 10 diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c index cb3245756a394..24be3952c009d 100644 --- a/clang/tools/c-index-test/c-index-test.c +++ b/clang/tools/c-index-test/c-index-test.c @@ -1865,7 +1865,8 @@ static enum CXChildVisitResult PrintBinOps(CXCursor C, CXCursor p, enum CXCursorKind ck = clang_getCursorKind(C); enum CXBinaryOperatorKind bok; CXString opstr; - if (ck != CXCursor_BinaryOperator && ck != CXCursor_CompoundAssignOperator) + if (ck != CXCursor_BinaryOperator && ck != CXCursor_CompoundAssignOperator && + ck != CXCursor_CallExpr) return CXChildVisit_Recurse; PrintCursor(C, NULL); @@ -1876,6 +1877,22 @@ static enum CXChildVisitResult PrintBinOps(CXCursor C, CXCursor p, return CXChildVisit_Recurse; } +static enum CXChildVisitResult PrintUnOps(CXCursor C, CXCursor p, + CXClientData d) { + enum CXCursorKind ck = clang_getCursorKind(C); + enum CXUnaryOperatorKind bok; + CXString opstr; + if (ck != CXCursor_UnaryOperator && ck != CXCursor_CallExpr) + return CXChildVisit_Recurse; + + PrintCursor(C, NULL); + bok = clang_getCursorUnaryOperatorKind(C); + opstr = clang_getUnaryOperatorKindSpelling(bok); + printf(" UnOp=%s %d\n", clang_getCString(opstr), bok); + clang_disposeString(opstr); + return CXChildVisit_Recurse; +} + /******************************************************************************/ /* Mangling testing. */ /******************************************************************************/ @@ -5182,6 +5199,8 @@ int cindextest_main(int argc, const char **argv) { PrintBitWidth, 0); else if (argc > 2 && strcmp(argv[1], "-test-print-binops") == 0) return perform_test_load_source(argc - 2, argv + 2, "all", PrintBinOps, 0); + else if (argc > 2 && strcmp(argv[1], "-test-print-unops") == 0) + return perform_test_load_source(argc - 2, argv + 2, "all", PrintUnOps, 0); else if (argc > 2 && strcmp(argv[1], "-test-print-mangle") == 0) return perform_test_load_tu(argv[2], "all", NULL, PrintMangledName, NULL); else if (argc > 2 && strcmp(argv[1], "-test-print-manglings") == 0) diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 15eec87652451..4e22fbddb1e3d 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -10181,16 +10181,28 @@ CXString clang_getBinaryOperatorKindSpelling(enum CXBinaryOperatorKind kind) { } enum CXBinaryOperatorKind clang_getCursorBinaryOperatorKind(CXCursor cursor) { - if (clang_isExpression(cursor.kind)) { - const Expr *expr = getCursorExpr(cursor); + if (!clang_isExpression(cursor.kind)) + return CXBinaryOperator_Invalid; - if (const auto *op = dyn_cast<BinaryOperator>(expr)) - return static_cast<CXBinaryOperatorKind>(op->getOpcode() + 1); + const Expr *expr = getCursorExpr(cursor); + if (!expr) + return CXBinaryOperator_Invalid; - if (const auto *op = dyn_cast<CXXRewrittenBinaryOperator>(expr)) - return static_cast<CXBinaryOperatorKind>(op->getOpcode() + 1); - } + if (const auto *op = dyn_cast<BinaryOperator>(expr)) + return static_cast<CXBinaryOperatorKind>(op->getOpcode() + 1); + if (const auto *op = dyn_cast<CXXRewrittenBinaryOperator>(expr)) + return static_cast<CXBinaryOperatorKind>(op->getOpcode() + 1); + + if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(expr)) { + const OverloadedOperatorKind Kind = OCE->getOperator(); + bool isPostfixOp = (OCE->getNumArgs() == 2 && + (Kind == OO_PlusPlus || Kind == OO_MinusMinus)); + if (OCE->getNumArgs() == 2 && !isPostfixOp) { + auto opcode = BinaryOperator::getOverloadedOpcode(Kind); + return static_cast<CXBinaryOperatorKind>(opcode + 1); + } + } return CXBinaryOperator_Invalid; } @@ -10200,11 +10212,27 @@ CXString clang_getUnaryOperatorKindSpelling(enum CXUnaryOperatorKind kind) { } enum CXUnaryOperatorKind clang_getCursorUnaryOperatorKind(CXCursor cursor) { - if (clang_isExpression(cursor.kind)) { - const Expr *expr = getCursorExpr(cursor); + if (!clang_isExpression(cursor.kind)) { + return CXUnaryOperator_Invalid; + } - if (const auto *op = dyn_cast<UnaryOperator>(expr)) - return static_cast<CXUnaryOperatorKind>(op->getOpcode() + 1); + const Expr *expr = getCursorExpr(cursor); + if (!expr) { + return CXUnaryOperator_Invalid; + } + + if (const auto *op = dyn_cast<UnaryOperator>(expr)) { + return static_cast<CXUnaryOperatorKind>(op->getOpcode() + 1); + } + + if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(expr)) { + const OverloadedOperatorKind Kind = OCE->getOperator(); + bool isPostfixOp = (OCE->getNumArgs() == 2 && + (Kind == OO_PlusPlus || Kind == OO_MinusMinus)); + if (OCE->getNumArgs() == 1 || isPostfixOp) { + auto opcode = UnaryOperator::getOverloadedOpcode(Kind, isPostfixOp); + return static_cast<CXUnaryOperatorKind>(opcode + 1); + } } return CXUnaryOperator_Invalid; `````````` </details> https://github.com/llvm/llvm-project/pull/182303 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
