//===- MCLDAttribute.cpp --------------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "mcld/MC/Attribute.h" #include "mcld/MC/AttributeSet.h" #include "mcld/Support/MsgHandling.h" namespace mcld { //===----------------------------------------------------------------------===// // AttrConstraint //===----------------------------------------------------------------------===// bool AttrConstraint::isLegal(const Attribute& pAttr) const { if (!isWholeArchive() && pAttr.isWholeArchive()) { error(diag::err_unsupported_whole_archive); return false; } if (!isAsNeeded() && pAttr.isAsNeeded()) { error(diag::err_unsupported_as_needed); return false; } if (!isAddNeeded() && pAttr.isAddNeeded()) { error(diag::err_unsupported_add_needed); return false; } if (isStaticSystem() && pAttr.isDynamic()) { error(diag::err_unsupported_Bdynamic); return false; } if (isStaticSystem() && pAttr.isAsNeeded()) { warning(diag::err_enable_as_needed_on_static_system); return true; } // FIXME: may be it's legal, but ignored by GNU ld. if (pAttr.isAsNeeded() && pAttr.isStatic()) { warning(diag::err_mix_static_as_needed); return true; } return true; } //===----------------------------------------------------------------------===// // AttributeProxy //===----------------------------------------------------------------------===// AttributeProxy::AttributeProxy(AttributeSet& pParent, const Attribute& pBase, const AttrConstraint& pConstraint) : m_AttrPool(pParent), m_pBase(&pBase), m_Constraint(pConstraint) { } AttributeProxy::~AttributeProxy() { } bool AttributeProxy::isWholeArchive() const { if (m_Constraint.isWholeArchive()) return m_pBase->isWholeArchive(); else return false; } bool AttributeProxy::isAsNeeded() const { if (m_Constraint.isAsNeeded()) return m_pBase->isAsNeeded(); else return false; } bool AttributeProxy::isAddNeeded() const { if (m_Constraint.isAddNeeded()) return m_pBase->isAddNeeded(); else return false; } bool AttributeProxy::isStatic() const { if (m_Constraint.isSharedSystem()) return m_pBase->isStatic(); else return true; } bool AttributeProxy::isDynamic() const { if (m_Constraint.isSharedSystem()) return m_pBase->isDynamic(); else return false; } static inline void ReplaceOrRecord(AttributeSet& pParent, const Attribute*& pBase, Attribute*& pCopy) { Attribute* result = pParent.exists(*pCopy); if (result == NULL) { // can not find pParent.record(*pCopy); pBase = pCopy; } else { // find delete pCopy; pBase = result; } } void AttributeProxy::setWholeArchive() { Attribute* copy = new Attribute(*m_pBase); copy->setWholeArchive(); ReplaceOrRecord(m_AttrPool, m_pBase, copy); } void AttributeProxy::unsetWholeArchive() { Attribute* copy = new Attribute(*m_pBase); copy->unsetWholeArchive(); ReplaceOrRecord(m_AttrPool, m_pBase, copy); } void AttributeProxy::setAsNeeded() { Attribute* copy = new Attribute(*m_pBase); copy->setAsNeeded(); ReplaceOrRecord(m_AttrPool, m_pBase, copy); } void AttributeProxy::unsetAsNeeded() { Attribute* copy = new Attribute(*m_pBase); copy->unsetAsNeeded(); ReplaceOrRecord(m_AttrPool, m_pBase, copy); } void AttributeProxy::setAddNeeded() { Attribute* copy = new Attribute(*m_pBase); copy->setAddNeeded(); ReplaceOrRecord(m_AttrPool, m_pBase, copy); } void AttributeProxy::unsetAddNeeded() { Attribute* copy = new Attribute(*m_pBase); copy->unsetAddNeeded(); ReplaceOrRecord(m_AttrPool, m_pBase, copy); } void AttributeProxy::setStatic() { Attribute* copy = new Attribute(*m_pBase); copy->setStatic(); ReplaceOrRecord(m_AttrPool, m_pBase, copy); } void AttributeProxy::setDynamic() { Attribute* copy = new Attribute(*m_pBase); copy->setDynamic(); ReplaceOrRecord(m_AttrPool, m_pBase, copy); } AttributeProxy& AttributeProxy::assign(Attribute* pBase) { m_pBase = pBase; return *this; } } // namespace mcld