<div dir="ltr">Heads-up: This causes Chromium's build to fail with<div><br></div><div>clang-cl: /usr/local/google/home/thakis/src/chrome/src/third_party/llvm/clang/lib/AST/ASTContext.cpp:4823: clang::QualType clang::ASTContext::getPackExpansionType(clang::QualType, llvm::Optional<unsigned int>, bool): Assertion `(!ExpectPackInType || Pattern->containsUnexpandedParameterPack()) && "Pack expansions must expand one or more parameter packs"' failed.<br></div><div><br></div><div>under certain scenarios with precompiled headers. At the moment I only have a repro when we use a Chromium-specific compiler plugin (<a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1110981#c19">https://bugs.chromium.org/p/chromium/issues/detail?id=1110981#c19</a>), but it's likely I'll have one without that soonish.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Jul 28, 2020 at 4:23 PM Richard Smith via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Author: Richard Smith<br>
Date: 2020-07-28T13:23:13-07:00<br>
New Revision: 740a164dec483225cbd02ab6c82199e2747ffacb<br>
<br>
URL: <a href="https://github.com/llvm/llvm-project/commit/740a164dec483225cbd02ab6c82199e2747ffacb" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/740a164dec483225cbd02ab6c82199e2747ffacb</a><br>
DIFF: <a href="https://github.com/llvm/llvm-project/commit/740a164dec483225cbd02ab6c82199e2747ffacb.diff" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/740a164dec483225cbd02ab6c82199e2747ffacb.diff</a><br>
<br>
LOG: PR46377: Fix dependence calculation for function types and typedef<br>
types.<br>
<br>
We previously did not treat a function type as dependent if it had a<br>
parameter pack with a non-dependent type -- such a function type depends<br>
on the arity of the pack so is dependent even though none of the<br>
parameter types is dependent. In order to properly handle this, we now<br>
treat pack expansion types as always being dependent types (depending on<br>
at least the pack arity), and always canonically being pack expansion<br>
types, even in the unusual case when the pattern is not a dependent<br>
type. This does mean that we can have canonical types that are pack<br>
expansions that contain no unexpanded packs, which is unfortunate but<br>
not inaccurate.<br>
<br>
We also previously did not treat a typedef type as<br>
instantiation-dependent if its canonical type was not<br>
instantiation-dependent. That's wrong because instantiation-dependence<br>
is a property of the type sugar, not of the type; an<br>
instantiation-dependent type can have a non-instantiation-dependent<br>
canonical type.<br>
<br>
Added: <br>
    clang/test/SemaTemplate/alias-template-nondependent.cpp<br>
<br>
Modified: <br>
    clang/include/clang/AST/ASTContext.h<br>
    clang/include/clang/AST/Type.h<br>
    clang/include/clang/Basic/TypeNodes.td<br>
    clang/lib/AST/ASTContext.cpp<br>
    clang/lib/AST/Type.cpp<br>
    clang/lib/CodeGen/CGDebugInfo.cpp<br>
    clang/lib/CodeGen/CodeGenFunction.cpp<br>
    clang/lib/Sema/SemaExpr.cpp<br>
    clang/lib/Sema/SemaLambda.cpp<br>
    clang/lib/Sema/SemaTemplateVariadic.cpp<br>
    clang/lib/Sema/SemaType.cpp<br>
<br>
Removed: <br>
<br>
<br>
<br>
################################################################################<br>
diff  --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h<br>
index 59e2679ddded..6c00fe86f282 100644<br>
--- a/clang/include/clang/AST/ASTContext.h<br>
+++ b/clang/include/clang/AST/ASTContext.h<br>
@@ -1459,8 +1459,16 @@ class ASTContext : public RefCountedBase<ASTContext> {<br>
   void getInjectedTemplateArgs(const TemplateParameterList *Params,<br>
                                SmallVectorImpl<TemplateArgument> &Args);<br>
<br>
+  /// Form a pack expansion type with the given pattern.<br>
+  /// \param NumExpansions The number of expansions for the pack, if known.<br>
+  /// \param ExpectPackInType If \c false, we should not expect \p Pattern to<br>
+  ///        contain an unexpanded pack. This only makes sense if the pack<br>
+  ///        expansion is used in a context where the arity is inferred from<br>
+  ///        elsewhere, such as if the pattern contains a placeholder type or<br>
+  ///        if this is the canonical type of another pack expansion type.<br>
   QualType getPackExpansionType(QualType Pattern,<br>
-                                Optional<unsigned> NumExpansions);<br>
+                                Optional<unsigned> NumExpansions,<br>
+                                bool ExpectPackInType = true);<br>
<br>
   QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,<br>
                                 ObjCInterfaceDecl *PrevDecl = nullptr) const;<br>
<br>
diff  --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h<br>
index 9a745ef20fac..7fe652492b0e 100644<br>
--- a/clang/include/clang/AST/Type.h<br>
+++ b/clang/include/clang/AST/Type.h<br>
@@ -4383,11 +4383,7 @@ class TypedefType : public Type {<br>
 protected:<br>
   friend class ASTContext; // ASTContext creates these.<br>
<br>
-  TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can)<br>
-      : Type(tc, can, can->getDependence() & ~TypeDependence::UnexpandedPack),<br>
-        Decl(const_cast<TypedefNameDecl *>(D)) {<br>
-    assert(!isa<TypedefType>(can) && "Invalid canonical type");<br>
-  }<br>
+  TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can);<br>
<br>
 public:<br>
   TypedefNameDecl *getDecl() const { return Decl; }<br>
@@ -5624,7 +5620,8 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {<br>
   PackExpansionType(QualType Pattern, QualType Canon,<br>
                     Optional<unsigned> NumExpansions)<br>
       : Type(PackExpansion, Canon,<br>
-             (Pattern->getDependence() | TypeDependence::Instantiation) &<br>
+             (Pattern->getDependence() | TypeDependence::Dependent |<br>
+              TypeDependence::Instantiation) &<br>
                  ~TypeDependence::UnexpandedPack),<br>
         Pattern(Pattern) {<br>
     PackExpansionTypeBits.NumExpansions =<br>
@@ -5645,8 +5642,8 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {<br>
     return None;<br>
   }<br>
<br>
-  bool isSugared() const { return !Pattern->isDependentType(); }<br>
-  QualType desugar() const { return isSugared() ? Pattern : QualType(this, 0); }<br>
+  bool isSugared() const { return false; }<br>
+  QualType desugar() const { return QualType(this, 0); }<br>
<br>
   void Profile(llvm::FoldingSetNodeID &ID) {<br>
     Profile(ID, getPattern(), getNumExpansions());<br>
<br>
diff  --git a/clang/include/clang/Basic/TypeNodes.td b/clang/include/clang/Basic/TypeNodes.td<br>
index a4e3002b9075..011394c3ef45 100644<br>
--- a/clang/include/clang/Basic/TypeNodes.td<br>
+++ b/clang/include/clang/Basic/TypeNodes.td<br>
@@ -100,7 +100,7 @@ def DeducedTemplateSpecializationType : TypeNode<DeducedType>;<br>
 def InjectedClassNameType : TypeNode<Type>, AlwaysDependent, LeafType;<br>
 def DependentNameType : TypeNode<Type>, AlwaysDependent;<br>
 def DependentTemplateSpecializationType : TypeNode<Type>, AlwaysDependent;<br>
-def PackExpansionType : TypeNode<Type>, NeverCanonicalUnlessDependent;<br>
+def PackExpansionType : TypeNode<Type>, AlwaysDependent;<br>
 def ObjCTypeParamType : TypeNode<Type>, NeverCanonical;<br>
 def ObjCObjectType : TypeNode<Type>;<br>
 def ObjCInterfaceType : TypeNode<ObjCObjectType>, LeafType;<br>
<br>
diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp<br>
index e7518a538fe6..25bf71519d1c 100644<br>
--- a/clang/lib/AST/ASTContext.cpp<br>
+++ b/clang/lib/AST/ASTContext.cpp<br>
@@ -4817,37 +4817,27 @@ ASTContext::getInjectedTemplateArgs(const TemplateParameterList *Params,<br>
 }<br>
<br>
 QualType ASTContext::getPackExpansionType(QualType Pattern,<br>
-                                          Optional<unsigned> NumExpansions) {<br>
+                                          Optional<unsigned> NumExpansions,<br>
+                                          bool ExpectPackInType) {<br>
+  assert((!ExpectPackInType || Pattern->containsUnexpandedParameterPack()) &&<br>
+         "Pack expansions must expand one or more parameter packs");<br>
+<br>
   llvm::FoldingSetNodeID ID;<br>
   PackExpansionType::Profile(ID, Pattern, NumExpansions);<br>
<br>
-  // A deduced type can deduce to a pack, eg<br>
-  //   auto ...x = some_pack;<br>
-  // That declaration isn't (yet) valid, but is created as part of building an<br>
-  // init-capture pack:<br>
-  //   [...x = some_pack] {}<br>
-  assert((Pattern->containsUnexpandedParameterPack() ||<br>
-          Pattern->getContainedDeducedType()) &&<br>
-         "Pack expansions must expand one or more parameter packs");<br>
   void *InsertPos = nullptr;<br>
-  PackExpansionType *T<br>
-    = PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos);<br>
+  PackExpansionType *T = PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos);<br>
   if (T)<br>
     return QualType(T, 0);<br>
<br>
   QualType Canon;<br>
   if (!Pattern.isCanonical()) {<br>
-    Canon = getCanonicalType(Pattern);<br>
-    // The canonical type might not contain an unexpanded parameter pack, if it<br>
-    // contains an alias template specialization which ignores one of its<br>
-    // parameters.<br>
-    if (Canon->containsUnexpandedParameterPack()) {<br>
-      Canon = getPackExpansionType(Canon, NumExpansions);<br>
-<br>
-      // Find the insert position again, in case we inserted an element into<br>
-      // PackExpansionTypes and invalidated our insert position.<br>
-      PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos);<br>
-    }<br>
+    Canon = getPackExpansionType(getCanonicalType(Pattern), NumExpansions,<br>
+                                 /*ExpectPackInType=*/false);<br>
+<br>
+    // Find the insert position again, in case we inserted an element into<br>
+    // PackExpansionTypes and invalidated our insert position.<br>
+    PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos);<br>
   }<br>
<br>
   T = new (*this, TypeAlignment)<br>
<br>
diff  --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp<br>
index 0122d2e7de52..d40ba4c648c4 100644<br>
--- a/clang/lib/AST/Type.cpp<br>
+++ b/clang/lib/AST/Type.cpp<br>
@@ -1187,9 +1187,6 @@ struct SimpleTransformVisitor : public TypeVisitor<Derived, QualType> {<br>
                            T->getTypeConstraintArguments());<br>
   }<br>
<br>
-  // FIXME: Non-trivial to implement, but important for C++<br>
-  SUGARED_TYPE_CLASS(PackExpansion)<br>
-<br>
   QualType VisitObjCObjectType(const ObjCObjectType *T) {<br>
     QualType baseType = recurse(T->getBaseType());<br>
     if (baseType.isNull())<br>
@@ -3348,6 +3345,12 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID,<br>
           getExtProtoInfo(), Ctx, isCanonicalUnqualified());<br>
 }<br>
<br>
+TypedefType::TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can)<br>
+    : Type(tc, can, D->getUnderlyingType()->getDependence()),<br>
+      Decl(const_cast<TypedefNameDecl *>(D)) {<br>
+  assert(!isa<TypedefType>(can) && "Invalid canonical type");<br>
+}<br>
+<br>
 QualType TypedefType::desugar() const {<br>
   return getDecl()->getUnderlyingType();<br>
 }<br>
<br>
diff  --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp<br>
index 6965c4a1209c..780e0c692c05 100644<br>
--- a/clang/lib/CodeGen/CGDebugInfo.cpp<br>
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp<br>
@@ -3252,7 +3252,6 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {<br>
   case Type::TypeOf:<br>
   case Type::Decltype:<br>
   case Type::UnaryTransform:<br>
-  case Type::PackExpansion:<br>
     break;<br>
   }<br>
<br>
<br>
diff  --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp<br>
index 8ce488f35dd3..8f79cc77f0e6 100644<br>
--- a/clang/lib/CodeGen/CodeGenFunction.cpp<br>
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp<br>
@@ -2075,7 +2075,6 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {<br>
     case Type::UnaryTransform:<br>
     case Type::Attributed:<br>
     case Type::SubstTemplateTypeParm:<br>
-    case Type::PackExpansion:<br>
     case Type::MacroQualified:<br>
       // Keep walking after single level desugaring.<br>
       type = type.getSingleStepDesugaredType(getContext());<br>
<br>
diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp<br>
index 21d3bbf419a9..bb0b1fa49851 100644<br>
--- a/clang/lib/Sema/SemaExpr.cpp<br>
+++ b/clang/lib/Sema/SemaExpr.cpp<br>
@@ -4345,7 +4345,6 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T,<br>
     case Type::UnaryTransform:<br>
     case Type::Attributed:<br>
     case Type::SubstTemplateTypeParm:<br>
-    case Type::PackExpansion:<br>
     case Type::MacroQualified:<br>
       // Keep walking after single level desugaring.<br>
       T = T.getSingleStepDesugaredType(Context);<br>
<br>
diff  --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp<br>
index 657ed13f207a..dc74f6e2f7dc 100644<br>
--- a/clang/lib/Sema/SemaLambda.cpp<br>
+++ b/clang/lib/Sema/SemaLambda.cpp<br>
@@ -803,7 +803,8 @@ QualType Sema::buildLambdaInitCaptureInitialization(<br>
       Diag(EllipsisLoc, getLangOpts().CPlusPlus20<br>
                             ? diag::warn_cxx17_compat_init_capture_pack<br>
                             : diag::ext_init_capture_pack);<br>
-      DeductType = Context.getPackExpansionType(DeductType, NumExpansions);<br>
+      DeductType = Context.getPackExpansionType(DeductType, NumExpansions,<br>
+                                                /*ExpectPackInType=*/false);<br>
       TLB.push<PackExpansionTypeLoc>(DeductType).setEllipsisLoc(EllipsisLoc);<br>
     } else {<br>
       // Just ignore the ellipsis for now and form a non-pack variable. We'll<br>
<br>
diff  --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp<br>
index 7b77d1cb482a..259cc5165776 100644<br>
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp<br>
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp<br>
@@ -614,7 +614,8 @@ QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange PatternRange,<br>
     return QualType();<br>
   }<br>
<br>
-  return Context.getPackExpansionType(Pattern, NumExpansions);<br>
+  return Context.getPackExpansionType(Pattern, NumExpansions,<br>
+                                      /*ExpectPackInType=*/false);<br>
 }<br>
<br>
 ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) {<br>
<br>
diff  --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp<br>
index 3eabe7ca6ffe..4c7eece68bca 100644<br>
--- a/clang/lib/Sema/SemaType.cpp<br>
+++ b/clang/lib/Sema/SemaType.cpp<br>
@@ -5516,7 +5516,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,<br>
           << T <<  D.getSourceRange();<br>
         D.setEllipsisLoc(SourceLocation());<br>
       } else {<br>
-        T = Context.getPackExpansionType(T, None);<br>
+        T = Context.getPackExpansionType(T, None, /*ExpectPackInType=*/false);<br>
       }<br>
       break;<br>
     case DeclaratorContext::TemplateParamContext:<br>
<br>
diff  --git a/clang/test/SemaTemplate/alias-template-nondependent.cpp b/clang/test/SemaTemplate/alias-template-nondependent.cpp<br>
new file mode 100644<br>
index 000000000000..e8ea16483a09<br>
--- /dev/null<br>
+++ b/clang/test/SemaTemplate/alias-template-nondependent.cpp<br>
@@ -0,0 +1,24 @@<br>
+// RUN: %clang_cc1 -std=c++20 -verify %s<br>
+<br>
+namespace PR46377 {<br>
+  template<typename> using IntPtr = int*;<br>
+  template<typename ...T> auto non_dependent_typedef() {<br>
+    typedef int(*P)(IntPtr<T>...);<br>
+    return P();<br>
+  }<br>
+  template<typename ...T> auto non_dependent_alias() {<br>
+    using P = int(*)(IntPtr<T>...);<br>
+    return P();<br>
+  }<br>
+  template<typename ...T> auto non_dependent_via_sizeof() {<br>
+    using P = int(*)(int(...pack)[sizeof(sizeof(T))]); // expected-error {{invalid application of 'sizeof'}}<br>
+    return P();<br>
+  }<br>
+<br>
+  using a = int (*)(int*, int*);<br>
+  using a = decltype(non_dependent_typedef<void, void>());<br>
+  using a = decltype(non_dependent_alias<void, void>());<br>
+  using a = decltype(non_dependent_via_sizeof<float, float>());<br>
+<br>
+  using b = decltype(non_dependent_via_sizeof<float, void>()); // expected-note {{instantiation of}}<br>
+}<br>
<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div>