Author: rsmith Date: Thu Aug 11 20:55:21 2016 New Revision: 278458 URL: http://llvm.org/viewvc/llvm-project?rev=278458&view=rev Log: P0217R3: template instantiation support for decomposition declarations.
Added: cfe/trunk/test/SemaTemplate/cxx1z-decomposition.cpp Modified: cfe/trunk/include/clang/AST/ExprCXX.h cfe/trunk/include/clang/Sema/Initialization.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/include/clang/Sema/Template.h cfe/trunk/lib/Sema/Sema.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/lib/Sema/SemaInit.cpp cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp Modified: cfe/trunk/include/clang/AST/ExprCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=278458&r1=278457&r2=278458&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ExprCXX.h (original) +++ cfe/trunk/include/clang/AST/ExprCXX.h Thu Aug 11 20:55:21 2016 @@ -4011,6 +4011,12 @@ public: // within a default initializer. if (isa<FieldDecl>(ExtendingDecl)) return SD_Automatic; + // FIXME: This only works because storage class specifiers are not allowed + // on decomposition declarations. + if (isa<BindingDecl>(ExtendingDecl)) + return ExtendingDecl->getDeclContext()->isFunctionOrMethod() + ? SD_Automatic + : SD_Static; return cast<VarDecl>(ExtendingDecl)->getStorageDuration(); } Modified: cfe/trunk/include/clang/Sema/Initialization.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=278458&r1=278457&r2=278458&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Initialization.h (original) +++ cfe/trunk/include/clang/Sema/Initialization.h Thu Aug 11 20:55:21 2016 @@ -184,9 +184,8 @@ private: ManglingNumber(0), VariableOrMember(Member) { } /// \brief Create the initialization entity for a binding. - InitializedEntity(BindingDecl *Binding, QualType Type, - const InitializedEntity &Parent) - : Kind(EK_Binding), Parent(&Parent), Type(Type), + InitializedEntity(BindingDecl *Binding, QualType Type) + : Kind(EK_Binding), Parent(nullptr), Type(Type), ManglingNumber(0), VariableOrMember(Binding) {} /// \brief Create the initialization entity for an array element. @@ -324,10 +323,9 @@ public: } /// \brief Create the initialization entity for a structured binding. - static InitializedEntity InitializeBinding(const InitializedEntity &Parent, - BindingDecl *Binding, + static InitializedEntity InitializeBinding(BindingDecl *Binding, QualType Type) { - return InitializedEntity(Binding, Type, Parent); + return InitializedEntity(Binding, Type); } /// \brief Create the initialization entity for a lambda capture. Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=278458&r1=278457&r2=278458&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Thu Aug 11 20:55:21 2016 @@ -1728,9 +1728,8 @@ public: // Returns true if the variable declaration is a redeclaration bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous); void CheckVariableDeclarationType(VarDecl *NewVD); - void CheckCompleteVariableDeclaration(VarDecl *VD, InitializedEntity &Entity); - void CheckCompleteDecompositionDeclaration(DecompositionDecl *DD, - InitializedEntity &Entity); + void CheckCompleteVariableDeclaration(VarDecl *VD); + void CheckCompleteDecompositionDeclaration(DecompositionDecl *DD); void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D); NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, Modified: cfe/trunk/include/clang/Sema/Template.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Template.h?rev=278458&r1=278457&r2=278458&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Template.h (original) +++ cfe/trunk/include/clang/Sema/Template.h Thu Aug 11 20:55:21 2016 @@ -433,7 +433,8 @@ namespace clang { Decl *VisitFunctionDecl(FunctionDecl *D, TemplateParameterList *TemplateParams); Decl *VisitDecl(Decl *D); - Decl *VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate); + Decl *VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate, + ArrayRef<BindingDecl *> *Bindings = nullptr); // Enable late instantiation of attributes. Late instantiated attributes // will be stored in LA. Modified: cfe/trunk/lib/Sema/Sema.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=278458&r1=278457&r2=278458&view=diff ============================================================================== --- cfe/trunk/lib/Sema/Sema.cpp (original) +++ cfe/trunk/lib/Sema/Sema.cpp Thu Aug 11 20:55:21 2016 @@ -811,8 +811,7 @@ void Sema::ActOnEndOfTranslationUnit() { VD->setInvalidDecl(); // No initialization is performed for a tentative definition. - InitializedEntity Entity = InitializedEntity::InitializeVariable(VD); - CheckCompleteVariableDeclaration(VD, Entity); + CheckCompleteVariableDeclaration(VD); // Notify the consumer that we've completed a tentative definition. if (!VD->isInvalidDecl()) Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=278458&r1=278457&r2=278458&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Aug 11 20:55:21 2016 @@ -9720,8 +9720,8 @@ void Sema::AddInitializerToDecl(Decl *Re // Perform the initialization. ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init); - InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); if (!VDecl->isInvalidDecl()) { + InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); InitializationKind Kind = DirectInit ? CXXDirectInit @@ -9972,7 +9972,7 @@ void Sema::AddInitializerToDecl(Decl *Re VDecl->setInitStyle(VarDecl::ListInit); } - CheckCompleteVariableDeclaration(VDecl, Entity); + CheckCompleteVariableDeclaration(VDecl); } /// ActOnInitializerError - Given that there was an error parsing an @@ -10257,7 +10257,7 @@ void Sema::ActOnUninitializedDecl(Decl * Var->setInitStyle(VarDecl::CallInit); } - CheckCompleteVariableDeclaration(Var, Entity); + CheckCompleteVariableDeclaration(Var); } } @@ -10334,8 +10334,7 @@ Sema::ActOnCXXForRangeIdentifier(Scope * AttrEnd.isValid() ? AttrEnd : IdentLoc); } -void Sema::CheckCompleteVariableDeclaration(VarDecl *var, - InitializedEntity &Entity) { +void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { if (var->isInvalidDecl()) return; if (getLangOpts().OpenCL) { @@ -10445,7 +10444,7 @@ void Sema::CheckCompleteVariableDeclarat if (!getLangOpts().CPlusPlus) return; if (auto *DD = dyn_cast<DecompositionDecl>(var)) - CheckCompleteDecompositionDeclaration(DD, Entity); + CheckCompleteDecompositionDeclaration(DD); QualType type = var->getType(); if (type->isDependentType()) return; Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=278458&r1=278457&r2=278458&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Aug 11 20:55:21 2016 @@ -1065,10 +1065,10 @@ struct BindingDiagnosticTrap { }; } -static bool -checkTupleLikeDecomposition(Sema &S, ArrayRef<BindingDecl *> Bindings, - ValueDecl *Src, InitializedEntity &ParentEntity, - QualType DecompType, llvm::APSInt TupleSize) { +static bool checkTupleLikeDecomposition(Sema &S, + ArrayRef<BindingDecl *> Bindings, + ValueDecl *Src, QualType DecompType, + llvm::APSInt TupleSize) { if ((int64_t)Bindings.size() != TupleSize) { S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings) << DecompType << (unsigned)Bindings.size() << TupleSize.toString(10) @@ -1152,8 +1152,7 @@ checkTupleLikeDecomposition(Sema &S, Arr if (RefType.isNull()) return true; - InitializedEntity Entity = - InitializedEntity::InitializeBinding(ParentEntity, B, RefType); + InitializedEntity Entity = InitializedEntity::InitializeBinding(B, RefType); InitializationKind Kind = InitializationKind::CreateCopy(Loc, Loc); InitializationSequence Seq(S, Entity, Kind, Init); E = Seq.Perform(S, Entity, Kind, Init); @@ -1341,8 +1340,7 @@ static bool checkMemberDecomposition(Sem return false; } -void Sema::CheckCompleteDecompositionDeclaration(DecompositionDecl *DD, - InitializedEntity &Entity) { +void Sema::CheckCompleteDecompositionDeclaration(DecompositionDecl *DD) { QualType DecompType = DD->getType(); // If the type of the decomposition is dependent, then so is the type of @@ -1386,8 +1384,7 @@ void Sema::CheckCompleteDecompositionDec return; case IsTupleLike::TupleLike: - if (checkTupleLikeDecomposition(*this, Bindings, DD, Entity, DecompType, - TupleSize)) + if (checkTupleLikeDecomposition(*this, Bindings, DD, DecompType, TupleSize)) DD->setInvalidDecl(); return; Modified: cfe/trunk/lib/Sema/SemaInit.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=278458&r1=278457&r2=278458&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaInit.cpp (original) +++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Aug 11 20:55:21 2016 @@ -5886,7 +5886,9 @@ static const InitializedEntity *getEntit return Entity; case InitializedEntity::EK_Binding: - return getEntityForTemporaryLifetimeExtension(Entity->getParent(), nullptr); + // Per [dcl.decomp]p3, the binding is treated as a variable of reference + // type. + return Entity; case InitializedEntity::EK_Parameter: case InitializedEntity::EK_Parameter_CF_Audited: Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=278458&r1=278457&r2=278458&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Aug 11 20:55:21 2016 @@ -19,6 +19,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/TypeLoc.h" +#include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Template.h" @@ -599,13 +600,27 @@ TemplateDeclInstantiator::VisitTypeAlias } Decl *TemplateDeclInstantiator::VisitBindingDecl(BindingDecl *D) { - return BindingDecl::Create(SemaRef.Context, Owner, D->getLocation(), - D->getIdentifier()); + auto *NewBD = BindingDecl::Create(SemaRef.Context, Owner, D->getLocation(), + D->getIdentifier()); + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewBD); + return NewBD; } Decl *TemplateDeclInstantiator::VisitDecompositionDecl(DecompositionDecl *D) { - // FIXME: Instantiate bindings and pass them in. - return VisitVarDecl(D, /*InstantiatingVarTemplate=*/false); + // Transform the bindings first. + SmallVector<BindingDecl*, 16> NewBindings; + for (auto *OldBD : D->bindings()) + NewBindings.push_back(cast<BindingDecl>(VisitBindingDecl(OldBD))); + ArrayRef<BindingDecl*> NewBindingArray = NewBindings; + + auto *NewDD = cast_or_null<DecompositionDecl>( + VisitVarDecl(D, /*InstantiatingVarTemplate=*/false, &NewBindingArray)); + + if (!NewDD || NewDD->isInvalidDecl()) + for (auto *NewBD : NewBindings) + NewBD->setInvalidDecl(); + + return NewDD; } Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { @@ -613,7 +628,8 @@ Decl *TemplateDeclInstantiator::VisitVar } Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, - bool InstantiatingVarTemplate) { + bool InstantiatingVarTemplate, + ArrayRef<BindingDecl*> *Bindings) { // Do substitution on the type of the declaration TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(), @@ -634,9 +650,15 @@ Decl *TemplateDeclInstantiator::VisitVar SemaRef.adjustContextForLocalExternDecl(DC); // Build the instantiated declaration. - VarDecl *Var = VarDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(), - D->getLocation(), D->getIdentifier(), - DI->getType(), DI, D->getStorageClass()); + VarDecl *Var; + if (Bindings) + Var = DecompositionDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(), + D->getLocation(), DI->getType(), DI, + D->getStorageClass(), *Bindings); + else + Var = VarDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(), + D->getLocation(), D->getIdentifier(), DI->getType(), + DI, D->getStorageClass()); // In ARC, infer 'retaining' for variables of retainable type. if (SemaRef.getLangOpts().ObjCAutoRefCount && Modified: cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp?rev=278458&r1=278457&r2=278458&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp Thu Aug 11 20:55:21 2016 @@ -38,6 +38,5 @@ constexpr bool g(S &&s) { static_assert(g({1, 2})); // FIXME: by-value array copies -// FIXME: template instantiation // FIXME: ast file support // FIXME: code generation Added: cfe/trunk/test/SemaTemplate/cxx1z-decomposition.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/cxx1z-decomposition.cpp?rev=278458&view=auto ============================================================================== --- cfe/trunk/test/SemaTemplate/cxx1z-decomposition.cpp (added) +++ cfe/trunk/test/SemaTemplate/cxx1z-decomposition.cpp Thu Aug 11 20:55:21 2016 @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s + +struct A { int x, y; }; +typedef int B[2]; +struct C { template<int> int get(); }; +struct D { int x, y, z; }; +struct E { int *p, n; }; + +namespace std { + using size_t = decltype(sizeof(0)); + template<typename> struct tuple_size; + template<size_t, typename> struct tuple_element { using type = int; }; +} + +template<> struct std::tuple_size<C> { enum { value = 2 }; }; + +template<typename T> int decomp(T &t) { + auto &[a, b] = t; // expected-error {{type 'D' decomposes into 3 elements, but only 2 names were provided}} + return a + b; // expected-error {{cannot initialize return object of type 'int' with an rvalue of type 'int *'}} +} + +void test() { + A a; + B b; + C c; + D d; + E e; + decomp(a); + decomp(b); + decomp(c); + decomp(d); // expected-note {{in instantiation of}} + decomp(e); // expected-note {{in instantiation of}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits