hokein updated this revision to Diff 292784.
hokein marked 2 inline comments as done.
hokein added a comment.

address comments:

- don't break existing mangling tests
- deduplicate instantiation-dependent-but-not-type-dependent DecltypeType node 
(for name mangling substitution)
- fix the dependence bit of DecltypeType


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D87349/new/

https://reviews.llvm.org/D87349

Files:
  clang/include/clang/AST/ASTContext.h
  clang/include/clang/AST/Type.h
  clang/lib/AST/ASTContext.cpp
  clang/lib/AST/ItaniumMangle.cpp
  clang/lib/AST/Type.cpp
  clang/test/CodeGenCXX/mangle.cpp
  clang/test/Sema/invalid-bitwidth-expr.mm
  clang/test/SemaCXX/invalid-template-base-specifier.cpp
  clang/test/SemaTemplate/dependent-expr.cpp
  clang/test/SemaTemplate/temp_arg_template_cxx1z.cpp

Index: clang/test/SemaTemplate/temp_arg_template_cxx1z.cpp
===================================================================
--- clang/test/SemaTemplate/temp_arg_template_cxx1z.cpp
+++ clang/test/SemaTemplate/temp_arg_template_cxx1z.cpp
@@ -115,6 +115,6 @@
 
   int n;
   template<auto A, decltype(A) B = &n> struct SubstFailure;
-  TInt<SubstFailure> isf; // FIXME: this should be ill-formed
+  TInt<SubstFailure> isf; // expected-error {{template template argument has different template parameters than its corresponding template template parameter}}
   TIntPtr<SubstFailure> ipsf;
 }
Index: clang/test/SemaTemplate/dependent-expr.cpp
===================================================================
--- clang/test/SemaTemplate/dependent-expr.cpp
+++ clang/test/SemaTemplate/dependent-expr.cpp
@@ -129,7 +129,7 @@
   template<typename> void f() {
     decltype(({})) x; // expected-error {{incomplete type}}
   }
-  template void f<int>(); // expected-note {{instantiation of}}
+  template void f<int>();
 
   template<typename> auto g() {
     auto c = [](auto, int) -> decltype(({})) {};
Index: clang/test/SemaCXX/invalid-template-base-specifier.cpp
===================================================================
--- clang/test/SemaCXX/invalid-template-base-specifier.cpp
+++ clang/test/SemaCXX/invalid-template-base-specifier.cpp
@@ -12,11 +12,12 @@
 template <typename T>
 using Alias = decltype(Foo(T())); // expected-error {{no matching function for call to 'Foo'}}
 template <typename T>
-struct Crash2 : decltype(Alias<T>()) { // expected-note {{in instantiation of template type alias 'Alias' requested here}}
+struct Crash2 : decltype(Alias<T>()) { // expected-note {{in instantiation of template type alias 'Alias' requested here}} \
+                                          expected-error {{base specifier must name a class}}
   Crash2(){};
 };
 
-void test2() { Crash2<int>(); } // expected-note {{in instantiation of template class 'Crash2<int>' requested here}}
+void test2() { Crash2<int>(); } // expected-note2 {{in instantiation of template class 'Crash2<int>' requested here}}
 
 template <typename T>
 class Base {};
Index: clang/test/Sema/invalid-bitwidth-expr.mm
===================================================================
--- clang/test/Sema/invalid-bitwidth-expr.mm
+++ clang/test/Sema/invalid-bitwidth-expr.mm
@@ -25,7 +25,8 @@
 template <typename T>
 auto func() {
   // error-bit should be propagated from TemplateArgument to NestNameSpecifier.
-  class Base<decltype(Foo(T()))>::type C; // expected-error {{no matching function for call to 'Foo'}}
+  class Base<decltype(Foo(T()))>::type C; // expected-error {{no matching function for call to 'Foo'}} \
+                                             expected-error {{no class named 'type' in}}
   return C;
 }
 struct Z {
Index: clang/test/CodeGenCXX/mangle.cpp
===================================================================
--- clang/test/CodeGenCXX/mangle.cpp
+++ clang/test/CodeGenCXX/mangle.cpp
@@ -805,6 +805,10 @@
   // CHECK-LABEL: define weak_odr void @_ZN6test341fIiEEvDTstDTplcvT__EcvS1__EEE
   template void f<int>(decltype(sizeof(1)));
 
+  template <typename T> void f(decltype(sizeof(T)), decltype(sizeof(T))) {}
+  // CHECK-LABEL: define weak_odr void @_ZN6test341fIiEEvDTstT_ES2_
+  template void f<int>(unsigned long, unsigned long);
+
   // Mangling for non-instantiation-dependent sizeof expressions.
   template<unsigned N>
   void f2(int (&)[N + sizeof(int*)]) {}
Index: clang/lib/AST/Type.cpp
===================================================================
--- clang/lib/AST/Type.cpp
+++ clang/lib/AST/Type.cpp
@@ -3396,19 +3396,21 @@
   E->Profile(ID, Context, true);
 }
 
-DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can)
-    // C++11 [temp.type]p2: "If an expression e involves a template parameter,
-    // decltype(e) denotes a unique dependent type." Hence a decltype type is
-    // type-dependent even if its expression is only instantiation-dependent.
+DecltypeType::DecltypeType(Expr *E, QualType underlyingType,
+                           const ASTContext &Context, QualType can)
+    // C++17 [temp.type]p2: "If an expression e is type-dependent, decltype(e)
+    // denotes a unique dependent type."
     : Type(Decltype, can,
-           toTypeDependence(E->getDependence()) |
-               (E->isInstantiationDependent() ? TypeDependence::Dependent
-                                              : TypeDependence::None) |
+           // C++17 [temp.dep.type]p9: "denoted by decltype(expression), where
+           // expression is type-dependent"
+           (toTypeDependence(E->getDependence()) & ~TypeDependence::Dependent) |
+               (E->isTypeDependent() ? TypeDependence::Dependent
+                                     : TypeDependence::None) |
                (E->getType()->getDependence() &
                 TypeDependence::VariablyModified)),
-      E(E), UnderlyingType(underlyingType) {}
+      E(E), UnderlyingType(underlyingType), Context(Context) {}
 
-bool DecltypeType::isSugared() const { return !E->isInstantiationDependent(); }
+bool DecltypeType::isSugared() const { return !E->isTypeDependent(); }
 
 QualType DecltypeType::desugar() const {
   if (isSugared())
@@ -3417,14 +3419,14 @@
   return QualType(this, 0);
 }
 
-DependentDecltypeType::DependentDecltypeType(const ASTContext &Context, Expr *E)
-    : DecltypeType(E, Context.DependentTy), Context(Context) {}
-
-void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID,
-                                    const ASTContext &Context, Expr *E) {
+void DecltypeType::Profile(llvm::FoldingSetNodeID &ID,
+                           const ASTContext &Context, Expr *E) {
   E->Profile(ID, Context, true);
 }
 
+DependentDecltypeType::DependentDecltypeType(const ASTContext &Context, Expr *E)
+    : DecltypeType(E, Context.DependentTy, Context) {}
+
 UnaryTransformType::UnaryTransformType(QualType BaseType,
                                        QualType UnderlyingType, UTTKind UKind,
                                        QualType CanonicalType)
Index: clang/lib/AST/ItaniumMangle.cpp
===================================================================
--- clang/lib/AST/ItaniumMangle.cpp
+++ clang/lib/AST/ItaniumMangle.cpp
@@ -2527,6 +2527,8 @@
     return true;
   if (Ty->isOpenCLSpecificType())
     return true;
+  if (Ty->isDecltypeType() && Ty->isInstantiationDependentType())
+    return true;
   if (Ty->isBuiltinType())
     return false;
   // Through to Clang 6.0, we accidentally treated undeduced auto types as
@@ -2582,6 +2584,12 @@
         if (!TST->isTypeAlias())
           break;
 
+      // Don't desugar through instantiation-dependent-but-not-type-dependent
+      // DecltypeType, as we want to mangle it as written.
+      if (const auto *DT = dyn_cast<DecltypeType>(T))
+        if (!DT->isDependentType() && DT->isInstantiationDependentType())
+          break;
+
       QualType Desugared
         = T.getSingleStepDesugaredType(Context.getASTContext());
       if (Desugared == T)
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -5343,14 +5343,16 @@
 /// nodes. This would never be helpful, since each such type has its own
 /// expression, and would not give a significant memory saving, since there
 /// is an Expr tree under each such type.
+/// The instantiation-dependent-but-not-type-dependent DecltypeType node is an
+/// exception, we unique it for forming correct substitutions in name mangling.
 QualType ASTContext::getDecltypeType(Expr *e, QualType UnderlyingType) const {
   DecltypeType *dt;
 
-  // C++11 [temp.type]p2:
-  //   If an expression e involves a template parameter, decltype(e) denotes a
+  // C++17 [temp.type]p2:
+  //   If an expression e is type-dependent (17.6.2.2), decltype(e) denotes a
   //   unique dependent type. Two such decltype-specifiers refer to the same
-  //   type only if their expressions are equivalent (14.5.6.1).
-  if (e->isInstantiationDependent()) {
+  //   type only if their expressions are equivalent (17.5.6.1).
+  if (e->isTypeDependent()) {
     llvm::FoldingSetNodeID ID;
     DependentDecltypeType::Profile(ID, *this, e);
 
@@ -5362,11 +5364,20 @@
       Canon = new (*this, TypeAlignment) DependentDecltypeType(*this, e);
       DependentDecltypeTypes.InsertNode(Canon, InsertPos);
     }
-    dt = new (*this, TypeAlignment)
-        DecltypeType(e, UnderlyingType, QualType((DecltypeType *)Canon, 0));
+    dt = new (*this, TypeAlignment) DecltypeType(
+        e, UnderlyingType, *this, QualType((DecltypeType *)Canon, 0));
+  } else if (e->isInstantiationDependent()) {
+    llvm::FoldingSetNodeID ID;
+    DecltypeType::Profile(ID, *this, e);
+    void *InsertPos = nullptr;
+    if (DecltypeType *DT = DecltypeTypes.FindNodeOrInsertPos(ID, InsertPos))
+      return QualType(DT, 0);
+    dt = new (*this, TypeAlignment) DecltypeType(
+        e, UnderlyingType, *this, getCanonicalType(UnderlyingType));
+    DecltypeTypes.InsertNode(dt, InsertPos);
   } else {
-    dt = new (*this, TypeAlignment)
-        DecltypeType(e, UnderlyingType, getCanonicalType(UnderlyingType));
+    dt = new (*this, TypeAlignment) DecltypeType(
+        e, UnderlyingType, *this, getCanonicalType(UnderlyingType));
   }
   Types.push_back(dt);
   return QualType(dt, 0);
Index: clang/include/clang/AST/Type.h
===================================================================
--- clang/include/clang/AST/Type.h
+++ clang/include/clang/AST/Type.h
@@ -4468,14 +4468,16 @@
 };
 
 /// Represents the type `decltype(expr)` (C++11).
-class DecltypeType : public Type {
+class DecltypeType : public Type, public llvm::FoldingSetNode {
   Expr *E;
   QualType UnderlyingType;
 
 protected:
   friend class ASTContext; // ASTContext creates these.
 
-  DecltypeType(Expr *E, QualType underlyingType, QualType can = QualType());
+  const ASTContext &Context;
+  DecltypeType(Expr *E, QualType underlyingType, const ASTContext &Context,
+               QualType can = QualType());
 
 public:
   Expr *getUnderlyingExpr() const { return E; }
@@ -4488,6 +4490,10 @@
   bool isSugared() const;
 
   static bool classof(const Type *T) { return T->getTypeClass() == Decltype; }
+
+  void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Context, E); }
+  static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
+                      Expr *E);
 };
 
 /// Internal representation of canonical, dependent
@@ -4496,18 +4502,9 @@
 /// This class is used internally by the ASTContext to manage
 /// canonical, dependent types, only. Clients will only see instances
 /// of this class via DecltypeType nodes.
-class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode {
-  const ASTContext &Context;
-
+class DependentDecltypeType : public DecltypeType {
 public:
   DependentDecltypeType(const ASTContext &Context, Expr *E);
-
-  void Profile(llvm::FoldingSetNodeID &ID) {
-    Profile(ID, Context, getUnderlyingExpr());
-  }
-
-  static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
-                      Expr *E);
 };
 
 /// A unary type transform, which is a type constructed from another.
Index: clang/include/clang/AST/ASTContext.h
===================================================================
--- clang/include/clang/AST/ASTContext.h
+++ clang/include/clang/AST/ASTContext.h
@@ -203,6 +203,7 @@
     FunctionProtoTypes;
   mutable llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes;
   mutable llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes;
+  mutable llvm::FoldingSet<DecltypeType> DecltypeTypes;
   mutable llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;
   mutable llvm::FoldingSet<ObjCTypeParamType> ObjCTypeParamTypes;
   mutable llvm::FoldingSet<SubstTemplateTypeParmType>
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to