<commit_before>/******************************************************************************\
* EventHandler.cpp                                                             *
* An event handler providing GUI-like events                                   *
*                                                                              *
*                                                                              *
* Copyright (C) 2006 by Leandro Motta Barros.                                  *
*                                                                              *
* This program is distributed under the OpenSceneGraph Public License. You     *
* should have received a copy of it with the source distribution, in a file    *
* named 'COPYING.txt'.                                                         *
\******************************************************************************/

#include "OSGUIsh/EventHandler.hpp"
#include <boost/lexical_cast.hpp>

namespace OSGUIsh
{

   // - EventHandler::EventHandler ---------------------------------------------
   EventHandler::EventHandler(
      osgProducer::Viewer& viewer,
      const FocusPolicyFactory& kbdPolicyFactory,
      const FocusPolicyFactory& wheelPolicyFactory)
      : viewer_(viewer),
        kbdFocusPolicy_(kbdPolicyFactory.create (kbdFocus_)),
        wheelFocusPolicy_(wheelPolicyFactory.create (wheelFocus_))
   {
      addNode (NodePtr());

      for (int i = 0; i < MOUSE_BUTTON_COUNT; ++i)
      {
         nodeThatGotMouseDown_[i] = NodePtr();
         nodeThatGotClick_[i] = NodePtr();
         timeOfLastClick_[i] = -1.0;
      }
   }

   // - EventHandler::handle ---------------------------------------------------
   bool EventHandler::handle (const osgGA::GUIEventAdapter& ea,
                              osgGA::GUIActionAdapter&)
   {
      switch (ea.getEventType())
      {
         case osgGA::GUIEventAdapter::FRAME:
            handleFrameEvent (ea);
            break;

         case osgGA::GUIEventAdapter::PUSH:
            handlePushEvent (ea);
            break;

         case osgGA::GUIEventAdapter::RELEASE:
            handleReleaseEvent (ea);
            break;

         case osgGA::GUIEventAdapter::KEYDOWN:
            handleKeyDownEvent (ea);
            break;

         case osgGA::GUIEventAdapter::KEYUP:
            handleKeyUpEvent (ea);
            break;

         case osgGA::GUIEventAdapter::SCROLL:
            handleScrollEvent (ea);
            break;

         default:
            break;
      }

      kbdFocusPolicy_->updateFocus (ea, nodeUnderMouse_);
      wheelFocusPolicy_->updateFocus (ea, nodeUnderMouse_);

      return handleReturnValues_[ea.getEventType()];
   }

   // - EventHandler::addNode --------------------------------------------------
   void EventHandler::addNode (const osg::ref_ptr<osg::Node> node)
   {
#     define OSGUISH_EVENTHANDLER_ADD_EVENT(EVENT) \
         signals_[node][#EVENT] = SignalPtr (new EventHandler::Signal_t());

      OSGUISH_EVENTHANDLER_ADD_EVENT (MouseEnter);
      OSGUISH_EVENTHANDLER_ADD_EVENT (MouseLeave);
      OSGUISH_EVENTHANDLER_ADD_EVENT (MouseMove);
      OSGUISH_EVENTHANDLER_ADD_EVENT (MouseDown);
      OSGUISH_EVENTHANDLER_ADD_EVENT (MouseUp);
      OSGUISH_EVENTHANDLER_ADD_EVENT (Click);
      OSGUISH_EVENTHANDLER_ADD_EVENT (DoubleClick);
      OSGUISH_EVENTHANDLER_ADD_EVENT (MouseWheelUp);
      OSGUISH_EVENTHANDLER_ADD_EVENT (MouseWheelDown);
      OSGUISH_EVENTHANDLER_ADD_EVENT (KeyUp);
      OSGUISH_EVENTHANDLER_ADD_EVENT (KeyDown);

#     undef OSGUISH_EVENTHANDLER_ADD_EVENT
   }

   // - EventHandler::getSignal ------------------------------------------------
   EventHandler::SignalPtr EventHandler::getSignal(
      const NodePtr node, const std::string& signal)
   {
       SignalsMap_t::const_iterator signalsCollectionIter =
          signals_.find (node);

      if (signalsCollectionIter == signals_.end())
      {
         throw std::runtime_error(
            ("Trying to get a signal of an unknown node: '" + node->getName()
             + "' (" + boost::lexical_cast<std::string>(node.get())
             + ").").c_str());
      }

      SignalCollection_t::const_iterator signalIter =
         signalsCollectionIter->second.find (signal);

      if (signalIter == signalsCollectionIter->second.end())
      {
         throw std::runtime_error (("Trying to get an unknown signal: '"
                                    + signal + "'.").c_str());
      }

      return signalIter->second;
   }

   // - EventHandler::setKeyboardFocus -----------------------------------------
   void EventHandler::setKeyboardFocus (const NodePtr node)
   {
      kbdFocus_ = node;
   }

   // - EventHandler::setMouseWheelFocus ---------------------------------------
   void EventHandler::setMouseWheelFocus (const NodePtr node)
   {
      wheelFocus_ = node;
   }

   // - EventHandler::setKeyboardFocusPolicy -----------------------------------
   void EventHandler::setKeyboardFocusPolicy(
      const FocusPolicyFactory& policyFactory)
   {
      kbdFocusPolicy_ = policyFactory.create (kbdFocus_);
   }

   // - EventHandler::setMouseWheelFocusPolicy ---------------------------------
   void EventHandler::setMouseWheelFocusPolicy(
      const FocusPolicyFactory& policyFactory)
   {
      wheelFocusPolicy_ = policyFactory.create (wheelFocus_);
   }

   // - EventHandler::getObservedNode ------------------------------------------
   osg::ref_ptr<osg::Node>
   EventHandler::getObservedNode (const osg::NodePath& nodePath)
   {
      typedef osg::NodePath::const_iterator iter_t;
      typedef osg::ref_ptr<osg::Node> nodePtr;
      for (iter_t p = nodePath.begin(); p != nodePath.end(); ++p)
      {
         if (signals_.find (nodePtr(*p)) != signals_.end())
            return nodePtr(*p);
      }

      return nodePtr();
   }

   // - EventHandler::handleFrameEvent -----------------------------------------
   void EventHandler::handleFrameEvent (const osgGA::GUIEventAdapter& ea)
   {
      // Find out who is, and who was under the mouse pointer
      hitList_.clear();
      viewer_.computeIntersections (ea.getX(), ea.getY(), hitList_);

      NodePtr currentNodeUnderMouse;
      osg::Vec3 currentPositionUnderMouse;

      if (hitList_.size() > 0)
      {
         currentNodeUnderMouse = getObservedNode (hitList_[0].getNodePath());
         assert (signals_.find (currentNodeUnderMouse) != signals_.end()
                 && "'getObservedNode()' returned an invalid value!");

         currentPositionUnderMouse = hitList_[0].getLocalIntersectPoint();
      }

      NodePtr prevNodeUnderMouse = nodeUnderMouse_;
      osg::Vec3 prevPositionUnderMouse = positionUnderMouse_;

      nodeUnderMouse_ = currentNodeUnderMouse;
      positionUnderMouse_ = currentPositionUnderMouse;

      // Trigger the events
      if (currentNodeUnderMouse == prevNodeUnderMouse)
      {
         if (prevNodeUnderMouse.valid()
             && currentPositionUnderMouse != prevPositionUnderMouse)
         {
            signals_[currentNodeUnderMouse]["MouseMove"]->operator()(
               ea, currentNodeUnderMouse);
         }
      }
      else // currentNodeUnderMouse != prevNodeUnderMouse
      {
         if (!currentNodeUnderMouse.valid())
         {
            signals_[prevNodeUnderMouse]["MouseLeave"]->operator()(
               ea, prevNodeUnderMouse);
         }
         else if (!prevNodeUnderMouse.valid())
         {
            signals_[currentNodeUnderMouse]["MouseEnter"]->operator()(
               ea, currentNodeUnderMouse);
         }
         else // different and both are valid
         {
            signals_[prevNodeUnderMouse]["MouseLeave"]->operator()(
               ea, prevNodeUnderMouse);
            signals_[currentNodeUnderMouse]["MouseEnter"]->operator()(
               ea, currentNodeUnderMouse);
         }
      }
   }

   // - EventHandler::handlePushEvent ------------------------------------------
   void EventHandler::handlePushEvent (const osgGA::GUIEventAdapter& ea)
   {
      // Trigger a "MouseDown" signal.
      if (nodeUnderMouse_.valid())
      {
         signals_[nodeUnderMouse_]["MouseDown"]->operator()(
            ea, nodeUnderMouse_);
      }

      // Do the bookkeeping for "Click" and "DoubleClick"
      MouseButton button = getMouseButton (ea);
      nodeThatGotMouseDown_[button] = nodeUnderMouse_;
   }

   // - EventHandler::handleReleaseEvent ---------------------------------------
   void EventHandler::handleReleaseEvent (const osgGA::GUIEventAdapter& ea)
   {
      const double DOUBLE_CLICK_INTERVAL = 0.3;

      if (nodeUnderMouse_.valid())
      {
         MouseButton button = getMouseButton (ea);

         // First the trivial case: the "MouseUp" event
         signals_[nodeUnderMouse_]["MouseUp"]->operator()(
            ea, nodeUnderMouse_);

         // Now, the trickier ones: "Click" and "DoubleClick"
         if (nodeUnderMouse_ == nodeThatGotMouseDown_[button])
         {
            signals_[nodeUnderMouse_]["Click"]->operator()(
               ea, nodeUnderMouse_);

            const double now = ea.getTime();

            if (now - timeOfLastClick_[button] < DOUBLE_CLICK_INTERVAL
                && nodeUnderMouse_ == nodeThatGotClick_[button])
            {
               signals_[nodeUnderMouse_]["DoubleClick"]->operator()(
                  ea, nodeUnderMouse_);
            }

            nodeThatGotClick_[button] = nodeUnderMouse_;
            timeOfLastClick_[button] = now;
         }
      }
   }

   // - EventHandler::handleKeyDownEvent ---------------------------------------
   void EventHandler::handleKeyDownEvent (const osgGA::GUIEventAdapter& ea)
   {
      signals_[kbdFocus_]["KeyDown"]->operator()(ea, kbdFocus_);
   }

   // - EventHandler::handleKeyUpEvent -----------------------------------------
   void EventHandler::handleKeyUpEvent (const osgGA::GUIEventAdapter& ea)
   {
      signals_[kbdFocus_]["KeyUp"]->operator()(ea, kbdFocus_);
   }

   // - EventHandler::handleScrollEvent ----------------------------------------
   void EventHandler::handleScrollEvent (const osgGA::GUIEventAdapter& ea)
   {
      switch (ea.getScrollingMotion())
      {
         case osgGA::GUIEventAdapter::SCROLL_UP:
         {
            signals_[wheelFocus_]["MouseWheelUp"]->operator()(ea, wheelFocus_);
            break;
         }

         case osgGA::GUIEventAdapter::SCROLL_DOWN:
         {
            signals_[wheelFocus_]["MouseWheelDown"]->operator()(ea, wheelFocus_);
            break;
         }

         default:
            break; // ignore other events
      }
   }

   // - EventHandler::getMouseButton -------------------------------------------
   EventHandler::MouseButton EventHandler::getMouseButton(
      const osgGA::GUIEventAdapter& ea)
   {
      switch (ea.getButton())
      {
         case osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON:
            return LEFT_MOUSE_BUTTON;
         case osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON:
            return MIDDLE_MOUSE_BUTTON;
         case osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON:
            return RIGHT_MOUSE_BUTTON;
         default:
         {
            assert (false && "Got an invalid mouse button code. Is 'ea' really "
                    "a mouse event?");
         }
      }
   }

} // namespace OSGUIsh
<commit_msg>Removed a typedef in 'EventHandler::getObservedNode()' that was the same as 'NodePtr'.<commit_after>/******************************************************************************\
* EventHandler.cpp                                                             *
* An event handler providing GUI-like events                                   *
*                                                                              *
*                                                                              *
* Copyright (C) 2006 by Leandro Motta Barros.                                  *
*                                                                              *
* This program is distributed under the OpenSceneGraph Public License. You     *
* should have received a copy of it with the source distribution, in a file    *
* named 'COPYING.txt'.                                                         *
\******************************************************************************/

#include "OSGUIsh/EventHandler.hpp"
#include <boost/lexical_cast.hpp>

namespace OSGUIsh
{

   // - EventHandler::EventHandler ---------------------------------------------
   EventHandler::EventHandler(
      osgProducer::Viewer& viewer,
      const FocusPolicyFactory& kbdPolicyFactory,
      const FocusPolicyFactory& wheelPolicyFactory)
      : viewer_(viewer),
        kbdFocusPolicy_(kbdPolicyFactory.create (kbdFocus_)),
        wheelFocusPolicy_(wheelPolicyFactory.create (wheelFocus_))
   {
      addNode (NodePtr());

      for (int i = 0; i < MOUSE_BUTTON_COUNT; ++i)
      {
         nodeThatGotMouseDown_[i] = NodePtr();
         nodeThatGotClick_[i] = NodePtr();
         timeOfLastClick_[i] = -1.0;
      }
   }

   // - EventHandler::handle ---------------------------------------------------
   bool EventHandler::handle (const osgGA::GUIEventAdapter& ea,
                              osgGA::GUIActionAdapter&)
   {
      switch (ea.getEventType())
      {
         case osgGA::GUIEventAdapter::FRAME:
            handleFrameEvent (ea);
            break;

         case osgGA::GUIEventAdapter::PUSH:
            handlePushEvent (ea);
            break;

         case osgGA::GUIEventAdapter::RELEASE:
            handleReleaseEvent (ea);
            break;

         case osgGA::GUIEventAdapter::KEYDOWN:
            handleKeyDownEvent (ea);
            break;

         case osgGA::GUIEventAdapter::KEYUP:
            handleKeyUpEvent (ea);
            break;

         case osgGA::GUIEventAdapter::SCROLL:
            handleScrollEvent (ea);
            break;

         default:
            break;
      }

      kbdFocusPolicy_->updateFocus (ea, nodeUnderMouse_);
      wheelFocusPolicy_->updateFocus (ea, nodeUnderMouse_);

      return handleReturnValues_[ea.getEventType()];
   }

   // - EventHandler::addNode --------------------------------------------------
   void EventHandler::addNode (const osg::ref_ptr<osg::Node> node)
   {
#     define OSGUISH_EVENTHANDLER_ADD_EVENT(EVENT) \
         signals_[node][#EVENT] = SignalPtr (new EventHandler::Signal_t());

      OSGUISH_EVENTHANDLER_ADD_EVENT (MouseEnter);
      OSGUISH_EVENTHANDLER_ADD_EVENT (MouseLeave);
      OSGUISH_EVENTHANDLER_ADD_EVENT (MouseMove);
      OSGUISH_EVENTHANDLER_ADD_EVENT (MouseDown);
      OSGUISH_EVENTHANDLER_ADD_EVENT (MouseUp);
      OSGUISH_EVENTHANDLER_ADD_EVENT (Click);
      OSGUISH_EVENTHANDLER_ADD_EVENT (DoubleClick);
      OSGUISH_EVENTHANDLER_ADD_EVENT (MouseWheelUp);
      OSGUISH_EVENTHANDLER_ADD_EVENT (MouseWheelDown);
      OSGUISH_EVENTHANDLER_ADD_EVENT (KeyUp);
      OSGUISH_EVENTHANDLER_ADD_EVENT (KeyDown);

#     undef OSGUISH_EVENTHANDLER_ADD_EVENT
   }

   // - EventHandler::getSignal ------------------------------------------------
   EventHandler::SignalPtr EventHandler::getSignal(
      const NodePtr node, const std::string& signal)
   {
       SignalsMap_t::const_iterator signalsCollectionIter =
          signals_.find (node);

      if (signalsCollectionIter == signals_.end())
      {
         throw std::runtime_error(
            ("Trying to get a signal of an unknown node: '" + node->getName()
             + "' (" + boost::lexical_cast<std::string>(node.get())
             + ").").c_str());
      }

      SignalCollection_t::const_iterator signalIter =
         signalsCollectionIter->second.find (signal);

      if (signalIter == signalsCollectionIter->second.end())
      {
         throw std::runtime_error (("Trying to get an unknown signal: '"
                                    + signal + "'.").c_str());
      }

      return signalIter->second;
   }

   // - EventHandler::setKeyboardFocus -----------------------------------------
   void EventHandler::setKeyboardFocus (const NodePtr node)
   {
      kbdFocus_ = node;
   }

   // - EventHandler::setMouseWheelFocus ---------------------------------------
   void EventHandler::setMouseWheelFocus (const NodePtr node)
   {
      wheelFocus_ = node;
   }

   // - EventHandler::setKeyboardFocusPolicy -----------------------------------
   void EventHandler::setKeyboardFocusPolicy(
      const FocusPolicyFactory& policyFactory)
   {
      kbdFocusPolicy_ = policyFactory.create (kbdFocus_);
   }

   // - EventHandler::setMouseWheelFocusPolicy ---------------------------------
   void EventHandler::setMouseWheelFocusPolicy(
      const FocusPolicyFactory& policyFactory)
   {
      wheelFocusPolicy_ = policyFactory.create (wheelFocus_);
   }

   // - EventHandler::getObservedNode ------------------------------------------
   NodePtr EventHandler::getObservedNode (const osg::NodePath& nodePath)
   {
      typedef osg::NodePath::const_iterator iter_t;
      for (iter_t p = nodePath.begin(); p != nodePath.end(); ++p)
      {
         if (signals_.find (NodePtr(*p)) != signals_.end())
            return NodePtr(*p);
      }

      return NodePtr();
   }

   // - EventHandler::handleFrameEvent -----------------------------------------
   void EventHandler::handleFrameEvent (const osgGA::GUIEventAdapter& ea)
   {
      // Find out who is, and who was under the mouse pointer
      hitList_.clear();
      viewer_.computeIntersections (ea.getX(), ea.getY(), hitList_);

      NodePtr currentNodeUnderMouse;
      osg::Vec3 currentPositionUnderMouse;

      if (hitList_.size() > 0)
      {
         currentNodeUnderMouse = getObservedNode (hitList_[0].getNodePath());
         assert (signals_.find (currentNodeUnderMouse) != signals_.end()
                 && "'getObservedNode()' returned an invalid value!");

         currentPositionUnderMouse = hitList_[0].getLocalIntersectPoint();
      }

      NodePtr prevNodeUnderMouse = nodeUnderMouse_;
      osg::Vec3 prevPositionUnderMouse = positionUnderMouse_;

      nodeUnderMouse_ = currentNodeUnderMouse;
      positionUnderMouse_ = currentPositionUnderMouse;

      // Trigger the events
      if (currentNodeUnderMouse == prevNodeUnderMouse)
      {
         if (prevNodeUnderMouse.valid()
             && currentPositionUnderMouse != prevPositionUnderMouse)
         {
            signals_[currentNodeUnderMouse]["MouseMove"]->operator()(
               ea, currentNodeUnderMouse);
         }
      }
      else // currentNodeUnderMouse != prevNodeUnderMouse
      {
         if (!currentNodeUnderMouse.valid())
         {
            signals_[prevNodeUnderMouse]["MouseLeave"]->operator()(
               ea, prevNodeUnderMouse);
         }
         else if (!prevNodeUnderMouse.valid())
         {
            signals_[currentNodeUnderMouse]["MouseEnter"]->operator()(
               ea, currentNodeUnderMouse);
         }
         else // different and both are valid
         {
            signals_[prevNodeUnderMouse]["MouseLeave"]->operator()(
               ea, prevNodeUnderMouse);
            signals_[currentNodeUnderMouse]["MouseEnter"]->operator()(
               ea, currentNodeUnderMouse);
         }
      }
   }

   // - EventHandler::handlePushEvent ------------------------------------------
   void EventHandler::handlePushEvent (const osgGA::GUIEventAdapter& ea)
   {
      // Trigger a "MouseDown" signal.
      if (nodeUnderMouse_.valid())
      {
         signals_[nodeUnderMouse_]["MouseDown"]->operator()(
            ea, nodeUnderMouse_);
      }

      // Do the bookkeeping for "Click" and "DoubleClick"
      MouseButton button = getMouseButton (ea);
      nodeThatGotMouseDown_[button] = nodeUnderMouse_;
   }

   // - EventHandler::handleReleaseEvent ---------------------------------------
   void EventHandler::handleReleaseEvent (const osgGA::GUIEventAdapter& ea)
   {
      const double DOUBLE_CLICK_INTERVAL = 0.3;

      if (nodeUnderMouse_.valid())
      {
         MouseButton button = getMouseButton (ea);

         // First the trivial case: the "MouseUp" event
         signals_[nodeUnderMouse_]["MouseUp"]->operator()(
            ea, nodeUnderMouse_);

         // Now, the trickier ones: "Click" and "DoubleClick"
         if (nodeUnderMouse_ == nodeThatGotMouseDown_[button])
         {
            signals_[nodeUnderMouse_]["Click"]->operator()(
               ea, nodeUnderMouse_);

            const double now = ea.getTime();

            if (now - timeOfLastClick_[button] < DOUBLE_CLICK_INTERVAL
                && nodeUnderMouse_ == nodeThatGotClick_[button])
            {
               signals_[nodeUnderMouse_]["DoubleClick"]->operator()(
                  ea, nodeUnderMouse_);
            }

            nodeThatGotClick_[button] = nodeUnderMouse_;
            timeOfLastClick_[button] = now;
         }
      }
   }

   // - EventHandler::handleKeyDownEvent ---------------------------------------
   void EventHandler::handleKeyDownEvent (const osgGA::GUIEventAdapter& ea)
   {
      signals_[kbdFocus_]["KeyDown"]->operator()(ea, kbdFocus_);
   }

   // - EventHandler::handleKeyUpEvent -----------------------------------------
   void EventHandler::handleKeyUpEvent (const osgGA::GUIEventAdapter& ea)
   {
      signals_[kbdFocus_]["KeyUp"]->operator()(ea, kbdFocus_);
   }

   // - EventHandler::handleScrollEvent ----------------------------------------
   void EventHandler::handleScrollEvent (const osgGA::GUIEventAdapter& ea)
   {
      switch (ea.getScrollingMotion())
      {
         case osgGA::GUIEventAdapter::SCROLL_UP:
         {
            signals_[wheelFocus_]["MouseWheelUp"]->operator()(ea, wheelFocus_);
            break;
         }

         case osgGA::GUIEventAdapter::SCROLL_DOWN:
         {
            signals_[wheelFocus_]["MouseWheelDown"]->operator()(ea, wheelFocus_);
            break;
         }

         default:
            break; // ignore other events
      }
   }

   // - EventHandler::getMouseButton -------------------------------------------
   EventHandler::MouseButton EventHandler::getMouseButton(
      const osgGA::GUIEventAdapter& ea)
   {
      switch (ea.getButton())
      {
         case osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON:
            return LEFT_MOUSE_BUTTON;
         case osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON:
            return MIDDLE_MOUSE_BUTTON;
         case osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON:
            return RIGHT_MOUSE_BUTTON;
         default:
         {
            assert (false && "Got an invalid mouse button code. Is 'ea' really "
                    "a mouse event?");
         }
      }
   }

} // namespace OSGUIsh
<|endoftext|>


<commit_before>// RUN: clang-cc -fsyntax-only -verify %s

#include <stddef.h>

struct S // expected-note {{candidate}}
{
  S(int, int, double); // expected-note {{candidate}}
  S(double, int); // expected-note 2 {{candidate}}
  S(float, int); // expected-note 2 {{candidate}}
};
struct T; // expected-note{{forward declaration of 'struct T'}}
struct U
{
  // A special new, to verify that the global version isn't used.
  void* operator new(size_t, S*); // expected-note {{candidate}}
};
struct V : U
{
};

void* operator new(size_t); // expected-note 2 {{candidate}}
void* operator new(size_t, int*); // expected-note 3 {{candidate}}
void* operator new(size_t, float*); // expected-note 3 {{candidate}}
void* operator new(size_t, S); // expected-note 2 {{candidate}}

void good_news()
{
  int *pi = new int;
  float *pf = new (pi) float();
  pi = new int(1);
  pi = new int('c');
  const int *pci = new const int();
  S *ps = new S(1, 2, 3.4);
  ps = new (pf) (S)(1, 2, 3.4);
  S *(*paps)[2] = new S*[*pi][2];
  ps = new (S[3])(1, 2, 3.4);
  typedef int ia4[4];
  ia4 *pai = new (int[3][4]);
  pi = ::new int;
  U *pu = new (ps) U;
  V *pv = new (ps) V;

  pi = new (S(1.0f, 2)) int;

  (void)new int[true];
}

struct abstract {
  virtual ~abstract() = 0;
};

void bad_news(int *ip)
{
  int i = 1;
  (void)new; // expected-error {{missing type specifier}}
  (void)new 4; // expected-error {{missing type specifier}}
  (void)new () int; // expected-error {{expected expression}}
  (void)new int[1.1]; // expected-error {{array size expression must have integral or enumerated type, not 'double'}}
  (void)new int[1][i]; // expected-error {{only the first dimension}}
  (void)new (int[1][i]); // expected-error {{only the first dimension}}
  (void)new (int[i]); // expected-error {{when type is in parentheses}}
  (void)new int(*(S*)0); // expected-error {{incompatible type initializing}}
  (void)new int(1, 2); // expected-error {{initializer of a builtin type can only take one argument}}
  (void)new S(1); // expected-error {{no matching constructor}}
  (void)new S(1, 1); // expected-error {{call to constructor of 'S' is ambiguous}}
  (void)new const int; // expected-error {{must provide an initializer}}
  (void)new float*(ip); // expected-error {{incompatible type initializing 'int *', expected 'float *'}}
  // Undefined, but clang should reject it directly.
  (void)new int[-1]; // expected-error {{array size is negative}}
  (void)new int[*(S*)0]; // expected-error {{array size expression must have integral or enumerated type, not 'struct S'}}
  (void)::S::new int; // expected-error {{expected unqualified-id}}
  (void)new (0, 0) int; // expected-error {{no matching function for call to 'operator new'}}
  (void)new (0L) int; // expected-error {{call to 'operator new' is ambiguous}}
  // This must fail, because the member version shouldn't be found.
  (void)::new ((S*)0) U; // expected-error {{no matching function for call to 'operator new'}}
  // This must fail, because any member version hides all global versions.
  (void)new U; // expected-error {{no matching function for call to 'operator new'}}
  (void)new (int[]); // expected-error {{array size must be specified in new expressions}}
  (void)new int&; // expected-error {{cannot allocate reference type 'int &' with new}}
  // Some lacking cases due to lack of sema support.
}

void good_deletes()
{
  delete (int*)0;
  delete [](int*)0;
  delete (S*)0;
  ::delete (int*)0;
}

void bad_deletes()
{
  delete 0; // expected-error {{cannot delete expression of type 'int'}}
  delete [0] (int*)0; // expected-error {{expected ']'}} \
                      // expected-note {{to match this '['}}
  delete (void*)0; // expected-error {{cannot delete expression}}
  delete (T*)0; // expected-warning {{deleting pointer to incomplete type}}
  ::S::delete (int*)0; // expected-error {{expected unqualified-id}}
}

struct X0 { };

struct X1 {
  operator int*();
  operator float();
};

struct X2 {
  operator int*(); // expected-note {{candidate function}}
  operator float*(); // expected-note {{candidate function}}
};

void test_delete_conv(X0 x0, X1 x1, X2 x2) {
  delete x0; // expected-error{{cannot delete}}
  delete x1;
  delete x2; // expected-error{{ambiguous conversion of delete expression of type 'struct X2' to a pointer}}
}

// PR4782
class X3 {
public:
  static void operator delete(void * mem, unsigned long size);
};

class X4 {
public:
  static void release(X3 *x);
  static void operator delete(void * mem, unsigned long size);
};

void X4::release(X3 *x) {
  delete x;
}

class X5 {
public:
  void Destroy() const { delete this; }
};

class Base {
public:
  static int operator new(unsigned size) throw(); // expected-error {{'operator new' takes type size_t}} \
						  // expected-error {{operator new' must return type 'void *'}}
  static int operator new[] (unsigned size) throw(); // expected-error {{'operator new[]' takes type size_t}} \
						     // expected-error {{operator new[]' must return type 'void *'}}
};

class Tier {};
class Comp : public Tier {};

class Thai : public Base {
public:
  Thai(const Tier *adoptDictionary);
};

void loadEngineFor() {
  const Comp *dict;
  new Thai(dict);
}

template <class T> struct TBase {
  void* operator new(T size, int); // expected-error {{'operator new' takes type size_t}}
};

TBase<int> t1; // expected-note {{in instantiation of template class 'struct TBase<int>' requested here}}

<commit_msg>Make test more platform independent (per Sebastian's comment).<commit_after>// RUN: clang-cc -fsyntax-only -verify %s

#include <stddef.h>

struct S // expected-note {{candidate}}
{
  S(int, int, double); // expected-note {{candidate}}
  S(double, int); // expected-note 2 {{candidate}}
  S(float, int); // expected-note 2 {{candidate}}
};
struct T; // expected-note{{forward declaration of 'struct T'}}
struct U
{
  // A special new, to verify that the global version isn't used.
  void* operator new(size_t, S*); // expected-note {{candidate}}
};
struct V : U
{
};

void* operator new(size_t); // expected-note 2 {{candidate}}
void* operator new(size_t, int*); // expected-note 3 {{candidate}}
void* operator new(size_t, float*); // expected-note 3 {{candidate}}
void* operator new(size_t, S); // expected-note 2 {{candidate}}

void good_news()
{
  int *pi = new int;
  float *pf = new (pi) float();
  pi = new int(1);
  pi = new int('c');
  const int *pci = new const int();
  S *ps = new S(1, 2, 3.4);
  ps = new (pf) (S)(1, 2, 3.4);
  S *(*paps)[2] = new S*[*pi][2];
  ps = new (S[3])(1, 2, 3.4);
  typedef int ia4[4];
  ia4 *pai = new (int[3][4]);
  pi = ::new int;
  U *pu = new (ps) U;
  V *pv = new (ps) V;

  pi = new (S(1.0f, 2)) int;

  (void)new int[true];
}

struct abstract {
  virtual ~abstract() = 0;
};

void bad_news(int *ip)
{
  int i = 1;
  (void)new; // expected-error {{missing type specifier}}
  (void)new 4; // expected-error {{missing type specifier}}
  (void)new () int; // expected-error {{expected expression}}
  (void)new int[1.1]; // expected-error {{array size expression must have integral or enumerated type, not 'double'}}
  (void)new int[1][i]; // expected-error {{only the first dimension}}
  (void)new (int[1][i]); // expected-error {{only the first dimension}}
  (void)new (int[i]); // expected-error {{when type is in parentheses}}
  (void)new int(*(S*)0); // expected-error {{incompatible type initializing}}
  (void)new int(1, 2); // expected-error {{initializer of a builtin type can only take one argument}}
  (void)new S(1); // expected-error {{no matching constructor}}
  (void)new S(1, 1); // expected-error {{call to constructor of 'S' is ambiguous}}
  (void)new const int; // expected-error {{must provide an initializer}}
  (void)new float*(ip); // expected-error {{incompatible type initializing 'int *', expected 'float *'}}
  // Undefined, but clang should reject it directly.
  (void)new int[-1]; // expected-error {{array size is negative}}
  (void)new int[*(S*)0]; // expected-error {{array size expression must have integral or enumerated type, not 'struct S'}}
  (void)::S::new int; // expected-error {{expected unqualified-id}}
  (void)new (0, 0) int; // expected-error {{no matching function for call to 'operator new'}}
  (void)new (0L) int; // expected-error {{call to 'operator new' is ambiguous}}
  // This must fail, because the member version shouldn't be found.
  (void)::new ((S*)0) U; // expected-error {{no matching function for call to 'operator new'}}
  // This must fail, because any member version hides all global versions.
  (void)new U; // expected-error {{no matching function for call to 'operator new'}}
  (void)new (int[]); // expected-error {{array size must be specified in new expressions}}
  (void)new int&; // expected-error {{cannot allocate reference type 'int &' with new}}
  // Some lacking cases due to lack of sema support.
}

void good_deletes()
{
  delete (int*)0;
  delete [](int*)0;
  delete (S*)0;
  ::delete (int*)0;
}

void bad_deletes()
{
  delete 0; // expected-error {{cannot delete expression of type 'int'}}
  delete [0] (int*)0; // expected-error {{expected ']'}} \
                      // expected-note {{to match this '['}}
  delete (void*)0; // expected-error {{cannot delete expression}}
  delete (T*)0; // expected-warning {{deleting pointer to incomplete type}}
  ::S::delete (int*)0; // expected-error {{expected unqualified-id}}
}

struct X0 { };

struct X1 {
  operator int*();
  operator float();
};

struct X2 {
  operator int*(); // expected-note {{candidate function}}
  operator float*(); // expected-note {{candidate function}}
};

void test_delete_conv(X0 x0, X1 x1, X2 x2) {
  delete x0; // expected-error{{cannot delete}}
  delete x1;
  delete x2; // expected-error{{ambiguous conversion of delete expression of type 'struct X2' to a pointer}}
}

// PR4782
class X3 {
public:
  static void operator delete(void * mem, unsigned long size);
};

class X4 {
public:
  static void release(X3 *x);
  static void operator delete(void * mem, unsigned long size);
};

void X4::release(X3 *x) {
  delete x;
}

class X5 {
public:
  void Destroy() const { delete this; }
};

class Base {
public:
  static int operator new(signed char) throw(); // expected-error {{'operator new' takes type size_t}} \
						  // expected-error {{operator new' must return type 'void *'}}
  static int operator new[] (signed char) throw(); // expected-error {{'operator new[]' takes type size_t}} \
						     // expected-error {{operator new[]' must return type 'void *'}}
};

class Tier {};
class Comp : public Tier {};

class Thai : public Base {
public:
  Thai(const Tier *adoptDictionary);
};

void loadEngineFor() {
  const Comp *dict;
  new Thai(dict);
}

template <class T> struct TBase {
  void* operator new(T size, int); // expected-error {{'operator new' takes type size_t}}
};

TBase<int> t1; // expected-note {{in instantiation of template class 'struct TBase<int>' requested here}}

<|endoftext|>


<commit_before>/*
    This file is part of KDE.

    Copyright (c) 2004 Cornelius Schumacher <schumacher@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "parserrelaxng.h"
#include "creator.h"
#include "schema.h"

#include <libkode/code.h>
#include <libkode/printer.h>
#include <libkode/typedef.h>

#include <kaboutdata.h>
#include <kapplication.h>
#include <kdebug.h>
#include <klocale.h>
#include <kcmdlineargs.h>
#include <kglobal.h>
#include <kconfig.h>
#include <ksimpleconfig.h>
#include <kstandarddirs.h>
#include <kurl.h>

#include <qfile.h>
#include <qtextstream.h>
#include <qdom.h>
#include <qregexp.h>
#include <qmap.h>
#include <QList>

#include <iostream>

static const KCmdLineOptions options[] =
{
  { "d", 0, 0 },
  { "directory <dir>", I18N_NOOP("Directory to generate files in"), "." },
  { "+relaxng", I18N_NOOP("RelaxNG schema of XML file"), 0 },
  { "external-parser", I18N_NOOP("Generate parser in separate source file"),
    0 },
  { "custom-parser", I18N_NOOP("Generate parser customized for schema"), 0 },
  KCmdLineLastOption
};

int main( int argc, char **argv )
{
  KAboutData aboutData( "kxml_compiler", I18N_NOOP("KDE xml compiler"), "0.1",
  	I18N_NOOP("KDE XML Compiler") , KAboutData::License_LGPL );
  aboutData.addAuthor( "Cornelius Schumacher", 0, "schumacher@kde.org" );

  KCmdLineArgs::init( argc, argv, &aboutData, KCmdLineArgs::CmdLineArgNone );
  KCmdLineArgs::addCmdLineOptions( options );

  KApplication app( false );

  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();

  if ( args->count() < 1 ) {
    kError() << "Too few arguments." << endl;
    return 1;
  }
  if ( args->count() > 1 ) {
    kError() << "Too many arguments." << endl;
    return 1;
  }

  QString baseDir = QFile::decodeName( args->getOption( "directory" ) );
  if ( !baseDir.endsWith( "/" ) ) baseDir.append( "/" );

  QString dtdFilename = args->url( 0 ).path();

  QString baseName = args->url( 0 ).fileName();
  int pos = baseName.lastIndexOf( '.' );
  if ( pos > 0 ) baseName = baseName.left( pos );

  QFile dtdFile( dtdFilename );
  if ( !dtdFile.open( QIODevice::ReadOnly ) ) {
    kError() << "Unable to open '" << dtdFilename << "'" << endl;
    return 1;
  }

  QString errorMsg;
  int errorLine, errorCol;
  QDomDocument doc;
  if ( !doc.setContent( &dtdFile, false, &errorMsg, &errorLine, &errorCol ) ) {
    kError() << errorMsg << " at " << errorLine << "," << errorCol << endl;
    return 1;
  }

  kDebug() << "Begin parsing" << endl;

  RNG::ParserRelaxng p;
  RNG::Element *start = p.parse( doc.documentElement() );
  if ( !start ) {
    kError() << "Could not find start element" << endl;
    return 1;
  }

  p.dumpDefinitionMap();

//  return 0;

  p.substituteReferences( start );

#if 1
  std::cout << "--- TREE:" << std::endl;
  p.dumpTree( start );
#endif

  Schema::Document schemaDocument = p.convertToSchema( start );
  std::cout << "--- SCHEMA:" << std::endl;
  schemaDocument.dump();

  kDebug() << "Begin creating code" << endl;

  Creator::XmlParserType pt;
  if ( args->isSet( "custom-parser" ) ) {
    pt = Creator::XmlParserCustomExternal;
  } else if ( args->isSet( "external-parser" ) ) {
    pt = Creator::XmlParserDomExternal;
  } else {
    pt = Creator::XmlParserDom;
  }

  Creator c( schemaDocument, pt );

  kDebug() << "Create classes" << endl;
  foreach( Schema::Element e, schemaDocument.usedElements() ) {
    c.createClass( e );
  }
  kDebug() << "Create parser" << endl;
  Schema::Element startElement = schemaDocument.startElement();
  c.setExternalClassPrefix( c.upperFirst( startElement.name() ) );
  c.createFileParser( startElement );
  c.createFileWriter( startElement, dtdFilename.replace( "rng", "dtd" ) );

  c.createListTypedefs();

  kDebug() << "Begin printing code" << endl;

  KODE::File &f = c.file();

  f.setFilename( baseName );

  KODE::Printer printer;
  printer.setCreationWarning( true );
  printer.setGenerator( aboutData.appName() );
  printer.setOutputDirectory( baseDir );
  printer.setSourceFile( args->url( 0 ).fileName() );

  c.printFiles( printer );

  kDebug() << "Finished." << endl;
}
<commit_msg>Disable dcop registration stuff so kxml_compiler from trunk can run in a KDE3 environment without wrecking stuff.<commit_after>/*
    This file is part of KDE.

    Copyright (c) 2004 Cornelius Schumacher <schumacher@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "parserrelaxng.h"
#include "creator.h"
#include "schema.h"

#include <libkode/code.h>
#include <libkode/printer.h>
#include <libkode/typedef.h>

#include <kaboutdata.h>
#include <kapplication.h>
#include <kdebug.h>
#include <klocale.h>
#include <kcmdlineargs.h>
#include <kglobal.h>
#include <kconfig.h>
#include <ksimpleconfig.h>
#include <kstandarddirs.h>
#include <kurl.h>

#include <qfile.h>
#include <qtextstream.h>
#include <qdom.h>
#include <qregexp.h>
#include <qmap.h>
#include <QList>

#include <iostream>

static const KCmdLineOptions options[] =
{
  { "d", 0, 0 },
  { "directory <dir>", I18N_NOOP("Directory to generate files in"), "." },
  { "+relaxng", I18N_NOOP("RelaxNG schema of XML file"), 0 },
  { "external-parser", I18N_NOOP("Generate parser in separate source file"),
    0 },
  { "custom-parser", I18N_NOOP("Generate parser customized for schema"), 0 },
  KCmdLineLastOption
};

int main( int argc, char **argv )
{
  KApplication::disableAutoDcopRegistration();
  KAboutData aboutData( "kxml_compiler", I18N_NOOP("KDE xml compiler"), "0.1",
  	I18N_NOOP("KDE XML Compiler") , KAboutData::License_LGPL );
  aboutData.addAuthor( "Cornelius Schumacher", 0, "schumacher@kde.org" );

  KCmdLineArgs::init( argc, argv, &aboutData, KCmdLineArgs::CmdLineArgNone );
  KCmdLineArgs::addCmdLineOptions( options );

  KApplication app( false );

  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();

  if ( args->count() < 1 ) {
    kError() << "Too few arguments." << endl;
    return 1;
  }
  if ( args->count() > 1 ) {
    kError() << "Too many arguments." << endl;
    return 1;
  }

  QString baseDir = QFile::decodeName( args->getOption( "directory" ) );
  if ( !baseDir.endsWith( "/" ) ) baseDir.append( "/" );

  QString dtdFilename = args->url( 0 ).path();

  QString baseName = args->url( 0 ).fileName();
  int pos = baseName.lastIndexOf( '.' );
  if ( pos > 0 ) baseName = baseName.left( pos );

  QFile dtdFile( dtdFilename );
  if ( !dtdFile.open( QIODevice::ReadOnly ) ) {
    kError() << "Unable to open '" << dtdFilename << "'" << endl;
    return 1;
  }

  QString errorMsg;
  int errorLine, errorCol;
  QDomDocument doc;
  if ( !doc.setContent( &dtdFile, false, &errorMsg, &errorLine, &errorCol ) ) {
    kError() << errorMsg << " at " << errorLine << "," << errorCol << endl;
    return 1;
  }

  kDebug() << "Begin parsing" << endl;

  RNG::ParserRelaxng p;
  RNG::Element *start = p.parse( doc.documentElement() );
  if ( !start ) {
    kError() << "Could not find start element" << endl;
    return 1;
  }

  p.dumpDefinitionMap();

//  return 0;

  p.substituteReferences( start );

#if 1
  std::cout << "--- TREE:" << std::endl;
  p.dumpTree( start );
#endif

  Schema::Document schemaDocument = p.convertToSchema( start );
  std::cout << "--- SCHEMA:" << std::endl;
  schemaDocument.dump();

  kDebug() << "Begin creating code" << endl;

  Creator::XmlParserType pt;
  if ( args->isSet( "custom-parser" ) ) {
    pt = Creator::XmlParserCustomExternal;
  } else if ( args->isSet( "external-parser" ) ) {
    pt = Creator::XmlParserDomExternal;
  } else {
    pt = Creator::XmlParserDom;
  }

  Creator c( schemaDocument, pt );

  kDebug() << "Create classes" << endl;
  foreach( Schema::Element e, schemaDocument.usedElements() ) {
    c.createClass( e );
  }
  kDebug() << "Create parser" << endl;
  Schema::Element startElement = schemaDocument.startElement();
  c.setExternalClassPrefix( c.upperFirst( startElement.name() ) );
  c.createFileParser( startElement );
  c.createFileWriter( startElement, dtdFilename.replace( "rng", "dtd" ) );

  c.createListTypedefs();

  kDebug() << "Begin printing code" << endl;

  KODE::File &f = c.file();

  f.setFilename( baseName );

  KODE::Printer printer;
  printer.setCreationWarning( true );
  printer.setGenerator( aboutData.appName() );
  printer.setOutputDirectory( baseDir );
  printer.setSourceFile( args->url( 0 ).fileName() );

  c.printFiles( printer );

  kDebug() << "Finished." << endl;
}
<|endoftext|>


<commit_before>//===- InstructionSimplify.cpp - Fold instruction operands ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements routines for folding instructions into simpler forms
// that do not require creating new instructions.  For example, this does
// constant folding, and can handle identities like (X&0)->0.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Instructions.h"
#include "llvm/Support/PatternMatch.h"
using namespace llvm;
using namespace llvm::PatternMatch;

/// SimplifyAndInst - Given operands for an And, see if we can
/// fold the result.  If not, this returns null.
Value *llvm::SimplifyAndInst(Value *Op0, Value *Op1,
                             const TargetData *TD) {
  if (Constant *CLHS = dyn_cast<Constant>(Op0)) {
    if (Constant *CRHS = dyn_cast<Constant>(Op1)) {
      Constant *Ops[] = { CLHS, CRHS };
      return ConstantFoldInstOperands(Instruction::And, CLHS->getType(),
                                      Ops, 2, TD);
    }

    // Canonicalize the constant to the RHS.
    std::swap(Op0, Op1);
  }

  // X & undef -> 0
  if (isa<UndefValue>(Op1))
    return Constant::getNullValue(Op0->getType());

  // X & X = X
  if (Op0 == Op1)
    return Op0;

  // X & <0,0> = <0,0>
  if (isa<ConstantAggregateZero>(Op1))
    return Op1;

  // X & <-1,-1> = X
  if (ConstantVector *CP = dyn_cast<ConstantVector>(Op1))
    if (CP->isAllOnesValue())
      return Op0;

  if (ConstantInt *Op1CI = dyn_cast<ConstantInt>(Op1)) {
    // X & 0 = 0
    if (Op1CI->isZero())
      return Op1CI;
    // X & -1 = X
    if (Op1CI->isAllOnesValue())
      return Op0;
  }

  // A & ~A  =  ~A & A  =  0
  Value *A, *B;
  if (match(Op0, m_Not(m_Value(A)) && A == Op1) ||
      match(Op1, m_Not(m_Value(A)) && A == Op0))
    return Constant::getNullValue(Op0->getType());

  // (A | ?) & A = A
  if (match(Op0, m_Or(m_Value(A), m_Value(B))) &&
      (A == Op1 || B == Op1))
    return Op1;

  // A & (A | ?) = A
  if (match(Op1, m_Or(m_Value(A), m_Value(B))) &&
      (A == Op0 || B == Op0))
    return Op0;

  return 0;
}

/// SimplifyOrInst - Given operands for an Or, see if we can
/// fold the result.  If not, this returns null.
Value *llvm::SimplifyOrInst(Value *Op0, Value *Op1,
                            const TargetData *TD) {
  if (Constant *CLHS = dyn_cast<Constant>(Op0)) {
    if (Constant *CRHS = dyn_cast<Constant>(Op1)) {
      Constant *Ops[] = { CLHS, CRHS };
      return ConstantFoldInstOperands(Instruction::Or, CLHS->getType(),
                                      Ops, 2, TD);
    }

    // Canonicalize the constant to the RHS.
    std::swap(Op0, Op1);
  }

  // X | undef -> -1
  if (isa<UndefValue>(Op1))
    return Constant::getAllOnesValue(Op0->getType());

  // X | X = X
  if (Op0 == Op1)
    return Op0;

  // X | <0,0> = X
  if (isa<ConstantAggregateZero>(Op1))
    return Op0;

  // X | <-1,-1> = <-1,-1>
  if (ConstantVector *CP = dyn_cast<ConstantVector>(Op1))
    if (CP->isAllOnesValue())
      return Op1;

  if (ConstantInt *Op1CI = dyn_cast<ConstantInt>(Op1)) {
    // X | 0 = X
    if (Op1CI->isZero())
      return Op0;
    // X | -1 = -1
    if (Op1CI->isAllOnesValue())
      return Op1CI;
  }

  // A | ~A  =  ~A | A  =  -1
  Value *A, *B;
  if (match(Op0, m_Not(m_Value(A)) && A == Op1) ||
      match(Op1, m_Not(m_Value(A)) && A == Op0))
    return Constant::getAllOnesValue(Op0->getType());

  // (A & ?) | A = A
  if (match(Op0, m_And(m_Value(A), m_Value(B))) &&
      (A == Op1 || B == Op1))
    return Op1;

  // A | (A & ?) = A
  if (match(Op1, m_And(m_Value(A), m_Value(B))) &&
      (A == Op0 || B == Op0))
    return Op0;

  return 0;
}

static const Type *GetCompareTy(Value *Op) {
  return CmpInst::makeCmpResultType(Op->getType());
}

/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
/// fold the result.  If not, this returns null.
Value *llvm::SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
                              const TargetData *TD) {
  CmpInst::Predicate Pred = (CmpInst::Predicate)Predicate;
  assert(CmpInst::isIntPredicate(Pred) && "Not an integer compare!");

  if (Constant *CLHS = dyn_cast<Constant>(LHS)) {
    if (Constant *CRHS = dyn_cast<Constant>(RHS))
      return ConstantFoldCompareInstOperands(Pred, CLHS, CRHS, TD);

    // If we have a constant, make sure it is on the RHS.
    std::swap(LHS, RHS);
    Pred = CmpInst::getSwappedPredicate(Pred);
  }

  // ITy - This is the return type of the compare we're considering.
  const Type *ITy = GetCompareTy(LHS);

  // icmp X, X -> true/false
  if (LHS == RHS)
    return ConstantInt::get(ITy, CmpInst::isTrueWhenEqual(Pred));

  if (isa<UndefValue>(RHS))                  // X icmp undef -> undef
    return UndefValue::get(ITy);

  // icmp <global/alloca*/null>, <global/alloca*/null> - Global/Stack value
  // addresses never equal each other!  We already know that Op0 != Op1.
  if ((isa<GlobalValue>(LHS) || isa<AllocaInst>(LHS) ||
       isa<ConstantPointerNull>(LHS)) &&
      (isa<GlobalValue>(RHS) || isa<AllocaInst>(RHS) ||
       isa<ConstantPointerNull>(RHS)))
    return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred));

  // See if we are doing a comparison with a constant.
  if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
    // If we have an icmp le or icmp ge instruction, turn it into the
    // appropriate icmp lt or icmp gt instruction.  This allows us to rely on
    // them being folded in the code below.
    switch (Pred) {
    default: break;
    case ICmpInst::ICMP_ULE:
      if (CI->isMaxValue(false))                 // A <=u MAX -> TRUE
        return ConstantInt::getTrue(CI->getContext());
      break;
    case ICmpInst::ICMP_SLE:
      if (CI->isMaxValue(true))                  // A <=s MAX -> TRUE
        return ConstantInt::getTrue(CI->getContext());
      break;
    case ICmpInst::ICMP_UGE:
      if (CI->isMinValue(false))                 // A >=u MIN -> TRUE
        return ConstantInt::getTrue(CI->getContext());
      break;
    case ICmpInst::ICMP_SGE:
      if (CI->isMinValue(true))                  // A >=s MIN -> TRUE
        return ConstantInt::getTrue(CI->getContext());
      break;
    }
  }

  return 0;
}

/// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can
/// fold the result.  If not, this returns null.
Value *llvm::SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
                              const TargetData *TD) {
  CmpInst::Predicate Pred = (CmpInst::Predicate)Predicate;
  assert(CmpInst::isFPPredicate(Pred) && "Not an FP compare!");

  if (Constant *CLHS = dyn_cast<Constant>(LHS)) {
    if (Constant *CRHS = dyn_cast<Constant>(RHS))
      return ConstantFoldCompareInstOperands(Pred, CLHS, CRHS, TD);

    // If we have a constant, make sure it is on the RHS.
    std::swap(LHS, RHS);
    Pred = CmpInst::getSwappedPredicate(Pred);
  }

  // Fold trivial predicates.
  if (Pred == FCmpInst::FCMP_FALSE)
    return ConstantInt::get(GetCompareTy(LHS), 0);
  if (Pred == FCmpInst::FCMP_TRUE)
    return ConstantInt::get(GetCompareTy(LHS), 1);

  if (isa<UndefValue>(RHS))                  // fcmp pred X, undef -> undef
    return UndefValue::get(GetCompareTy(LHS));

  // fcmp x,x -> true/false.  Not all compares are foldable.
  if (LHS == RHS) {
    if (CmpInst::isTrueWhenEqual(Pred))
      return ConstantInt::get(GetCompareTy(LHS), 1);
    if (CmpInst::isFalseWhenEqual(Pred))
      return ConstantInt::get(GetCompareTy(LHS), 0);
  }

  // Handle fcmp with constant RHS
  if (Constant *RHSC = dyn_cast<Constant>(RHS)) {
    // If the constant is a nan, see if we can fold the comparison based on it.
    if (ConstantFP *CFP = dyn_cast<ConstantFP>(RHSC)) {
      if (CFP->getValueAPF().isNaN()) {
        if (FCmpInst::isOrdered(Pred))   // True "if ordered and foo"
          return ConstantInt::getFalse(CFP->getContext());
        assert(FCmpInst::isUnordered(Pred) &&
               "Comparison must be either ordered or unordered!");
        // True if unordered.
        return ConstantInt::getTrue(CFP->getContext());
      }
    }
  }

  return 0;
}

//=== Helper functions for higher up the class hierarchy.

/// SimplifyBinOp - Given operands for a BinaryOperator, see if we can
/// fold the result.  If not, this returns null.
Value *llvm::SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
                           const TargetData *TD) {
  switch (Opcode) {
  case Instruction::And: return SimplifyAndInst(LHS, RHS, TD);
  case Instruction::Or:  return SimplifyOrInst(LHS, RHS, TD);
  default:
    if (Constant *CLHS = dyn_cast<Constant>(LHS))
      if (Constant *CRHS = dyn_cast<Constant>(RHS)) {
        Constant *COps[] = {CLHS, CRHS};
        return ConstantFoldInstOperands(Opcode, LHS->getType(), COps, 2, TD);
      }
    return 0;
  }
}

/// SimplifyCmpInst - Given operands for a CmpInst, see if we can
/// fold the result.
Value *llvm::SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
                             const TargetData *TD) {
  if (CmpInst::isIntPredicate((CmpInst::Predicate)Predicate))
    return SimplifyICmpInst(Predicate, LHS, RHS, TD);
  return SimplifyFCmpInst(Predicate, LHS, RHS, TD);
}

/// SimplifyInstruction - See if we can compute a simplified version of this
/// instruction.  If not, this returns null.
Value *llvm::SimplifyInstruction(Instruction *I, const TargetData *TD) {
  switch (I->getOpcode()) {
  default:
    return ConstantFoldInstruction(I, TD);
  case Instruction::And:
    return SimplifyAndInst(I->getOperand(0), I->getOperand(1), TD);
  case Instruction::Or:
    return SimplifyOrInst(I->getOperand(0), I->getOperand(1), TD);
  case Instruction::ICmp:
    return SimplifyICmpInst(cast<ICmpInst>(I)->getPredicate(),
                            I->getOperand(0), I->getOperand(1), TD);
  case Instruction::FCmp:
    return SimplifyFCmpInst(cast<FCmpInst>(I)->getPredicate(),
                            I->getOperand(0), I->getOperand(1), TD);
  }
}

<commit_msg>I misread the parens, not so redundant after all.<commit_after>//===- InstructionSimplify.cpp - Fold instruction operands ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements routines for folding instructions into simpler forms
// that do not require creating new instructions.  For example, this does
// constant folding, and can handle identities like (X&0)->0.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Instructions.h"
#include "llvm/Support/PatternMatch.h"
using namespace llvm;
using namespace llvm::PatternMatch;

/// SimplifyAndInst - Given operands for an And, see if we can
/// fold the result.  If not, this returns null.
Value *llvm::SimplifyAndInst(Value *Op0, Value *Op1,
                             const TargetData *TD) {
  if (Constant *CLHS = dyn_cast<Constant>(Op0)) {
    if (Constant *CRHS = dyn_cast<Constant>(Op1)) {
      Constant *Ops[] = { CLHS, CRHS };
      return ConstantFoldInstOperands(Instruction::And, CLHS->getType(),
                                      Ops, 2, TD);
    }

    // Canonicalize the constant to the RHS.
    std::swap(Op0, Op1);
  }

  // X & undef -> 0
  if (isa<UndefValue>(Op1))
    return Constant::getNullValue(Op0->getType());

  // X & X = X
  if (Op0 == Op1)
    return Op0;

  // X & <0,0> = <0,0>
  if (isa<ConstantAggregateZero>(Op1))
    return Op1;

  // X & <-1,-1> = X
  if (ConstantVector *CP = dyn_cast<ConstantVector>(Op1))
    if (CP->isAllOnesValue())
      return Op0;

  if (ConstantInt *Op1CI = dyn_cast<ConstantInt>(Op1)) {
    // X & 0 = 0
    if (Op1CI->isZero())
      return Op1CI;
    // X & -1 = X
    if (Op1CI->isAllOnesValue())
      return Op0;
  }

  // A & ~A  =  ~A & A  =  0
  Value *A, *B;
  if ((match(Op0, m_Not(m_Value(A))) && A == Op1) ||
      (match(Op1, m_Not(m_Value(A))) && A == Op0))
    return Constant::getNullValue(Op0->getType());

  // (A | ?) & A = A
  if (match(Op0, m_Or(m_Value(A), m_Value(B))) &&
      (A == Op1 || B == Op1))
    return Op1;

  // A & (A | ?) = A
  if (match(Op1, m_Or(m_Value(A), m_Value(B))) &&
      (A == Op0 || B == Op0))
    return Op0;

  return 0;
}

/// SimplifyOrInst - Given operands for an Or, see if we can
/// fold the result.  If not, this returns null.
Value *llvm::SimplifyOrInst(Value *Op0, Value *Op1,
                            const TargetData *TD) {
  if (Constant *CLHS = dyn_cast<Constant>(Op0)) {
    if (Constant *CRHS = dyn_cast<Constant>(Op1)) {
      Constant *Ops[] = { CLHS, CRHS };
      return ConstantFoldInstOperands(Instruction::Or, CLHS->getType(),
                                      Ops, 2, TD);
    }

    // Canonicalize the constant to the RHS.
    std::swap(Op0, Op1);
  }

  // X | undef -> -1
  if (isa<UndefValue>(Op1))
    return Constant::getAllOnesValue(Op0->getType());

  // X | X = X
  if (Op0 == Op1)
    return Op0;

  // X | <0,0> = X
  if (isa<ConstantAggregateZero>(Op1))
    return Op0;

  // X | <-1,-1> = <-1,-1>
  if (ConstantVector *CP = dyn_cast<ConstantVector>(Op1))
    if (CP->isAllOnesValue())
      return Op1;

  if (ConstantInt *Op1CI = dyn_cast<ConstantInt>(Op1)) {
    // X | 0 = X
    if (Op1CI->isZero())
      return Op0;
    // X | -1 = -1
    if (Op1CI->isAllOnesValue())
      return Op1CI;
  }

  // A | ~A  =  ~A | A  =  -1
  Value *A, *B;
  if ((match(Op0, m_Not(m_Value(A))) && A == Op1) ||
      (match(Op1, m_Not(m_Value(A))) && A == Op0))
    return Constant::getAllOnesValue(Op0->getType());

  // (A & ?) | A = A
  if (match(Op0, m_And(m_Value(A), m_Value(B))) &&
      (A == Op1 || B == Op1))
    return Op1;

  // A | (A & ?) = A
  if (match(Op1, m_And(m_Value(A), m_Value(B))) &&
      (A == Op0 || B == Op0))
    return Op0;

  return 0;
}

static const Type *GetCompareTy(Value *Op) {
  return CmpInst::makeCmpResultType(Op->getType());
}

/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
/// fold the result.  If not, this returns null.
Value *llvm::SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
                              const TargetData *TD) {
  CmpInst::Predicate Pred = (CmpInst::Predicate)Predicate;
  assert(CmpInst::isIntPredicate(Pred) && "Not an integer compare!");

  if (Constant *CLHS = dyn_cast<Constant>(LHS)) {
    if (Constant *CRHS = dyn_cast<Constant>(RHS))
      return ConstantFoldCompareInstOperands(Pred, CLHS, CRHS, TD);

    // If we have a constant, make sure it is on the RHS.
    std::swap(LHS, RHS);
    Pred = CmpInst::getSwappedPredicate(Pred);
  }

  // ITy - This is the return type of the compare we're considering.
  const Type *ITy = GetCompareTy(LHS);

  // icmp X, X -> true/false
  if (LHS == RHS)
    return ConstantInt::get(ITy, CmpInst::isTrueWhenEqual(Pred));

  if (isa<UndefValue>(RHS))                  // X icmp undef -> undef
    return UndefValue::get(ITy);

  // icmp <global/alloca*/null>, <global/alloca*/null> - Global/Stack value
  // addresses never equal each other!  We already know that Op0 != Op1.
  if ((isa<GlobalValue>(LHS) || isa<AllocaInst>(LHS) ||
       isa<ConstantPointerNull>(LHS)) &&
      (isa<GlobalValue>(RHS) || isa<AllocaInst>(RHS) ||
       isa<ConstantPointerNull>(RHS)))
    return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred));

  // See if we are doing a comparison with a constant.
  if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
    // If we have an icmp le or icmp ge instruction, turn it into the
    // appropriate icmp lt or icmp gt instruction.  This allows us to rely on
    // them being folded in the code below.
    switch (Pred) {
    default: break;
    case ICmpInst::ICMP_ULE:
      if (CI->isMaxValue(false))                 // A <=u MAX -> TRUE
        return ConstantInt::getTrue(CI->getContext());
      break;
    case ICmpInst::ICMP_SLE:
      if (CI->isMaxValue(true))                  // A <=s MAX -> TRUE
        return ConstantInt::getTrue(CI->getContext());
      break;
    case ICmpInst::ICMP_UGE:
      if (CI->isMinValue(false))                 // A >=u MIN -> TRUE
        return ConstantInt::getTrue(CI->getContext());
      break;
    case ICmpInst::ICMP_SGE:
      if (CI->isMinValue(true))                  // A >=s MIN -> TRUE
        return ConstantInt::getTrue(CI->getContext());
      break;
    }
  }

  return 0;
}

/// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can
/// fold the result.  If not, this returns null.
Value *llvm::SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
                              const TargetData *TD) {
  CmpInst::Predicate Pred = (CmpInst::Predicate)Predicate;
  assert(CmpInst::isFPPredicate(Pred) && "Not an FP compare!");

  if (Constant *CLHS = dyn_cast<Constant>(LHS)) {
    if (Constant *CRHS = dyn_cast<Constant>(RHS))
      return ConstantFoldCompareInstOperands(Pred, CLHS, CRHS, TD);

    // If we have a constant, make sure it is on the RHS.
    std::swap(LHS, RHS);
    Pred = CmpInst::getSwappedPredicate(Pred);
  }

  // Fold trivial predicates.
  if (Pred == FCmpInst::FCMP_FALSE)
    return ConstantInt::get(GetCompareTy(LHS), 0);
  if (Pred == FCmpInst::FCMP_TRUE)
    return ConstantInt::get(GetCompareTy(LHS), 1);

  if (isa<UndefValue>(RHS))                  // fcmp pred X, undef -> undef
    return UndefValue::get(GetCompareTy(LHS));

  // fcmp x,x -> true/false.  Not all compares are foldable.
  if (LHS == RHS) {
    if (CmpInst::isTrueWhenEqual(Pred))
      return ConstantInt::get(GetCompareTy(LHS), 1);
    if (CmpInst::isFalseWhenEqual(Pred))
      return ConstantInt::get(GetCompareTy(LHS), 0);
  }

  // Handle fcmp with constant RHS
  if (Constant *RHSC = dyn_cast<Constant>(RHS)) {
    // If the constant is a nan, see if we can fold the comparison based on it.
    if (ConstantFP *CFP = dyn_cast<ConstantFP>(RHSC)) {
      if (CFP->getValueAPF().isNaN()) {
        if (FCmpInst::isOrdered(Pred))   // True "if ordered and foo"
          return ConstantInt::getFalse(CFP->getContext());
        assert(FCmpInst::isUnordered(Pred) &&
               "Comparison must be either ordered or unordered!");
        // True if unordered.
        return ConstantInt::getTrue(CFP->getContext());
      }
    }
  }

  return 0;
}

//=== Helper functions for higher up the class hierarchy.

/// SimplifyBinOp - Given operands for a BinaryOperator, see if we can
/// fold the result.  If not, this returns null.
Value *llvm::SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
                           const TargetData *TD) {
  switch (Opcode) {
  case Instruction::And: return SimplifyAndInst(LHS, RHS, TD);
  case Instruction::Or:  return SimplifyOrInst(LHS, RHS, TD);
  default:
    if (Constant *CLHS = dyn_cast<Constant>(LHS))
      if (Constant *CRHS = dyn_cast<Constant>(RHS)) {
        Constant *COps[] = {CLHS, CRHS};
        return ConstantFoldInstOperands(Opcode, LHS->getType(), COps, 2, TD);
      }
    return 0;
  }
}

/// SimplifyCmpInst - Given operands for a CmpInst, see if we can
/// fold the result.
Value *llvm::SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
                             const TargetData *TD) {
  if (CmpInst::isIntPredicate((CmpInst::Predicate)Predicate))
    return SimplifyICmpInst(Predicate, LHS, RHS, TD);
  return SimplifyFCmpInst(Predicate, LHS, RHS, TD);
}

/// SimplifyInstruction - See if we can compute a simplified version of this
/// instruction.  If not, this returns null.
Value *llvm::SimplifyInstruction(Instruction *I, const TargetData *TD) {
  switch (I->getOpcode()) {
  default:
    return ConstantFoldInstruction(I, TD);
  case Instruction::And:
    return SimplifyAndInst(I->getOperand(0), I->getOperand(1), TD);
  case Instruction::Or:
    return SimplifyOrInst(I->getOperand(0), I->getOperand(1), TD);
  case Instruction::ICmp:
    return SimplifyICmpInst(cast<ICmpInst>(I)->getPredicate(),
                            I->getOperand(0), I->getOperand(1), TD);
  case Instruction::FCmp:
    return SimplifyFCmpInst(cast<FCmpInst>(I)->getPredicate(),
                            I->getOperand(0), I->getOperand(1), TD);
  }
}

<|endoftext|>


<commit_before>//===-- llvm/CodeGen/DwarfFile.cpp - Dwarf Debug Framework ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "DwarfFile.h"
#include "DwarfDebug.h"
#include "DwarfUnit.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Target/TargetLoweringObjectFile.h"

namespace llvm {
DwarfFile::DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA)
    : Asm(AP), StrPool(DA, *Asm, Pref) {}

DwarfFile::~DwarfFile() {}

// Define a unique number for the abbreviation.
//
DIEAbbrev &DwarfFile::assignAbbrevNumber(DIE &Die) {
  FoldingSetNodeID ID;
  DIEAbbrev Abbrev = Die.generateAbbrev();
  Abbrev.Profile(ID);

  void *InsertPos;
  if (DIEAbbrev *Existing =
          AbbreviationsSet.FindNodeOrInsertPos(ID, InsertPos)) {
    Die.setAbbrevNumber(Existing->getNumber());
    return *Existing;
  }

  // Move the abbreviation to the heap and assign a number.
  DIEAbbrev *New = new (AbbrevAllocator) DIEAbbrev(std::move(Abbrev));
  Abbreviations.push_back(New);
  New->setNumber(Abbreviations.size());
  Die.setAbbrevNumber(Abbreviations.size());

  // Store it for lookup.
  AbbreviationsSet.InsertNode(New, InsertPos);
  return *New;
}

void DwarfFile::addUnit(std::unique_ptr<DwarfUnit> U) {
  CUs.push_back(std::move(U));
}

// Emit the various dwarf units to the unit section USection with
// the abbreviations going into ASection.
void DwarfFile::emitUnits(bool UseOffsets) {
  for (const auto &TheU : CUs) {
    DIE &Die = TheU->getUnitDie();
    MCSection *USection = TheU->getSection();
    Asm->OutStreamer->SwitchSection(USection);

    TheU->emitHeader(UseOffsets);

    Asm->emitDwarfDIE(Die);
  }
}

// Compute the size and offset for each DIE.
void DwarfFile::computeSizeAndOffsets() {
  // Offset from the first CU in the debug info section is 0 initially.
  unsigned SecOffset = 0;

  // Iterate over each compile unit and set the size and offsets for each
  // DIE within each compile unit. All offsets are CU relative.
  for (const auto &TheU : CUs) {
    TheU->setDebugInfoOffset(SecOffset);

    // CU-relative offset is reset to 0 here.
    unsigned Offset = sizeof(int32_t) +      // Length of Unit Info
                      TheU->getHeaderSize(); // Unit-specific headers

    // EndOffset here is CU-relative, after laying out
    // all of the CU DIE.
    unsigned EndOffset = computeSizeAndOffset(TheU->getUnitDie(), Offset);
    SecOffset += EndOffset;
  }
}
// Compute the size and offset of a DIE. The offset is relative to start of the
// CU. It returns the offset after laying out the DIE.
unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
  // Record the abbreviation.
  const DIEAbbrev &Abbrev = assignAbbrevNumber(Die);

  // Set DIE offset
  Die.setOffset(Offset);

  // Start the size with the size of abbreviation code.
  Offset += getULEB128Size(Die.getAbbrevNumber());

  // Size the DIE attribute values.
  for (const auto &V : Die.values())
    // Size attribute value.
    Offset += V.SizeOf(Asm, V.getForm());

  // Get the children.
  const auto &Children = Die.getChildren();

  // Size the DIE children if any.
  if (!Children.empty()) {
    assert(Abbrev.hasChildren() && "Children flag not set");

    for (auto &Child : Children)
      Offset = computeSizeAndOffset(*Child, Offset);

    // End of children marker.
    Offset += sizeof(int8_t);
  }

  Die.setSize(Offset - Die.getOffset());
  return Offset;
}

void DwarfFile::emitAbbrevs(MCSection *Section) {
  // Check to see if it is worth the effort.
  if (!Abbreviations.empty()) {
    // Start the debug abbrev section.
    Asm->OutStreamer->SwitchSection(Section);
    Asm->emitDwarfAbbrevs(Abbreviations);
  }
}

// Emit strings into a string section.
void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection) {
  StrPool.emit(*Asm, StrSection, OffsetSection);
}

bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
  SmallVectorImpl<DbgVariable *> &Vars = ScopeVariables[LS];
  const DILocalVariable *DV = Var->getVariable();
  // Variables with positive arg numbers are parameters.
  if (unsigned ArgNum = DV->getArg()) {
    // Keep all parameters in order at the start of the variable list to ensure
    // function types are correct (no out-of-order parameters)
    //
    // This could be improved by only doing it for optimized builds (unoptimized
    // builds have the right order to begin with), searching from the back (this
    // would catch the unoptimized case quickly), or doing a binary search
    // rather than linear search.
    auto I = Vars.begin();
    while (I != Vars.end()) {
      unsigned CurNum = (*I)->getVariable()->getArg();
      // A local (non-parameter) variable has been found, insert immediately
      // before it.
      if (CurNum == 0)
        break;
      // A later indexed parameter has been found, insert immediately before it.
      if (CurNum > ArgNum)
        break;
      if (CurNum == ArgNum) {
        (*I)->addMMIEntry(*Var);
        return false;
      }
      ++I;
    }
    Vars.insert(I, Var);
    return true;
  }

  Vars.push_back(Var);
  return true;
}
}
<commit_msg>AsmPrinter: Avoid a warning in NDEBUG, NFC<commit_after>//===-- llvm/CodeGen/DwarfFile.cpp - Dwarf Debug Framework ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "DwarfFile.h"
#include "DwarfDebug.h"
#include "DwarfUnit.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Target/TargetLoweringObjectFile.h"

namespace llvm {
DwarfFile::DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA)
    : Asm(AP), StrPool(DA, *Asm, Pref) {}

DwarfFile::~DwarfFile() {}

// Define a unique number for the abbreviation.
//
DIEAbbrev &DwarfFile::assignAbbrevNumber(DIE &Die) {
  FoldingSetNodeID ID;
  DIEAbbrev Abbrev = Die.generateAbbrev();
  Abbrev.Profile(ID);

  void *InsertPos;
  if (DIEAbbrev *Existing =
          AbbreviationsSet.FindNodeOrInsertPos(ID, InsertPos)) {
    Die.setAbbrevNumber(Existing->getNumber());
    return *Existing;
  }

  // Move the abbreviation to the heap and assign a number.
  DIEAbbrev *New = new (AbbrevAllocator) DIEAbbrev(std::move(Abbrev));
  Abbreviations.push_back(New);
  New->setNumber(Abbreviations.size());
  Die.setAbbrevNumber(Abbreviations.size());

  // Store it for lookup.
  AbbreviationsSet.InsertNode(New, InsertPos);
  return *New;
}

void DwarfFile::addUnit(std::unique_ptr<DwarfUnit> U) {
  CUs.push_back(std::move(U));
}

// Emit the various dwarf units to the unit section USection with
// the abbreviations going into ASection.
void DwarfFile::emitUnits(bool UseOffsets) {
  for (const auto &TheU : CUs) {
    DIE &Die = TheU->getUnitDie();
    MCSection *USection = TheU->getSection();
    Asm->OutStreamer->SwitchSection(USection);

    TheU->emitHeader(UseOffsets);

    Asm->emitDwarfDIE(Die);
  }
}

// Compute the size and offset for each DIE.
void DwarfFile::computeSizeAndOffsets() {
  // Offset from the first CU in the debug info section is 0 initially.
  unsigned SecOffset = 0;

  // Iterate over each compile unit and set the size and offsets for each
  // DIE within each compile unit. All offsets are CU relative.
  for (const auto &TheU : CUs) {
    TheU->setDebugInfoOffset(SecOffset);

    // CU-relative offset is reset to 0 here.
    unsigned Offset = sizeof(int32_t) +      // Length of Unit Info
                      TheU->getHeaderSize(); // Unit-specific headers

    // EndOffset here is CU-relative, after laying out
    // all of the CU DIE.
    unsigned EndOffset = computeSizeAndOffset(TheU->getUnitDie(), Offset);
    SecOffset += EndOffset;
  }
}
// Compute the size and offset of a DIE. The offset is relative to start of the
// CU. It returns the offset after laying out the DIE.
unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
  // Record the abbreviation.
  const DIEAbbrev &Abbrev = assignAbbrevNumber(Die);

  // Set DIE offset
  Die.setOffset(Offset);

  // Start the size with the size of abbreviation code.
  Offset += getULEB128Size(Die.getAbbrevNumber());

  // Size the DIE attribute values.
  for (const auto &V : Die.values())
    // Size attribute value.
    Offset += V.SizeOf(Asm, V.getForm());

  // Get the children.
  const auto &Children = Die.getChildren();

  // Size the DIE children if any.
  if (!Children.empty()) {
    (void)Abbrev;
    assert(Abbrev.hasChildren() && "Children flag not set");

    for (auto &Child : Children)
      Offset = computeSizeAndOffset(*Child, Offset);

    // End of children marker.
    Offset += sizeof(int8_t);
  }

  Die.setSize(Offset - Die.getOffset());
  return Offset;
}

void DwarfFile::emitAbbrevs(MCSection *Section) {
  // Check to see if it is worth the effort.
  if (!Abbreviations.empty()) {
    // Start the debug abbrev section.
    Asm->OutStreamer->SwitchSection(Section);
    Asm->emitDwarfAbbrevs(Abbreviations);
  }
}

// Emit strings into a string section.
void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection) {
  StrPool.emit(*Asm, StrSection, OffsetSection);
}

bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
  SmallVectorImpl<DbgVariable *> &Vars = ScopeVariables[LS];
  const DILocalVariable *DV = Var->getVariable();
  // Variables with positive arg numbers are parameters.
  if (unsigned ArgNum = DV->getArg()) {
    // Keep all parameters in order at the start of the variable list to ensure
    // function types are correct (no out-of-order parameters)
    //
    // This could be improved by only doing it for optimized builds (unoptimized
    // builds have the right order to begin with), searching from the back (this
    // would catch the unoptimized case quickly), or doing a binary search
    // rather than linear search.
    auto I = Vars.begin();
    while (I != Vars.end()) {
      unsigned CurNum = (*I)->getVariable()->getArg();
      // A local (non-parameter) variable has been found, insert immediately
      // before it.
      if (CurNum == 0)
        break;
      // A later indexed parameter has been found, insert immediately before it.
      if (CurNum > ArgNum)
        break;
      if (CurNum == ArgNum) {
        (*I)->addMMIEntry(*Var);
        return false;
      }
      ++I;
    }
    Vars.insert(I, Var);
    return true;
  }

  Vars.push_back(Var);
  return true;
}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#ifndef __ARCH_SPARC_UTILITY_HH__
#define __ARCH_SPARC_UTILITY_HH__

#include "arch/sparc/faults.hh"
#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/registers.hh"
#include "arch/sparc/tlb.hh"
#include "base/misc.hh"
#include "base/bitfield.hh"
#include "cpu/thread_context.hh"

namespace SparcISA
{

    uint64_t getArgument(ThreadContext *tc, int number, bool fp);

    static inline bool
    inUserMode(ThreadContext *tc)
    {
        return !((tc->readMiscRegNoEffect(MISCREG_PSTATE) & (1 << 2)) ||
                 (tc->readMiscRegNoEffect(MISCREG_HPSTATE) & (1 << 2)));
    }

    inline bool isCallerSaveIntegerRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    inline bool isCalleeSaveIntegerRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    inline bool isCallerSaveFloatRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    inline bool isCalleeSaveFloatRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    // Instruction address compression hooks
    inline Addr realPCToFetchPC(const Addr &addr)
    {
        return addr;
    }

    inline Addr fetchPCToRealPC(const Addr &addr)
    {
        return addr;
    }

    // the size of "fetched" instructions (not necessarily the size
    // of real instructions for PISA)
    inline size_t fetchInstSize()
    {
        return sizeof(MachInst);
    }

    /**
     * Function to insure ISA semantics about 0 registers.
     * @param tc The thread context.
     */
    template <class TC>
    void zeroRegisters(TC *tc);

    inline void initCPU(ThreadContext *tc, int cpuId)
    {
        static Fault por = new PowerOnReset();
        if (cpuId == 0)
            por->invoke(tc);

    }

    inline void startupCPU(ThreadContext *tc, int cpuId)
    {
#if FULL_SYSTEM
        // Other CPUs will get activated by IPIs
        if (cpuId == 0)
            tc->activate(0);
#else
        tc->activate(0);
#endif
    }

    void copyRegs(ThreadContext *src, ThreadContext *dest);

    void copyMiscRegs(ThreadContext *src, ThreadContext *dest);

} // namespace SparcISA

#endif
<commit_msg>SPARC: Fix some style issues in utility.hh.<commit_after>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#ifndef __ARCH_SPARC_UTILITY_HH__
#define __ARCH_SPARC_UTILITY_HH__

#include "arch/sparc/faults.hh"
#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/registers.hh"
#include "arch/sparc/tlb.hh"
#include "base/misc.hh"
#include "base/bitfield.hh"
#include "cpu/thread_context.hh"

namespace SparcISA
{
    uint64_t getArgument(ThreadContext *tc, int number, bool fp);

    static inline bool
    inUserMode(ThreadContext *tc)
    {
        return !((tc->readMiscRegNoEffect(MISCREG_PSTATE) & (1 << 2)) ||
                 (tc->readMiscRegNoEffect(MISCREG_HPSTATE) & (1 << 2)));
    }

    inline bool isCallerSaveIntegerRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    inline bool isCalleeSaveIntegerRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    inline bool isCallerSaveFloatRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    inline bool isCalleeSaveFloatRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    // Instruction address compression hooks
    inline Addr realPCToFetchPC(const Addr &addr)
    {
        return addr;
    }

    inline Addr fetchPCToRealPC(const Addr &addr)
    {
        return addr;
    }

    // the size of "fetched" instructions (not necessarily the size
    // of real instructions for PISA)
    inline size_t fetchInstSize()
    {
        return sizeof(MachInst);
    }

    /**
     * Function to insure ISA semantics about 0 registers.
     * @param tc The thread context.
     */
    template <class TC>
    void zeroRegisters(TC *tc);

    inline void
    initCPU(ThreadContext *tc, int cpuId)
    {
        static Fault por = new PowerOnReset();
        if (cpuId == 0)
            por->invoke(tc);

    }

    inline void
    startupCPU(ThreadContext *tc, int cpuId)
    {
#if FULL_SYSTEM
        // Other CPUs will get activated by IPIs
        if (cpuId == 0)
            tc->activate(0);
#else
        tc->activate(0);
#endif
    }

    void copyRegs(ThreadContext *src, ThreadContext *dest);

    void copyMiscRegs(ThreadContext *src, ThreadContext *dest);

} // namespace SparcISA

#endif
<|endoftext|>