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.vassi...@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@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
From 5ccd8851142e6a40b47d892cced9ec53b294ce3d Mon Sep 17 00:00:00 2001
From: Vassil Vassilev <v.g.vassi...@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@-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)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits