//==- StateVariant.h - Variant to wrap generated analysis states --*- C++ -*-=//
//
//                     The LLVM Compiler Infrastructure
//
//        This file is distributed under the University of Illinois 
//        Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the template class StateVariant, which serves to wrap
//  states that are generated by transfer functions.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_ANALYSIS_PS_STATEVARIANT
#define LLVM_CLANG_ANALYSIS_PS_STATEVARIANT

namespace clang {

template<typename StateTy>
class StateVariant {
  enum VariantFlag { Infeasible, ImpotentStmt, HasState };  
  StateTy* State;
  VariantFlag Flag;  

  explicit StateVariant(StateTy* state, VariantFlag f) : State(state), Flag(f){}
  
public:
  StateVariant(StateTy* state) : State(state), Flag(HasState) {}
  
  bool isInfeasible() const { return Flag == Infeasible; }
  bool isStmtImpotent() const { return Flag == ImpotentStmt; }
  
  StateTy* getState() const {
    assert (!isInfeasible());
    return State;
  }  
  
  // Factory methods to create states indicating infeasible paths or that
  // a statement can never modify the program state (from the perspective of
  // the analysis).  
  static inline StateVariant DenoteInfeasiblePath(StateTy* state = NULL) {
    return StateVariant(state,Infeasible);
  }
  
  static inline StateVariant DenoteImpotentStmt(StateTy* state) {
    return StateVariant(state,ImpotentStmt);
  }
};
  
} // end clang namespace

#endif
