r278458 - P0217R3: template instantiation support for decomposition declarations.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 11 18:55:21 PDT 2016


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}}
+}




More information about the cfe-commits mailing list