CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
899 lines
27 KiB
C++
899 lines
27 KiB
C++
// RUN: %check_clang_tidy -check-suffix=,CPP20ORLATER -std=c++20-or-later %s modernize-use-structured-binding %t -- -- -I %S/Inputs/use-structured-binding/
|
|
// RUN: %check_clang_tidy -std=c++17 %s modernize-use-structured-binding %t -- -- -I %S/Inputs/use-structured-binding/
|
|
|
|
#include <utility>
|
|
#include <tuple>
|
|
|
|
#include <unordered_map>
|
|
|
|
template<typename T1, typename T2>
|
|
std::pair<T1, T2> getPair();
|
|
|
|
template<typename T1, typename T2>
|
|
constexpr std::pair<T1, T2> getConstexprPair() {
|
|
return std::pair<T1, T2>();
|
|
}
|
|
|
|
template<typename T1, typename T2, typename T3>
|
|
std::tuple<T1, T2, T3> getTuple();
|
|
|
|
template<typename T>
|
|
void MarkUsed(T x);
|
|
|
|
struct TestClass {
|
|
int a;
|
|
int b;
|
|
TestClass() : a(0), b(0) {}
|
|
TestClass& operator++();
|
|
TestClass(int x, int y) : a(x), b(y) {}
|
|
};
|
|
|
|
void DecomposeByAssignWarnCases() {
|
|
{
|
|
auto P = getPair<int, int>();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto [x, y] = getPair<int, int>();
|
|
// CHECK-NEXT: // REMOVE
|
|
int x = P.first;
|
|
int y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
{
|
|
auto P = getPair<int, int>();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto [x, y] = getPair<int, int>();
|
|
int x = P.first, y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
{
|
|
auto P = getPair<int, int>();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto [x, y] = getPair<int, int>();
|
|
int x = P.first, y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
int z;
|
|
}
|
|
|
|
{
|
|
auto P = getPair<int, int>();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto [x, y] = getPair<int, int>();
|
|
// CHECK-NEXT: // REMOVE
|
|
int x = P.first;
|
|
auto y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
{
|
|
const auto P = getPair<int, int>();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: const auto [x, y] = getPair<int, int>();
|
|
// CHECK-NEXT: // REMOVE
|
|
const int x = P.first;
|
|
const auto y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
{
|
|
std::pair<int, int> otherP;
|
|
auto& P = otherP;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto& [x, y] = otherP;
|
|
// CHECK-NEXT: // REMOVE
|
|
int& x = P.first;
|
|
auto& y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
{
|
|
std::pair<int, int> otherP;
|
|
const auto& P = otherP;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: const auto& [x, y] = otherP;
|
|
// CHECK-NEXT: // REMOVE
|
|
const int& x = P.first;
|
|
const auto& y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
{
|
|
auto P = getPair<int, int>();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto [x, y] = getPair<int, int>();
|
|
// CHECK-NEXT: // REMOVE
|
|
int x = P.first;
|
|
int y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
|
|
auto another_p = getPair<int, int>();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto [another_x, another_y] = getPair<int, int>();
|
|
// CHECK-NEXT: // REMOVE
|
|
int another_x = another_p.first;
|
|
int another_y = another_p.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
}
|
|
|
|
void forRangeWarnCases() {
|
|
std::pair<int, int> Pairs[10];
|
|
for (auto P : Pairs) {
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: for (auto [x, y] : Pairs) {
|
|
// CHECK-NEXT: // REMOVE
|
|
int x = P.first;
|
|
int y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
for (auto P : Pairs) {
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: for (auto [x, y] : Pairs) {
|
|
int x = P.first, y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
for (auto P : Pairs) {
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: for (auto [x, y] : Pairs) {
|
|
int x = P.first, y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
int z;
|
|
}
|
|
|
|
for (const auto P : Pairs) {
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: for (const auto [x, y] : Pairs) {
|
|
// CHECK-NEXT: // REMOVE
|
|
const int x = P.first;
|
|
const int y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
for (auto& P : Pairs) {
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: for (auto& [x, y] : Pairs) {
|
|
// CHECK-NEXT: // REMOVE
|
|
int& x = P.first;
|
|
int& y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
for (const auto& P : Pairs) {
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: for (const auto& [x, y] : Pairs) {
|
|
// CHECK-NEXT: // REMOVE
|
|
const int& x = P.first;
|
|
const int& y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
std::pair<TestClass, TestClass> ClassPairs[10];
|
|
for (auto P : ClassPairs) {
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: for (auto [c1, c2] : ClassPairs) {
|
|
// CHECK-NEXT: // REMOVE
|
|
TestClass c1 = P.first;
|
|
TestClass c2 = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
for (const auto P : ClassPairs) {
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: for (const auto [c1, c2] : ClassPairs) {
|
|
// CHECK-NEXT: // REMOVE
|
|
const TestClass c1 = P.first;
|
|
const TestClass c2 = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
}
|
|
|
|
void forRangeNotWarnCases() {
|
|
std::pair<int, int> Pairs[10];
|
|
for (auto P : Pairs) {
|
|
int x = P.first;
|
|
MarkUsed(x);
|
|
int y = P.second;
|
|
}
|
|
|
|
for (auto P : Pairs) {
|
|
MarkUsed(P);
|
|
int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
|
|
for (auto P : Pairs) {
|
|
int x = P.first;
|
|
int y = P.second;
|
|
MarkUsed(P);
|
|
}
|
|
|
|
std::pair<TestClass, TestClass> ClassPairs[10];
|
|
for (auto P : ClassPairs) {
|
|
TestClass c1 = P.first;
|
|
++ c1 ;
|
|
TestClass c2 = P.second;
|
|
}
|
|
|
|
int c;
|
|
for (auto P : ClassPairs) {
|
|
TestClass c1 = P.first;
|
|
c ++ ;
|
|
TestClass c2 = P.second;
|
|
}
|
|
}
|
|
|
|
void stdTieWarnCases() {
|
|
// CHECK-NEXT: // REMOVE
|
|
int a = 0;
|
|
int b = 0; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
std::tie(a, b) = getPair<int, int>();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto [a, b] = getPair<int, int>();
|
|
|
|
int x = 0, y = 0; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
std::tie(x, y) = getPair<int, int>();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto [x, y] = getPair<int, int>();
|
|
|
|
// CHECK-NEXT: // REMOVE
|
|
int* pa = nullptr;
|
|
int* pb = nullptr; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
std::tie(pa, pb) = getPair<int*, int*>();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto [pa, pb] = getPair<int*, int*>();
|
|
|
|
// CHECK-NEXT: // REMOVE
|
|
TestClass c1 (1, 2);
|
|
TestClass c2 = TestClass {3, 4}; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
std::tie(c1, c2) = getPair<TestClass, TestClass>();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto [c1, c2] = getPair<TestClass, TestClass>();
|
|
}
|
|
|
|
void stdTieNotWarnCases() {
|
|
int a = 0;
|
|
int b = 0;
|
|
a = 4;
|
|
std::tie(a, b) = getPair<int, int>(); // no warning
|
|
|
|
int c = 0, d = 0;
|
|
int e = 0;
|
|
std::tie(a, b) = getPair<int, int>(); // no warning
|
|
|
|
int* pa = nullptr;
|
|
int* pb = nullptr;
|
|
MarkUsed(pa);
|
|
std::tie(pa, pb) = getPair<int*, int*>(); // no warning
|
|
|
|
TestClass c1 (1, 2);
|
|
TestClass c2 = TestClass {3, 4};
|
|
MarkUsed(c2);
|
|
std::tie(c1, c2) = getPair<TestClass, TestClass>();
|
|
}
|
|
|
|
void NotWarnForVarHasSpecifiers() {
|
|
{
|
|
auto P = getPair<int, int>();
|
|
const int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
|
|
{
|
|
auto P = getPair<int, int>();
|
|
volatile int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
|
|
{
|
|
auto P = getPair<int, int>();
|
|
int x = P.first;
|
|
[[maybe_unused]] int y = P.second;
|
|
}
|
|
|
|
{
|
|
static auto P = getPair<int, int>();
|
|
int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
|
|
{
|
|
thread_local auto P = getPair<int, int>();
|
|
int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
|
|
{
|
|
extern int a;
|
|
int b = 0;
|
|
std::tie(a, b) = getPair<int, int>();
|
|
}
|
|
}
|
|
|
|
void NotWarnForMultiUsedPairVar() {
|
|
{
|
|
auto P = getPair<int, int>();
|
|
int x = P.first;
|
|
int y = P.second;
|
|
MarkUsed(P);
|
|
}
|
|
|
|
{
|
|
auto P = getPair<int, int>();
|
|
int x = P.first;
|
|
MarkUsed(P);
|
|
int y = P.second;
|
|
}
|
|
|
|
{
|
|
auto P = getPair<int, int>();
|
|
MarkUsed(P);
|
|
int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
|
|
{
|
|
std::pair<int, int> Pairs[10];
|
|
for (auto P : Pairs) {
|
|
int x = P.first;
|
|
int y = P.second;
|
|
|
|
MarkUsed(P);
|
|
}
|
|
}
|
|
}
|
|
|
|
#define DECOMPOSE(P) \
|
|
int x = P.first; \
|
|
int y = P.second; \
|
|
|
|
void NotWarnForMacro1() {
|
|
auto P = getPair<int, int>();
|
|
DECOMPOSE(P);
|
|
}
|
|
|
|
#define GETPAIR auto P = getPair<int, int>()
|
|
|
|
void NotWarnForMacro2() {
|
|
GETPAIR;
|
|
int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
|
|
void captureByVal() {
|
|
auto P = getPair<int, int>();
|
|
// CHECK-MESSAGES-CPP20ORLATER: :[[@LINE-1]]:3: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES-CPP20ORLATER: auto [x, y] = getPair<int, int>();
|
|
// CHECK-NEXT-CPP20ORLATER: // REMOVE
|
|
int x = P.first;
|
|
int y = P.second; // REMOVE
|
|
// CHECK-FIXES-CPP20ORLATER: // REMOVE
|
|
|
|
auto lambda = [x]() {
|
|
int y = x;
|
|
};
|
|
}
|
|
|
|
void captureByRef() {
|
|
auto P = getPair<int, int>();
|
|
// CHECK-MESSAGES-CPP20ORLATER: :[[@LINE-1]]:3: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES-CPP20ORLATER: auto [x, y] = getPair<int, int>();
|
|
// CHECK-NEXT-CPP20ORLATER: // REMOVE
|
|
int x = P.first;
|
|
int y = P.second; // REMOVE
|
|
// CHECK-FIXES-CPP20ORLATER: // REMOVE
|
|
|
|
auto lambda = [&x]() {
|
|
x = 1;
|
|
};
|
|
}
|
|
|
|
void captureByAllRef() {
|
|
auto P = getPair<int, int>();
|
|
// CHECK-MESSAGES-CPP20ORLATER: :[[@LINE-1]]:3: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES-CPP20ORLATER: auto [x, y] = getPair<int, int>();
|
|
// CHECK-NEXT-CPP20ORLATER: // REMOVE
|
|
int x = P.first;
|
|
int y = P.second; // REMOVE
|
|
// CHECK-FIXES-CPP20ORLATER: // REMOVE
|
|
|
|
auto lambda = [&]() {
|
|
x = 1;
|
|
};
|
|
}
|
|
|
|
void deepLambda() {
|
|
auto P = getPair<int, int>();
|
|
// CHECK-MESSAGES-CPP20ORLATER: :[[@LINE-1]]:3: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES-CPP20ORLATER: auto [x, y] = getPair<int, int>();
|
|
// CHECK-NEXT-CPP20ORLATER: // REMOVE
|
|
int x = P.first;
|
|
int y = P.second; // REMOVE
|
|
// CHECK-FIXES-CPP20ORLATER: // REMOVE
|
|
|
|
{
|
|
auto lambda = [x]() {
|
|
int y = x;
|
|
};
|
|
}
|
|
}
|
|
|
|
void forRangeNotWarn() {
|
|
std::pair<int, int> Pairs[10];
|
|
for (auto P : Pairs) {
|
|
// CHECK-MESSAGES-CPP20ORLATER: :[[@LINE-1]]:8: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES-CPP20ORLATER: for (auto [x, y] : Pairs) {
|
|
// CHECK-NEXT-CPP20ORLATER: // REMOVE
|
|
int x = P.first;
|
|
int y = P.second; // REMOVE
|
|
// CHECK-FIXES-CPP20ORLATER: // REMOVE
|
|
|
|
auto lambda = [&]() {
|
|
x = 1;
|
|
};
|
|
}
|
|
}
|
|
|
|
void stdTieNotWarn() {
|
|
// CHECK-NEXT-CPP20ORLATER: // REMOVE
|
|
int x = 0;
|
|
int y = 0; // REMOVE
|
|
// CHECK-FIXES-CPP20ORLATER: // REMOVE
|
|
std::tie(x, y) = getPair<int, int>();
|
|
// CHECK-MESSAGES-CPP20ORLATER: :[[@LINE-1]]:3: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES-CPP20ORLATER: auto [x, y] = getPair<int, int>();
|
|
|
|
auto lambda = [&x]() {
|
|
x = 1;
|
|
};
|
|
}
|
|
|
|
struct otherPair {
|
|
int first;
|
|
int second;
|
|
};
|
|
|
|
void OtherPairTest() {
|
|
{
|
|
auto P = otherPair();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto [x, y] = otherPair();
|
|
// CHECK-NEXT: // REMOVE
|
|
int x = P.first;
|
|
int y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
{
|
|
const auto P = otherPair();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: const auto [x, y] = otherPair();
|
|
// CHECK-NEXT: // REMOVE
|
|
const int x = P.first;
|
|
const auto y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
{
|
|
otherPair otherP;
|
|
auto& P = otherP;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto& [x, y] = otherP;
|
|
// CHECK-NEXT: // REMOVE
|
|
int& x = P.first;
|
|
auto& y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
{
|
|
std::pair<int, int> otherP;
|
|
const auto& P = otherP;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: const auto& [x, y] = otherP;
|
|
// CHECK-NEXT: // REMOVE
|
|
const int& x = P.first;
|
|
const auto& y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
}
|
|
|
|
void OtherPairNotWarnCases() {
|
|
{
|
|
auto P = otherPair();
|
|
const int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
|
|
{
|
|
auto P = otherPair();
|
|
volatile int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
|
|
{
|
|
auto P = otherPair();
|
|
int x = P.first;
|
|
[[maybe_unused]] int y = P.second;
|
|
}
|
|
|
|
{
|
|
static auto P = getPair<int, int>();
|
|
int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
}
|
|
|
|
struct otherNonPair1 {
|
|
int first;
|
|
int second;
|
|
|
|
private:
|
|
int third;
|
|
};
|
|
|
|
struct otherNonPair2 {
|
|
int first;
|
|
int second;
|
|
int third;
|
|
};
|
|
|
|
void OtherNonPairTest() {
|
|
{
|
|
auto P = otherNonPair1();
|
|
int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
|
|
{
|
|
auto P = otherNonPair2();
|
|
int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
}
|
|
|
|
template<typename PairType>
|
|
PairType getCertainPair();
|
|
|
|
struct ConstFieldPair {
|
|
const int first;
|
|
int second;
|
|
};
|
|
|
|
void ConstFieldPairTests() {
|
|
{
|
|
const ConstFieldPair P = getCertainPair<ConstFieldPair>();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: const auto [x, y] = getCertainPair<ConstFieldPair>();
|
|
// CHECK-NEXT: // REMOVE
|
|
const int x = P.first;
|
|
const int y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
{
|
|
const ConstFieldPair& P = getCertainPair<ConstFieldPair>();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: const auto& [x, y] = getCertainPair<ConstFieldPair>();
|
|
// CHECK-NEXT: // REMOVE
|
|
const int& x = P.first;
|
|
const int& y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
{
|
|
ConstFieldPair P = getCertainPair<ConstFieldPair>(); // no warning
|
|
int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
}
|
|
|
|
struct PointerFieldPair {
|
|
int* first;
|
|
int second;
|
|
};
|
|
|
|
void PointerFieldPairTests() {
|
|
{
|
|
PointerFieldPair P = getCertainPair<PointerFieldPair>();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto [x, y] = getCertainPair<PointerFieldPair>();
|
|
// CHECK-NEXT: // REMOVE
|
|
int* x = P.first;
|
|
int y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
{
|
|
PointerFieldPair P = getCertainPair<PointerFieldPair>(); // no warning
|
|
const int* x = P.first;
|
|
int y = P.second;
|
|
}
|
|
}
|
|
|
|
struct ConstRefFieldPair {
|
|
const int& first;
|
|
int second;
|
|
ConstRefFieldPair(int& f, int s) : first(f), second(s) {}
|
|
};
|
|
|
|
void ConstRefFieldPairTests() {
|
|
{
|
|
ConstRefFieldPair P = getCertainPair<ConstRefFieldPair>();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto [x, y] = getCertainPair<ConstRefFieldPair>();
|
|
// CHECK-NEXT: // REMOVE
|
|
const int& x = P.first;
|
|
int y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
{
|
|
ConstRefFieldPair P = getCertainPair<ConstRefFieldPair>();; // no warning
|
|
int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
}
|
|
|
|
struct StaticFieldPair {
|
|
static int first;
|
|
int second;
|
|
};
|
|
|
|
void StaticFieldPairTests() {
|
|
{
|
|
StaticFieldPair P; // Should not warn
|
|
int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
|
|
{
|
|
StaticFieldPair P; // Should not warn
|
|
static int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
}
|
|
|
|
void IgnoreDirectInit() {
|
|
{
|
|
std::pair<int, int> P{1, 1};
|
|
int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
|
|
{
|
|
std::pair<int, int> P(1, 1);
|
|
int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
|
|
{
|
|
std::pair<int, int> P;
|
|
int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
}
|
|
|
|
void StdMapTestCases() {
|
|
for (const auto p : std::unordered_map<int, int>()) {
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: for (const auto [x, y] : std::unordered_map<int, int>()) {
|
|
// CHECK-NEXT: // REMOVE
|
|
const int x = p.first;
|
|
const int y = p.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
}
|
|
|
|
void SpecialCases1() {
|
|
{
|
|
auto P = getPair<int, int>();
|
|
int y = P.second; // second first
|
|
int x = P.first;
|
|
}
|
|
|
|
{
|
|
auto P = getPair<int, int>();
|
|
int x = P.first;
|
|
// P.second never assigned
|
|
}
|
|
|
|
{
|
|
auto P = getPair<int, int>();
|
|
int x = P.first + 1;
|
|
int y = P.second;
|
|
}
|
|
{
|
|
auto P = getPair<int, int>();
|
|
float x = P.first; // int -> float
|
|
float y = P.second;
|
|
}
|
|
|
|
{
|
|
auto P = getPair<int, int>();
|
|
int x = P.first;
|
|
int dummy = 42;
|
|
int y = P.second;
|
|
}
|
|
|
|
{
|
|
for (auto P : std::unordered_map<int, int>()) {
|
|
int x = P.first;
|
|
int dummy = 42;
|
|
int y = P.second;
|
|
}
|
|
}
|
|
|
|
{
|
|
std::pair<int, int> somePair;
|
|
std::pair<int, int>* P = &somePair;
|
|
int x = P->first;
|
|
int y = P->second;
|
|
}
|
|
|
|
{
|
|
std::pair<int, int> somePair;
|
|
std::pair<int, int>& P = somePair;
|
|
int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
|
|
{
|
|
std::pair<int, int> somePair;
|
|
const std::pair<int, int>& P = somePair;
|
|
int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
}
|
|
|
|
// Partial and full templates
|
|
// Currently not supported because we can't get type from CXXDependentScopeMemberExpr, needs some extra work to do that.
|
|
template<typename T>
|
|
void templateFuncTest() {
|
|
auto P = getPair<T, int>();
|
|
T x = P.first;
|
|
int y = P.second;
|
|
}
|
|
|
|
template<typename T1, typename T2>
|
|
void templateFuncTest() {
|
|
auto P = getPair<T1, T2>();
|
|
T1 x = P.first;
|
|
T2 y = P.second;
|
|
}
|
|
|
|
void SpecialCases2() {
|
|
// nested pairs
|
|
{
|
|
auto P = getPair<std::pair<int, int>, int>();
|
|
int val = P.second;
|
|
std::pair<int, int> inner = P.first;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto [a_in, b_in] = P.first;
|
|
// CHECK-NEXT: // REMOVE
|
|
int a_in = inner.first;
|
|
int b_in = inner.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
// shadow
|
|
{
|
|
int x = 10;
|
|
{
|
|
auto P = getPair<int, int>();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto [x, y] = getPair<int, int>();
|
|
// CHECK-NEXT: // REMOVE
|
|
int x = P.first;
|
|
int y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
}
|
|
|
|
// only use first
|
|
{
|
|
auto P = getPair<int, int>();
|
|
int x = P.first;
|
|
int y = P.first;
|
|
}
|
|
|
|
// std::ignore in std::tie
|
|
{
|
|
int a = 0;
|
|
std::tie(a, std::ignore) = getPair<int, int>();
|
|
}
|
|
|
|
// tuple pair mixup
|
|
{
|
|
int a = 0, b = 0, c = 0;
|
|
std::tie(a, b, c) = getTuple<int, int, int>();
|
|
std::tie(a, a) = getPair<int, int>();
|
|
}
|
|
|
|
// volatile specifier
|
|
{
|
|
volatile std::pair<int, int> P = getPair<int, int>();
|
|
int x = P.first;
|
|
int y = P.second;
|
|
}
|
|
|
|
// decltype usage (there are invisible DeclRefExpr in decltype)
|
|
{
|
|
auto P = getPair<int, int>();
|
|
decltype(P.first) x = P.first;
|
|
decltype(P.second) y = P.second;
|
|
}
|
|
|
|
// constexpr pair
|
|
{
|
|
constexpr auto P = getConstexprPair<int, int>();
|
|
constexpr int x = P.first;
|
|
constexpr int y = P.second;
|
|
}
|
|
|
|
// initializer list
|
|
{
|
|
struct AggregatePair {
|
|
int first;
|
|
int second;
|
|
};
|
|
auto P = AggregatePair{.first = 1, .second = 2};
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto [x, y] = AggregatePair{.first = 1, .second = 2};
|
|
// CHECK-NEXT: // REMOVE
|
|
int x = P.first;
|
|
int y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
// reference to original pair
|
|
{
|
|
std::pair<int, int> original = getPair<int, int>();
|
|
const auto& P = original;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: const auto& [x, y] = original;
|
|
// CHECK-NEXT: // REMOVE
|
|
const int& x = P.first;
|
|
const int& y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
// typedef pair
|
|
{
|
|
using IntPair = std::pair<int, int>;
|
|
IntPair P = getPair<int, int>();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto [x, y] = getPair<int, int>();
|
|
// CHECK-NEXT: // REMOVE
|
|
int x = P.first;
|
|
int y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
|
|
// assign to existing vars
|
|
{
|
|
int x, y;
|
|
auto P = getPair<int, int>();
|
|
x = P.first;
|
|
y = P.second;
|
|
}
|
|
|
|
// conditional operator
|
|
{
|
|
bool cond;
|
|
std::pair<int, int> p1{1, 2}, p2{3, 4};
|
|
auto P = cond ? p1 : p2;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a structured binding to decompose a pair [modernize-use-structured-binding]
|
|
// CHECK-FIXES: auto [x, y] = cond ? p1 : p2;
|
|
// CHECK-NEXT: // REMOVE
|
|
int x = P.first;
|
|
int y = P.second; // REMOVE
|
|
// CHECK-FIXES: // REMOVE
|
|
}
|
|
}
|