mirror of
https://github.com/intel/llvm.git
synced 2026-01-25 01:07:04 +08:00
Canonicalize UnaryTransformType types when they don't have a known underlying type.
Fixes https://llvm.org/bugs/show_bug.cgi?id=26014 Reviewed by Richard Smith. llvm-svn: 264937
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
13
clang/test/Modules/Inputs/PR26014/A.h
Normal file
13
clang/test/Modules/Inputs/PR26014/A.h
Normal file
@@ -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"
|
||||
10
clang/test/Modules/Inputs/PR26014/B.h
Normal file
10
clang/test/Modules/Inputs/PR26014/B.h
Normal file
@@ -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
|
||||
9
clang/test/Modules/Inputs/PR26014/module.modulemap
Normal file
9
clang/test/Modules/Inputs/PR26014/module.modulemap
Normal file
@@ -0,0 +1,9 @@
|
||||
module A {
|
||||
header "A.h"
|
||||
export *
|
||||
}
|
||||
|
||||
module B {
|
||||
header "B.h"
|
||||
export *
|
||||
}
|
||||
7
clang/test/Modules/pr26014.cpp
Normal file
7
clang/test/Modules/pr26014.cpp
Normal file
@@ -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
|
||||
@@ -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'}}
|
||||
|
||||
Reference in New Issue
Block a user