#include <llvm/Function.h>
#include <llvm/Pass.h>

#include <string>

using namespace std;

class Base : public FunctionPass {
public:
  virtual const string& name() const = 0;

  virtual bool runOnFunction(Function& F) {
    cerr << "Hello from " << name() << ": " << F.getName() << '\n';
    return false;
  }

  virtual void getAnalysisUsage(AnalysisUsage& AU) const {
    AU.preservesAll();
  }
};

class A : public Base {
public:
  virtual const string& name() const
  { static string a("A"); return a; }
};

static RegisterOpt<A> reg_a("opt-a","");

class B : public Base {
public:
  virtual const string& name() const
  { static string a("B"); return a; }
};

static RegisterOpt<B> reg_b("opt-b","");

class C : public Base {
public:
  virtual const string& name() const
  { static string a("C"); return a; }

  virtual void getAnalysisUsage(AnalysisUsage& AU) const {
    Base::getAnalysisUsage(AU);

    AU.addRequired<A>();
    AU.addRequired<B>();
  }
};

static RegisterOpt<C> reg_c("opt-c","");
