summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/DeclCXX.h3
-rw-r--r--include/clang/Serialization/ASTBitCodes.h4
-rw-r--r--lib/AST/DeclCXX.cpp5
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp20
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp21
-rw-r--r--test/PCH/cxx1z-decomposition.cpp32
-rw-r--r--test/SemaCXX/cxx1z-decomposition.cpp1
7 files changed, 81 insertions, 5 deletions
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 48ada29bb6..5a692e97ce 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -3414,6 +3414,8 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Decl::Binding; }
+
+ friend class ASTDeclReader;
};
/// A decomposition declaration. For instance, given:
@@ -3463,6 +3465,7 @@ public:
static bool classofKind(Kind K) { return K == Decomposition; }
friend TrailingObjects;
+ friend class ASTDeclReader;
};
/// An instance of this class represents the declaration of a property
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index cd71410d2c..47678a1637 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -1056,6 +1056,10 @@ namespace clang {
DECL_IMPLICIT_PARAM,
/// \brief A ParmVarDecl record.
DECL_PARM_VAR,
+ /// \brief A DecompositionDecl record.
+ DECL_DECOMPOSITION,
+ /// \brief A BindingDecl record.
+ DECL_BINDING,
/// \brief A FileScopeAsmDecl record.
DECL_FILE_SCOPE_ASM,
/// \brief A BlockDecl record.
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 14df382697..54fd723d97 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -2334,8 +2334,9 @@ DecompositionDecl *DecompositionDecl::CreateDeserialized(ASTContext &C,
unsigned ID,
unsigned NumBindings) {
size_t Extra = additionalSizeToAlloc<BindingDecl *>(NumBindings);
- auto *Result = new (C, ID, Extra) DecompositionDecl(
- C, nullptr, SourceLocation(), SourceLocation(), QualType(), nullptr, StorageClass(), None);
+ auto *Result = new (C, ID, Extra)
+ DecompositionDecl(C, nullptr, SourceLocation(), SourceLocation(),
+ QualType(), nullptr, StorageClass(), None);
// Set up and clean out the bindings array.
Result->NumBindings = NumBindings;
auto *Trail = Result->getTrailingObjects<BindingDecl *>();
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 88a08560e3..e1859388f5 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -312,6 +312,8 @@ namespace clang {
void VisitVarDecl(VarDecl *VD) { VisitVarDeclImpl(VD); }
void VisitImplicitParamDecl(ImplicitParamDecl *PD);
void VisitParmVarDecl(ParmVarDecl *PD);
+ void VisitDecompositionDecl(DecompositionDecl *DD);
+ void VisitBindingDecl(BindingDecl *BD);
void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
DeclID VisitTemplateDecl(TemplateDecl *D);
RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
@@ -1295,6 +1297,18 @@ void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
// inheritance of default arguments.
}
+void ASTDeclReader::VisitDecompositionDecl(DecompositionDecl *DD) {
+ VisitVarDecl(DD);
+ BindingDecl **BDs = DD->getTrailingObjects<BindingDecl*>();
+ for (unsigned I = 0; I != DD->NumBindings; ++I)
+ BDs[I] = ReadDeclAs<BindingDecl>(Record, Idx);
+}
+
+void ASTDeclReader::VisitBindingDecl(BindingDecl *BD) {
+ VisitValueDecl(BD);
+ BD->Binding = Reader.ReadExpr(F);
+}
+
void ASTDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {
VisitDecl(AD);
AD->setAsmString(cast<StringLiteral>(Reader.ReadExpr(F)));
@@ -3400,6 +3414,12 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
case DECL_PARM_VAR:
D = ParmVarDecl::CreateDeserialized(Context, ID);
break;
+ case DECL_DECOMPOSITION:
+ D = DecompositionDecl::CreateDeserialized(Context, ID, Record[Idx++]);
+ break;
+ case DECL_BINDING:
+ D = BindingDecl::CreateDeserialized(Context, ID);
+ break;
case DECL_FILE_SCOPE_ASM:
D = FileScopeAsmDecl::CreateDeserialized(Context, ID);
break;
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 8205d60ca7..158123b1c0 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -96,6 +96,8 @@ namespace clang {
void VisitVarDecl(VarDecl *D);
void VisitImplicitParamDecl(ImplicitParamDecl *D);
void VisitParmVarDecl(ParmVarDecl *D);
+ void VisitDecompositionDecl(DecompositionDecl *D);
+ void VisitBindingDecl(BindingDecl *D);
void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
void VisitTemplateDecl(TemplateDecl *D);
void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
@@ -941,8 +943,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
D->getFirstDecl() == D->getMostRecentDecl() &&
D->getInitStyle() == VarDecl::CInit &&
D->getInit() == nullptr &&
- !isa<ParmVarDecl>(D) &&
- !isa<VarTemplateSpecializationDecl>(D) &&
+ D->getKind() == Decl::Var &&
!D->isInline() &&
!D->isConstexpr() &&
!D->isInitCapture() &&
@@ -1005,6 +1006,22 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
"PARM_VAR_DECL can't be static data member");
}
+void ASTDeclWriter::VisitDecompositionDecl(DecompositionDecl *D) {
+ // Record the number of bindings first to simplify deserialization.
+ Record.push_back(D->bindings().size());
+
+ VisitVarDecl(D);
+ for (auto *B : D->bindings())
+ Record.AddDeclRef(B);
+ Code = serialization::DECL_DECOMPOSITION;
+}
+
+void ASTDeclWriter::VisitBindingDecl(BindingDecl *D) {
+ VisitValueDecl(D);
+ Record.AddStmt(D->getBinding());
+ Code = serialization::DECL_BINDING;
+}
+
void ASTDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
VisitDecl(D);
Record.AddStmt(D->getAsmString());
diff --git a/test/PCH/cxx1z-decomposition.cpp b/test/PCH/cxx1z-decomposition.cpp
new file mode 100644
index 0000000000..e033577162
--- /dev/null
+++ b/test/PCH/cxx1z-decomposition.cpp
@@ -0,0 +1,32 @@
+// No PCH:
+// RUN: %clang_cc1 -pedantic -std=c++1z -include %s -verify %s
+//
+// With PCH:
+// RUN: %clang_cc1 -pedantic -std=c++1z -emit-pch %s -o %t
+// RUN: %clang_cc1 -pedantic -std=c++1z -include-pch %t -verify %s
+
+#ifndef HEADER
+#define HEADER
+
+template<typename T> auto decomp(const T &t) {
+ auto &[a, b] = t;
+ return a + b;
+}
+
+struct Q { int a, b; };
+constexpr int foo(Q &&q) {
+ auto &[a, b] = q;
+ return a * 10 + b;
+}
+
+#else
+
+int arr[2];
+int k = decomp(arr);
+
+static_assert(foo({1, 2}) == 12);
+
+// expected-error@12 {{cannot decompose non-class, non-array type 'const int'}}
+int z = decomp(10); // expected-note {{instantiation of}}
+
+#endif
diff --git a/test/SemaCXX/cxx1z-decomposition.cpp b/test/SemaCXX/cxx1z-decomposition.cpp
index 22d48b3ca8..9bb8eeca50 100644
--- a/test/SemaCXX/cxx1z-decomposition.cpp
+++ b/test/SemaCXX/cxx1z-decomposition.cpp
@@ -38,5 +38,4 @@ constexpr bool g(S &&s) {
static_assert(g({1, 2}));
// FIXME: by-value array copies
-// FIXME: ast file support
// FIXME: code generation