QualType TypeResolver::resolveCanonical(QualType Q) const { if (Q->hasCanonicalType()) return Q.getCanonicalType(); const Type* T = Q.getTypePtr(); switch (Q->getTypeClass()) { case TC_BUILTIN: return Q; case TC_POINTER: { const PointerType* P = cast<PointerType>(T); QualType t1 = P->getPointeeType(); // Pointee will always be in same TypeContext (file), since it's either built-in or UnresolvedType QualType t2 = resolveCanonical(t1); assert(t2.isValid()); if (t1 == t2) { Q->setCanonicalType(Q); return Q; } else { // TODO qualifiers QualType Canon = typeContext.getPointerType(t2); if (!Canon->hasCanonicalType()) Canon->setCanonicalType(Canon); Q->setCanonicalType(Canon); return Canon; } } case TC_ARRAY: { const ArrayType* A = cast<ArrayType>(T); QualType t1 = A->getElementType(); // NOTE: qualifiers are lost here! QualType t2 = resolveCanonical(t1); if (t1 == t2) { Q->setCanonicalType(Q); return Q; } else { // NOTE: need size Expr, but set ownership to none QualType Canon = typeContext.getArrayType(t2, A->getSizeExpr(), false, A->isIncremental()); if (!Canon->hasCanonicalType()) Canon->setCanonicalType(Canon); Q->setCanonicalType(Canon); return Canon; } } case TC_UNRESOLVED: assert(0 && "should not get here"); return QualType(); case TC_ALIAS: case TC_STRUCT: case TC_ENUM: case TC_FUNCTION: return Q.getCanonicalType(); case TC_MODULE: assert(0 && "TBD"); return Q; } assert(0); }
QualType TypeResolver::resolveType(QualType Q, bool usedPublic) { if (Q->hasCanonicalType()) return Q; // should be ok already // basic resolving of Unresolved if (checkType(Q, usedPublic)) return QualType(); QualType resolved = resolveUnresolved(Q); resolveCanonical(resolved); return resolved; }
QualType TypeContext::getPointerType(QualType ref) { assert(ref.isValid()); for (unsigned i=0; i<types.size(); i++) { Type* t = types[i]; if (isa<PointerType>(t)) { PointerType* P = cast<PointerType>(t); if (P->getPointeeType() == ref) return t; } } Type* N = new PointerType(ref); if (ref->hasCanonicalType()) N->setCanonicalType(N); return add(N); }
EnumTypeDecl* C2Sema::ActOnEnumType(const char* name, SourceLocation loc, Expr* implType, bool is_public) { assert(implType); TypeExpr* T = cast<TypeExpr>(implType); QualType impl = T->getType(); assert(impl->hasCanonicalType()); delete T; QualType qt = typeContext.getEnumType(); EnumTypeDecl* E = new EnumTypeDecl(name, loc, impl, qt, is_public); EnumType* ET = cast<EnumType>(qt.getTypePtr()); ET->setCanonicalType(impl); ET->setDecl(E); ast.addType(E); addSymbol(E); return E; }
QualType TypeResolver::checkCanonicals(Decls& decls, QualType Q, bool set) const { if (Q->hasCanonicalType()) return Q.getCanonicalType(); const Type* T = Q.getTypePtr(); switch (Q->getTypeClass()) { case TC_BUILTIN: return Q; case TC_POINTER: { const PointerType* P = cast<PointerType>(T); QualType t1 = P->getPointeeType(); // Pointee will always be in same TypeContext (file), since it's either built-in or UnresolvedType QualType t2 = checkCanonicals(decls, t1, set); if (!t2.isValid()) return t2; QualType canon; if (t1 == t2) canon = Q; else { canon = typeContext.getPointerType(t2); if (!canon->hasCanonicalType()) canon->setCanonicalType(canon); } assert(Q.isValid()); if (set) P->setCanonicalType(canon); return canon; } case TC_ARRAY: { const ArrayType* A = cast<ArrayType>(T); QualType t1 = A->getElementType(); // NOTE: qualifiers are lost here! QualType t2 = checkCanonicals(decls, t1, set); if (!t2.isValid()) return t2; QualType canon; if (t1 == t2) canon = Q; // NOTE: need size Expr, but set ownership to none else { canon = typeContext.getArrayType(t2, A->getSizeExpr(), false, A->isIncremental()); if (!canon->hasCanonicalType()) canon->setCanonicalType(canon); } if (set) A->setCanonicalType(canon); return canon; } case TC_UNRESOLVED: { const UnresolvedType* U = cast<UnresolvedType>(T); TypeDecl* TD = U->getDecl(); assert(TD); // check if exists if (!checkDecls(decls, TD)) { return QualType(); } QualType canonical = checkCanonicals(decls, TD->getType(), false); if (set) U->setCanonicalType(canonical); return canonical; } case TC_ALIAS: { const AliasType* A = cast<AliasType>(T); if (!checkDecls(decls, A->getDecl())) { return QualType(); } QualType canonical = checkCanonicals(decls, A->getRefType(), set); assert(Q.isValid()); if (set) A->setCanonicalType(canonical); return canonical; } case TC_STRUCT: return Q.getCanonicalType(); case TC_ENUM: { assert(0 && "TODO"); return 0; } case TC_FUNCTION: return Q.getCanonicalType(); case TC_MODULE: assert(0 && "TBD"); return 0; } assert(0); }
QualType TypeContext::getArrayType(QualType element, Expr* size, bool ownSize, bool isIncremental) { Type* N = new ArrayType(element, size, ownSize, isIncremental); if (element->hasCanonicalType()) N->setCanonicalType(N); return add(N); }