forked from OSchip/llvm-project
Canonicalization for dependent typeof(expr) types.
llvm-svn: 77639
This commit is contained in:
parent
7ec07a573c
commit
a5dd9f858f
|
@ -75,13 +75,13 @@ class ASTContext {
|
|||
llvm::FoldingSet<VectorType> VectorTypes;
|
||||
llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes;
|
||||
llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes;
|
||||
llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes;
|
||||
llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;
|
||||
llvm::FoldingSet<TemplateSpecializationType> TemplateSpecializationTypes;
|
||||
llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes;
|
||||
llvm::FoldingSet<TypenameType> TypenameTypes;
|
||||
llvm::FoldingSet<ObjCInterfaceType> ObjCInterfaceTypes;
|
||||
llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
|
||||
|
||||
llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
|
||||
llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
|
||||
|
||||
|
|
|
@ -1577,6 +1577,8 @@ public:
|
|||
/// TypeOfExprType (GCC extension).
|
||||
class TypeOfExprType : public Type {
|
||||
Expr *TOExpr;
|
||||
|
||||
protected:
|
||||
TypeOfExprType(Expr *E, QualType can = QualType());
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
|
@ -1589,6 +1591,24 @@ public:
|
|||
static bool classof(const TypeOfExprType *) { return true; }
|
||||
};
|
||||
|
||||
/// Subclass of TypeOfExprType that is used for canonical, dependent
|
||||
/// typeof(expr) types.
|
||||
class DependentTypeOfExprType
|
||||
: public TypeOfExprType, public llvm::FoldingSetNode {
|
||||
ASTContext &Context;
|
||||
|
||||
public:
|
||||
DependentTypeOfExprType(ASTContext &Context, Expr *E)
|
||||
: TypeOfExprType(E), Context(Context) { }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, Context, getUnderlyingExpr());
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
|
||||
Expr *E);
|
||||
};
|
||||
|
||||
/// TypeOfType (GCC extension).
|
||||
class TypeOfType : public Type {
|
||||
QualType TOType;
|
||||
|
|
|
@ -1876,9 +1876,26 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
|
|||
/// on canonical type's (which are always unique).
|
||||
QualType ASTContext::getTypeOfExprType(Expr *tofExpr) {
|
||||
TypeOfExprType *toe;
|
||||
if (tofExpr->isTypeDependent())
|
||||
toe = new (*this, 8) TypeOfExprType(tofExpr);
|
||||
else {
|
||||
if (tofExpr->isTypeDependent()) {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
DependentTypeOfExprType::Profile(ID, *this, tofExpr);
|
||||
|
||||
void *InsertPos = 0;
|
||||
DependentTypeOfExprType *Canon
|
||||
= DependentTypeOfExprTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
if (Canon) {
|
||||
// We already have a "canonical" version of an identical, dependent
|
||||
// typeof(expr) type. Use that as our canonical type.
|
||||
toe = new (*this, 8) TypeOfExprType(tofExpr,
|
||||
QualType((TypeOfExprType*)Canon, 0));
|
||||
}
|
||||
else {
|
||||
// Build a new, canonical typeof(expr) type.
|
||||
Canon = new (*this, 8) DependentTypeOfExprType(*this, tofExpr);
|
||||
DependentTypeOfExprTypes.InsertNode(Canon, InsertPos);
|
||||
toe = Canon;
|
||||
}
|
||||
} else {
|
||||
QualType Canonical = getCanonicalType(tofExpr->getType());
|
||||
toe = new (*this,8) TypeOfExprType(tofExpr, Canonical);
|
||||
}
|
||||
|
|
|
@ -602,9 +602,9 @@ void StmtProfiler::VisitObjCIsaExpr(ObjCIsaExpr *S) {
|
|||
}
|
||||
|
||||
void StmtProfiler::VisitDecl(Decl *D) {
|
||||
if (Canonical) {
|
||||
if (Canonical && D) {
|
||||
if (NonTypeTemplateParmDecl *NTTP
|
||||
= dyn_cast_or_null<NonTypeTemplateParmDecl>(D)) {
|
||||
= dyn_cast<NonTypeTemplateParmDecl>(D)) {
|
||||
ID.AddInteger(NTTP->getDepth());
|
||||
ID.AddInteger(NTTP->getIndex());
|
||||
VisitType(NTTP->getType());
|
||||
|
|
|
@ -958,6 +958,11 @@ TypeOfExprType::TypeOfExprType(Expr *E, QualType can)
|
|||
: Type(TypeOfExpr, can, E->isTypeDependent()), TOExpr(E) {
|
||||
}
|
||||
|
||||
void DependentTypeOfExprType::Profile(llvm::FoldingSetNodeID &ID,
|
||||
ASTContext &Context, Expr *E) {
|
||||
E->Profile(ID, Context, true);
|
||||
}
|
||||
|
||||
DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can)
|
||||
: Type(Decltype, can, E->isTypeDependent()), E(E),
|
||||
UnderlyingType(underlyingType) {
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
void f();
|
||||
|
||||
// FIXME: would like to refer to the first function parameter in these test,
|
||||
// but that won't work (yet).
|
||||
|
||||
// Test typeof(expr) canonicalization
|
||||
template<typename T, T N>
|
||||
void f0(T x, __typeof__(f(N)) y) { } // expected-note{{previous}}
|
||||
|
||||
template<typename T, T N>
|
||||
void f0(T x, __typeof__((f)(N)) y) { }
|
||||
|
||||
template<typename U, U M>
|
||||
void f0(U u, __typeof__(f(M))) { } // expected-error{{redefinition}}
|
Loading…
Reference in New Issue