[PATCH] Canonicalize UnaryTransformType types when they don't have a known underlying type

Vassil Vassilev via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 10 06:33:47 PST 2016


Would this one more reasonable to commit. As you suggested if the base 
type is dependent, create a unique canonical UnaryTransformType with the 
canonical form of the base type as its base type and with DependentTy as 
its underlying type, then use that canonical dependent type as the 
underlying type for your sugared UnaryTransformType.
The attached patch follows the getDecltypeType approach.
--Vassil
On 24/02/16 23:09, Richard Smith wrote:
> A UnaryTransformType should itself be a canonical type if its BaseType
> is dependent -- that is, its CanonicalType should be QualType(this,
> 0). It should definitely not be treated as being canonically
> equivalent to its BaseType.
>
> On Wed, Feb 24, 2016 at 2:03 PM, Vassil Vassilev <v.g.vassilev at gmail.com> wrote:
>> ping...
>>
>> On 07/01/16 08:09, Vassil Vassilev via cfe-commits wrote:
>>
>> Hi all,
>>    I am attaching a fix for https://llvm.org/bugs/show_bug.cgi?id=26014
>>    To which type should I tie the canonical type of the unknown underlying
>> type? Currently it is tied to its BaseType.
>>
>>    Please review.
>> --Vassil
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>
>>

-------------- next part --------------
From 5ccd8851142e6a40b47d892cced9ec53b294ce3d Mon Sep 17 00:00:00 2001
From: Vassil Vassilev <v.g.vassilev at gmail.com>
Date: Mon, 4 Jan 2016 20:48:36 +0200
Subject: [PATCH] Canonicalize UnaryTransformType types when they don't have a
 known underlying type.

Fixes https://llvm.org/bugs/show_bug.cgi?id=26014
---
 include/clang/AST/ASTContext.h               |  4 ++-
 include/clang/AST/Type.h                     | 22 ++++++++++++++++
 lib/AST/ASTContext.cpp                       | 38 +++++++++++++++++++++-------
 lib/AST/Type.cpp                             | 29 +++++++++++++--------
 test/Modules/Inputs/PR26014/A.h              | 13 ++++++++++
 test/Modules/Inputs/PR26014/B.h              | 10 ++++++++
 test/Modules/Inputs/PR26014/module.modulemap |  9 +++++++
 test/Modules/pr26014.cpp                     |  7 +++++
 test/SemaCXX/underlying_type.cpp             |  5 ++++
 9 files changed, 116 insertions(+), 21 deletions(-)
 create mode 100644 test/Modules/Inputs/PR26014/A.h
 create mode 100644 test/Modules/Inputs/PR26014/B.h
 create mode 100644 test/Modules/Inputs/PR26014/module.modulemap
 create mode 100644 test/Modules/pr26014.cpp

diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 438e676..f455bb9 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -128,6 +128,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
   llvm::FoldingSet<PackExpansionType> PackExpansionTypes;
   mutable llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes;
   mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
+  mutable llvm::FoldingSet<DependentUnaryTransformType>
+    DependentUnaryTransformTypes;
   mutable llvm::FoldingSet<AutoType> AutoTypes;
   mutable llvm::FoldingSet<AtomicType> AtomicTypes;
   llvm::FoldingSet<AttributedType> AttributedTypes;
@@ -1301,7 +1303,7 @@ public:
   QualType getDecltypeType(Expr *e, QualType UnderlyingType) const;
 
   /// \brief Unary type transforms
-  QualType getUnaryTransformType(QualType BaseType, QualType UnderlyingType,
+  QualType getUnaryTransformType(QualType BaseTy, QualType UnderlyingTy,
                                  UnaryTransformType::UTTKind UKind) const;
 
   /// \brief C++11 deduced auto type.
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index d63b2c4..328ef05 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -3518,6 +3518,28 @@ public:
   }
 };
 
+/// \brief Internal representation of canonical, dependent
+/// __underlying_type(type) types.
+///
+/// This class is used internally by the ASTContext to manage
+/// canonical, dependent types, only. Clients will only see instances
+/// of this class via UnaryTransformType nodes.
+class DependentUnaryTransformType : public UnaryTransformType,
+                                    public llvm::FoldingSetNode {
+public:
+  DependentUnaryTransformType(const ASTContext &C, QualType BaseTy,
+                              UTTKind UKind);
+  void Profile(llvm::FoldingSetNodeID &ID) {
+    Profile(ID, getBaseType(), getUTTKind());
+  }
+
+  static void Profile(llvm::FoldingSetNodeID &ID, QualType BaseTy,
+                      UTTKind UKind) {
+    ID.AddPointer(BaseTy.getAsOpaquePtr());
+    ID.AddInteger((unsigned)UKind);
+  }
+};
+
 class TagType : public Type {
   /// Stores the TagDecl associated with this type. The decl may point to any
   /// TagDecl that declares the entity.
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index eba3578..9e01976 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -4009,17 +4009,37 @@ QualType ASTContext::getDecltypeType(Expr *e, QualType UnderlyingType) const {
 
 /// getUnaryTransformationType - We don't unique these, since the memory
 /// savings are minimal and these are rare.
-QualType ASTContext::getUnaryTransformType(QualType BaseType,
-                                           QualType UnderlyingType,
+QualType ASTContext::getUnaryTransformType(QualType BaseTy,
+                                           QualType UnderlyingTy,
                                            UnaryTransformType::UTTKind Kind)
     const {
-  UnaryTransformType *Ty =
-    new (*this, TypeAlignment) UnaryTransformType (BaseType, UnderlyingType, 
-                                                   Kind,
-                                 UnderlyingType->isDependentType() ?
-                                 QualType() : getCanonicalType(UnderlyingType));
-  Types.push_back(Ty);
-  return QualType(Ty, 0);
+  UnaryTransformType *ut = nullptr;
+
+  if (BaseTy->isDependentType()) {
+    // Look in the folding set for an existing type.
+    llvm::FoldingSetNodeID ID;
+    DependentUnaryTransformType::Profile(ID, getCanonicalType(BaseTy), Kind);
+
+    void *InsertPos = nullptr;
+    DependentUnaryTransformType *Canon
+      = DependentUnaryTransformTypes.FindNodeOrInsertPos(ID, InsertPos);
+
+    if (!Canon) {
+      // Build a new, canonical __underlying_type(type) type.
+      Canon = new (*this, TypeAlignment)
+             DependentUnaryTransformType(*this, getCanonicalType(BaseTy), Kind);
+      DependentDecltypeTypes.InsertNode(Canon, InsertPos);
+    }
+    ut = new (*this, TypeAlignment) UnaryTransformType (BaseTy, UnderlyingTy,
+                                                        Kind,
+                                                        QualType(Canon, 0));
+  } else {
+    QualType CanonTy = getCanonicalType(UnderlyingTy);
+    ut = new (*this, TypeAlignment) UnaryTransformType (BaseTy, UnderlyingTy,
+                                                        Kind, CanonTy);
+  }
+  Types.push_back(ut);
+  return QualType(ut, 0);
 }
 
 /// getAutoType - Return the uniqued reference to the 'auto' type which has been
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index b467dac..989dbd4 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -2931,6 +2931,24 @@ void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID,
   E->Profile(ID, Context, true);
 }
 
+UnaryTransformType::UnaryTransformType(QualType BaseType,
+                                       QualType UnderlyingType,
+                                       UTTKind UKind,
+                                       QualType CanonicalType)
+  : Type(UnaryTransform, CanonicalType, UnderlyingType->isDependentType(),
+         UnderlyingType->isInstantiationDependentType(),
+         UnderlyingType->isVariablyModifiedType(),
+         BaseType->containsUnexpandedParameterPack())
+  , BaseType(BaseType), UnderlyingType(UnderlyingType), UKind(UKind)
+{}
+
+DependentUnaryTransformType::DependentUnaryTransformType(const ASTContext &C,
+                                                         QualType BaseTy,
+                                                         UTTKind UKind)
+   : UnaryTransformType(BaseTy, C.DependentTy, UKind, QualType())
+{}
+
+
 TagType::TagType(TypeClass TC, const TagDecl *D, QualType can)
   : Type(TC, can, D->isDependentType(), 
          /*InstantiationDependent=*/D->isDependentType(),
@@ -2947,17 +2965,6 @@ static TagDecl *getInterestingTagDecl(TagDecl *decl) {
   return decl;
 }
 
-UnaryTransformType::UnaryTransformType(QualType BaseType,
-                                       QualType UnderlyingType,
-                                       UTTKind UKind,
-                                       QualType CanonicalType)
-  : Type(UnaryTransform, CanonicalType, UnderlyingType->isDependentType(),
-         UnderlyingType->isInstantiationDependentType(),
-         UnderlyingType->isVariablyModifiedType(),
-         BaseType->containsUnexpandedParameterPack())
-  , BaseType(BaseType), UnderlyingType(UnderlyingType), UKind(UKind)
-{}
-
 TagDecl *TagType::getDecl() const {
   return getInterestingTagDecl(decl);
 }
diff --git a/test/Modules/Inputs/PR26014/A.h b/test/Modules/Inputs/PR26014/A.h
new file mode 100644
index 0000000..49de5ba
--- /dev/null
+++ b/test/Modules/Inputs/PR26014/A.h
@@ -0,0 +1,13 @@
+#ifndef _LIBCPP_TYPE_TRAITS
+#define _LIBCPP_TYPE_TRAITS
+
+
+template <class _Tp>
+struct underlying_type
+{
+    typedef __underlying_type(_Tp) type;
+};
+
+#endif  // _LIBCPP_TYPE_TRAITS
+
+#include "B.h"
diff --git a/test/Modules/Inputs/PR26014/B.h b/test/Modules/Inputs/PR26014/B.h
new file mode 100644
index 0000000..58d1f8f
--- /dev/null
+++ b/test/Modules/Inputs/PR26014/B.h
@@ -0,0 +1,10 @@
+#ifndef _LIBCPP_TYPE_TRAITS
+#define _LIBCPP_TYPE_TRAITS
+
+template <class _Tp>
+struct underlying_type
+{
+    typedef __underlying_type(_Tp) type;
+};
+
+#endif  // _LIBCPP_TYPE_TRAITS
diff --git a/test/Modules/Inputs/PR26014/module.modulemap b/test/Modules/Inputs/PR26014/module.modulemap
new file mode 100644
index 0000000..4937418
--- /dev/null
+++ b/test/Modules/Inputs/PR26014/module.modulemap
@@ -0,0 +1,9 @@
+module A {
+  header "A.h"
+  export *
+}
+
+module B {
+  header "B.h"
+  export *
+}
diff --git a/test/Modules/pr26014.cpp b/test/Modules/pr26014.cpp
new file mode 100644
index 0000000..f9ebd4e
--- /dev/null
+++ b/test/Modules/pr26014.cpp
@@ -0,0 +1,7 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -I%S/Inputs/PR26014 -verify %s
+// RUN: %clang_cc1 -fmodules -fmodule-map-file=%S/Inputs/PR26014/module.modulemap -fmodules-cache-path=%t -I%S/Inputs/PR26014 -verify %s
+
+#include "A.h"
+
+// expected-no-diagnostics
diff --git a/test/SemaCXX/underlying_type.cpp b/test/SemaCXX/underlying_type.cpp
index 61208c7..2d0695c 100644
--- a/test/SemaCXX/underlying_type.cpp
+++ b/test/SemaCXX/underlying_type.cpp
@@ -55,3 +55,8 @@ namespace PR19966 {
     // expected-error at -2 {{constant expression}}
   };
 }
+
+template<typename T> void f(__underlying_type(T));
+template<typename T> void f(__underlying_type(T));
+enum E {};
+void PR26014() { f<E>(0); } // should not yield an ambiguity error.
-- 
2.3.8 (Apple Git-58)



More information about the cfe-commits mailing list