summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/ASTContext.h2
-rw-r--r--clang/include/clang/AST/Type.h22
-rw-r--r--clang/lib/AST/ASTContext.cpp36
-rw-r--r--clang/lib/AST/Type.cpp29
-rw-r--r--clang/test/Modules/Inputs/PR26014/A.h13
-rw-r--r--clang/test/Modules/Inputs/PR26014/B.h10
-rw-r--r--clang/test/Modules/Inputs/PR26014/module.modulemap9
-rw-r--r--clang/test/Modules/pr26014.cpp7
-rw-r--r--clang/test/SemaCXX/underlying_type.cpp7
9 files changed, 117 insertions, 18 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 2851c4d9fe0..55511e03a3a 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -129,6 +129,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;
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index aef891c8984..e8f54fd4bd2 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -3633,6 +3633,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 BaseType,
+ UTTKind UKind);
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getBaseType(), getUTTKind());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType BaseType,
+ UTTKind UKind) {
+ ID.AddPointer(BaseType.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/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 77e5087b8c7..aa9277cdc1a 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -4020,13 +4020,35 @@ QualType ASTContext::getUnaryTransformType(QualType BaseType,
QualType UnderlyingType,
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 (BaseType->isDependentType()) {
+ // Look in the folding set for an existing type.
+ llvm::FoldingSetNodeID ID;
+ DependentUnaryTransformType::Profile(ID, getCanonicalType(BaseType), 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(BaseType),
+ Kind);
+ DependentUnaryTransformTypes.InsertNode(Canon, InsertPos);
+ }
+ ut = new (*this, TypeAlignment) UnaryTransformType (BaseType,
+ QualType(), Kind,
+ QualType(Canon, 0));
+ } else {
+ QualType CanonType = getCanonicalType(UnderlyingType);
+ ut = new (*this, TypeAlignment) UnaryTransformType (BaseType,
+ UnderlyingType, Kind,
+ CanonType);
+ }
+ Types.push_back(ut);
+ return QualType(ut, 0);
}
/// getAutoType - Return the uniqued reference to the 'auto' type which has been
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 74aa323dbc8..d3c7259c38d 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2935,6 +2935,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, BaseType->isDependentType(),
+ BaseType->isInstantiationDependentType(),
+ BaseType->isVariablyModifiedType(),
+ BaseType->containsUnexpandedParameterPack())
+ , BaseType(BaseType), UnderlyingType(UnderlyingType), UKind(UKind)
+{}
+
+DependentUnaryTransformType::DependentUnaryTransformType(const ASTContext &C,
+ QualType BaseType,
+ UTTKind UKind)
+ : UnaryTransformType(BaseType, C.DependentTy, UKind, QualType())
+{}
+
+
TagType::TagType(TypeClass TC, const TagDecl *D, QualType can)
: Type(TC, can, D->isDependentType(),
/*InstantiationDependent=*/D->isDependentType(),
@@ -2951,17 +2969,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/clang/test/Modules/Inputs/PR26014/A.h b/clang/test/Modules/Inputs/PR26014/A.h
new file mode 100644
index 00000000000..49de5ba479a
--- /dev/null
+++ b/clang/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/clang/test/Modules/Inputs/PR26014/B.h b/clang/test/Modules/Inputs/PR26014/B.h
new file mode 100644
index 00000000000..58d1f8ff2a3
--- /dev/null
+++ b/clang/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/clang/test/Modules/Inputs/PR26014/module.modulemap b/clang/test/Modules/Inputs/PR26014/module.modulemap
new file mode 100644
index 00000000000..49374181d75
--- /dev/null
+++ b/clang/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/clang/test/Modules/pr26014.cpp b/clang/test/Modules/pr26014.cpp
new file mode 100644
index 00000000000..f9ebd4e1dd7
--- /dev/null
+++ b/clang/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/clang/test/SemaCXX/underlying_type.cpp b/clang/test/SemaCXX/underlying_type.cpp
index 61208c72af0..dd019ae6e27 100644
--- a/clang/test/SemaCXX/underlying_type.cpp
+++ b/clang/test/SemaCXX/underlying_type.cpp
@@ -55,3 +55,10 @@ 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.
+
+template<typename ...T> void f(__underlying_type(T) v); // expected-error {{declaration type contains unexpanded parameter pack 'T'}}
OpenPOWER on IntegriCloud