ValuePrinterInfo::ValuePrinterInfo(Expr* E, ASTContext* Ctx) : m_Expr(E), m_Context(Ctx), m_Flags(0) { assert(E && "Expression cannot be null!"); assert(Ctx && "ASTContext cannot be null!"); // 1. Get the flags const QualType QT = m_Expr->getType(); if (E->isRValue() || QT.isLocalConstQualified() || QT.isConstant(*Ctx)){ m_Flags |= VPI_Const; } if (QT->isPointerType()) { // treat arrary-to-pointer decay as array: QualType PQT = QT->getPointeeType(); const Type* PTT = PQT.getTypePtr(); if (!PTT || !PTT->isArrayType()) { m_Flags |= VPI_Ptr; if (const RecordType* RT = dyn_cast<RecordType>(QT.getTypePtr())) if (RecordDecl* RD = RT->getDecl()) { CXXRecordDecl* CRD = dyn_cast<CXXRecordDecl>(RD); if (CRD && CRD->isPolymorphic()) m_Flags |= VPI_Polymorphic; } } } }
void ValuePrinterInfo::Init(clang::QualType Ty) { assert(!Ty.isNull() && "Type must be valid!"); assert(m_Context && "ASTContext cannot be null!"); assert(sizeof(m_Type) >= sizeof(clang::QualType) && "m_Type too small!"); m_Type = *reinterpret_cast<void**>(&Ty); // 1. Get the flags if (Ty.isLocalConstQualified() || Ty.isConstant(*m_Context)){ m_Flags |= VPI_Const; } if (Ty->isPointerType()) { // treat arrary-to-pointer decay as array: QualType PQT = Ty->getPointeeType(); const Type* PTT = PQT.getTypePtr(); if (!PTT || !PTT->isArrayType()) { m_Flags |= VPI_Ptr; if (const RecordType* RT = dyn_cast<RecordType>(Ty.getTypePtr())) if (RecordDecl* RD = RT->getDecl()) { CXXRecordDecl* CRD = dyn_cast<CXXRecordDecl>(RD); if (CRD && CRD->isPolymorphic()) m_Flags |= VPI_Polymorphic; } } } }
void CopyablePolymorphic::VisitDecl(clang::Decl *decl) { CXXRecordDecl *record = dyn_cast<CXXRecordDecl>(decl); if (!record || !record->hasDefinition() || record->getDefinition() != record || !record->isPolymorphic()) return; CXXConstructorDecl *copyCtor = Utils::copyCtor(record); CXXMethodDecl *copyAssign = Utils::copyAssign(record); const bool hasCallableCopyCtor = copyCtor && !copyCtor->isDeleted() && copyCtor->getAccess() != clang::AS_private; const bool hasCallableCopyAssign = copyAssign && !copyAssign->isDeleted() && copyAssign->getAccess() != clang::AS_private; if (!hasCallableCopyCtor && !hasCallableCopyAssign) return; emitWarning(record->getLocStart(), "Polymorphic class is copyable. Potential slicing."); }