https://github.com/Murthy-Manideep updated https://github.com/llvm/llvm-project/pull/235427
>From 988f161231196f2a0779086d2cc8c2512a72f3bd Mon Sep 17 00:00:00 2001 From: Murthy-Manideep <[email protected]> Date: Sun, 25 Oct 2026 17:19:17 +0530 Subject: [PATCH 1/4] Fix extra error message (#222605) --- clang/lib/Sema/SemaDeclCXX.cpp | 14 ++++-- clang/test/Parser/cxx1z-decomposition.cpp | 4 +- clang/test/SemaCXX/GH222605.cpp | 53 +++++++++++++++++++++++ 3 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 clang/test/SemaCXX/GH222605.cpp diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 0fe0daa71c1bcf..2b9059f24f0214 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -863,10 +863,11 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, // The syntax only allows a single ref-qualifier prior to the decomposition // declarator. No other declarator chunks are permitted. Also check the type // specifier here. - if (DS.getTypeSpecType() != DeclSpec::TST_auto || + bool HasBadDeclarator = D.hasGroupingParens() || D.getNumTypeObjects() > 1 || (D.getNumTypeObjects() == 1 && - D.getTypeObject(0).Kind != DeclaratorChunk::Reference)) { + D.getTypeObject(0).Kind != DeclaratorChunk::Reference); + if (DS.getTypeSpecType() != DeclSpec::TST_auto || HasBadDeclarator) { Diag(Decomp.getLSquareLoc(), (D.hasGroupingParens() || (D.getNumTypeObjects() && @@ -878,7 +879,9 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, // In most cases, there's no actual problem with an explicitly-specified // type, but a function type won't work here, and ActOnVariableDeclarator // shouldn't be called for such a type. - if (R->isFunctionType()) + // If the declaration is invalid, there is no need to continue with deduction + // or binding, as this can lead to extra error messages. + if (R->isFunctionType() || HasBadDeclarator) D.setInvalidType(); } @@ -988,6 +991,11 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, CurContext->addHiddenDecl(New); } + if (New && New->isInvalidDecl()) { + for (auto *B : Bindings) + B->setInvalidDecl(); + } + if (OpenMP().isInOpenMPDeclareTargetContext()) OpenMP().checkDeclIsAllowedInOpenMPTarget(nullptr, New); diff --git a/clang/test/Parser/cxx1z-decomposition.cpp b/clang/test/Parser/cxx1z-decomposition.cpp index 45329b766bc281..dcccd63ae40ef3 100644 --- a/clang/test/Parser/cxx1z-decomposition.cpp +++ b/clang/test/Parser/cxx1z-decomposition.cpp @@ -121,8 +121,8 @@ namespace BadSpecifiers { // CHECK: :[[@LINE-1]]:13: error: structured binding declaration '[K]' requires an initializer; expected '=' or braced initializer list int [5] arr = {0}; // expected-error {{place the brackets after the name}} - auto *[f] = s; // expected-error {{cannot be declared with type 'auto *'}} expected-error {{incompatible initializer}} - auto S::*[g] = s; // expected-error {{cannot be declared with type 'auto S::*'}} expected-error {{incompatible initializer}} + auto *[f] = s; // expected-error {{cannot be declared with type 'auto *'}} + auto S::*[g] = s; // expected-error {{cannot be declared with type 'auto S::*'}} // ref-qualifiers are OK. auto &&[ok_1] = S(); diff --git a/clang/test/SemaCXX/GH222605.cpp b/clang/test/SemaCXX/GH222605.cpp new file mode 100644 index 00000000000000..dbe81addf49847 --- /dev/null +++ b/clang/test/SemaCXX/GH222605.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s + +struct S { + int *p; + int *q; +}; + +struct Point { + double x; + double y; + double z; +}; + +void test_original(S s) { + auto* [x, y] = s; // expected-error {{structured binding declaration cannot be declared with type 'auto *'; declared type must be 'auto' or reference to 'auto'}} +} + +void test_other_struct(Point pt) { + auto* [x, y, z] = pt; // expected-error {{structured binding declaration cannot be declared with type 'auto *'; declared type must be 'auto' or reference to 'auto'}} +} + +void test_auto_variations(S s) { + auto*& [a, b] = s; // expected-error {{structured binding declaration cannot be declared with type 'auto *&'; declared type must be 'auto' or reference to 'auto'}} + const auto* [c, d] = s; // expected-error {{structured binding declaration cannot be declared with type 'const auto *'; declared type must be 'auto' or reference to 'auto'}} + const auto*& [e, f] = s; // expected-error {{structured binding declaration cannot be declared with type 'const auto *&'; declared type must be 'auto' or reference to 'auto'}} +} + +void test_valid(S s, Point pt) { + auto [a, b] = s; + auto& [c, d] = s; + const auto& [e, f] = s; + auto&& [g, h] = S{}; + + auto [x, y, z] = pt; + const auto& [cx, cy, cz] = pt; +} + +void test_other_errors(S s) { + auto* p = s; // expected-error {{variable 'p' with type 'auto *' has incompatible initializer of type 'S'}} + + auto [a] = s; // expected-error {{type 'S' binds to 2 elements, but only 1 name was provided}} + auto [b, c, d] = s; // expected-error {{type 'S' binds to 2 elements, but 3 names were provided}} + + int n = 0; + auto [x, y] = n; // expected-error {{cannot bind non-class, non-array type 'int'}} +} + +void test_pointer(S *s) { + auto* [a, b] = s; // expected-error {{structured binding declaration cannot be declared with type 'auto *'; declared type must be 'auto' or reference to 'auto'}} + auto** [c, d] = &s; // expected-error {{structured binding declaration cannot be declared with type 'auto **'; declared type must be 'auto' or reference to 'auto'}} +} >From 56e584e89cc821dffb9a1444732d247fe970a7e5 Mon Sep 17 00:00:00 2001 From: Murthy-Manideep <[email protected]> Date: Mon, 26 Oct 2026 22:17:38 +0530 Subject: [PATCH 2/4] Improve recovery for structured binding pointer declarators --- clang/docs/ReleaseNotes.md | 5 +++++ clang/include/clang/Sema/DeclSpec.h | 11 +++++++--- clang/lib/Sema/SemaDeclCXX.cpp | 28 ++++++++++++++++++++---- clang/test/SemaCXX/GH222605.cpp | 34 +++++++++++++++++++++-------- 4 files changed, 62 insertions(+), 16 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 44f30666457f94..1aa987ec437b00 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -889,6 +889,11 @@ documentation](CIR/index.md) for more information regarding ClangIR's status and type. (#GH204756) #### Bug Fixes to C++ Support +- Clang now handles invalid pointer declarators in structured bindings + (such as ``auto* [x, y] = s;``) by removing the pointer part. This + avoids extra type deduction errors and improves error messages. + (#GH222605) + - Instantiate constexpr functions as needed before they are evaluated. (#GH73232) (#GH35052) (#GH100897) - Fixed lambdas with specifiers or attributes after the capture list being diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 7b58bfcf53d98a..bc93eaaeeda158 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -2489,10 +2489,15 @@ class Declarator { return type_object_range(DeclTypeInfo.begin(), DeclTypeInfo.end()); } + /// Removes the type object at the specified index. + void DropTypeObject(unsigned index) { + assert(index < DeclTypeInfo.size() && "Invalid type chunk"); + DeclTypeInfo[index].destroy(); + DeclTypeInfo.erase(DeclTypeInfo.begin() + index); + } + void DropFirstTypeObject() { - assert(!DeclTypeInfo.empty() && "No type chunks to drop."); - DeclTypeInfo.front().destroy(); - DeclTypeInfo.erase(DeclTypeInfo.begin()); + DropTypeObject(0); } /// Return the innermost (closest to the declarator) chunk of this diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 2b9059f24f0214..0d67212c21c611 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -878,10 +878,30 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, // In most cases, there's no actual problem with an explicitly-specified // type, but a function type won't work here, and ActOnVariableDeclarator - // shouldn't be called for such a type. - // If the declaration is invalid, there is no need to continue with deduction - // or binding, as this can lead to extra error messages. - if (R->isFunctionType() || HasBadDeclarator) + // shouldn't be called for such a type. + // Recover from invalid pointer declarators by removing pointer chunks + // so type deduction can proceed and the bindings remain usable. + bool DroppedPointer = false; + for (unsigned I = D.getNumTypeObjects(); I > 0; --I) { + const DeclaratorChunk &Chunk = D.getTypeObject(I - 1); + if (Chunk.Kind == DeclaratorChunk::Pointer || + Chunk.Kind == DeclaratorChunk::MemberPointer) { + D.DropTypeObject(I - 1); + DroppedPointer = true; + } + } + + if (DroppedPointer) { + TInfo = GetTypeForDeclarator(D); + R = TInfo->getType(); + } + + bool StillHasBadDeclarator = + D.hasGroupingParens() || D.getNumTypeObjects() > 1 || + (D.getNumTypeObjects() == 1 && + D.getTypeObject(0).Kind != DeclaratorChunk::Reference); + + if (R->isFunctionType() || StillHasBadDeclarator) D.setInvalidType(); } diff --git a/clang/test/SemaCXX/GH222605.cpp b/clang/test/SemaCXX/GH222605.cpp index dbe81addf49847..b6cd1651ff46d1 100644 --- a/clang/test/SemaCXX/GH222605.cpp +++ b/clang/test/SemaCXX/GH222605.cpp @@ -13,18 +13,32 @@ struct Point { double z; }; -void test_original(S s) { +void test_recovery(S s) { auto* [x, y] = s; // expected-error {{structured binding declaration cannot be declared with type 'auto *'; declared type must be 'auto' or reference to 'auto'}} + x = nullptr; + y = nullptr; + + auto*& [r1, r2] = s; // expected-error {{structured binding declaration cannot be declared with type 'auto *&'; declared type must be 'auto' or reference to 'auto'}} + r1 = nullptr; + r2 = nullptr; + + const auto* [c1, c2] = s; // expected-error {{structured binding declaration cannot be declared with type 'const auto *'; declared type must be 'auto' or reference to 'auto'}} + + const auto*& [cr1, cr2] = s; // expected-error {{structured binding declaration cannot be declared with type 'const auto *&'; declared type must be 'auto' or reference to 'auto'}} + + auto** [p1, p2] = s; // expected-error {{structured binding declaration cannot be declared with type 'auto **'; declared type must be 'auto' or reference to 'auto'}} + p1 = nullptr; + p2 = nullptr; } -void test_other_struct(Point pt) { +void test_aggregate(Point pt) { auto* [x, y, z] = pt; // expected-error {{structured binding declaration cannot be declared with type 'auto *'; declared type must be 'auto' or reference to 'auto'}} + double sum = x + y + z; } -void test_auto_variations(S s) { - auto*& [a, b] = s; // expected-error {{structured binding declaration cannot be declared with type 'auto *&'; declared type must be 'auto' or reference to 'auto'}} - const auto* [c, d] = s; // expected-error {{structured binding declaration cannot be declared with type 'const auto *'; declared type must be 'auto' or reference to 'auto'}} - const auto*& [e, f] = s; // expected-error {{structured binding declaration cannot be declared with type 'const auto *&'; declared type must be 'auto' or reference to 'auto'}} +void test_downstream_type_checking(Point pt) { + auto* [x, y, z] = pt; // expected-error {{structured binding declaration cannot be declared with type 'auto *'; declared type must be 'auto' or reference to 'auto'}} + decltype(x) bad = "string"; // expected-error {{cannot initialize a variable of type 'decltype(x)' (aka 'double') with an lvalue of type 'const char[7]'}} } void test_valid(S s, Point pt) { @@ -47,7 +61,9 @@ void test_other_errors(S s) { auto [x, y] = n; // expected-error {{cannot bind non-class, non-array type 'int'}} } -void test_pointer(S *s) { - auto* [a, b] = s; // expected-error {{structured binding declaration cannot be declared with type 'auto *'; declared type must be 'auto' or reference to 'auto'}} - auto** [c, d] = &s; // expected-error {{structured binding declaration cannot be declared with type 'auto **'; declared type must be 'auto' or reference to 'auto'}} +void test_pointer(S *sp) { + auto* [a, b] = sp; // expected-error {{structured binding declaration cannot be declared with type 'auto *'; declared type must be 'auto' or reference to 'auto'}} \ + // expected-error {{cannot bind non-class, non-array type 'S *'}} + auto** [c, d] = &sp; // expected-error {{structured binding declaration cannot be declared with type 'auto **'; declared type must be 'auto' or reference to 'auto'}} \ + // expected-error {{cannot bind non-class, non-array type 'S **'}} } >From 3bdb87f4b968ef94a1c38a056c2e96d3ff36a134 Mon Sep 17 00:00:00 2001 From: Murthy-Manideep <[email protected]> Date: Tue, 27 Oct 2026 21:08:49 +0530 Subject: [PATCH 3/4] Fix formatting in code --- clang/include/clang/Sema/DeclSpec.h | 4 +--- clang/lib/Sema/SemaDeclCXX.cpp | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index bc93eaaeeda158..a803ec39a706c6 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -2496,9 +2496,7 @@ class Declarator { DeclTypeInfo.erase(DeclTypeInfo.begin() + index); } - void DropFirstTypeObject() { - DropTypeObject(0); - } + void DropFirstTypeObject() { DropTypeObject(0); } /// Return the innermost (closest to the declarator) chunk of this /// declarator that is not a parens chunk, or null if there are no diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 0d67212c21c611..80dd74bbe6a9fb 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -878,7 +878,7 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, // In most cases, there's no actual problem with an explicitly-specified // type, but a function type won't work here, and ActOnVariableDeclarator - // shouldn't be called for such a type. + // shouldn't be called for such a type. // Recover from invalid pointer declarators by removing pointer chunks // so type deduction can proceed and the bindings remain usable. bool DroppedPointer = false; >From 39b9c79f610f973b9d898cfe09ed44f1847e5bb4 Mon Sep 17 00:00:00 2001 From: Murthy-Manideep <[email protected]> Date: Sat, 31 Oct 2026 13:45:59 +0530 Subject: [PATCH 4/4] Restrict recovery to single pointer declarators --- clang/docs/ReleaseNotes.md | 10 ++-- clang/include/clang/Sema/DeclSpec.h | 11 ++-- clang/lib/Sema/SemaDeclCXX.cpp | 41 +++++---------- clang/test/Parser/cxx1z-decomposition.cpp | 2 +- clang/test/SemaCXX/GH222605.cpp | 61 +++++++++-------------- 5 files changed, 46 insertions(+), 79 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 1aa987ec437b00..cde1aa80436fce 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -889,11 +889,11 @@ documentation](CIR/index.md) for more information regarding ClangIR's status and type. (#GH204756) #### Bug Fixes to C++ Support -- Clang now handles invalid pointer declarators in structured bindings - (such as ``auto* [x, y] = s;``) by removing the pointer part. This - avoids extra type deduction errors and improves error messages. - (#GH222605) - +- Clang now recovers from invalid single pointer declarators in structured + bindings (such as ``auto *[x, y] = s;``) by removing the pointer declarator. + This allows type deduction to proceed and avoids redundant follow-up + diagnostics. (#GH222605) + - Instantiate constexpr functions as needed before they are evaluated. (#GH73232) (#GH35052) (#GH100897) - Fixed lambdas with specifiers or attributes after the capture list being diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index a803ec39a706c6..7b58bfcf53d98a 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -2489,15 +2489,12 @@ class Declarator { return type_object_range(DeclTypeInfo.begin(), DeclTypeInfo.end()); } - /// Removes the type object at the specified index. - void DropTypeObject(unsigned index) { - assert(index < DeclTypeInfo.size() && "Invalid type chunk"); - DeclTypeInfo[index].destroy(); - DeclTypeInfo.erase(DeclTypeInfo.begin() + index); + void DropFirstTypeObject() { + assert(!DeclTypeInfo.empty() && "No type chunks to drop."); + DeclTypeInfo.front().destroy(); + DeclTypeInfo.erase(DeclTypeInfo.begin()); } - void DropFirstTypeObject() { DropTypeObject(0); } - /// Return the innermost (closest to the declarator) chunk of this /// declarator that is not a parens chunk, or null if there are no /// non-parens chunks. diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 80dd74bbe6a9fb..35af92d6f1d5c6 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -863,11 +863,10 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, // The syntax only allows a single ref-qualifier prior to the decomposition // declarator. No other declarator chunks are permitted. Also check the type // specifier here. - bool HasBadDeclarator = - D.hasGroupingParens() || D.getNumTypeObjects() > 1 || + if (DS.getTypeSpecType() != DeclSpec::TST_auto || D.hasGroupingParens() || + D.getNumTypeObjects() > 1 || (D.getNumTypeObjects() == 1 && - D.getTypeObject(0).Kind != DeclaratorChunk::Reference); - if (DS.getTypeSpecType() != DeclSpec::TST_auto || HasBadDeclarator) { + D.getTypeObject(0).Kind != DeclaratorChunk::Reference)) { Diag(Decomp.getLSquareLoc(), (D.hasGroupingParens() || (D.getNumTypeObjects() && @@ -879,30 +878,19 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, // In most cases, there's no actual problem with an explicitly-specified // type, but a function type won't work here, and ActOnVariableDeclarator // shouldn't be called for such a type. - // Recover from invalid pointer declarators by removing pointer chunks - // so type deduction can proceed and the bindings remain usable. - bool DroppedPointer = false; - for (unsigned I = D.getNumTypeObjects(); I > 0; --I) { - const DeclaratorChunk &Chunk = D.getTypeObject(I - 1); - if (Chunk.Kind == DeclaratorChunk::Pointer || - Chunk.Kind == DeclaratorChunk::MemberPointer) { - D.DropTypeObject(I - 1); - DroppedPointer = true; - } - } + if (R->isFunctionType()) + D.setInvalidType(); - if (DroppedPointer) { + // Recover from an invalid 'auto *' structured binding by removing the + // pointer declarator. This allows type deduction to proceed and keeps + // the bindings usable in subsequent code. + if (D.getNumTypeObjects() == 1 && + D.getTypeObject(0).Kind == DeclaratorChunk::Pointer && + D.getTypeObject(0).Ptr.TypeQuals == 0) { + D.DropFirstTypeObject(); TInfo = GetTypeForDeclarator(D); R = TInfo->getType(); } - - bool StillHasBadDeclarator = - D.hasGroupingParens() || D.getNumTypeObjects() > 1 || - (D.getNumTypeObjects() == 1 && - D.getTypeObject(0).Kind != DeclaratorChunk::Reference); - - if (R->isFunctionType() || StillHasBadDeclarator) - D.setInvalidType(); } // Constrained auto is prohibited by [decl.pre]p6, so check that here. @@ -1011,11 +999,6 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, CurContext->addHiddenDecl(New); } - if (New && New->isInvalidDecl()) { - for (auto *B : Bindings) - B->setInvalidDecl(); - } - if (OpenMP().isInOpenMPDeclareTargetContext()) OpenMP().checkDeclIsAllowedInOpenMPTarget(nullptr, New); diff --git a/clang/test/Parser/cxx1z-decomposition.cpp b/clang/test/Parser/cxx1z-decomposition.cpp index dcccd63ae40ef3..2e1b4507002db2 100644 --- a/clang/test/Parser/cxx1z-decomposition.cpp +++ b/clang/test/Parser/cxx1z-decomposition.cpp @@ -122,7 +122,7 @@ namespace BadSpecifiers { int [5] arr = {0}; // expected-error {{place the brackets after the name}} auto *[f] = s; // expected-error {{cannot be declared with type 'auto *'}} - auto S::*[g] = s; // expected-error {{cannot be declared with type 'auto S::*'}} + auto S::*[g] = s; // expected-error {{cannot be declared with type 'auto S::*'}} expected-error {{incompatible initializer}} // ref-qualifiers are OK. auto &&[ok_1] = S(); diff --git a/clang/test/SemaCXX/GH222605.cpp b/clang/test/SemaCXX/GH222605.cpp index b6cd1651ff46d1..d17f3ec2295071 100644 --- a/clang/test/SemaCXX/GH222605.cpp +++ b/clang/test/SemaCXX/GH222605.cpp @@ -13,57 +13,44 @@ struct Point { double z; }; -void test_recovery(S s) { +void test_recovered(S s, Point pt) { auto* [x, y] = s; // expected-error {{structured binding declaration cannot be declared with type 'auto *'; declared type must be 'auto' or reference to 'auto'}} x = nullptr; y = nullptr; - auto*& [r1, r2] = s; // expected-error {{structured binding declaration cannot be declared with type 'auto *&'; declared type must be 'auto' or reference to 'auto'}} - r1 = nullptr; - r2 = nullptr; - const auto* [c1, c2] = s; // expected-error {{structured binding declaration cannot be declared with type 'const auto *'; declared type must be 'auto' or reference to 'auto'}} - const auto*& [cr1, cr2] = s; // expected-error {{structured binding declaration cannot be declared with type 'const auto *&'; declared type must be 'auto' or reference to 'auto'}} - - auto** [p1, p2] = s; // expected-error {{structured binding declaration cannot be declared with type 'auto **'; declared type must be 'auto' or reference to 'auto'}} - p1 = nullptr; - p2 = nullptr; + auto* [px, py, pz] = pt; // expected-error {{structured binding declaration cannot be declared with type 'auto *'; declared type must be 'auto' or reference to 'auto'}} + double sum = px + py + pz; + decltype(px) bad = "string"; // expected-error {{cannot initialize a variable of type 'decltype(px)' (aka 'double') with an lvalue of type 'const char[7]'}} } -void test_aggregate(Point pt) { - auto* [x, y, z] = pt; // expected-error {{structured binding declaration cannot be declared with type 'auto *'; declared type must be 'auto' or reference to 'auto'}} - double sum = x + y + z; -} +void test_unrecovered(S s) { + auto** [p1, p2] = s; // expected-error {{structured binding declaration cannot be declared with type 'auto **'; declared type must be 'auto' or reference to 'auto'}} \ + // expected-error {{variable '' with type 'auto **' has incompatible initializer of type 'S'}} -void test_downstream_type_checking(Point pt) { - auto* [x, y, z] = pt; // expected-error {{structured binding declaration cannot be declared with type 'auto *'; declared type must be 'auto' or reference to 'auto'}} - decltype(x) bad = "string"; // expected-error {{cannot initialize a variable of type 'decltype(x)' (aka 'double') with an lvalue of type 'const char[7]'}} -} + auto* const [k1, k2] = s; // expected-error {{structured binding declaration cannot be declared with type 'auto *const'; declared type must be 'auto' or reference to 'auto'}} \ + // expected-error {{variable '' with type 'auto *const' has incompatible initializer of type 'S'}} -void test_valid(S s, Point pt) { - auto [a, b] = s; - auto& [c, d] = s; - const auto& [e, f] = s; - auto&& [g, h] = S{}; + auto*& [r1, r2] = s; // expected-error {{structured binding declaration cannot be declared with type 'auto *&'; declared type must be 'auto' or reference to 'auto'}} \ + // expected-error {{variable '' with type 'auto *&' has incompatible initializer of type 'S'}} - auto [x, y, z] = pt; - const auto& [cx, cy, cz] = pt; + auto S::*[m1, m2] = s; // expected-error {{structured binding declaration cannot be declared with type 'auto S::*'; declared type must be 'auto' or reference to 'auto'}} \ + // expected-error {{variable '' with type 'auto S::*' has incompatible initializer of type 'S'}} } -void test_other_errors(S s) { - auto* p = s; // expected-error {{variable 'p' with type 'auto *' has incompatible initializer of type 'S'}} - - auto [a] = s; // expected-error {{type 'S' binds to 2 elements, but only 1 name was provided}} - auto [b, c, d] = s; // expected-error {{type 'S' binds to 2 elements, but 3 names were provided}} +void test_pointer_object(S *sp) { + auto* [a, b] = sp; // expected-error {{structured binding declaration cannot be declared with type 'auto *'; declared type must be 'auto' or reference to 'auto'}} \ + // expected-error {{cannot bind non-class, non-array type 'S *'}} +} - int n = 0; - auto [x, y] = n; // expected-error {{cannot bind non-class, non-array type 'int'}} +template <typename T> +void test_template(T s) { + auto* [x, y] = s; // expected-error {{structured binding declaration cannot be declared with type 'auto *'; declared type must be 'auto' or reference to 'auto'}} + x = nullptr; + y = nullptr; } -void test_pointer(S *sp) { - auto* [a, b] = sp; // expected-error {{structured binding declaration cannot be declared with type 'auto *'; declared type must be 'auto' or reference to 'auto'}} \ - // expected-error {{cannot bind non-class, non-array type 'S *'}} - auto** [c, d] = &sp; // expected-error {{structured binding declaration cannot be declared with type 'auto **'; declared type must be 'auto' or reference to 'auto'}} \ - // expected-error {{cannot bind non-class, non-array type 'S **'}} +void test_template_instantiation(S s) { + test_template(s); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
