Skip to content

Commit

Permalink
[SemaCXX] Fix ICE with structure bindings to members of template
Browse files Browse the repository at this point in the history
Summary:
Trying to use structure binding with a structure that doesn't implement
std::tuple_size, should unpack the data members. When the struct is a
template though, clang might hit an assertion (if the type has not been
completed before), because CXXRecordDecl::DefinitionData is nullptr.

This commit fixes the problem by completing the type while trying to
decompose the structured binding.

The ICE happens in real world code, for example, when trying to iterate
a protobuf generated map with a range-based for loop and structure
bindings (because google::protobuf::MapPair is a template and doesn't
support std::tuple_size).

Reported-by: nicholas.sun@nlsun.com

Patch by Daniele Di Proietto

Reviewers: #clang, rsmith

Reviewed By: #clang, rsmith

Subscribers: cpplearner, Rakete1111, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D56974

llvm-svn: 352323
  • Loading branch information
Rakete1111 committed Jan 27, 2019
1 parent 1dc4e01 commit 0276d12
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 0 deletions.
4 changes: 4 additions & 0 deletions clang/lib/Sema/SemaDeclCXX.cpp
Expand Up @@ -1300,6 +1300,10 @@ static DeclAccessPair findDecomposableBaseClass(Sema &S, SourceLocation Loc,
static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
ValueDecl *Src, QualType DecompType,
const CXXRecordDecl *OrigRD) {
if (S.RequireCompleteType(Src->getLocation(), DecompType,
diag::err_incomplete_type))
return true;

CXXCastPath BasePath;
DeclAccessPair BasePair =
findDecomposableBaseClass(S, Src->getLocation(), OrigRD, BasePath);
Expand Down
17 changes: 17 additions & 0 deletions clang/test/SemaCXX/cxx1z-decomposition.cpp
Expand Up @@ -81,4 +81,21 @@ struct PR37352 {
void f() { static auto [a] = *this; } // expected-error {{cannot be declared 'static'}}
};

namespace instantiate_template {

template <typename T1, typename T2>
struct pair {
T1 a;
T2 b;
};

const pair<int, int> &f1();

int f2() {
const auto &[a, b] = f1();
return a + b;
}

} // namespace instantiate_template

// FIXME: by-value array copies

0 comments on commit 0276d12

Please sign in to comment.