Index: include/clang/ASTProcessing/ArtificialIdentifierPolicy.h
===================================================================
--- include/clang/ASTProcessing/ArtificialIdentifierPolicy.h	(revision 0)
+++ include/clang/ASTProcessing/ArtificialIdentifierPolicy.h	(revision 0)
@@ -0,0 +1,59 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASTPROCESSING_ARTIFICIALIDENTIFIERPOLICY_H
+#define LLVM_CLANG_ASTPROCESSING_ARTIFICIALIDENTIFIERPOLICY_H
+
+#include <string>
+#include <sstream>
+
+//--------------------------------------------------------- 
+namespace clang {
+
+//--------------------------------------------------------- forwards
+class ASTContext;
+class IdentifierInfo;
+class LabelStmt;
+class NamedDecl;
+
+//--------------------------------------------------------- 
+class ArtificialIdentifierPolicy
+{
+public:
+  std::string LabelPrefix, LabelAlternate, LabelSuffix;
+  std::string VarPrefix, VarAlternate, VarSuffix;
+
+  // if set and a original variable is given, the result is Prefix_VarName_PostFix_Count (without underscores)
+  // otherwise the result is VarAlternate_Count (without underscores)
+  unsigned UseOriginalLabelName : 1;
+
+  // if set and a original label is given, the result is Prefix_LabelName_PostFix_Count (without underscores)
+  // otherwise the result is LabelAlternate_Count (without underscores)
+  unsigned UseOriginalVarName : 1;
+
+  // initializes all suffix with commonSuffix, all alternates with "art_" + commonSuffix, 
+  // leaves prefix empty and uses original names, when possible:
+  explicit ArtificialIdentifierPolicy(const std::string& commonSuffix);
+
+  // the pointers may be 0 meaning there is no appropriate original variable 
+  IdentifierInfo *createVariable(ASTContext& Ctx, const NamedDecl* originalVar);
+  IdentifierInfo *createLabel(ASTContext& Ctx, const LabelStmt* originalLabel);
+
+private:
+  IdentifierInfo *createInfo(ASTContext& Ctx, std::stringstream& nameStream);
+};
+
+//--------------------------------------------------------- 
+} // namespace clang
+
+#endif  //LLVM_CLANG_ASTPROCESSING_ARTIFICIALIDENTIFIERGENERATOR_H
Index: include/clang/ASTProcessing/Inline.h
===================================================================
--- include/clang/ASTProcessing/Inline.h	(revision 0)
+++ include/clang/ASTProcessing/Inline.h	(revision 0)
@@ -0,0 +1,39 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASTPROCESSING_INLINE_H
+#define LLVM_CLANG_ASTPROCESSING_INLINE_H
+
+#include <functional>
+
+//--------------------------------------------------------- 
+namespace clang {
+
+//--------------------------------------------------------- forwards
+class Stmt;
+class Expr;
+class StmtEditor;
+
+//--------------------------------------------------------- 
+namespace ASTProcessing {
+
+// inlines all inlineable function calls in Node
+// precondition: Node is a child of the stmt tree hold by StmtEditor
+void doInline(StmtEditor& editor, Stmt* Node);
+
+//--------------------------------------------------------- 
+} // namespace ASTProcessing
+
+} // namespace clang
+
+#endif  //LLVM_CLANG_ASTPROCESSING_INLINE_H
Index: include/clang/ASTProcessing/InvariantIf.h
===================================================================
--- include/clang/ASTProcessing/InvariantIf.h	(revision 0)
+++ include/clang/ASTProcessing/InvariantIf.h	(revision 0)
@@ -0,0 +1,55 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASTPROCESSING_INVARIANTIF_H
+#define LLVM_CLANG_ASTPROCESSING_INVARIANTIF_H
+
+//--------------------------------------------------------- 
+namespace clang {
+
+//--------------------------------------------------------- forwards
+class Stmt;
+class StmtEditor;
+
+//--------------------------------------------------------- 
+namespace ASTProcessing {
+
+// searches all for stmts in Node for invariant if's
+// (that is the condition does't change due to the loop)
+// invariant if's are then moved outside the loop and the 
+// loop is duplicated with the 'then' and 'else' part
+// in the two loops:
+// for(stmt, expr, expr)
+//   if (invariant)
+//     stmt1;
+//   else
+//     stmt2;
+
+// becomes:
+
+// if (invariant)
+//   for(stmt, expr, expr)
+//     stmt1;
+// else
+//   for(stmt, expr, expr)
+//     stmt2;
+
+// precondition: Node is a child of the stmt tree hold by StmtEditor
+void splitInvariantIfs(StmtEditor& editor, Stmt* Node);
+
+//--------------------------------------------------------- 
+} // namespace ASTProcessing
+
+} // namespace clang
+
+#endif  //LLVM_CLANG_ASTPROCESSING_INVARIANTIF_H
Index: include/clang/ASTProcessing/ParentInfo.h
===================================================================
--- include/clang/ASTProcessing/ParentInfo.h	(revision 0)
+++ include/clang/ASTProcessing/ParentInfo.h	(revision 0)
@@ -0,0 +1,52 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASTPROCESSING_PARENTINFO_H
+#define LLVM_CLANG_ASTPROCESSING_PARENTINFO_H
+
+#include "clang/AST/ParentMap.h"
+
+//--------------------------------------------------------- 
+namespace clang {
+
+class ParentInfo
+{
+public:
+  ParentInfo(Stmt* root);
+  void updateParentMap(Stmt* S);    // adds and/or updates the parent/child-relations of the stmt tree of S
+
+  // postconditon: result != 0
+  Stmt* getParent(Stmt* s) const;
+
+  // postconditon: result != 0 
+  Expr* getFullExpression(Expr* subexpr) const;
+
+  // what is the statement containing an expression:
+  // if in a ReturnStmt or IndirectGotoStmt it's that ReturnStmt or IndirectGotoStmt
+  // if it's the expr in "case expr: body;" it's that  CaseStmt
+  // if it's in a DeclStmt, which is part of for(init;;), while(cond), switch(cond), if(cond), it's the appropriate For/While/Do/Switch/IfStmt
+  // if it's in a other DeclStmt, it's that DeclStmt
+  // otherwise it's the full expression
+  // postconditon: (fullexpr == result || parent(fullexpr) == result || (parent(parent(fullexpr)) == result && isa<DeclStmt>(parent(fullexpr)))
+  Stmt* getStatementOfExpression(Expr* subexpr) const;
+
+private:
+  Stmt* getStatementOfStmtWhereDeclIsAllowed(Stmt* result, Stmt* parent) const;
+
+  ParentMap m_ParentMap;           
+};
+
+//--------------------------------------------------------- 
+} // namespace clang
+
+#endif  //LLVM_CLANG_ASTPROCESSING_PARENTINFO_H
Index: include/clang/ASTProcessing/ReplaceExprWithStmt.h
===================================================================
--- include/clang/ASTProcessing/ReplaceExprWithStmt.h	(revision 0)
+++ include/clang/ASTProcessing/ReplaceExprWithStmt.h	(revision 0)
@@ -0,0 +1,47 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASTPROCESSING_REPLACEEXPRWITHSTMT_H
+#define LLVM_CLANG_ASTPROCESSING_REPLACEEXPRWITHSTMT_H
+
+#include <functional>
+
+//--------------------------------------------------------- 
+namespace clang {
+
+//--------------------------------------------------------- forwards
+class Stmt;
+class Expr;
+class StmtEditor;
+
+//--------------------------------------------------------- 
+namespace ASTProcessing {
+
+// Replace the expression 'from' with a statement produced by 
+// fnGenerator.  fnGenerator, when given an expr as input, must produce
+// some code which leaves its result in the given expr. The output
+// from fnGenerator is then inserted into the original program in such a
+// way that whenever the expression had previously been evaluated, the
+// statements produced by the generator are run instead and their result is
+// used in place of from. If expr given to fnGenerator is 0, the generated
+// code ignores its result too.
+// precondition: from is a child of the stmt tree hold by StmtEditor
+// returns: the generated statement
+Stmt* replaceExprWithStmt(StmtEditor& editor, Expr* from, const std::tr1::function<Stmt*(Expr*)>& fnGenerator);
+
+//--------------------------------------------------------- 
+} // namespace ASTProcessing
+
+} // namespace clang
+
+#endif  //LLVM_CLANG_ASTPROCESSING_REPLACEEXPRWITHSTMT_H
Index: include/clang/ASTProcessing/StmtClone.h
===================================================================
--- include/clang/ASTProcessing/StmtClone.h	(revision 0)
+++ include/clang/ASTProcessing/StmtClone.h	(revision 0)
@@ -0,0 +1,146 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASTPROCESSING_STMTCLONE_H
+#define LLVM_CLANG_ASTPROCESSING_STMTCLONE_H
+
+#include "clang/AST/StmtVisitor.h"
+#include "llvm/ADT/DenseMap.h"
+
+//--------------------------------------------------------- 
+namespace clang {
+
+//--------------------------------------------------------- forwards
+struct StmtCloneMapping;
+
+//--------------------------------------------------------- 
+class StmtClone : public StmtVisitor<StmtClone, Stmt*> 
+{
+public:
+  // first: original stmt, second: appropriate cloned stmt
+  typedef llvm::DenseMap<Stmt*, Stmt*> StmtMapping; 
+  typedef llvm::DenseMap<NamedDecl*, NamedDecl*> DeclMapping; 
+  typedef StmtCloneMapping Mapping; 
+
+private:  
+  ASTContext& Ctx;
+  Mapping*    m_OriginalToClonedStmts;
+
+  Decl* CloneDecl(Decl* Node);
+
+public:
+  StmtClone(ASTContext& ctx, Mapping* originalToClonedStmts = 0);
+
+  template<class StmtTy>
+  StmtTy* Clone(StmtTy* S);
+
+  //--------------------------------------------------------- visitor part (not for public use)
+  // Stmt.def could be used if ABSTR_STMT is introduced
+#define DECLARE_CLONE_FN(CLASS) Stmt* StmtClone::Visit ## CLASS(CLASS *Node);
+  DECLARE_CLONE_FN(BinaryOperator)
+  DECLARE_CLONE_FN(UnaryOperator)
+  DECLARE_CLONE_FN(ReturnStmt)
+  DECLARE_CLONE_FN(GotoStmt)
+  DECLARE_CLONE_FN(IfStmt)
+  DECLARE_CLONE_FN(ForStmt)
+  DECLARE_CLONE_FN(NullStmt)
+  DECLARE_CLONE_FN(LabelStmt)
+  DECLARE_CLONE_FN(CompoundStmt)
+  DECLARE_CLONE_FN(DeclRefExpr)
+  DECLARE_CLONE_FN(DeclStmt)
+  DECLARE_CLONE_FN(IntegerLiteral)
+  DECLARE_CLONE_FN(SwitchStmt)
+  DECLARE_CLONE_FN(CaseStmt)
+  DECLARE_CLONE_FN(DefaultStmt)
+  DECLARE_CLONE_FN(WhileStmt)
+  DECLARE_CLONE_FN(DoStmt)
+  DECLARE_CLONE_FN(ContinueStmt)
+  DECLARE_CLONE_FN(BreakStmt)
+  DECLARE_CLONE_FN(CXXCatchStmt)
+  DECLARE_CLONE_FN(CXXTryStmt)
+  DECLARE_CLONE_FN(PredefinedExpr)
+  DECLARE_CLONE_FN(CharacterLiteral)
+  DECLARE_CLONE_FN(FloatingLiteral)
+  DECLARE_CLONE_FN(ImaginaryLiteral)
+  DECLARE_CLONE_FN(StringLiteral)
+  DECLARE_CLONE_FN(ParenExpr)
+  DECLARE_CLONE_FN(ArraySubscriptExpr)
+  DECLARE_CLONE_FN(MemberExpr)
+  DECLARE_CLONE_FN(CompoundLiteralExpr)
+  DECLARE_CLONE_FN(ImplicitCastExpr)
+  DECLARE_CLONE_FN(CStyleCastExpr)
+  DECLARE_CLONE_FN(CompoundAssignOperator)
+  DECLARE_CLONE_FN(ConditionalOperator)
+  DECLARE_CLONE_FN(InitListExpr)
+  DECLARE_CLONE_FN(DesignatedInitExpr)
+  DECLARE_CLONE_FN(AddrLabelExpr)
+  DECLARE_CLONE_FN(StmtExpr)
+  DECLARE_CLONE_FN(TypesCompatibleExpr)
+  DECLARE_CLONE_FN(ChooseExpr)
+  DECLARE_CLONE_FN(GNUNullExpr)
+  DECLARE_CLONE_FN(VAArgExpr)
+  DECLARE_CLONE_FN(ImplicitValueInitExpr)
+  DECLARE_CLONE_FN(ExtVectorElementExpr)
+  DECLARE_CLONE_FN(SizeOfAlignOfExpr)
+  DECLARE_CLONE_FN(CallExpr)
+  DECLARE_CLONE_FN(ShuffleVectorExpr)
+  DECLARE_CLONE_FN(CXXOperatorCallExpr)
+  DECLARE_CLONE_FN(CXXMemberCallExpr)
+  DECLARE_CLONE_FN(CXXStaticCastExpr)
+  DECLARE_CLONE_FN(CXXDynamicCastExpr)
+  DECLARE_CLONE_FN(CXXReinterpretCastExpr)
+  DECLARE_CLONE_FN(CXXConstCastExpr)
+  DECLARE_CLONE_FN(CXXBoolLiteralExpr)
+  DECLARE_CLONE_FN(CXXNullPtrLiteralExpr)
+  DECLARE_CLONE_FN(CXXThisExpr)
+  DECLARE_CLONE_FN(CXXThrowExpr)
+
+  Stmt* VisitStmt(Stmt*);
+};
+
+//--------------------------------------------------------- 
+// not a StmtClone member class to make it forwardable:
+struct StmtCloneMapping
+{
+  StmtClone::StmtMapping m_StmtMapping; 
+  StmtClone::DeclMapping m_DeclMapping;
+};
+
+
+//--------------------------------------------------------- inlines
+inline StmtClone::StmtClone(ASTContext& ctx, Mapping* originalToClonedStmts) : 
+  Ctx(ctx), 
+  m_OriginalToClonedStmts(originalToClonedStmts) 
+{}
+
+//--------------------------------------------------------- 
+template<class StmtTy>
+StmtTy* StmtClone::Clone(StmtTy* S)
+{
+  if (S == NULL)
+  {
+    return NULL;
+  }
+
+  Stmt* cloned_Stmt = Visit(S);
+  if (m_OriginalToClonedStmts != 0)
+  {
+    m_OriginalToClonedStmts->m_StmtMapping[S] = cloned_Stmt;
+  }
+  return static_cast<StmtTy*>(cloned_Stmt);
+}
+
+//--------------------------------------------------------- 
+} // namespace clang
+
+#endif  //LLVM_CLANG_ASTPROCESSING_STMTCLONE_H
Index: include/clang/ASTProcessing/StmtCollector.h
===================================================================
--- include/clang/ASTProcessing/StmtCollector.h	(revision 0)
+++ include/clang/ASTProcessing/StmtCollector.h	(revision 0)
@@ -0,0 +1,142 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASTPROCESSING_STMTCOLLECTOR_H
+#define LLVM_CLANG_ASTPROCESSING_STMTCOLLECTOR_H
+
+#include "llvm/ADT/DenseSet.h"
+#include "clang/ASTProcessing/ParentInfo.h"
+#include "clang/ASTProcessing/ArtificialIdentifierPolicy.h"
+#include "clang/ASTProcessing/StmtTraversal.h"
+#include <functional>
+#include <memory>
+#include <list>
+
+//--------------------------------------------------------- 
+namespace clang {
+
+//--------------------------------------------------------- forwards
+class ASTContext;
+class Stmt;
+class FunctionDecl;
+class StmtEditor;
+class Rewriter;
+
+//--------------------------------------------------------- 
+// StmtCollector is the root class used by (perhaps multiple) 
+// StmtEditors when manipulating a particular stmt tree. It 
+// tracks all the changes in the tree and after you are finished
+// it provides the means to rewrite the changes and collect the garbage
+class StmtCollector
+{
+public:
+  typedef std::vector<Stmt*> tStmtCollection;
+  typedef std::list< std::pair<SourceRange, tStmtCollection> > tReplaceInfo;
+
+private:
+  Stmt*                 m_Root;           // placed at top for c'tor purposes 
+  ASTContext&           Ctx;
+  FunctionDecl&         m_FnContext;
+  llvm::DenseSet<Stmt*> m_AllNodes, m_OriginalNodes;
+  ParentInfo            m_ParentInfo;
+  ArtificialIdentifierPolicy m_IdentifierPolicy;
+  Diagnostic&           m_Diags;
+
+  struct tStmtTreeMirror
+  {
+    typedef std::tr1::shared_ptr<tStmtTreeMirror> tSharedPtr;
+    typedef llvm::SmallVector<tSharedPtr, 8>      tChildrenVector;
+
+    Stmt*           m_OriginalStmt;
+    SourceRange     m_SourceRange;
+    tChildrenVector m_Children;
+    explicit tStmtTreeMirror(Stmt* s);
+
+    bool compareOneLevel(tReplaceInfo& sourceRanges);
+    static tChildrenVector::const_iterator find(tChildrenVector::const_iterator b, tChildrenVector::const_iterator e, Stmt*S);
+  };
+  tStmtTreeMirror       m_OriginalTree;
+  
+  class CommentPrinter;
+  llvm::OwningPtr<CommentPrinter>  m_CommentCollector;
+  void attachComment(Stmt* S, const char* pComment);
+
+  template<class T>
+  T* record(T* Node);     //return Node;
+
+  template<class T>
+  T* recordAll(T* Node);  //return Node;
+
+  // a very simple garbage collector for AST processing: when calling gc(), 
+  // all recorded Stmts, which are not in the root tree (anymore) are destroyed
+  void gc();
+
+  unsigned getIndentLevel(Stmt* S) const;
+
+  StmtCollector(const StmtCollector&);            // not defined
+  StmtCollector& operator=(const StmtCollector&); // not defined
+
+public:
+  // the fnContext contains the function defines of the processed Stmt tree
+  // precondition: fnContext.getBody(Ctx) != 0
+  explicit StmtCollector(ASTContext& ctx, const ArtificialIdentifierPolicy& identifierPolicy, 
+                         Diagnostic& diags, FunctionDecl& fnContext);
+  // calls gc:
+  ~StmtCollector();
+
+  void setArtificialIdentifierPolicy(const ArtificialIdentifierPolicy& identifierPolicy);
+
+  void getReplacedNodes(tReplaceInfo& sourceRanges);
+  void rewrite(Rewriter& rewriter);
+
+  // returns true, if S is part of the original stmt tree (useful in order to 
+  // prevent changes of not-generated AST parts:
+  bool isOriginalStmt(Stmt* S) const;
+
+  friend class StmtEditor;
+};
+
+
+//--------------------------------------------------------- inlines
+template<class T>
+inline T* StmtCollector::record(T* Node)
+{
+  m_AllNodes.insert(Node);
+  return Node;
+}
+
+//--------------------------------------------------------- 
+template<class T>
+inline T* StmtCollector::recordAll(T* Node)
+{
+  using namespace std::tr1;
+  ASTProcessing::for_each_df(Node, bind(&llvm::DenseSet<Stmt*>::insert, ref(m_AllNodes), placeholders::_1));
+  return Node;
+}
+
+//--------------------------------------------------------- 
+inline bool StmtCollector::isOriginalStmt(Stmt* S) const
+{
+  return m_OriginalNodes.count(S);
+}
+
+//--------------------------------------------------------- 
+inline void StmtCollector::setArtificialIdentifierPolicy(const ArtificialIdentifierPolicy& identifierPolicy)
+{
+  m_IdentifierPolicy = identifierPolicy;
+}
+
+//--------------------------------------------------------- 
+} // namespace clang
+
+#endif  //LLVM_CLANG_ASTPROCESSING_STMTCOLLECTOR_H
Index: include/clang/ASTProcessing/StmtEditor.h
===================================================================
--- include/clang/ASTProcessing/StmtEditor.h	(revision 0)
+++ include/clang/ASTProcessing/StmtEditor.h	(revision 0)
@@ -0,0 +1,123 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASTPROCESSING_STMTEDITOR_H
+#define LLVM_CLANG_ASTPROCESSING_STMTEDITOR_H
+
+#include "clang/AST/Expr.h"
+
+//--------------------------------------------------------- 
+namespace clang {
+
+//--------------------------------------------------------- forwards
+class StmtCollector;
+struct StmtCloneMapping;
+
+// StmtEditor provides all the basic means needed to manipulate statement trees.
+// You create a StmtEditor either by supplying a StmtCollector or by simply
+// copiing another StmtEditor (which is cheap). The best way to use StmtEditor 
+// is to derive from it and define a ctor in the derived class which takes an 
+// existing StmtEditor. See the replaceExpressionWithStatement implementation
+// for an example.
+class StmtEditor
+{
+  StmtCollector&  m_Collector;
+
+  Stmt* CloneInternal(Stmt*, StmtCloneMapping*);
+
+public:
+  explicit StmtEditor(StmtCollector& collector);
+
+  static const SourceLocation nopos;
+  ASTContext& Ctx();
+
+  // create variable names
+  IdentifierInfo *createVariable(const NamedDecl* originalVar);
+  IdentifierInfo *createLabel(const LabelStmt* originalLabel);
+
+  // stmt creation
+  IfStmt* If_(Expr* cond, Stmt* thenStmt, Stmt* elseStmt = 0);
+  GotoStmt* Goto_(LabelStmt* target);
+  LabelStmt* Label_(Stmt* subStmt);
+  NullStmt* NullStmt_();
+  BreakStmt* Break_();
+
+  // expr creation
+  BinaryOperator* BinaryOp_(Expr* lhs, Expr* rhs, BinaryOperator::Opcode opc);
+  UnaryOperator* UnaryOp_(Expr* sub, UnaryOperator::Opcode opc);
+  BinaryOperator* Assign_(Expr* lhs, Expr* rhs);
+  DeclRefExpr* DeclRef_(DeclStmt* singleVarDecl);
+  Expr* Bool_(bool value);
+
+  // temp variable creation
+  DeclStmt* TmpVar_(QualType tmpType, Expr* init = 0);
+
+  // compound stmt creation
+  CompoundStmt* Compound_(Stmt* s1, Stmt* s2);
+  CompoundStmt* Compound_(Stmt** s, unsigned numStmts);
+  template<unsigned N>
+  CompoundStmt* Compound_(Stmt* (&s)[N]);
+
+  // fundamental types
+  const QualType& BoolTy_();
+
+  // compound stmt editing
+  void appendStmt(CompoundStmt* S, Stmt* stmtToAppend);
+  void removeStmt(CompoundStmt* S, Stmt* stmtToRemove);
+  void replaceStmts(CompoundStmt* S, Stmt **Stmts, unsigned NumStmts);
+
+  // stmt tree deep copy
+  template<class T>
+  T* Clone_(T* stmt, StmtCloneMapping* mapping = 0);
+
+  // replaces from in the parent with newStmt, returns newStmt
+  Stmt* replaceStatement(Stmt* from, Stmt* newStmt);
+
+  // removes stmtToRemove from the parent 
+  // only applicable if parent can be an CompoundStmt or NullStmt
+  void removeStmt(Stmt* stmtToRemove);
+
+  // delegates from parent map
+  Stmt* getParent(Stmt* s);
+  Expr* getFullExpression(Expr* subexpr);
+  Stmt* getStatementOfExpression(Expr* subexpr);
+
+  // delegates StmtCollector
+  bool isOriginalStmt(Stmt* S) const;
+  void attachComment(Stmt* S, const char* pComment);
+};
+
+
+//--------------------------------------------------------- inlines
+inline StmtEditor::StmtEditor(StmtCollector& collector) :
+  m_Collector(collector)
+{}
+
+//--------------------------------------------------------- 
+template<unsigned N>
+inline CompoundStmt* StmtEditor::Compound_(Stmt* (&s)[N])
+{
+  return Compound_(s, N);
+}
+
+//--------------------------------------------------------- 
+template<class T>
+T* StmtEditor::Clone_(T* stmt, StmtCloneMapping* mapping)
+{
+  return static_cast<T*>(CloneInternal(stmt, mapping));
+}
+
+//--------------------------------------------------------- 
+} // namespace clang
+
+#endif  //LLVM_CLANG_ASTPROCESSING_STMTEDITOR_H
Index: include/clang/ASTProcessing/StmtTraversal.h
===================================================================
--- include/clang/ASTProcessing/StmtTraversal.h	(revision 0)
+++ include/clang/ASTProcessing/StmtTraversal.h	(revision 0)
@@ -0,0 +1,125 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASTPROCESSING_STMTTRAVERSAL_H
+#define LLVM_CLANG_ASTPROCESSING_STMTTRAVERSAL_H
+
+#include "clang/AST/StmtGraphTraits.h"
+#include "llvm/ADT/DepthFirstIterator.h"
+#include "llvm/ADT/PostOrderIterator.h"
+#include <algorithm>
+
+//--------------------------------------------------------- 
+namespace clang {
+
+//--------------------------------------------------------- 
+namespace ASTProcessing
+{
+
+//--------------------------------------------------------- 
+namespace Private {
+
+template<class T, class U>
+struct visit_all_stmts_tagged;
+
+//--------------------------------------------------------- 
+template<class T>
+struct visit_all_stmts_tagged<T, bool>
+{
+  static void traverse_df(Stmt* S, const T& visitor)
+  {
+    for (llvm::df_iterator<Stmt*> i = llvm::df_begin(S), e = llvm::df_end(S); i != e;)
+    {
+      const_cast<T&>(visitor).Visit(*i) ? i.skipChildren() : ++i;
+    }
+  }
+
+  static void traverse_df(Stmt* S, T& visitor)
+  {
+    for (llvm::df_iterator<Stmt*> i = llvm::df_begin(S), e = llvm::df_end(S); i != e;)
+    {
+      visitor.Visit(*i) ? i.skipChildren() : ++i;
+    }
+  }
+};
+
+//--------------------------------------------------------- 
+template<class T>
+struct visit_all_stmts_tagged<T, void>
+{
+  static void traverse_df(Stmt* S, const T& visitor)
+  {
+    for (llvm::df_iterator<Stmt*> i = llvm::df_begin(S), e = llvm::df_end(S); i != e; ++i)
+    {
+      const_cast<T&>(visitor).Visit(*i);
+    }
+  }
+
+  static void traverse_df(Stmt* S, T& visitor)
+  {
+    for (llvm::df_iterator<Stmt*> i = llvm::df_begin(S), e = llvm::df_end(S); i != e; ++i)
+    {
+      visitor.Visit(*i);
+    }
+  }
+};
+
+} // namespace Private
+
+//--------------------------------------------------------- 
+template<class T>
+inline void for_each_df(Stmt* S, T fn)
+{
+  std::for_each(llvm::df_begin(S), llvm::df_end(S), fn);
+}
+
+//--------------------------------------------------------- 
+template<class T>
+inline void visit_df(Stmt* S, const T& visitor)
+{
+  Private::visit_all_stmts_tagged<T, typename T::result_type>::traverse_df(S, visitor);
+}
+
+//--------------------------------------------------------- 
+template<class T>
+inline void visit_df(Stmt* S, T& visitor)
+{
+  Private::visit_all_stmts_tagged<T, typename T::result_type>::traverse_df(S, visitor);
+}
+
+//--------------------------------------------------------- 
+template<class T>
+inline void visit_po(Stmt* S, const T& visitor)
+{
+  for (llvm::po_iterator<Stmt*> i = llvm::po_begin(S), e = llvm::po_end(S); i != e; ++i)
+  {
+    const_cast<T&>(visitor).Visit(*i);
+  }
+}
+
+//--------------------------------------------------------- 
+template<class T>
+inline void visit_po(Stmt* S, T& visitor)
+{
+  for (llvm::po_iterator<Stmt*> i = llvm::po_begin(S), e = llvm::po_end(S); i != e; ++i)
+  {
+    visitor.Visit(*i);
+  }
+}
+
+//--------------------------------------------------------- 
+} // namespace ASTProcessing
+
+} // namespace clang
+
+#endif  //LLVM_CLANG_ASTPROCESSING_STMTTRAVERSAL_H
Index: include/clang/ASTProcessing/Toolbox.h
===================================================================
--- include/clang/ASTProcessing/Toolbox.h	(revision 0)
+++ include/clang/ASTProcessing/Toolbox.h	(revision 0)
@@ -0,0 +1,77 @@
+//===--- Cleanup.h - "Umbrella" header for AST library ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASTPROCESSING_TOOLBOX_H
+#define LLVM_CLANG_ASTPROCESSING_TOOLBOX_H
+
+#include <functional>
+
+//--------------------------------------------------------- 
+namespace clang {
+
+//--------------------------------------------------------- forwards
+class Stmt;
+class StmtEditor;
+struct StmtCloneMapping;
+
+//--------------------------------------------------------- 
+namespace ASTProcessing {
+
+// clones the given Node and does all the common preprocessing necessary anyway
+// it generates new names for all cloned labels and all cloned declarations
+// and rechain label references (from GotoStmt, AddrLabelExpr), variable references (from DeclRefExpr),
+// SwitchCase lists (from SwitchStmt) to their respective clones
+// precondition: Node is a child of the stmt tree hold by StmtEditor
+template<class T> 
+inline T* cloneStmtTree(StmtEditor& editor, T* Node, StmtCloneMapping* pCloneMapping = 0)
+{
+  return static_cast<T*>(cloneStmtTreeInternal(editor, Node, pCloneMapping));
+}
+
+// remove all compounds (include original compounds if bAllBlocks is true) that are
+// straight embedded in other compounds
+// note: the lifetime of variables may change. but this should not be an issue
+// if original compounds aren't touched
+// precondition: Node is a child of the stmt tree hold by StmtEditor
+void flattenBlocks(StmtEditor& editor, Stmt* Node, bool bAllBlocks = false);
+
+// remove all generated gotos that jumps to the label immediately follwing the goto,
+// then it removes all generated labels for which no goto exists anymore
+// note: call flattenBlocks before removeGotosToNextLabel
+// precondition: Node is a child of the stmt tree hold by StmtEditor
+void removeGotosToNextLabel(StmtEditor& editor, Stmt* Node);
+
+// merges generated variable declarations and first assignment to initializations
+// note: call flattenBlocks before removeGotosToNextLabel
+// precondition: Node is a child of the stmt tree hold by StmtEditor
+void moveDeclsToFirstWrite(StmtEditor& editor, Stmt* Node);
+
+// if generated variable declaration is used only once, the appropriate init-expr 
+// is moved to that use and the variable declaration is removed
+// note: call moveDeclsToFirstWrite before 
+// precondition: Node is a child of the stmt tree hold by StmtEditor
+void expandOneUsedInitDeclsToUse(StmtEditor& editor, Stmt* Node);
+
+// remove all stmts after unconditional break's or continue's
+// precondition: Node is a child of the stmt tree hold by StmtEditor
+void removeStmtsAfterBreakAndContinue(StmtEditor& editor, Stmt* Node);
+
+// internal function for cloneStmtTree template
+Stmt* cloneStmtTreeInternal(StmtEditor& editor, Stmt* Node, StmtCloneMapping* pCloneMapping);
+
+//--------------------------------------------------------- 
+} // namespace ASTProcessing
+
+} // namespace clang
+
+#endif  //LLVM_CLANG_ASTPROCESSING_TOOLBOX_H
Index: lib/ASTProcessing/ArtificialIdentifierPolicy.cpp
===================================================================
--- lib/ASTProcessing/ArtificialIdentifierPolicy.cpp	(revision 0)
+++ lib/ASTProcessing/ArtificialIdentifierPolicy.cpp	(revision 0)
@@ -0,0 +1,91 @@
+//===--- ArtificialIdentifierPolicy.cpp -----------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTProcessing/ArtificialIdentifierPolicy.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/ASTContext.h"
+
+//--------------------------------------------------------- 
+namespace clang {
+
+//--------------------------------------------------------- 
+ArtificialIdentifierPolicy::ArtificialIdentifierPolicy(const std::string& commonSuffix) :
+  LabelSuffix(commonSuffix),
+  VarSuffix(commonSuffix),
+  UseOriginalLabelName(1),
+  UseOriginalVarName(1)
+{
+  LabelAlternate = "art_" + commonSuffix;
+  VarAlternate = "art_" + commonSuffix;
+}
+
+//--------------------------------------------------------- 
+IdentifierInfo *ArtificialIdentifierPolicy::createInfo(ASTContext& Ctx, std::stringstream& nameStream)
+{
+  static unsigned s_Count = 0;
+
+  nameStream << s_Count++;
+  const std::string& strName = nameStream.str();     
+  const char* pLabelName = strName.c_str();
+  return &Ctx.Idents.CreateIdentifierInfo(pLabelName, pLabelName + strName.size());
+}
+
+//--------------------------------------------------------- 
+namespace {
+
+std::string getOriginalNameWithSuffix(const std::string& originalName, const std::string& suffix)
+{
+  std::string::size_type pos = originalName.rfind(suffix);
+  if (pos != std::string::npos && 
+      pos + suffix.size() < originalName.size() &&
+      originalName.find_first_not_of("0123456789", pos + suffix.size()) == std::string::npos)
+  {  
+    return originalName.substr(0, pos + suffix.size());
+  }
+  return originalName + suffix;
+}
+
+}
+//--------------------------------------------------------- 
+IdentifierInfo *ArtificialIdentifierPolicy::createVariable(ASTContext& Ctx, const NamedDecl* originalVar)
+{
+  std::stringstream newName;
+  if (UseOriginalVarName != 0 && originalVar != NULL)
+  {
+    newName << VarPrefix << getOriginalNameWithSuffix(originalVar->getNameAsCString(), VarSuffix);
+  }
+  else
+  {
+    newName << VarAlternate;
+  }
+  return createInfo(Ctx, newName);     
+}
+
+//--------------------------------------------------------- 
+IdentifierInfo *ArtificialIdentifierPolicy::createLabel(ASTContext& Ctx, const LabelStmt* originalLabel)
+{
+  std::stringstream newName;
+  if (UseOriginalLabelName != 0 && originalLabel != NULL)
+  {
+    newName << LabelPrefix << getOriginalNameWithSuffix(originalLabel->getName(), LabelSuffix);
+  }
+  else
+  {
+    newName << LabelAlternate;
+  }
+  return createInfo(Ctx, newName);     
+}
+
+//--------------------------------------------------------- 
+} // ns clang
Index: lib/ASTProcessing/CMakeLists.txt
===================================================================
--- lib/ASTProcessing/CMakeLists.txt	(revision 0)
+++ lib/ASTProcessing/CMakeLists.txt	(revision 0)
@@ -0,0 +1,14 @@
+set(LLVM_NO_RTTI 1)
+
+add_clang_library(clangASTProcessing
+  ArtificialIdentifierPolicy.cpp
+  Inline.cpp
+  InvariantIf.cpp
+  ParentInfo.cpp
+  ReplaceExprWithStmt.cpp
+  StmtClone.cpp
+  StmtCollector.cpp
+  StmtEditor.cpp
+  Toolbox.cpp
+  )
+
Index: lib/ASTProcessing/Inline.cpp
===================================================================
--- lib/ASTProcessing/Inline.cpp	(revision 0)
+++ lib/ASTProcessing/Inline.cpp	(revision 0)
@@ -0,0 +1,197 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTProcessing/Inline.h"    
+#include "clang/ASTProcessing/StmtEditor.h"    
+#include "clang/ASTProcessing/StmtClone.h"    
+#include "clang/ASTProcessing/Toolbox.h"    
+#include "clang/ASTProcessing/ReplaceExprWithStmt.h"    
+#include "clang/ASTProcessing/StmtTraversal.h"    
+#include "clang/AST/StmtVisitor.h"    
+#include "clang/AST/DeclCXX.h"    
+#include "llvm/ADT/DenseMap.h"
+
+using namespace std::tr1::placeholders;
+
+//--------------------------------------------------------- 
+namespace clang {
+
+namespace ASTProcessing {
+
+namespace {
+
+//--------------------------------------------------------- 
+struct ReplaceParameters : StmtVisitor<ReplaceParameters> 
+{
+  typedef llvm::DenseMap<ParmVarDecl*, NamedDecl*> tReplaceFnArgsMap;
+  const tReplaceFnArgsMap& m_ReplaceFnArgsMap;
+
+  ReplaceParameters(tReplaceFnArgsMap& replaceFnArgsMap) : m_ReplaceFnArgsMap(replaceFnArgsMap) {}
+
+  void VisitDeclRefExpr(DeclRefExpr* Node)
+  {
+    if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(Node->getDecl())) 
+    {
+      tReplaceFnArgsMap::const_iterator i = m_ReplaceFnArgsMap.find(PVD);
+      if (i != m_ReplaceFnArgsMap.end())
+      {
+        Node->setDecl(i->second);
+      }
+      else
+      {
+        assert(0 && "no replacement for function argument?");
+      }
+    }
+  }
+};
+
+
+//--------------------------------------------------------- 
+struct ReplaceReturns : public StmtVisitor<ReplaceReturns, bool>, StmtEditor
+{
+  LabelStmt*  m_GotoTarget;
+  Expr*       m_ResultTarget;
+
+  ReplaceReturns(StmtEditor& editor, LabelStmt* gotoTarget, Expr* resultTarget) : StmtEditor(editor), m_GotoTarget(gotoTarget), m_ResultTarget(resultTarget) {}
+
+  static Stmt* generate(StmtEditor* ctx, Stmt* stmtBody, LabelStmt* gotoTarget, Expr* resultTarget)
+  {
+    ASTProcessing::visit_df(stmtBody, ReplaceReturns(*ctx, gotoTarget, resultTarget));
+    return stmtBody;
+  }
+
+  bool VisitReturnStmt(ReturnStmt* Node)
+  {
+    // return expr; -> { m_ResultTarget = expr; goto m_GotoTarget; }
+    Stmt* newStmts[2];
+    unsigned newStmtCnt = 0;
+    if (Node->getRetValue()) 
+    {
+      if (m_ResultTarget)
+      {
+        newStmts[newStmtCnt++] = Assign_(Clone_(m_ResultTarget), Node->getRetValue());
+      }
+      else
+      {
+        newStmts[newStmtCnt++] = Node->getRetValue();   // ensure the expression is executed
+      }
+    }
+    newStmts[newStmtCnt++] = Goto_(m_GotoTarget);
+    replaceStatement(Node, Compound_(newStmts, newStmtCnt));
+    return true;
+  }
+};
+
+//--------------------------------------------------------- 
+struct InlineVisitor : public StmtVisitor<InlineVisitor, bool>, StmtEditor
+{
+  explicit InlineVisitor(StmtEditor& editor) : StmtEditor(editor) {}
+
+  void replaceParameterWithTemps(FunctionDecl *FD, CallExpr* expr, CompoundStmt* S)
+  {
+    ReplaceParameters::tReplaceFnArgsMap  paramToTempMap;
+    std::vector<Stmt*> allStmts(FD->getNumParams() + S->size());
+    std::copy(S->body_begin(), S->body_end(), allStmts.begin() + FD->getNumParams());
+    for (unsigned i = 0, e = FD->getNumParams(); i < e; ++i)
+    {
+      ParmVarDecl *PVD = FD->getParamDecl(i);
+      DeclStmt* tmpDecl = TmpVar_(PVD->getType(), expr->getArg(i));
+      paramToTempMap[PVD] = static_cast<NamedDecl*>(tmpDecl->getSingleDecl());
+      allStmts[i] = tmpDecl;
+    }
+    // since ReplaceParameters rechain some decl pointers only, we can execute it safely before adding
+    // the tmp decl stmts to S, thus we can assert in ReplaceParameters 
+    // (otherwise the init exprs of the tmp decl stmts could itself contain ParmVarDecl)
+    ASTProcessing::visit_df(S, ReplaceParameters(paramToTempMap));
+    replaceStmts(S, &allStmts[0], allStmts.size());
+  }
+
+  CompoundStmt* getInlineAbleBody(FunctionDecl *FD)
+  {
+    if (CXXMethodDecl* CMD = dyn_cast<CXXMethodDecl>(FD))
+    {
+      if (CMD->isVirtual())
+      {
+        //ReportDiag(FD->getTypeSpecStartLoc(), "xxx");
+        return NULL;
+      }
+    }
+    return FD->isInline() ? dyn_cast<CompoundStmt>(FD->getBody()) : NULL;
+  }
+
+  FunctionDecl* findFunctionDecl(CallExpr* expr)
+  {
+    CastExpr* castExpr;
+    Expr* calleeExpr = expr->getCallee();
+    while (castExpr = dyn_cast<CastExpr>(calleeExpr)) 
+    {
+      calleeExpr = castExpr->getSubExpr();
+    }
+    
+    DeclRefExpr* fnRef = dyn_cast<DeclRefExpr>(calleeExpr);
+    return fnRef ? dyn_cast<FunctionDecl>(fnRef->getDecl()) : NULL;
+  }
+
+  void cleanup(Stmt* stmt)
+  {
+    ASTProcessing::flattenBlocks(*this, stmt);
+    ASTProcessing::removeGotosToNextLabel(*this, stmt);
+    ASTProcessing::moveDeclsToFirstWrite(*this, stmt);
+    ASTProcessing::expandOneUsedInitDeclsToUse(*this, stmt);
+  }
+
+  bool VisitCallExpr(CallExpr* expr)
+  {
+    FunctionDecl *FD = findFunctionDecl(expr);
+    CompoundStmt* Body = FD ? getInlineAbleBody(FD) : NULL;
+    if (Body)
+    {
+      StmtClone::Mapping cloneMap;
+      CompoundStmt* Body_copy = ASTProcessing::cloneStmtTree(*this, Body);
+
+      replaceParameterWithTemps(FD, expr, Body_copy);
+      LabelStmt* exitLabel = Label_(NullStmt_());
+      appendStmt(Body_copy, exitLabel);
+      Stmt* generatedStmt = ASTProcessing::replaceExprWithStmt(*this, expr, std::tr1::bind(&ReplaceReturns::generate, this, Body_copy, exitLabel, _1));
+      cleanup(generatedStmt);
+      return true;
+    }
+    return false;
+  }
+};
+
+//--------------------------------------------------------- 
+} // anon namespace 
+
+//--------------------------------------------------------- 
+void doInline(StmtEditor& editor, Stmt* Node)
+{
+  InlineVisitor inliner(editor);
+  for (llvm::df_iterator<Stmt*> i = llvm::df_begin(Node), e = llvm::df_end(Node); i != e;)
+  {
+    if (inliner.Visit(*i))
+    {
+      i = llvm::df_begin(Node);
+    }
+    else
+    {
+      ++i;
+    }
+  }
+}
+
+//--------------------------------------------------------- 
+} // namespace ASTProcessing
+
+} // namespace clang
+
Index: lib/ASTProcessing/InvariantIf.cpp
===================================================================
--- lib/ASTProcessing/InvariantIf.cpp	(revision 0)
+++ lib/ASTProcessing/InvariantIf.cpp	(revision 0)
@@ -0,0 +1,170 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTProcessing/InvariantIf.h"    
+#include "clang/ASTProcessing/StmtEditor.h"    
+#include "clang/ASTProcessing/StmtClone.h"    
+#include "clang/ASTProcessing/Toolbox.h"    
+#include "clang/ASTProcessing/ReplaceExprWithStmt.h"    
+#include "clang/ASTProcessing/StmtTraversal.h"    
+#include "clang/AST/StmtVisitor.h"    
+#include "clang/AST/DeclCXX.h"    
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+
+using namespace std::tr1::placeholders;
+
+//--------------------------------------------------------- 
+namespace clang {
+
+namespace ASTProcessing {
+
+namespace {
+
+//--------------------------------------------------------- 
+struct FindAndSplitIfs : public StmtVisitor<FindAndSplitIfs, bool>, StmtEditor
+{
+  ForStmt* m_ForNode;
+  bool     m_bResult;
+  llvm::DenseSet<Decl*>  m_LocalDecls;
+
+  explicit FindAndSplitIfs(StmtEditor& editor, ForStmt* Node) : StmtEditor(editor), m_ForNode(Node), m_bResult(false) 
+  {
+    if (m_ForNode->getInit() != NULL)
+    {
+      Visit(m_ForNode->getInit());    // maybe it's an decl stmt
+    }
+  }
+
+  Stmt* split(IfStmt* ifNode)
+  {
+    StmtCloneMapping cloneMapping;
+    ForStmt* elseForStmt = cloneStmtTree(*this, m_ForNode, &cloneMapping);
+    IfStmt* ifNodeCloned = static_cast<IfStmt*>(cloneMapping.m_StmtMapping[ifNode]);
+    assert(ifNodeCloned && "ifNode must be part of the for loop");
+    Stmt* enclosingIf = replaceStatement(m_ForNode, If_(ifNode->getCond(), m_ForNode, elseForStmt));
+    
+    {
+      attachComment(m_ForNode, "if-splitted loop, then condition");
+      llvm::df_iterator<Stmt*> e = llvm::df_end(cast<Stmt>(m_ForNode)),
+                               i = std::find(llvm::df_begin(cast<Stmt>(m_ForNode)), e, ifNode);
+      assert(i != e && "ifNode must be part of the for loop");
+      replaceStatement(*i, ifNode->getThen());
+    }
+
+    {
+      attachComment(elseForStmt, "if-splitted loop, else condition");
+      llvm::df_iterator<Stmt*> e = llvm::df_end(cast<Stmt>(elseForStmt)),
+                               i = std::find(llvm::df_begin(cast<Stmt>(elseForStmt)), e, ifNodeCloned);
+      assert(i != e && "ifNodeCloned must be part of the cloned for loop");
+      if (ifNodeCloned->getElse() != 0)
+      {
+        replaceStatement(*i, ifNodeCloned->getElse());
+      }
+      else
+      {
+        removeStmt(*i);
+      }
+    }
+    return enclosingIf;
+  }
+
+  bool VisitIfStmt(IfStmt* Node)
+  {
+    if (m_bResult)
+    {
+      return true;
+    }
+
+    for (llvm::df_iterator<Stmt*> i = llvm::df_begin(cast<Stmt>(Node->getCond())), 
+         e = llvm::df_end(cast<Stmt>(Node->getCond())); i != e; ++i)
+    {
+      if (DeclRefExpr* DE = dyn_cast<DeclRefExpr>(*i))
+      {
+        if (m_LocalDecls.count(DE->getDecl()) != 0) 
+        {
+          // probably not invariant:
+          return false;
+        }
+      }
+    }
+
+    Stmt* enclosingIf = split(Node);
+    flattenBlocks(*this, enclosingIf, true);
+    removeStmtsAfterBreakAndContinue(*this, enclosingIf);
+    m_bResult = true;
+    return true;
+  }
+
+  bool VisitWhileStmt(WhileStmt*)
+  {
+    return true;
+  }
+  bool VisitForStmt(ForStmt*)
+  {
+    return true;
+  }
+  bool VisitDoStmt(DoStmt*)
+  {
+    return true;
+  }
+
+  bool VisitDeclStmt(DeclStmt* Node)
+  {
+    std::for_each(Node->decl_begin(), Node->decl_end(), std::tr1::bind(&llvm::DenseSet<Decl*>::insert, std::tr1::ref(m_LocalDecls), _1));
+    return false;
+  }
+};
+
+
+struct InvariantIfSplitterVisitor : public StmtVisitor<InvariantIfSplitterVisitor, bool>, StmtEditor
+{
+  explicit InvariantIfSplitterVisitor(StmtEditor& editor) : StmtEditor(editor) {}
+
+  bool VisitForStmt(ForStmt* Node)
+  {
+    if (Node->getBody() != 0)
+    {
+      FindAndSplitIfs visitor(*this, Node);
+      visit_df(Node->getBody(), visitor);
+      return visitor.m_bResult;
+    }
+    return false;
+  }
+};
+
+//--------------------------------------------------------- 
+} // anon namespace 
+
+//--------------------------------------------------------- 
+void splitInvariantIfs(StmtEditor& editor, Stmt* Node)
+{
+  InvariantIfSplitterVisitor splitter(editor);
+  for (llvm::df_iterator<Stmt*> i = llvm::df_begin(Node), e = llvm::df_end(Node); i != e;)
+  {
+    if (splitter.Visit(*i))
+    {
+      i = llvm::df_begin(Node);
+    }
+    else
+    {
+      ++i;
+    }
+  }
+}
+
+//--------------------------------------------------------- 
+} // namespace ASTProcessing
+
+} // namespace clang
+
Index: lib/ASTProcessing/ParentInfo.cpp
===================================================================
--- lib/ASTProcessing/ParentInfo.cpp	(revision 0)
+++ lib/ASTProcessing/ParentInfo.cpp	(revision 0)
@@ -0,0 +1,113 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTProcessing/ParentInfo.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtCXX.h"
+
+//--------------------------------------------------------- 
+namespace clang {
+
+//--------------------------------------------------------- 
+ParentInfo::ParentInfo(Stmt* root) :
+  m_ParentMap(root)
+{}
+
+//--------------------------------------------------------- 
+void ParentInfo::updateParentMap(Stmt* S)
+{
+  m_ParentMap.addStmt(S);
+}
+
+//--------------------------------------------------------- 
+Stmt* ParentInfo::getParent(Stmt* s) const
+{
+  Stmt* parentStmt = m_ParentMap.getParent(s);
+  assert(parentStmt && "not in parent map, did you forget to update a clone or similiar?");
+  return parentStmt;
+}
+
+//--------------------------------------------------------- 
+Expr* ParentInfo::getFullExpression(Expr* subexpr) const
+{
+  Expr* result = NULL;
+  for (Stmt* s = subexpr; 
+       s != 0 && dyn_cast<Expr>(s) != NULL; s = getParent(s))
+  {
+    result = static_cast<Expr*>(s);
+  }
+  return result; 
+}
+
+//--------------------------------------------------------- 
+Stmt* ParentInfo::getStatementOfStmtWhereDeclIsAllowed(Stmt* result, Stmt* parent) const
+{
+  if (IfStmt* IS = dyn_cast<IfStmt>(parent))
+  {
+    return result == IS->getCond() ? parent : result;
+  }
+  else if (SwitchStmt* SS = dyn_cast<SwitchStmt>(parent))
+  {
+    return result == SS->getCond() ? parent : result;
+  }
+  else if (WhileStmt* WS = dyn_cast<WhileStmt>(parent))
+  {
+    return result == WS->getCond() ? parent : result;
+  }
+  else if (DoStmt* DoS = dyn_cast<DoStmt>(parent))
+  {
+    return result == DoS->getCond() ? parent : result;
+  }
+  else if (ForStmt* FS = dyn_cast<ForStmt>(parent))
+  {
+    return result == FS->getBody() ? result : parent;
+  }
+  return result;
+}
+
+//--------------------------------------------------------- 
+Stmt* ParentInfo::getStatementOfExpression(Expr* subexpr) const
+{
+  Expr* result = getFullExpression(subexpr);
+  Stmt* parent = getParent(result);
+
+  if (isa<CompoundStmt>(parent) || 
+      isa<LabelStmt>(parent) ||
+      isa<DefaultStmt>(parent) ||
+      isa<CXXCatchStmt>(parent))
+  {
+    return result;
+  } 
+  else if (isa<ReturnStmt>(parent) || 
+           isa<IndirectGotoStmt>(parent))
+  {
+    return parent;
+  } 
+  else if (CaseStmt* CS = dyn_cast<CaseStmt>(parent))
+  {
+    return result == CS->getSubStmt() ? result : parent;
+  }
+  else if (isa<DeclStmt>(parent))
+  {
+    return getStatementOfStmtWhereDeclIsAllowed(parent, getParent(parent));
+  }
+  else 
+  {
+    return getStatementOfStmtWhereDeclIsAllowed(result, parent);
+  }
+}
+
+//--------------------------------------------------------- 
+} // ns clang
Index: lib/ASTProcessing/ReplaceExprWithStmt.cpp
===================================================================
--- lib/ASTProcessing/ReplaceExprWithStmt.cpp	(revision 0)
+++ lib/ASTProcessing/ReplaceExprWithStmt.cpp	(revision 0)
@@ -0,0 +1,434 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTProcessing/ReplaceExprWithStmt.h"    
+#include "clang/ASTProcessing/StmtEditor.h"    
+#include "clang/AST/StmtVisitor.h"    
+#include "clang/AST/StmtGraphTraits.h"
+#include "llvm/ADT/DepthFirstIterator.h"
+
+using namespace std::tr1::placeholders;
+
+//--------------------------------------------------------- 
+namespace clang {
+
+namespace ASTProcessing {
+
+namespace {
+
+//--------------------------------------------------------- 
+class MoveTestToStmt : public StmtVisitor<MoveTestToStmt, Stmt*>, StmtEditor 
+{
+  Expr* top;
+
+  void generateTest(Stmt** whereToPut, Expr* boolExpr)
+  {
+    // generates in whereToPut:
+    //   bool temp;
+    //   temp = boolExpr;
+    //   if (!temp) break;
+    DeclStmt* tmpVarDecl = TmpVar_(BoolTy_());
+    whereToPut[0] = tmpVarDecl;
+    whereToPut[1] = Assign_(DeclRef_(tmpVarDecl), boolExpr);
+    whereToPut[2] = If_(UnaryOp_(DeclRef_(tmpVarDecl), UnaryOperator::LNot), Break_());
+  }
+
+  void replaceContinueWithGoto(Stmt* body, LabelStmt* gotoTarget)
+  {
+    for (llvm::df_iterator<Stmt*> i = llvm::df_begin(body), e = llvm::df_end(body); i != e;)
+    {
+      if (isa<Expr>(*i) || isa<ForStmt>(*i) || isa<DoStmt>(*i) || isa<WhileStmt>(*i))
+      {
+        i.skipChildren();
+      }
+      else
+      {
+        if (isa<ContinueStmt>(*i))
+        {
+          replaceStatement(*i, Goto_(gotoTarget));   
+        }
+        ++i;
+      }
+    }
+  }
+
+public:
+  MoveTestToStmt(StmtEditor& editor, Expr* t) : StmtEditor(editor), top(t) {}
+
+  Stmt* VisitIfStmt(IfStmt* IS)
+  {
+    assert(IS->getCond() == top);
+    // if (e) body; becomes
+    // {
+    //   bool temp;
+    //   temp = e;
+    //   if (temp) body;
+    // }
+    DeclStmt* tmpVarDecl = TmpVar_(BoolTy_());
+    Stmt* ifBodyCompound[3] = {
+      tmpVarDecl,
+      Assign_(DeclRef_(tmpVarDecl), IS->getCond()),
+      IS };
+    IS->setCond(DeclRef_(tmpVarDecl));
+    return replaceStatement(IS, Compound_(ifBodyCompound));
+  }
+
+  Stmt* VisitSwitchStmt(SwitchStmt* SS)
+  {
+    assert(SS->getCond() == top);
+    // switch(e) body; becomes
+    // { 
+    //   type_{e} temp; 
+    //   temp = e; 
+    //   switch(temp) body; 
+    // }
+    DeclStmt* tmpVarDecl = TmpVar_(SS->getCond()->getType());
+    Stmt* switchBodyCompound[3] = {
+      tmpVarDecl,
+      Assign_(DeclRef_(tmpVarDecl), SS->getCond()),
+      SS };
+    SS->setCond(DeclRef_(tmpVarDecl));
+    return replaceStatement(SS, Compound_(switchBodyCompound));
+  }
+
+  Stmt* VisitWhileStmt(WhileStmt* WS)
+  {
+    assert(WS->getCond() == top);
+    // while (e) body; becomes
+    // while (true) {
+    //   bool temp;
+    //   temp = e;
+    //   if (!temp) break;
+    //   body;
+    // }
+    Stmt* whileBodyCompound[4];
+    generateTest(whileBodyCompound, WS->getCond());
+    whileBodyCompound[3] = WS->getBody();
+    WS->setCond(Bool_(true));
+    WS->setBody(Compound_(whileBodyCompound));
+    return replaceStatement(WS, WS);
+  }
+
+  Stmt* VisitDoStmt(DoStmt* DS)
+  {
+    assert(DS->getCond() == top);
+    assert(0 && "FIXME: first fix DoStmt::getSourceRange");
+
+    // do body; while (e); 
+    // {bool temp = true;
+    //  do {
+    //    body (with "continue" changed to "goto label";)
+    //    label:
+    //    temp = e;
+    //  } while (temp);}
+
+    DeclStmt* tmpVarDecl = TmpVar_(BoolTy_());
+    LabelStmt* tmpLabel = Label_(Assign_(DeclRef_(tmpVarDecl), DS->getCond()));
+    replaceContinueWithGoto(DS->getBody(), tmpLabel);
+    DS->setCond(DeclRef_(tmpVarDecl));
+    DS->setBody(Compound_(DS->getBody(), tmpLabel));
+    return replaceStatement(DS, Compound_(tmpVarDecl, DS));
+  }
+
+  Stmt* VisitForStmt(ForStmt* FS)
+  {
+    if (FS->getInit() == top)
+    {
+      // for (e; x; y) body; (where e contains from) becomes
+      // {
+      //   e;
+      //   for (; x; y) body;
+      // }
+      FS->setInit(NULL);
+      return replaceStatement(FS, Compound_(top, FS));
+    }
+    else if (FS->getCond() == top)
+    {
+      // for (x; e; y) body; (where e contains from) becomes
+      // for (x; true; y) {
+      //   bool temp;
+      //   temp = e;
+      //   if (!temp) break;
+      //   body;
+      // }
+      FS->setCond(Bool_(true));
+      Stmt* forBodyCompound[4];
+      generateTest(forBodyCompound, top);
+      forBodyCompound[3] = FS->getBody();
+      FS->setBody(Compound_(forBodyCompound));
+      return replaceStatement(FS, FS);
+    }
+    else 
+    {
+      assert(FS->getInc() == top);
+      // for (x; y; e) body; (where e contains from) becomes
+      // for (x; y; ) {
+      //   body (with "continue" changed to "goto label");
+      //   label: e;
+      // }
+      FS->setInc(NULL);
+      LabelStmt* tmpLabel = Label_(top);
+      replaceContinueWithGoto(FS->getBody(), tmpLabel);
+      FS->setBody(Compound_(FS->getBody(), tmpLabel));
+      return replaceStatement(FS, FS);
+    }
+  }
+};
+
+//--------------------------------------------------------- 
+class ShortCutGenerator : public StmtVisitor<ShortCutGenerator>, StmtEditor 
+{
+  Stmt* generateSequencePointReplacement(BinaryOperator* binOp, Expr* resultTarget);
+  Stmt* generateConditionReplacement(ConditionalOperator* condOp, Expr* resultTarget);
+
+public:
+  ShortCutGenerator(StmtEditor& editor) : StmtEditor(editor) {}
+
+  //--------------------------------------------------------- visitor part (not for public use)
+  void VisitBinaryOperator(BinaryOperator* Node)
+  {
+    replaceExprWithStmt(*this, Node, std::tr1::bind(&ShortCutGenerator::generateSequencePointReplacement, this, Node, _1));
+  }
+
+  void VisitConditionalOperator(ConditionalOperator* Node)
+  {
+    replaceExprWithStmt(*this, Node, std::tr1::bind(&ShortCutGenerator::generateConditionReplacement, this, Node, _1));
+  }
+
+  void VisitStmt(Stmt*) { assert(0 && "unknown stmt class to break up"); }
+};
+
+//--------------------------------------------------------- 
+Stmt* ShortCutGenerator::generateSequencePointReplacement(BinaryOperator* binOp, Expr* resultTarget)
+{
+  if (binOp->getOpcode() == BinaryOperator::LAnd)
+  {
+    // resultTarget = a && b -> if (a) resultTarget = b; else resultTarget = false;
+    return resultTarget ? If_(binOp->getLHS(), 
+                              Assign_(resultTarget, binOp->getRHS()), 
+                              Assign_(Clone_(resultTarget), Bool_(false)))
+                        : If_(binOp->getLHS(), 
+                              binOp->getRHS());
+  }
+  else if (binOp->getOpcode() == BinaryOperator::LOr)
+  {
+    // resultTarget = a || b -> if (a) resultTarget = true; else resultTarget = b;
+    return resultTarget ? If_(binOp->getLHS(), 
+                              Assign_(resultTarget, Bool_(true)), 
+                              Assign_(Clone_(resultTarget), binOp->getRHS()))
+                        : If_(binOp->getLHS(), 
+                              NullStmt_(),
+                              binOp->getRHS());
+
+
+  }
+  else
+  {
+    assert(binOp->getOpcode() == BinaryOperator::Comma && "the given operator is not a sequence point");
+    // resultTarget = a, b -> { a; resultTarget = b; }
+    return resultTarget ? Compound_(binOp->getLHS(), Assign_(resultTarget, binOp->getRHS())) 
+                        : Compound_(binOp->getLHS(), binOp->getRHS());
+  }
+}
+
+//--------------------------------------------------------- 
+Stmt* ShortCutGenerator::generateConditionReplacement(ConditionalOperator* condOp, Expr* resultTarget)
+{
+  return resultTarget ? If_(condOp->getCond(), 
+                            Assign_(resultTarget, condOp->getTrueExpr()), 
+                            Assign_(Clone_(resultTarget), condOp->getFalseExpr())) :
+                        If_(condOp->getCond(), 
+                            condOp->getTrueExpr(), 
+                            condOp->getFalseExpr());
+}
+
+//--------------------------------------------------------- 
+class ReplaceExpression : StmtEditor
+{
+  Stmt* replaceSubexpressionWithStatement(Expr* from, const std::tr1::function<Stmt*(Expr*)>& fnGenerator);
+  BinaryOperator* splitExpression(Expr* from, Stmt* stmt);
+  CompoundStmt* ensureCompoundParent(Stmt* stmt);
+  bool breakShortcutExpressions(Expr* from);
+
+public:
+  ReplaceExpression(StmtEditor& editor);
+
+  Stmt* doReplace(Expr* from, const std::tr1::function<Stmt*(Expr*)>& fnGenerator);
+};
+
+//--------------------------------------------------------- 
+ReplaceExpression::ReplaceExpression(StmtEditor& editor) :
+  StmtEditor(editor)
+{}
+
+//--------------------------------------------------------- 
+Stmt* ReplaceExpression::doReplace(Expr* from, const std::tr1::function<Stmt*(Expr*)>& fnGenerator)
+{
+  Stmt* result = NULL;
+  Expr* top = getFullExpression(from);
+  Stmt* stmt = getStatementOfExpression(top);
+  if (stmt != top && getParent(top) != stmt)
+  {
+    // this is a decl stmt in a for,while or if init-expr
+    DeclStmt* decl = dyn_cast<DeclStmt>(getParent(top));
+    assert(decl && getParent(decl) == stmt);
+    assert(isa<ForStmt>(stmt) || isa<DoStmt>(stmt) || isa<WhileStmt>(stmt) || isa<IfStmt>(stmt));
+    if (ForStmt* FS = dyn_cast<ForStmt>(stmt))
+    {
+      assert(FS->getInit() == decl);
+      // for (e; x; y) body; (where e contains from) becomes
+      // {
+      //   e;
+      //   for (; x; y) body;
+      // }
+      FS->setInit(NULL);
+      result = replaceStatement(FS, Compound_(decl, FS));
+    }
+    else
+    {
+      assert(0 && "FIXME: to do");
+    }
+  }
+  else
+  {
+    result = MoveTestToStmt(*this, top).Visit(stmt);
+  }
+  Stmt* subExprStmt = replaceSubexpressionWithStatement(from, fnGenerator);
+  return result ? result : subExprStmt;
+}
+
+//--------------------------------------------------------- 
+Stmt* ReplaceExpression::replaceSubexpressionWithStatement(Expr* from, const std::tr1::function<Stmt*(Expr*)>& fnGenerator)
+{
+  // precondition: from is part of a statement where a CompoundStmt is allowed
+  Expr* top = getFullExpression(from);
+  Stmt* stmt = getStatementOfExpression(top);
+  if (Expr::classof(stmt))
+  {
+    BinaryOperator* binOp;
+    assert(stmt == top && "if a statement is an expression, it should be a full expression");
+    if (top == from)
+    {
+      // expression result is ignored 
+      return replaceStatement(from, fnGenerator(0));
+    }
+    else if ((binOp = dyn_cast<BinaryOperator>(top)) != NULL && 
+             binOp ->getOpcode() == BinaryOperator::Assign &&
+             binOp->getRHS() == from)
+    {
+      // the other simple case: erase the complete asssigment expression and instead put the statement in that place
+      return replaceStatement(binOp, fnGenerator(binOp->getLHS()));
+    }
+  }
+  BinaryOperator* assignExpr = splitExpression(from, stmt);
+  assert(assignExpr->getRHS() == from && "split expression should deliver the simple case");
+  Stmt* result = getParent(assignExpr);
+  replaceStatement(assignExpr, fnGenerator(assignExpr->getLHS()));
+  return result;
+}
+
+
+//--------------------------------------------------------- 
+BinaryOperator* ReplaceExpression::splitExpression(Expr* from, Stmt* stmt)
+{
+  // precondition: from is a (maybe indirect) child of stmt, stmt is in a place where a compound stmt is allowed
+  // postcondition: parent of stmt is a CompoundStmt
+  // postcondition: stmt_{from}; -> type_{from} tmpvar; tmpvar = from; stmt_{tmpvar}; 
+  // returns: tmpvar = from; 
+  CompoundStmt* parentCompound = ensureCompoundParent(stmt);
+  if (breakShortcutExpressions(from))
+  {
+    stmt = getStatementOfExpression(from);
+    parentCompound = ensureCompoundParent(stmt);
+  }
+
+  QualType tmpType = from->getType();
+  tmpType.removeConst();
+  DeclStmt* tmpDecl = TmpVar_(tmpType);
+  BinaryOperator* tmpAssign = Assign_(DeclRef_(tmpDecl), from); 
+
+  llvm::SmallVector<Stmt*, 8> stmtCompound(parentCompound->size() + 2);
+  llvm::SmallVector<Stmt*, 8>::iterator insertIter = stmtCompound.begin();
+  for (CompoundStmt::body_iterator i = parentCompound->body_begin(), e = parentCompound->body_end(); i != e; ++i)
+  {
+    if (*i == stmt)
+    {
+      replaceStatement(from, DeclRef_(tmpDecl));    // stmt_{from} -> stmt_{tmpvar}; 
+      *insertIter++ = tmpDecl;
+      *insertIter++ = tmpAssign;
+    }
+    *insertIter++ = *i;
+  }
+  replaceStmts(parentCompound, &stmtCompound[0], stmtCompound.size());
+  return tmpAssign;
+}
+
+//--------------------------------------------------------- 
+CompoundStmt* ReplaceExpression::ensureCompoundParent(Stmt* stmt)
+{
+  // precondition: stmt is in a place where a compound stmt is allowed
+  // postcondition: parent of stmt is a CompoundStmt
+  Stmt* parent = getParent(stmt);
+  CompoundStmt* compundParent;
+  if ((compundParent = dyn_cast<CompoundStmt>(parent)) == NULL)
+  {
+    Stmt* newBlock[1] = { stmt };
+    compundParent = Compound_(newBlock);
+    replaceStatement(stmt, compundParent);
+  }
+  return compundParent;
+}
+
+//--------------------------------------------------------- 
+bool ReplaceExpression::breakShortcutExpressions(Expr* from)
+{
+  llvm::SmallVector<Expr*, 8> ancestors;
+  for (Expr* parent = dyn_cast<Expr>(getParent(from)); parent != 0; from = parent, parent = dyn_cast<Expr>(getParent(from)))
+  {
+    BinaryOperator* binOp = dyn_cast<BinaryOperator>(parent);
+    if (binOp != 0 &&
+        binOp->getLHS() != from &&       
+        (binOp->getOpcode() == BinaryOperator::LAnd || 
+         binOp->getOpcode() == BinaryOperator::LOr  || 
+         binOp->getOpcode() == BinaryOperator::Comma))
+    {
+      ancestors.push_back(binOp);
+    }
+    ConditionalOperator* condOp = dyn_cast<ConditionalOperator>(parent);
+    if (condOp != 0 &&
+        condOp->getCond() != from)       
+    {
+      ancestors.push_back(condOp);
+    }
+  }
+  for (llvm::SmallVector<Expr*, 8>::reverse_iterator i = ancestors.rbegin(), e = ancestors.rend(); i != e; ++i)
+  {
+    ShortCutGenerator(*this).Visit(*i);
+  }      
+  return !ancestors.empty();
+}
+
+//--------------------------------------------------------- 
+} // anon namespace 
+
+//--------------------------------------------------------- 
+Stmt* replaceExprWithStmt(StmtEditor& editor, Expr* from, const std::tr1::function<Stmt*(Expr*)>& fnGenerator)
+{
+  return ReplaceExpression(editor).doReplace(from, fnGenerator);
+}
+
+//--------------------------------------------------------- 
+} // namespace ASTProcessing
+
+} // namespace clang
+
Index: lib/ASTProcessing/StmtClone.cpp
===================================================================
--- lib/ASTProcessing/StmtClone.cpp	(revision 0)
+++ lib/ASTProcessing/StmtClone.cpp	(revision 0)
@@ -0,0 +1,290 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTProcessing/StmtClone.h"
+#include "llvm/ADT/SmallVector.h"
+
+//--------------------------------------------------------- 
+namespace clang {
+
+//--------------------------------------------------------- 
+#define DEFINE_CLONE_STMT(CLASS, CTORARGS)    \
+Stmt* StmtClone::Visit ## CLASS(CLASS *Node)  \
+{                                             \
+  return new (Ctx) CLASS CTORARGS;            \
+}                 
+
+//--------------------------------------------------------- 
+#define DEFINE_CLONE_EXPR(CLASS, CTORARGS)    \
+Stmt* StmtClone::Visit ## CLASS(CLASS *Node)  \
+{                                             \
+  CLASS* result = new (Ctx) CLASS CTORARGS;   \
+  result->setValueDependent(Node->isValueDependent());  \
+  result->setTypeDependent(Node->isTypeDependent());    \
+  return result;                              \
+}                 
+
+//--------------------------------------------------------- 
+DEFINE_CLONE_EXPR(BinaryOperator, (Clone(Node->getLHS()), Clone(Node->getRHS()), Node->getOpcode(), Node->getType(), Node->getOperatorLoc()))
+DEFINE_CLONE_EXPR(UnaryOperator, (Clone(Node->getSubExpr()), Node->getOpcode(), Node->getType(), Node->getOperatorLoc()))
+DEFINE_CLONE_EXPR(DeclRefExpr, (Node->getDecl(), Node->getType(), Node->getLocation(), Node->isTypeDependent(), Node->isValueDependent()))
+DEFINE_CLONE_EXPR(IntegerLiteral, (Node->getValue(), Node->getType(), Node->getLocation()))
+DEFINE_CLONE_EXPR(PredefinedExpr, (Node->getLocation(), Node->getType(), Node->getIdentType()))
+DEFINE_CLONE_EXPR(CharacterLiteral, (Node->getValue(), Node->isWide(), Node->getType(), Node->getLoc()))
+DEFINE_CLONE_EXPR(FloatingLiteral, (Node->getValue(), Node->isExact(), Node->getType(), Node->getLocation()))
+DEFINE_CLONE_EXPR(ImaginaryLiteral, (Clone(Node->getSubExpr()), Node->getType()))
+DEFINE_CLONE_EXPR(ParenExpr, (Node->getLParen(), Node->getRParen(), Clone(Node->getSubExpr())))
+DEFINE_CLONE_EXPR(ArraySubscriptExpr, (Clone(Node->getLHS()), Clone(Node->getRHS()), Node->getType(), Node->getRBracketLoc()))
+DEFINE_CLONE_EXPR(MemberExpr, (Clone(Node->getBase()), Node->isArrow(), Node->getMemberDecl(), Node->getMemberLoc(), Node->getType()))
+DEFINE_CLONE_EXPR(CompoundLiteralExpr, (Node->getLParenLoc(), Node->getType(), Clone(Node->getInitializer()), Node->isFileScope()))
+DEFINE_CLONE_EXPR(ImplicitCastExpr, (Node->getType(), Clone(Node->getSubExpr()), Node->isLvalueCast()))
+DEFINE_CLONE_EXPR(CStyleCastExpr, (Node->getType(), Clone(Node->getSubExpr()), Node->getTypeAsWritten(), Node->getLParenLoc(), Node->getRParenLoc()))
+DEFINE_CLONE_EXPR(CXXStaticCastExpr, (Node->getType(), Clone(Node->getSubExpr()), Node->getTypeAsWritten(), Node->getOperatorLoc()))
+DEFINE_CLONE_EXPR(CXXDynamicCastExpr, (Node->getType(), Clone(Node->getSubExpr()), Node->getTypeAsWritten(), Node->getOperatorLoc()))
+DEFINE_CLONE_EXPR(CXXReinterpretCastExpr, (Node->getType(), Clone(Node->getSubExpr()), Node->getTypeAsWritten(), Node->getOperatorLoc()))
+DEFINE_CLONE_EXPR(CXXConstCastExpr, (Node->getType(), Clone(Node->getSubExpr()), Node->getTypeAsWritten(), Node->getOperatorLoc()))
+DEFINE_CLONE_EXPR(CompoundAssignOperator, (Clone(Node->getLHS()), Clone(Node->getRHS()), Node->getOpcode(), Node->getType(), 
+                                           Node->getComputationLHSType(), Node->getComputationResultType(), Node->getOperatorLoc()))
+DEFINE_CLONE_EXPR(ConditionalOperator, (Clone(Node->getCond()), Clone(Node->getLHS()), Clone(Node->getRHS()), Node->getType()))
+DEFINE_CLONE_EXPR(AddrLabelExpr, (Node->getAmpAmpLoc(), Node->getLabelLoc(), Node->getLabel(), Node->getType()))
+DEFINE_CLONE_EXPR(StmtExpr, (Clone(Node->getSubStmt()), Node->getType(), Node->getLParenLoc(), Node->getRParenLoc()))
+DEFINE_CLONE_EXPR(TypesCompatibleExpr, (Node->getType(), Node->getBuiltinLoc(), Node->getArgType1(), Node->getArgType2(), Node->getRParenLoc()))
+DEFINE_CLONE_EXPR(ChooseExpr, (Node->getBuiltinLoc(), Clone(Node->getCond()), Clone(Node->getLHS()), Clone(Node->getRHS()), Node->getType(), Node->getRParenLoc()))
+DEFINE_CLONE_EXPR(GNUNullExpr, (Node->getType(), Node->getTokenLocation()))
+DEFINE_CLONE_EXPR(VAArgExpr, (Node->getBuiltinLoc(), Clone(Node->getSubExpr()), Node->getType(), Node->getRParenLoc()))
+DEFINE_CLONE_EXPR(ImplicitValueInitExpr, (Node->getType()))
+DEFINE_CLONE_EXPR(ExtVectorElementExpr, (Node->getType(), Clone(Node->getBase()), Node->getAccessor(), Node->getAccessorLoc()))
+DEFINE_CLONE_EXPR(CXXBoolLiteralExpr, (Node->getValue(), Node->getType(), Node->getSourceRange().getBegin()))
+DEFINE_CLONE_EXPR(CXXNullPtrLiteralExpr, (Node->getType(), Node->getSourceRange().getBegin()))
+DEFINE_CLONE_EXPR(CXXThisExpr, (Node->getSourceRange().getBegin(), Node->getType()))
+DEFINE_CLONE_EXPR(CXXThrowExpr, (Clone(Node->getSubExpr()), Node->getType(), Node->getThrowLoc()))
+//BlockExpr
+//BlockDeclRefExpr
+
+//--------------------------------------------------------- 
+Stmt* StmtClone::VisitStringLiteral(StringLiteral* Node)
+{
+  llvm::SmallVector<SourceLocation, 4> concatLocations(Node->tokloc_begin(), Node->tokloc_end());
+  return StringLiteral::Create(Ctx, Node->getStrData(),
+                               Node->getByteLength(), Node->isWide(), Node->getType(),
+                               &concatLocations[0], concatLocations.size());
+}
+
+//--------------------------------------------------------- 
+Stmt* StmtClone::VisitInitListExpr(InitListExpr* Node)
+{
+  llvm::SmallVector<Expr*, 8> initExprs(std::max(1u, Node->getNumInits()));
+  for (unsigned i = 0, e = Node->getNumInits(); i < e; ++i)
+  {
+    initExprs[i] = Clone(Node->getInit(i));
+  }
+
+  InitListExpr* result = new(Ctx) InitListExpr(Node->getLBraceLoc(), &initExprs[0], initExprs.size(), Node->getRBraceLoc());
+  result->setInitializedFieldInUnion(Node->getInitializedFieldInUnion());
+  // FIXME: clone the syntactic form, can this become recursive?
+  return result;
+}
+
+//--------------------------------------------------------- 
+Stmt* StmtClone::VisitDesignatedInitExpr(DesignatedInitExpr* Node)
+{
+  llvm::SmallVector<Expr*, 8> indexExprs(Node->getNumSubExprs());
+  for (int i = 0, e = indexExprs.size(); i < e; ++i)
+  { 
+    indexExprs[i] = Clone(Node->getSubExpr(i));
+  }
+
+  return DesignatedInitExpr::Create(Ctx, Node->getDesignator(0), Node->size(),
+                                    &indexExprs[0] + 1, indexExprs.size() - 1,    // no &indexExprs[1]
+                                    Node->getEqualOrColonLoc(),
+                                    Node->usesGNUSyntax(), indexExprs[0]);
+}
+
+//--------------------------------------------------------- 
+Stmt* StmtClone::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Node)
+{
+  return Node->isArgumentType() ? 
+         new (Ctx) SizeOfAlignOfExpr(Node->isSizeOf(), Node->getArgumentType(), Node->getType(), Node->getOperatorLoc(), Node->getRParenLoc()) :
+         new (Ctx) SizeOfAlignOfExpr(Node->isSizeOf(), Clone(Node->getArgumentExpr()), Node->getType(), Node->getOperatorLoc(), Node->getRParenLoc());
+}
+
+//--------------------------------------------------------- 
+Stmt* StmtClone::VisitCallExpr(CallExpr* Node)
+{
+  CallExpr* result = new (Ctx) CallExpr(Ctx, Clone(Node->getCallee()), NULL, 0, Node->getType(), Node->getRParenLoc());
+  result->setNumArgs(Ctx, Node->getNumArgs());
+  for (unsigned i = 0, e = Node->getNumArgs(); i < e; ++i)
+  {
+    result->setArg(i, Clone(Node->getArg(i)));
+  }
+  result->setValueDependent(Node->isValueDependent());  
+  result->setTypeDependent(Node->isTypeDependent());    
+  return result;
+}
+
+//--------------------------------------------------------- 
+Stmt* StmtClone::VisitCXXOperatorCallExpr(CXXOperatorCallExpr* Node)
+{
+  CXXOperatorCallExpr* result = new (Ctx) CXXOperatorCallExpr(Ctx, Node->getOperator(), Clone(Node->getCallee()), NULL, 0, Node->getType(), Node->getRParenLoc());
+  result->setNumArgs(Ctx, Node->getNumArgs());
+  for (unsigned i = 0, e = Node->getNumArgs(); i < e; ++i)
+  {
+    result->setArg(i, Clone(Node->getArg(i)));
+  }
+  result->setValueDependent(Node->isValueDependent());  
+  result->setTypeDependent(Node->isTypeDependent());    
+  return result;
+}
+
+//--------------------------------------------------------- 
+Stmt* StmtClone::VisitCXXMemberCallExpr(CXXMemberCallExpr * Node)
+{
+  CXXMemberCallExpr* result = new (Ctx) CXXMemberCallExpr(Ctx, Clone(Node->getCallee()), NULL, 0, Node->getType(), Node->getRParenLoc());
+  result->setNumArgs(Ctx, Node->getNumArgs());
+  for (unsigned i = 0, e = Node->getNumArgs(); i < e; ++i)
+  {
+    result->setArg(i, Clone(Node->getArg(i)));
+  }
+  result->setValueDependent(Node->isValueDependent());  
+  result->setTypeDependent(Node->isTypeDependent());    
+  return result;
+}
+
+//--------------------------------------------------------- 
+Stmt* StmtClone::VisitShuffleVectorExpr(ShuffleVectorExpr* Node)
+{
+  llvm::SmallVector<Expr*, 8> clonedBody(std::max(1u, Node->getNumSubExprs()));
+  for (unsigned i = 0, e = Node->getNumSubExprs(); i < e; ++i)
+  {
+    clonedBody[i] = Clone(Node->getExpr(i));
+  }
+  return new (Ctx) ShuffleVectorExpr(&clonedBody[0], Node->getNumSubExprs(), Node->getType(), Node->getBuiltinLoc(), Node->getRParenLoc());
+}
+
+//--------------------------------------------------------- 
+Stmt* StmtClone::VisitCaseStmt(CaseStmt* Node)
+{
+  CaseStmt* result = new (Ctx) CaseStmt(Clone(Node->getLHS()), Clone(Node->getRHS()), Node->getCaseLoc(), Node->getEllipsisLoc(), Node->getColonLoc());
+  result->setSubStmt(Clone(Node->getSubStmt()));
+  return result;
+}
+
+//--------------------------------------------------------- 
+Stmt* StmtClone::VisitSwitchStmt(SwitchStmt* Node)
+{
+  SwitchStmt* result = new (Ctx) SwitchStmt(Clone(Node->getCond()));
+  result->setBody(Clone(Node->getBody()));
+  result->setSwitchLoc(Node->getSwitchLoc());
+  return result;
+}
+
+//--------------------------------------------------------- 
+DEFINE_CLONE_STMT(ReturnStmt, (Node->getReturnLoc(), Clone(Node->getRetValue())))
+DEFINE_CLONE_STMT(DefaultStmt, (Node->getDefaultLoc(), Node->getColonLoc(), Clone(Node->getSubStmt())))
+DEFINE_CLONE_STMT(GotoStmt, (Node->getLabel(), Node->getGotoLoc(), Node->getLabelLoc()))
+DEFINE_CLONE_STMT(WhileStmt, (Clone(Node->getCond()), Clone(Node->getBody()), Node->getWhileLoc()))
+DEFINE_CLONE_STMT(DoStmt, (Clone(Node->getBody()), Clone(Node->getCond()), Node->getDoLoc(), Node->getWhileLoc(), Node->getRParenLoc()))
+DEFINE_CLONE_STMT(IfStmt, (Node->getIfLoc(), Clone(Node->getCond()), Clone(Node->getThen()), Node->getElseLoc(), Clone(Node->getElse())))
+DEFINE_CLONE_STMT(LabelStmt, (Node->getIdentLoc(), Node->getID(), Clone(Node->getSubStmt())))
+DEFINE_CLONE_STMT(NullStmt, (Node->getSemiLoc()))
+DEFINE_CLONE_STMT(ForStmt, (Clone(Node->getInit()), Clone(Node->getCond()), Clone(Node->getInc()), Clone(Node->getBody()), 
+                            Node->getForLoc(), Node->getLParenLoc(), Node->getRParenLoc()))
+DEFINE_CLONE_STMT(ContinueStmt, (Node->getContinueLoc()))
+DEFINE_CLONE_STMT(BreakStmt, (Node->getBreakLoc()))
+DEFINE_CLONE_STMT(CXXCatchStmt, (Node->getCatchLoc(), static_cast<VarDecl*>(CloneDecl(Node->getExceptionDecl())), Clone(Node->getHandlerBlock())))
+
+//--------------------------------------------------------- 
+Stmt* StmtClone::VisitCXXTryStmt(CXXTryStmt* Node)
+{
+  llvm::SmallVector<Stmt*, 4> CatchStmts(std::max(1u, Node->getNumHandlers()));
+  for (unsigned i = 0, e = Node->getNumHandlers(); i < e; ++i)
+  {
+    CatchStmts[i] = Clone(Node->getHandler(i));
+  }
+  return new (Ctx) CXXTryStmt(Node->getTryLoc(), Clone(Node->getTryBlock()), &CatchStmts[0], CatchStmts.size());
+}
+
+//--------------------------------------------------------- 
+Stmt* StmtClone::VisitCompoundStmt(CompoundStmt *Node)
+{
+  CompoundStmt* result = new (Ctx) CompoundStmt(Ctx, NULL, 0, Node->getLBracLoc(), Node->getLBracLoc());
+  unsigned numStmts = Node->size();
+  if (numStmts > 0)
+  {
+    llvm::SmallVector<Stmt*, 8> clonedBody(numStmts);
+    llvm::SmallVector<Stmt*, 8>::iterator insertIter = clonedBody.begin();
+    for (CompoundStmt::const_body_iterator i = Node->body_begin(), e = Node->body_end(); i != e; ++i, ++insertIter)
+    {
+      *insertIter = Clone(*i);
+    }
+    result->setStmts(Ctx, &clonedBody[0], numStmts);
+  }
+  return result;
+}
+
+//--------------------------------------------------------- 
+Decl* StmtClone::CloneDecl(Decl* Node) 
+{
+  if (Node->getKind() == Decl::Var) // we support only exactly this class, so no visitor is needed (yet?)
+  {
+    VarDecl* VD = static_cast<VarDecl*>(Node);
+
+    VarDecl* cloned_Decl = VarDecl::Create(Ctx, VD->getDeclContext(), VD->getLocation(), VD->getIdentifier(), 
+                                           VD->getType(), VD->getStorageClass(), VD->getTypeSpecStartLoc());
+    cloned_Decl->setInit(Ctx, Clone(VD->getInit()));
+    cloned_Decl->setThreadSpecified(VD->isThreadSpecified());
+    cloned_Decl->setCXXDirectInitializer(VD->hasCXXDirectInitializer());
+    cloned_Decl->setDeclaredInCondition(VD->isDeclaredInCondition());
+    if (m_OriginalToClonedStmts != 0)
+    {
+      m_OriginalToClonedStmts->m_DeclMapping[VD] = cloned_Decl;
+    }
+    return cloned_Decl;
+  }
+  else
+  {
+    assert(0 && "other decl clones aren't supported");
+    return 0;
+  }
+}
+
+//--------------------------------------------------------- 
+Stmt* StmtClone::VisitDeclStmt(DeclStmt* Node) 
+{ 
+  DeclGroupRef clonedDecls;
+  if (Node->isSingleDecl())
+  {
+    clonedDecls = DeclGroupRef(CloneDecl(Node->getSingleDecl()));
+  }
+  else if (Node->getDeclGroup().isDeclGroup())
+  {
+    llvm::SmallVector<Decl*, 8> clonedDeclGroup;
+    const DeclGroupRef& dg = Node->getDeclGroup();
+    for (DeclGroupRef::const_iterator i = dg.begin(), e = dg.end(); i != e; ++i)
+    {
+      clonedDeclGroup.push_back(CloneDecl(*i));
+    }
+    clonedDecls = DeclGroupRef(DeclGroup::Create(Ctx, &clonedDeclGroup[0], clonedDeclGroup.size()));
+  }
+  return new (Ctx) DeclStmt(clonedDecls, Node->getStartLoc(), Node->getEndLoc());
+}
+
+//--------------------------------------------------------- 
+Stmt* StmtClone::VisitStmt(Stmt*) 
+{ 
+  assert(0 && "clone not fully implemented"); 
+  return NULL; 
+}
+
+//--------------------------------------------------------- 
+} // ns clang
Index: lib/ASTProcessing/StmtCollector.cpp
===================================================================
--- lib/ASTProcessing/StmtCollector.cpp	(revision 0)
+++ lib/ASTProcessing/StmtCollector.cpp	(revision 0)
@@ -0,0 +1,299 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTProcessing/StmtCollector.h"
+#include "clang/Rewrite/Rewriter.h"
+#include "clang/AST/Expr.h"
+#include <algorithm>
+
+//--------------------------------------------------------- 
+namespace clang {
+
+class StmtCollector::CommentPrinter : public PrinterHelper
+{
+public:
+  virtual bool handledStmt(Stmt* E, llvm::raw_ostream& OS, unsigned IndentLevel);
+
+  typedef llvm::SmallVector<std::string, 8> tCommentCollection;
+  typedef llvm::DenseMap<Stmt*, tCommentCollection> tCommentMap;
+  tCommentMap m_AttachedComments;
+};
+
+//--------------------------------------------------------- 
+StmtCollector::StmtCollector(ASTContext& ctx, const ArtificialIdentifierPolicy& identifierPolicy, 
+                             Diagnostic& diags, FunctionDecl& fnContext) :
+  m_Root(fnContext.getBody()),      
+  Ctx(ctx),
+  m_FnContext(fnContext),
+  m_ParentInfo(m_Root),
+  m_IdentifierPolicy(identifierPolicy),
+  m_Diags(diags),
+  m_OriginalTree(m_Root),
+  m_CommentCollector(new CommentPrinter())
+{
+  recordAll(m_Root);
+  using namespace std::tr1;
+  ASTProcessing::for_each_df(m_Root, bind(&llvm::DenseSet<Stmt*>::insert, ref(m_OriginalNodes), placeholders::_1));
+}
+
+//--------------------------------------------------------- 
+StmtCollector::~StmtCollector()
+{
+  gc();
+}
+
+//--------------------------------------------------------- 
+StmtCollector::tStmtTreeMirror::tStmtTreeMirror(Stmt* s) : 
+  m_OriginalStmt(s)
+{
+  if (s != 0)
+  {
+    m_SourceRange = s->getSourceRange();
+    for (Stmt::child_iterator i = s->child_begin(), e = s->child_end(); i != e; ++i)
+    {
+      m_Children.push_back(tSharedPtr(new tStmtTreeMirror(*i)));
+    }
+  }
+}
+
+//--------------------------------------------------------- 
+void StmtCollector::gc()
+{
+  using namespace std::tr1;
+  ASTProcessing::for_each_df(m_Root, bind(&llvm::DenseSet<Stmt*>::erase, ref(m_AllNodes), placeholders::_1));
+  for (llvm::DenseSet<Stmt*>::iterator i = m_AllNodes.begin(), e = m_AllNodes.end(); i != e; ++i)
+  {
+    std::fill((*i)->child_begin(), (*i)->child_end(), (Stmt*)0);
+    (*i)->Destroy(Ctx);
+  }
+}
+
+//--------------------------------------------------------- 
+StmtCollector::tStmtTreeMirror::tChildrenVector::const_iterator 
+StmtCollector::tStmtTreeMirror::find(tChildrenVector::const_iterator b, tChildrenVector::const_iterator e, Stmt*S)
+{
+  for (; b != e; ++b)
+  {
+    if ((*b)->m_OriginalStmt == S)
+    {
+      break;
+    }
+  }
+  return b;
+}
+
+//--------------------------------------------------------- 
+// returns false, if the parent must be rewritten
+bool StmtCollector::tStmtTreeMirror::compareOneLevel(tReplaceInfo& sourceRanges)
+{
+  if (m_OriginalStmt == 0)
+  {
+    return true;    // we are only here, if the new stmt is also 0
+  }
+
+  tChildrenVector::const_iterator originalStmts = m_Children.begin();
+  tChildrenVector::const_iterator originalStmtsEnd = m_Children.end();
+  Stmt::child_iterator newStmts = m_OriginalStmt->child_begin();
+  Stmt::child_iterator newStmtsEnd = m_OriginalStmt->child_end();
+  if (originalStmts == originalStmtsEnd)
+  {
+    return newStmts == newStmtsEnd;   // replace the complete parent node, if it had no sub-nodes before
+  }
+  if (newStmts == newStmtsEnd)
+  {
+    SourceRange replaceRange = (*originalStmts)->m_SourceRange;
+    replaceRange.setEnd((*--originalStmtsEnd)->m_SourceRange.getEnd());
+    sourceRanges.push_back(std::make_pair(replaceRange, tStmtCollection()));
+    return true;
+  }
+
+  tReplaceInfo localSourceRanges;
+
+
+  while (originalStmts != originalStmtsEnd && newStmts != newStmtsEnd)
+  {
+    SourceRange replaceRange = (*originalStmts)->m_SourceRange;
+
+    while (originalStmts != originalStmtsEnd && 
+           newStmts != newStmtsEnd && 
+           (*originalStmts)->m_OriginalStmt == *newStmts)
+    {
+      replaceRange = (*originalStmts)->m_SourceRange;
+      if (!(*originalStmts)->compareOneLevel(localSourceRanges))
+      {
+        localSourceRanges.push_back(std::make_pair(replaceRange, tStmtCollection()));
+        localSourceRanges.back().second.push_back(*newStmts);
+      }
+      ++originalStmts;
+      ++newStmts;
+    }
+
+    // here we are at a point where the original and new stmt sequence differ
+    replaceRange.setBegin(replaceRange.getEnd());
+    tStmtCollection insertedStmts;
+    for (; originalStmts != originalStmtsEnd; ++originalStmts)
+    {
+      Stmt::child_iterator i = std::find(newStmts, newStmtsEnd, (*originalStmts)->m_OriginalStmt);
+      if (i != newStmtsEnd)
+      {
+        //the current original statement is in the new statement sequence, so lets rewrite until there:
+        insertedStmts.insert(insertedStmts.end(), newStmts, i);
+        newStmts = i;
+        break;
+      }
+
+      // the current original statement was removed, so add its source range to the current rewrite range 
+      const SourceRange& mergeRange = (*originalStmts)->m_SourceRange;
+      if (replaceRange.getBegin() == replaceRange.getEnd())
+      {
+        replaceRange.setBegin(mergeRange.getBegin());
+      }
+      replaceRange.setEnd(mergeRange.getEnd());
+
+      // now try to replace pairwise to keep the replace block as small as possible:
+      /*if (newStmts != newStmtsEnd && 
+          find(originalStmts, originalStmtsEnd, *newStmts) == originalStmtsEnd)
+      {
+        localSourceRanges.push_back(std::make_pair(replaceRange, insertedStmts));
+        localSourceRanges.back().second.push_back(*newStmts);
+        replaceRange.setBegin(replaceRange.getEnd()); 
+        ++newStmts;
+      }*/
+    }
+    if (originalStmts == originalStmtsEnd)
+    {
+      insertedStmts.insert(insertedStmts.end(), newStmts, newStmtsEnd);
+    }
+    if (replaceRange.getBegin() == replaceRange.getEnd())
+    {
+      if (insertedStmts.empty())
+      {
+        assert(originalStmts == originalStmtsEnd && newStmts == newStmtsEnd && "should not happen");
+        break;
+      }
+
+      // now it becomes difficult: we have new statements but no old statements to replace
+      // instead of returning false and thus rewriting the complete parent block we 
+      // add an adjacent original stmt and its equal new statement to the rewrite
+      if (originalStmts != originalStmtsEnd)
+      {
+        // the easy case: just add the following statement pair to the rewrite:
+        assert(*newStmts == (*originalStmts)->m_OriginalStmt);
+        insertedStmts.push_back(*newStmts);
+        replaceRange = (*originalStmts)->m_SourceRange;
+        ++originalStmts;
+        ++newStmts;
+      }
+      else
+      {
+        // the difficult case: add the previous statement pair to the rewrite
+
+        // if we have statements to insert, we are lost, since no original source range 
+        // could computed, trash already collected ranges and rewrite the complete parent
+        return false;
+      }
+    }
+    localSourceRanges.push_back(std::make_pair(replaceRange, insertedStmts));
+  }
+  sourceRanges.splice(sourceRanges.end(), localSourceRanges);
+  return true;
+}
+  
+//--------------------------------------------------------- 
+void StmtCollector::getReplacedNodes(tReplaceInfo& sourceRanges)
+{
+  assert(m_OriginalTree.m_OriginalStmt == m_Root && "never replace the root! BTW: how did you managed this?");
+  if (!m_OriginalTree.compareOneLevel(sourceRanges))
+  {
+    sourceRanges.clear();
+    sourceRanges.push_back(std::make_pair(m_OriginalTree.m_SourceRange, tStmtCollection()));
+    sourceRanges.back().second.push_back(m_Root);
+  }
+}
+
+//--------------------------------------------------------- 
+void StmtCollector::attachComment(Stmt* S, const char* pComment)
+{
+  m_CommentCollector->m_AttachedComments[S].push_back(pComment);
+}
+
+//--------------------------------------------------------- 
+bool StmtCollector::CommentPrinter::handledStmt(Stmt* E, llvm::raw_ostream& OS, unsigned IndentLevel)
+{
+  tCommentMap::iterator stmtComments = m_AttachedComments.find(E);
+  if (stmtComments != m_AttachedComments.end())
+  {
+    for (int i = 0, e = IndentLevel; i < e; ++i)
+    {
+      OS << " ";
+    }
+    for (tCommentCollection::iterator i = stmtComments->second.begin(), e = stmtComments->second.end(); i != e; ++i)
+    {
+      OS << "// " << *i << "\n";
+    }
+  }
+  return false;
+}
+
+//--------------------------------------------------------- 
+unsigned StmtCollector::getIndentLevel(Stmt* S) const
+{
+  if (Expr* E = dyn_cast<Expr>(S))
+  {
+    S = m_ParentInfo.getStatementOfExpression(E);
+  }
+
+  unsigned result = 0;
+  for (; S != m_Root; S = m_ParentInfo.getParent(S))
+  {
+    if (!isa<LabelStmt>(S))
+    {
+      ++result;
+    }
+  }
+  return result;
+}
+
+//--------------------------------------------------------- 
+void StmtCollector::rewrite(Rewriter& rewriter)
+{
+  tReplaceInfo sourceRanges;
+  getReplacedNodes(sourceRanges);
+  PrintingPolicy policy(rewriter.getLangOpts());
+  policy.IndentStyle = PrintingPolicy::ANSIStyle;
+  for (tReplaceInfo::const_iterator i = sourceRanges.begin(), e = sourceRanges.end(); i != e; ++i)
+  {
+    std::string newStmtText;
+    for (tStmtCollection::const_iterator i2 = i->second.begin(), e2 = i->second.end(); i2 != e2; ++i2)
+    {
+      std::string SStr;
+      llvm::raw_string_ostream S(SStr);
+      (*i2)->printPretty(S, m_CommentCollector.get(), policy, getIndentLevel((*i2)) * policy.Indentation);
+      newStmtText += S.str();
+    }
+
+    const SourceRange& range = i->first;
+    int Size = rewriter.getRangeSize(range);
+    if (newStmtText.empty())
+    {
+      rewriter.RemoveText(range.getBegin(), Size);
+    }
+    else
+    {
+      rewriter.ReplaceText(range.getBegin(), Size, &newStmtText[0], newStmtText.size());
+    }
+  }
+}
+
+//--------------------------------------------------------- 
+} // ns clang
Index: lib/ASTProcessing/StmtEditor.cpp
===================================================================
--- lib/ASTProcessing/StmtEditor.cpp	(revision 0)
+++ lib/ASTProcessing/StmtEditor.cpp	(revision 0)
@@ -0,0 +1,237 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTProcessing/StmtEditor.h"
+#include "clang/ASTProcessing/StmtClone.h"
+#include "clang/ASTProcessing/StmtCollector.h"
+#include <algorithm>
+
+//--------------------------------------------------------- 
+namespace clang {
+
+const SourceLocation StmtEditor::nopos;
+
+//--------------------------------------------------------- 
+ASTContext& StmtEditor::Ctx()
+{
+  return m_Collector.Ctx;
+}
+
+//--------------------------------------------------------- 
+IdentifierInfo *StmtEditor::createVariable(const NamedDecl* originalVar)
+{
+  return m_Collector.m_IdentifierPolicy.createVariable(m_Collector.Ctx, originalVar);
+}
+
+//--------------------------------------------------------- 
+IdentifierInfo *StmtEditor::createLabel(const LabelStmt* originalLabel)
+{
+  return m_Collector.m_IdentifierPolicy.createLabel(m_Collector.Ctx, originalLabel);
+}
+
+//--------------------------------------------------------- 
+IfStmt* StmtEditor::If_(Expr* cond, Stmt* thenStmt, Stmt* elseStmt)
+{
+  return m_Collector.record(new(m_Collector.Ctx)IfStmt(nopos, cond, thenStmt, nopos, elseStmt));
+}
+
+//--------------------------------------------------------- 
+BinaryOperator* StmtEditor::BinaryOp_(Expr* lhs, Expr* rhs, BinaryOperator::Opcode opc)
+{
+  return m_Collector.record(new(m_Collector.Ctx)BinaryOperator(lhs, rhs, opc, lhs->getType(), nopos));
+}
+
+//--------------------------------------------------------- 
+BinaryOperator* StmtEditor::Assign_(Expr* lhs, Expr* rhs)
+{
+  return m_Collector.record(BinaryOp_(lhs, rhs, BinaryOperator::Assign));
+}
+
+//--------------------------------------------------------- 
+DeclStmt* StmtEditor::TmpVar_(QualType tmpType, Expr* init)
+{
+  VarDecl* tmpVar = VarDecl::Create(m_Collector.Ctx, &m_Collector.m_FnContext, nopos, createVariable(0), tmpType, VarDecl::None); 
+  if (init != 0)
+  {
+    tmpVar->setInit(m_Collector.Ctx, init);
+  }
+  return m_Collector.record(new(m_Collector.Ctx)DeclStmt(DeclGroupRef(tmpVar), nopos, nopos));
+}
+
+//--------------------------------------------------------- 
+DeclRefExpr* StmtEditor::DeclRef_(DeclStmt* singleVarDecl)
+{
+  assert(singleVarDecl->isSingleDecl() && isa<VarDecl>(singleVarDecl->getSingleDecl()));
+  VarDecl* VD = static_cast<VarDecl*>(singleVarDecl->getSingleDecl());
+  return m_Collector.record(new(m_Collector.Ctx)DeclRefExpr(VD, VD->getType(), nopos));
+}
+
+//--------------------------------------------------------- 
+UnaryOperator* StmtEditor::UnaryOp_(Expr* sub, UnaryOperator::Opcode opc)
+{
+  return m_Collector.record(new(m_Collector.Ctx)UnaryOperator(sub, opc, sub->getType(), nopos));
+}
+
+//--------------------------------------------------------- 
+BreakStmt* StmtEditor::Break_()
+{
+  return m_Collector.record(new(m_Collector.Ctx)BreakStmt(nopos));
+}
+
+//--------------------------------------------------------- 
+Stmt* StmtEditor::CloneInternal(Stmt* stmt, StmtCloneMapping* mapping)
+{
+  Stmt* result = m_Collector.recordAll(StmtClone(m_Collector.Ctx, mapping).Clone(stmt));
+  m_Collector.m_ParentInfo.updateParentMap(result);
+  return result;
+}
+
+//--------------------------------------------------------- 
+Expr* StmtEditor::Bool_(bool value)
+{
+  return m_Collector.record(new(m_Collector.Ctx)CXXBoolLiteralExpr(value, m_Collector.Ctx.BoolTy, nopos));
+}
+
+//--------------------------------------------------------- 
+CompoundStmt* StmtEditor::Compound_(Stmt** s, unsigned numStmts)
+{
+  return m_Collector.record(new(m_Collector.Ctx)CompoundStmt(m_Collector.Ctx, s, numStmts, nopos, nopos));
+}
+
+//--------------------------------------------------------- 
+CompoundStmt* StmtEditor::Compound_(Stmt* s1, Stmt* s2)
+{
+  Stmt* s[2] =  { s1, s2 };
+  return Compound_(s, 2);
+}
+
+//--------------------------------------------------------- 
+GotoStmt* StmtEditor::Goto_(LabelStmt* target)
+{
+  return m_Collector.record(new (m_Collector.Ctx) GotoStmt(target, nopos, nopos));
+}
+
+//--------------------------------------------------------- 
+LabelStmt* StmtEditor::Label_(Stmt* subStmt)
+{
+  return m_Collector.record(new (m_Collector.Ctx) LabelStmt(nopos, createLabel(0), subStmt));
+}
+
+//--------------------------------------------------------- 
+NullStmt* StmtEditor::NullStmt_()
+{
+  return m_Collector.record(new (m_Collector.Ctx) NullStmt(nopos));
+}
+
+//--------------------------------------------------------- 
+const QualType& StmtEditor::BoolTy_()
+{
+  return m_Collector.Ctx.BoolTy;
+}
+
+//--------------------------------------------------------- 
+Stmt* StmtEditor::replaceStatement(Stmt* from, Stmt* newStmt)
+{
+  if (from == m_Collector.m_Root)
+  {
+    assert(from == newStmt && "never replace the root, select another root or replace compund members only");
+    m_Collector.m_ParentInfo.updateParentMap(m_Collector.m_Root);
+  }
+  else
+  {
+    Stmt* parentStmt = m_Collector.m_ParentInfo.getParent(from);
+    Stmt::child_iterator i = std::find(parentStmt->child_begin(), parentStmt->child_end(), from);
+    if (i != parentStmt->child_end()) 
+    {
+      *i = newStmt;
+      m_Collector.m_ParentInfo.updateParentMap(parentStmt);
+    }
+    else
+    {
+      assert(0 && "parent-child relation broken");
+    }
+  }
+  return newStmt;
+}
+
+//--------------------------------------------------------- 
+void StmtEditor::removeStmt(Stmt* stmtToRemove)
+{
+  Stmt* parentStmt = m_Collector.m_ParentInfo.getParent(stmtToRemove);
+  if (CompoundStmt* CS = dyn_cast<CompoundStmt>(parentStmt))
+  {
+    removeStmt(CS, stmtToRemove);
+  }
+  else
+  {
+    replaceStatement(stmtToRemove, NullStmt_());
+  }
+}
+
+//--------------------------------------------------------- 
+void StmtEditor::appendStmt(CompoundStmt* S, Stmt* stmtToAppend)
+{
+  llvm::SmallVector<Stmt*, 8> allStmts(S->size() + 1);
+  std::copy(S->body_begin(), S->body_end(), allStmts.begin());
+  allStmts[S->size()] = stmtToAppend;
+  replaceStmts(S, &allStmts[0], allStmts.size());
+}
+
+//--------------------------------------------------------- 
+void StmtEditor::removeStmt(CompoundStmt* S, Stmt* stmtToRemove)
+{
+  llvm::SmallVector<Stmt*, 8> allStmts(S->size());
+  std::copy(S->body_begin(), S->body_end(), allStmts.begin());
+  std::remove(allStmts.begin(), allStmts.end(), stmtToRemove);
+  replaceStmts(S, &allStmts[0], allStmts.size() - 1);
+}
+
+//--------------------------------------------------------- 
+void StmtEditor::replaceStmts(CompoundStmt* S, Stmt **Stmts, unsigned NumStmts)
+{
+  S->setStmts(m_Collector.Ctx, Stmts, NumStmts);
+  m_Collector.m_ParentInfo.updateParentMap(S);
+}
+
+//--------------------------------------------------------- 
+Stmt* StmtEditor::getParent(Stmt* S)
+{
+  return m_Collector.m_ParentInfo.getParent(S);
+}
+
+//--------------------------------------------------------- 
+Expr* StmtEditor::getFullExpression(Expr* subexpr)
+{
+  return m_Collector.m_ParentInfo.getFullExpression(subexpr);
+}
+
+//--------------------------------------------------------- 
+Stmt* StmtEditor::getStatementOfExpression(Expr* subexpr)
+{
+  return m_Collector.m_ParentInfo.getStatementOfExpression(subexpr);
+}
+
+//--------------------------------------------------------- 
+bool StmtEditor::isOriginalStmt(Stmt* S) const
+{
+  return m_Collector.isOriginalStmt(S);
+}
+
+//--------------------------------------------------------- 
+void StmtEditor::attachComment(Stmt* S, const char* pComment)
+{
+  return m_Collector.attachComment(S, pComment);
+}
+
+//--------------------------------------------------------- 
+} // ns clang
Index: lib/ASTProcessing/Toolbox.cpp
===================================================================
--- lib/ASTProcessing/Toolbox.cpp	(revision 0)
+++ lib/ASTProcessing/Toolbox.cpp	(revision 0)
@@ -0,0 +1,392 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTProcessing/Toolbox.h"    
+#include "clang/ASTProcessing/StmtTraversal.h"    
+#include "clang/ASTProcessing/StmtEditor.h"    
+#include "clang/ASTProcessing/StmtClone.h"    
+#include "clang/AST/StmtVisitor.h"    
+
+using namespace std::tr1::placeholders;
+
+//--------------------------------------------------------- 
+namespace clang {
+
+namespace ASTProcessing {
+
+namespace {
+
+//--------------------------------------------------------- 
+struct RenameLabels : StmtVisitor<RenameLabels>, StmtEditor
+{
+  RenameLabels(StmtEditor& editor) : StmtEditor(editor) {}
+
+  void VisitLabelStmt(LabelStmt* label) 
+  { 
+    label->setID(createLabel(label));
+  }
+};
+
+//--------------------------------------------------------- 
+struct RechainRefs : StmtVisitor<RechainRefs> 
+{
+  const StmtCloneMapping& m_ClonedStmts;
+  RechainRefs(const StmtCloneMapping& clonedStmts) : m_ClonedStmts(clonedStmts) {}
+
+  void VisitGotoStmt(GotoStmt* Node) 
+  { 
+    StmtClone::StmtMapping::const_iterator i = m_ClonedStmts.m_StmtMapping.find(Node->getLabel());
+    if (i != m_ClonedStmts.m_StmtMapping.end())
+    {
+      Node->setLabel(static_cast<LabelStmt*>(i->second));
+    }
+  }
+
+  void VisitDeclRefExpr(DeclRefExpr* Node)
+  {
+    StmtClone::DeclMapping::const_iterator i = m_ClonedStmts.m_DeclMapping.find(Node->getDecl());
+    if (i != m_ClonedStmts.m_DeclMapping.end())
+    {
+      Node->setDecl(i->second);
+    }
+  }
+
+  void VisitSwitchStmt(SwitchStmt* Node)
+  { 
+    StmtClone::StmtMapping::const_iterator i = m_ClonedStmts.m_StmtMapping.find(Node->getSwitchCaseList());
+    if (i != m_ClonedStmts.m_StmtMapping.end())
+    {
+      Node->setSwitchCaseList(static_cast<SwitchCase*>(i->second));
+    }
+  }
+
+  void VisitAddrLabelExpr(AddrLabelExpr* Node)
+  { 
+    StmtClone::StmtMapping::const_iterator i = m_ClonedStmts.m_StmtMapping.find(Node->getLabel());
+    if (i != m_ClonedStmts.m_StmtMapping.end())
+    {
+      Node->setLabel(static_cast<LabelStmt*>(i->second));
+    }
+  }
+};
+
+//--------------------------------------------------------- 
+struct FlattenBlocks : public StmtVisitor<FlattenBlocks>, StmtEditor
+{
+  bool m_bAllBlocks;
+
+  FlattenBlocks(StmtEditor& editor, bool bAllBlocks) : StmtEditor(editor), m_bAllBlocks(bAllBlocks) {}
+
+  void VisitCompoundStmt(CompoundStmt* Node)
+  {
+    std::vector<Stmt*> newStmts;
+    bool result = false;
+    for (llvm::df_iterator<Stmt*> i = ++llvm::df_iterator<Stmt*>::begin(Node), e = llvm::df_iterator<Stmt*>::end(Node); i != e;)
+    {
+      if (dyn_cast<CompoundStmt>(*i) != 0 && (m_bAllBlocks || !isOriginalStmt(*i)))
+      {
+        ++i;  // dive into childs
+        result = true;
+      }
+      else
+      {
+        newStmts.push_back(*i);
+        i.skipChildren();
+      }
+    }
+    if (result)
+    {
+      replaceStmts(Node, &newStmts[0], newStmts.size());
+    }
+  }
+};
+
+//--------------------------------------------------------- 
+struct RemoveGotosToNextLabel : public StmtVisitor<RemoveGotosToNextLabel>, StmtEditor
+{
+  typedef llvm::DenseMap<LabelStmt*, int> tTouchedLabels;
+  tTouchedLabels m_TouchedLabels;
+
+  RemoveGotosToNextLabel(StmtEditor& editor) : StmtEditor(editor) {}
+
+  void VisitCompoundStmt(CompoundStmt* Node)
+  {
+    llvm::SmallVector<Stmt*, 8> newStmts(Node->size());
+    size_t stmtPos = 0;
+    for (Stmt::child_iterator i = Node->child_begin(), e = Node->child_end(); i != e; ++i)
+    {
+      if (GotoStmt* GS = dyn_cast<GotoStmt>(*i))
+      {
+        Stmt::child_iterator nextStmt = i;
+        ++nextStmt;
+        if (nextStmt != e && (!isOriginalStmt(GS->getLabel())) && *nextStmt == GS->getLabel())
+        {
+          if (!isOriginalStmt(GS->getLabel()))
+          {
+            m_TouchedLabels[GS->getLabel()];    // initializes with 0, if not present; otherwise left untouched
+          }
+          continue;
+        }
+      }
+      newStmts[stmtPos++] = *i;
+    }
+    if (stmtPos != newStmts.size())
+    {
+      replaceStmts(Node, &newStmts[0], stmtPos);
+    }
+  }
+
+  void VisitGotoStmt(GotoStmt* Node)
+  {
+    m_TouchedLabels[Node->getLabel()] = 1;
+  }
+};
+
+//--------------------------------------------------------- 
+struct MoveDeclsToFirstWrite : public StmtVisitor<MoveDeclsToFirstWrite>, StmtEditor
+{
+  MoveDeclsToFirstWrite(StmtEditor& editor) : StmtEditor(editor) {} 
+
+  static bool findFirstAssign(Stmt* node, NamedDecl* varDecl)
+  {
+    BinaryOperator* binOp = dyn_cast<BinaryOperator>(node);
+    if (binOp != 0 && binOp->getOpcode() == BinaryOperator::Assign)
+    {
+      DeclRefExpr* refExpr = dyn_cast<DeclRefExpr>(binOp->getLHS());
+      return refExpr != 0 && refExpr->getDecl() == varDecl;
+    }
+    return false;
+  }
+
+
+  void VisitCompoundStmt(CompoundStmt* Node)
+  {
+    llvm::SmallVector<Stmt*, 8> newStmts(Node->size());
+    size_t stmtPos = 0;
+    for (Stmt::child_iterator i = Node->child_begin(), e = Node->child_end(); i != e; ++i)
+    {
+      DeclStmt* DS = dyn_cast<DeclStmt>(*i);
+      if (DS && DS->isSingleDecl() && !isOriginalStmt(DS))
+      {
+        VarDecl* VD = dyn_cast<VarDecl>(DS->getSingleDecl());
+        if (VD && VD->getInit() == 0)
+        {
+          Stmt::child_iterator firstAssign = std::find_if(i, e, std::tr1::bind(&MoveDeclsToFirstWrite::findFirstAssign, _1, VD));
+          if (firstAssign != e)
+          {
+            BinaryOperator* binOp = dyn_cast<BinaryOperator>(*firstAssign);
+            assert(binOp);
+            VD->setInit(Ctx(), binOp->getRHS());
+            *firstAssign = DS;
+            continue;
+          }
+        }
+      }
+      newStmts[stmtPos++] = *i;
+    }
+    if (stmtPos != newStmts.size())
+    {
+      replaceStmts(Node, &newStmts[0], stmtPos);
+    }
+  }
+};
+
+//--------------------------------------------------------- 
+struct CountVarUses : public StmtVisitor<CountVarUses>, StmtEditor
+{
+  typedef llvm::DenseMap<VarDecl*, std::pair<DeclStmt*, int> > tVarRefCountMap;
+  tVarRefCountMap m_VarUseCount;
+
+  CountVarUses(StmtEditor& editor) : StmtEditor(editor) {} 
+
+  void VisitDeclStmt(DeclStmt* Node)
+  {
+    if ((!isOriginalStmt(Node)) && Node->isSingleDecl())
+    {
+      if (VarDecl* VD = dyn_cast<VarDecl>(Node->getSingleDecl()))
+      {
+        m_VarUseCount[VD] = std::make_pair(Node, 0);
+      }
+    }
+  }
+
+  void VisitDeclRefExpr(DeclRefExpr* Node)
+  {
+    if (VarDecl* VD = dyn_cast<VarDecl>(Node->getDecl()))
+    {
+      tVarRefCountMap::iterator i = m_VarUseCount.find(VD);
+      if (i != m_VarUseCount.end())
+      {
+        ++i->second.second;
+      }
+    }
+  }
+};
+
+//--------------------------------------------------------- 
+struct ExpandVariableRefs : public StmtVisitor<ExpandVariableRefs>, StmtEditor
+{
+  VarDecl*  m_VarDecl;
+  bool      m_bCloneInitExpr;
+
+  ExpandVariableRefs(StmtEditor& editor, VarDecl* varDecl, bool bCloneInitExpr) : 
+    StmtEditor(editor), m_VarDecl(varDecl), m_bCloneInitExpr(bCloneInitExpr) 
+  { 
+    assert (m_VarDecl->getInit()); 
+  }
+
+  void VisitDeclRefExpr(DeclRefExpr* Node)
+  {
+    if (Node->getDecl() == m_VarDecl)
+    {
+      replaceStatement(Node, m_bCloneInitExpr ? Clone_(m_VarDecl->getInit()) : m_VarDecl->getInit());
+    }
+  }
+};
+
+
+struct RemoveStmtsAfterBreakAndContinue : public StmtVisitor<RemoveStmtsAfterBreakAndContinue>, StmtEditor
+{
+  RemoveStmtsAfterBreakAndContinue(StmtEditor& editor) : StmtEditor(editor) {} 
+
+  void VisitCompoundStmt(CompoundStmt* Node)
+  {
+    for (CompoundStmt::body_iterator i = Node->body_begin(), e = Node->body_end(); i != e; ++i)
+    {
+      if (isa<BreakStmt>(*i) || isa<ContinueStmt>(*i))
+      {
+        ++i;
+        if (i != e)
+        {
+          llvm::SmallVector<Stmt*, 8> allStmts(Node->body_begin(), i);
+          replaceStmts(Node, &allStmts[0], allStmts.size());
+        }
+        break;
+      }
+    }
+  }
+};
+
+//--------------------------------------------------------- 
+} // anon namespace 
+
+
+//--------------------------------------------------------- 
+// generate new names for all cloned labels and all cloned declarations
+void generateNamesForClones(const StmtCloneMapping& cloneMapping, StmtEditor& editor)
+{
+  for (StmtClone::DeclMapping::iterator i = cloneMapping.m_DeclMapping.begin(), e = cloneMapping.m_DeclMapping.end(); i != e; ++i)
+  {
+    i->second->setDeclName(DeclarationName(editor.createVariable(i->second)));
+  }
+
+  RenameLabels labelVisitor(editor);
+  for (StmtClone::StmtMapping::const_iterator i = cloneMapping.m_StmtMapping.begin(), e = cloneMapping.m_StmtMapping.end(); i != e; ++i)
+  {  
+    labelVisitor.Visit(i->second);
+  }
+}
+
+//--------------------------------------------------------- 
+// rechain label refernces (from GotoStmt, AddrLabelExpr), variable references (from DeclRefExpr),
+// SwitchCase lists (from SwitchStmt) to their respective clones
+// Node is expected to be the clone
+void rechainRefs(const StmtCloneMapping& cloneMapping, Stmt* Node)
+{
+  visit_df(Node, RechainRefs(cloneMapping));
+}
+
+//--------------------------------------------------------- 
+Stmt* cloneStmtTreeInternal(StmtEditor& editor, Stmt* Node, StmtCloneMapping* pCloneMapping)
+{
+  StmtClone::Mapping cloneMap;
+  if (pCloneMapping == 0)
+  {
+    pCloneMapping = &cloneMap;
+  }
+  Stmt* Node_copy = editor.Clone_(Node, pCloneMapping);
+  generateNamesForClones(*pCloneMapping, editor);
+  rechainRefs(*pCloneMapping, Node_copy);
+  return Node_copy;
+}
+
+//--------------------------------------------------------- 
+void flattenBlocks(StmtEditor& editor, Stmt* Node, bool bAllBlocks)
+{
+  visit_df(Node, FlattenBlocks(editor, bAllBlocks));
+}
+
+//--------------------------------------------------------- 
+void removeGotosToNextLabel(StmtEditor& editor, Stmt* Node)
+{
+  RemoveGotosToNextLabel visitor(editor);
+  visit_df(Node, visitor);
+  for (RemoveGotosToNextLabel::tTouchedLabels::iterator i = visitor.m_TouchedLabels.begin(), 
+       e = visitor.m_TouchedLabels.end(); i != e; ++i)
+  {
+    if (i->second == 0)
+    {
+      CompoundStmt* CS = dyn_cast<CompoundStmt>(editor.getParent(i->first));
+      if (CS && CS->size() > 1 && isa<NullStmt>(i->first->getSubStmt()))
+      {
+        editor.removeStmt(CS, i->first);
+      }
+      else
+      {
+        editor.replaceStatement(i->first, i->first->getSubStmt());
+      }
+    }
+  }
+}
+
+//--------------------------------------------------------- 
+void moveDeclsToFirstWrite(StmtEditor& editor, Stmt* Node)
+{
+  visit_df(Node, MoveDeclsToFirstWrite(editor));
+}
+
+//--------------------------------------------------------- 
+void expandOneUsedInitDeclsToUse(StmtEditor& editor, Stmt* Node)
+{
+  CountVarUses visitor(editor);
+  visit_df(Node, visitor);
+  for (CountVarUses::tVarRefCountMap::iterator i = visitor.m_VarUseCount.begin(), 
+       e = visitor.m_VarUseCount.end(); i != e; ++i)
+  {
+    if (i->second.second < 2)
+    {
+      CompoundStmt* CS = dyn_cast<CompoundStmt>(editor.getParent(i->second.first));
+      if (CS && CS->size() > 1)
+      {
+        if (i->second.second > 0)
+        {
+          visit_df(Node, ExpandVariableRefs(editor, i->first, false));
+          i->first->setInit(editor.Ctx(), 0); // ownership was transferred, so don't confuse anyone after us
+        }
+        editor.removeStmt(CS, i->second.first);
+      }
+    }
+  }
+}
+
+//--------------------------------------------------------- 
+void removeStmtsAfterBreakAndContinue(StmtEditor& editor, Stmt* Node)
+{
+  visit_df(Node, RemoveStmtsAfterBreakAndContinue(editor));
+}
+
+//--------------------------------------------------------- 
+} // namespace ASTProcessing
+
+} // namespace clang
+
Index: lib/CMakeLists.txt
===================================================================
--- lib/CMakeLists.txt	(revision 74519)
+++ lib/CMakeLists.txt	(working copy)
@@ -3,6 +3,7 @@
 add_subdirectory(Lex)
 add_subdirectory(Parse)
 add_subdirectory(AST)
+add_subdirectory(ASTProcessing)
 add_subdirectory(Sema)
 add_subdirectory(CodeGen)
 add_subdirectory(Analysis)
Index: lib/Makefile
===================================================================
--- lib/Makefile	(revision 74519)
+++ lib/Makefile	(working copy)
@@ -8,7 +8,7 @@
 ##===----------------------------------------------------------------------===##
 LEVEL = ../../..
 
-PARALLEL_DIRS = Headers Basic Lex Parse AST Sema CodeGen Analysis Rewrite \
+PARALLEL_DIRS = Headers Basic Lex Parse AST ASTProcessing Sema CodeGen Analysis Rewrite \
 	Frontend Driver
 
 include $(LEVEL)/Makefile.common
Index: tools/min-clang-AST/min-clang-AST.cpp
===================================================================
--- tools/min-clang-AST/min-clang-AST.cpp	(revision 0)
+++ tools/min-clang-AST/min-clang-AST.cpp	(revision 0)
@@ -0,0 +1,1431 @@
+//===--- clang.cpp - C-Language Front-end ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This utility may be invoked in the following manner:
+//   clang --help                - Output help info.
+//   clang [options]             - Read from stdin.
+//   clang [options] file        - Read from "file".
+//   clang [options] file1 file2 - Read these files.
+//
+//===----------------------------------------------------------------------===//
+//
+// TODO: Options to support:
+//
+//   -Wfatal-errors
+//   -ftabstop=width
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Frontend/CompileOptions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/InitHeaderSearch.h"
+#include "clang/Frontend/InitPreprocessor.h"
+#include "clang/Frontend/Utils.h"
+
+
+#include "clang/Analysis/PathDiagnostic.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/Sema/ParseAST.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PluginLoader.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Streams.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Host.h"
+#include "llvm/System/Path.h"
+#include "llvm/System/Process.h"
+#include "llvm/System/Program.h"
+#include "llvm/System/Signals.h"
+#include <cstdlib>
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+
+namespace clang {
+// ObjC rewriter: attempts tp rewrite ObjC constructs into pure C code.
+// This is considered experimental, and only works with Apple's ObjC runtime.
+ASTConsumer *CreateInlineRewriter(const std::string& InFile,
+                                llvm::raw_ostream* OS,
+                                Diagnostic &Diags,
+                                const LangOptions &LOpts);
+
+}
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Global options.
+//===----------------------------------------------------------------------===//
+
+static bool HadErrors = false;
+
+static llvm::cl::opt<bool>
+Verbose("v", llvm::cl::desc("Enable verbose output"));
+
+enum ProgActions {
+  RewriteObjC,                  // ObjC->C Rewriter.
+  RewriteTest,                  // Rewriter playground
+  ASTPrintXML,                  // Parse ASTs and print them in XML.
+};
+
+static llvm::cl::opt<ProgActions> 
+ProgAction(llvm::cl::desc("Choose output type:"), llvm::cl::ZeroOrMore,
+           llvm::cl::init(RewriteObjC),
+           llvm::cl::values(
+             clEnumValN(ASTPrintXML, "ast-print-xml",
+                        "Build ASTs and then print them in XML format"),
+             clEnumValN(RewriteTest, "rewrite-test",
+                        "Rewriter playground"),
+             clEnumValN(RewriteObjC, "rewrite-objc",
+                        "Rewrite ObjC into C (code rewriter example)"),
+             clEnumValEnd));
+
+
+static llvm::cl::opt<std::string>
+OutputFile("o",
+ llvm::cl::value_desc("path"),
+ llvm::cl::desc("Specify output file"));
+
+
+//===----------------------------------------------------------------------===//
+// Diagnostic Options
+//===----------------------------------------------------------------------===//
+
+static llvm::cl::opt<bool>
+NoShowColumn("fno-show-column",
+             llvm::cl::desc("Do not include column number on diagnostics"));
+
+static llvm::cl::opt<bool>
+NoShowLocation("fno-show-source-location",
+               llvm::cl::desc("Do not include source location information with"
+                              " diagnostics"));
+
+static llvm::cl::opt<bool>
+NoCaretDiagnostics("fno-caret-diagnostics",
+                   llvm::cl::desc("Do not include source line and caret with"
+                                  " diagnostics"));
+
+static llvm::cl::opt<bool>
+NoDiagnosticsFixIt("fno-diagnostics-fixit-info",
+                   llvm::cl::desc("Do not include fixit information in"
+                                  " diagnostics"));
+
+static llvm::cl::opt<bool>
+PrintSourceRangeInfo("fdiagnostics-print-source-range-info",
+                     llvm::cl::desc("Print source range spans in numeric form"));
+
+static llvm::cl::opt<bool>
+PrintDiagnosticOption("fdiagnostics-show-option",
+             llvm::cl::desc("Print diagnostic name with mappable diagnostics"));
+
+static llvm::cl::opt<unsigned>
+MessageLength("fmessage-length",
+	      llvm::cl::desc("Format message diagnostics so that they fit "
+			     "within N columns or fewer, when possible."),
+	      llvm::cl::value_desc("N"));
+
+//===----------------------------------------------------------------------===//
+// Builtin Options
+//===----------------------------------------------------------------------===//
+
+static llvm::cl::opt<bool>
+Freestanding("ffreestanding",
+             llvm::cl::desc("Assert that the compilation takes place in a "
+                            "freestanding environment"));
+
+static llvm::cl::opt<bool>
+AllowBuiltins("fbuiltin", llvm::cl::init(true),
+             llvm::cl::desc("Disable implicit builtin knowledge of functions"));
+
+
+static llvm::cl::opt<bool>
+MathErrno("fmath-errno", llvm::cl::init(true),
+          llvm::cl::desc("Require math functions to respect errno"));
+
+//===----------------------------------------------------------------------===//
+// Language Options
+//===----------------------------------------------------------------------===//
+
+enum LangKind {
+  langkind_unspecified,
+  langkind_c,
+  langkind_c_cpp,
+  langkind_asm_cpp,
+  langkind_cxx,
+  langkind_cxx_cpp,
+  langkind_objc,
+  langkind_objc_cpp,
+  langkind_objcxx,
+  langkind_objcxx_cpp
+};
+
+static llvm::cl::opt<LangKind>
+BaseLang("x", llvm::cl::desc("Base language to compile"),
+         llvm::cl::init(langkind_unspecified),
+   llvm::cl::values(clEnumValN(langkind_c,     "c",            "C"),
+                    clEnumValN(langkind_cxx,   "c++",          "C++"),
+                    clEnumValN(langkind_objc,  "objective-c",  "Objective C"),
+                    clEnumValN(langkind_objcxx,"objective-c++","Objective C++"),
+                    clEnumValN(langkind_c_cpp,     "cpp-output",
+                               "Preprocessed C"),
+                    clEnumValN(langkind_asm_cpp,     "assembler-with-cpp",
+                               "Preprocessed asm"),
+                    clEnumValN(langkind_cxx_cpp,   "c++-cpp-output",
+                               "Preprocessed C++"),
+                    clEnumValN(langkind_objc_cpp,  "objective-c-cpp-output",
+                               "Preprocessed Objective C"),
+                    clEnumValN(langkind_objcxx_cpp, "objective-c++-cpp-output",
+                               "Preprocessed Objective C++"),
+                    clEnumValN(langkind_c, "c-header",
+                               "C header"),
+                    clEnumValN(langkind_objc, "objective-c-header",
+                               "Objective-C header"),
+                    clEnumValN(langkind_cxx, "c++-header",
+                               "C++ header"),
+                    clEnumValN(langkind_objcxx, "objective-c++-header",
+                               "Objective-C++ header"),
+                    clEnumValEnd));
+
+static llvm::cl::opt<bool>
+LangObjC("ObjC", llvm::cl::desc("Set base language to Objective-C"),
+         llvm::cl::Hidden);
+static llvm::cl::opt<bool>
+LangObjCXX("ObjC++", llvm::cl::desc("Set base language to Objective-C++"),
+           llvm::cl::Hidden);
+
+static llvm::cl::opt<bool>
+ObjCExclusiveGC("fobjc-gc-only",
+                llvm::cl::desc("Use GC exclusively for Objective-C related "
+                               "memory management"));
+
+static llvm::cl::opt<bool>
+ObjCEnableGC("fobjc-gc",
+             llvm::cl::desc("Enable Objective-C garbage collection"));
+
+static llvm::cl::opt<bool>
+ObjCEnableGCBitmapPrint("print-ivar-layout",
+             llvm::cl::desc("Enable Objective-C Ivar layout bitmap print trace"));
+
+static llvm::cl::opt<LangOptions::VisibilityMode>
+SymbolVisibility("fvisibility",
+                 llvm::cl::desc("Set the default symbol visibility:"),
+                 llvm::cl::init(LangOptions::Default),
+                 llvm::cl::values(clEnumValN(LangOptions::Default, "default",
+                                             "Use default symbol visibility"),
+                                  clEnumValN(LangOptions::Hidden, "hidden",
+                                             "Use hidden symbol visibility"),
+                                  clEnumValN(LangOptions::Protected,"protected",
+                                             "Use protected symbol visibility"),
+                                  clEnumValEnd));
+
+static llvm::cl::opt<bool>
+OverflowChecking("ftrapv",
+                 llvm::cl::desc("Trap on integer overflow"),
+                 llvm::cl::init(false));
+
+static llvm::cl::opt<bool>
+ObjCSenderDispatch("fobjc-sender-dependent-dispatch",
+				 llvm::cl::desc("Enable sender-dependent dispatch for"
+					 "Objective-C messages"), llvm::cl::init(false));
+
+/// InitializeBaseLanguage - Handle the -x foo options.
+static void InitializeBaseLanguage() {
+  if (LangObjC)
+    BaseLang = langkind_objc;
+  else if (LangObjCXX)
+    BaseLang = langkind_objcxx;
+}
+
+static LangKind GetLanguage(const std::string &Filename) {
+  if (BaseLang != langkind_unspecified)
+    return BaseLang;
+  
+  std::string::size_type DotPos = Filename.rfind('.');
+
+  if (DotPos == std::string::npos) {
+    BaseLang = langkind_c;  // Default to C if no extension.
+    return langkind_c;
+  }
+  
+  std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
+  // C header: .h
+  // C++ header: .hh or .H;
+  // assembler no preprocessing: .s
+  // assembler: .S
+  if (Ext == "c")
+    return langkind_c;
+  else if (Ext == "S" ||
+           // If the compiler is run on a .s file, preprocess it as .S
+           Ext == "s")
+    return langkind_asm_cpp;
+  else if (Ext == "i")
+    return langkind_c_cpp;
+  else if (Ext == "ii")
+    return langkind_cxx_cpp;
+  else if (Ext == "m")
+    return langkind_objc;
+  else if (Ext == "mi")
+    return langkind_objc_cpp;
+  else if (Ext == "mm" || Ext == "M")
+    return langkind_objcxx;
+  else if (Ext == "mii")
+    return langkind_objcxx_cpp;
+  else if (Ext == "C" || Ext == "cc" || Ext == "cpp" || Ext == "CPP" ||
+           Ext == "c++" || Ext == "cp" || Ext == "cxx")
+    return langkind_cxx;
+  else
+    return langkind_c;
+}
+
+
+static void InitializeCOptions(LangOptions &Options) {
+    // Do nothing.
+}
+
+static void InitializeObjCOptions(LangOptions &Options) {
+  Options.ObjC1 = Options.ObjC2 = 1;
+}
+  
+
+static void InitializeLangOptions(LangOptions &Options, LangKind LK){
+  // FIXME: implement -fpreprocessed mode.
+  bool NoPreprocess = false;
+  
+  switch (LK) {
+  default: assert(0 && "Unknown language kind!");
+  case langkind_asm_cpp:
+    Options.AsmPreprocessor = 1;
+    // FALLTHROUGH
+  case langkind_c_cpp:
+    NoPreprocess = true;
+    // FALLTHROUGH
+  case langkind_c:
+    InitializeCOptions(Options);
+    break;
+  case langkind_cxx_cpp:
+    NoPreprocess = true;
+    // FALLTHROUGH
+  case langkind_cxx:
+    Options.CPlusPlus = 1;
+    break;
+  case langkind_objc_cpp:
+    NoPreprocess = true;
+    // FALLTHROUGH
+  case langkind_objc:
+    InitializeObjCOptions(Options);
+    break;
+  case langkind_objcxx_cpp:
+    NoPreprocess = true;
+    // FALLTHROUGH
+  case langkind_objcxx:
+    Options.ObjC1 = Options.ObjC2 = 1;
+    Options.CPlusPlus = 1;
+    break;
+  }
+  
+  if (ObjCExclusiveGC)
+    Options.setGCMode(LangOptions::GCOnly);
+  else if (ObjCEnableGC)
+    Options.setGCMode(LangOptions::HybridGC);
+  
+  if (ObjCEnableGCBitmapPrint)
+    Options.ObjCGCBitmapPrint = 1;
+  
+  Options.setVisibilityMode(SymbolVisibility);
+  Options.OverflowChecking = OverflowChecking;
+}
+
+/// LangStds - Language standards we support.
+enum LangStds {
+  lang_unspecified,  
+  lang_c89, lang_c94, lang_c99,
+  lang_gnu_START,
+  lang_gnu89 = lang_gnu_START, lang_gnu99,
+  lang_cxx98, lang_gnucxx98,
+  lang_cxx0x, lang_gnucxx0x
+};
+
+static llvm::cl::opt<LangStds>
+LangStd("std", llvm::cl::desc("Language standard to compile for"),
+        llvm::cl::init(lang_unspecified),
+  llvm::cl::values(clEnumValN(lang_c89,      "c89",            "ISO C 1990"),
+                   clEnumValN(lang_c89,      "c90",            "ISO C 1990"),
+                   clEnumValN(lang_c89,      "iso9899:1990",   "ISO C 1990"),
+                   clEnumValN(lang_c94,      "iso9899:199409",
+                              "ISO C 1990 with amendment 1"),
+                   clEnumValN(lang_c99,      "c99",            "ISO C 1999"),
+                   clEnumValN(lang_c99,      "c9x",            "ISO C 1999"),
+                   clEnumValN(lang_c99,      "iso9899:1999",   "ISO C 1999"),
+                   clEnumValN(lang_c99,      "iso9899:199x",   "ISO C 1999"),
+                   clEnumValN(lang_gnu89,    "gnu89",
+                              "ISO C 1990 with GNU extensions"),
+                   clEnumValN(lang_gnu99,    "gnu99",
+                              "ISO C 1999 with GNU extensions (default for C)"),
+                   clEnumValN(lang_gnu99,    "gnu9x",
+                              "ISO C 1999 with GNU extensions"),
+                   clEnumValN(lang_cxx98,    "c++98",
+                              "ISO C++ 1998 with amendments"),
+                   clEnumValN(lang_gnucxx98, "gnu++98",
+                              "ISO C++ 1998 with amendments and GNU "
+                              "extensions (default for C++)"),
+                   clEnumValN(lang_cxx0x,    "c++0x",
+                              "Upcoming ISO C++ 200x with amendments"),
+                   clEnumValN(lang_gnucxx0x, "gnu++0x",
+                              "Upcoming ISO C++ 200x with amendments and GNU "
+                              "extensions"),
+                   clEnumValEnd));
+
+static llvm::cl::opt<bool>
+NoOperatorNames("fno-operator-names",
+                llvm::cl::desc("Do not treat C++ operator name keywords as "
+                               "synonyms for operators"));
+
+static llvm::cl::opt<bool>
+PascalStrings("fpascal-strings",
+              llvm::cl::desc("Recognize and construct Pascal-style "
+                             "string literals"));
+                             
+static llvm::cl::opt<bool>
+MSExtensions("fms-extensions",
+             llvm::cl::desc("Accept some non-standard constructs used in "
+                            "Microsoft header files "));
+
+static llvm::cl::opt<bool>
+WritableStrings("fwritable-strings",
+              llvm::cl::desc("Store string literals as writable data"));
+
+static llvm::cl::opt<bool>
+NoLaxVectorConversions("fno-lax-vector-conversions",
+                       llvm::cl::desc("Disallow implicit conversions between "
+                                      "vectors with a different number of "
+                                      "elements or different element types"));
+
+static llvm::cl::opt<bool>
+EnableBlocks("fblocks", llvm::cl::desc("enable the 'blocks' language feature"));
+
+static llvm::cl::opt<bool>
+EnableHeinousExtensions("fheinous-gnu-extensions",
+   llvm::cl::desc("enable GNU extensions that you really really shouldn't use"),
+                        llvm::cl::ValueDisallowed, llvm::cl::Hidden);
+
+static llvm::cl::opt<bool>
+ObjCNonFragileABI("fobjc-nonfragile-abi",
+                  llvm::cl::desc("enable objective-c's nonfragile abi"));
+
+
+static llvm::cl::opt<bool>
+EmitAllDecls("femit-all-decls",
+              llvm::cl::desc("Emit all declarations, even if unused"));
+
+static llvm::cl::opt<bool>
+Exceptions("fexceptions",
+           llvm::cl::desc("Enable support for exception handling"));
+
+static llvm::cl::opt<bool>
+GNURuntime("fgnu-runtime",
+            llvm::cl::desc("Generate output compatible with the standard GNU "
+                           "Objective-C runtime"));
+
+static llvm::cl::opt<bool>
+NeXTRuntime("fnext-runtime",
+            llvm::cl::desc("Generate output compatible with the NeXT "
+                           "runtime"));
+
+
+
+static llvm::cl::opt<bool>
+Trigraphs("trigraphs", llvm::cl::desc("Process trigraph sequences"));
+
+static llvm::cl::opt<unsigned>
+TemplateDepth("ftemplate-depth", llvm::cl::init(99),
+              llvm::cl::desc("Maximum depth of recursive template "
+                             "instantiation"));
+static llvm::cl::opt<bool>
+DollarsInIdents("fdollars-in-identifiers",
+                llvm::cl::desc("Allow '$' in identifiers"));
+
+
+static llvm::cl::opt<bool>
+OptSize("Os", llvm::cl::desc("Optimize for size"));
+
+static llvm::cl::opt<bool>
+NoCommon("fno-common",
+         llvm::cl::desc("Compile common globals like normal definitions"),
+         llvm::cl::ValueDisallowed);
+
+static llvm::cl::opt<std::string>
+MainFileName("main-file-name",
+             llvm::cl::desc("Main file name to use for debug info"));
+
+// FIXME: Also add an "-fno-access-control" option.
+static llvm::cl::opt<bool>
+AccessControl("faccess-control", 
+              llvm::cl::desc("Enable C++ access control"));
+
+// It might be nice to add bounds to the CommandLine library directly.
+struct OptLevelParser : public llvm::cl::parser<unsigned> {
+  bool parse(llvm::cl::Option &O, const char *ArgName,
+             const std::string &Arg, unsigned &Val) {
+    if (llvm::cl::parser<unsigned>::parse(O, ArgName, Arg, Val))
+      return true;
+    if (Val > 3)
+      return O.error(": '" + Arg + "' invalid optimization level!");
+    return false;
+  }
+};
+static llvm::cl::opt<unsigned, false, OptLevelParser>
+OptLevel("O", llvm::cl::Prefix,
+         llvm::cl::desc("Optimization level"),
+         llvm::cl::init(0));
+
+static llvm::cl::opt<unsigned>
+PICLevel("pic-level", llvm::cl::desc("Value for __PIC__"));
+
+static llvm::cl::opt<bool>
+StaticDefine("static-define", llvm::cl::desc("Should __STATIC__ be defined"));
+
+static void InitializeLanguageStandard(LangOptions &Options, LangKind LK,
+                                       TargetInfo *Target,
+                                       const llvm::StringMap<bool> &Features) {
+  // Allow the target to set the default the langauge options as it sees fit.
+  Target->getDefaultLangOptions(Options);
+
+  // Pass the map of target features to the target for validation and
+  // processing.
+  Target->HandleTargetFeatures(Features);
+  
+  if (LangStd == lang_unspecified) {
+    // Based on the base language, pick one.
+    switch (LK) {
+    case lang_unspecified: assert(0 && "Unknown base language");
+    case langkind_c:
+    case langkind_asm_cpp:
+    case langkind_c_cpp:
+    case langkind_objc:
+    case langkind_objc_cpp:
+      LangStd = lang_gnu99;
+      break;
+    case langkind_cxx:
+    case langkind_cxx_cpp:
+    case langkind_objcxx:
+    case langkind_objcxx_cpp:
+      LangStd = lang_gnucxx98;
+      break;
+    }
+  }
+  
+  switch (LangStd) {
+  default: assert(0 && "Unknown language standard!");
+
+  // Fall through from newer standards to older ones.  This isn't really right.
+  // FIXME: Enable specifically the right features based on the language stds.
+  case lang_gnucxx0x:
+  case lang_cxx0x:
+    Options.CPlusPlus0x = 1;
+    // FALL THROUGH
+  case lang_gnucxx98:
+  case lang_cxx98:
+    Options.CPlusPlus = 1;
+    Options.CXXOperatorNames = !NoOperatorNames;
+    // FALL THROUGH.
+  case lang_gnu99:
+  case lang_c99:
+    Options.C99 = 1;
+    Options.HexFloats = 1;
+    // FALL THROUGH.
+  case lang_gnu89:
+    Options.BCPLComment = 1;  // Only for C99/C++.
+    // FALL THROUGH.
+  case lang_c94:
+    Options.Digraphs = 1;     // C94, C99, C++.
+    // FALL THROUGH.
+  case lang_c89:
+    break;
+  }
+
+  // GNUMode - Set if we're in gnu99, gnu89, gnucxx98, etc.
+  Options.GNUMode = LangStd >= lang_gnu_START;
+  
+  if (Options.CPlusPlus) {
+    Options.C99 = 0;
+    Options.HexFloats = Options.GNUMode;
+  }
+  
+  if (LangStd == lang_c89 || LangStd == lang_c94 || LangStd == lang_gnu89)
+    Options.ImplicitInt = 1;
+  else
+    Options.ImplicitInt = 0;
+  
+  // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
+  // is specified, or -std is set to a conforming mode.
+  Options.Trigraphs = !Options.GNUMode;
+  if (Trigraphs.getPosition())
+    Options.Trigraphs = Trigraphs;  // Command line option wins if specified.
+
+  // If in a conformant language mode (e.g. -std=c99) Blocks defaults to off
+  // even if they are normally on for the target.  In GNU modes (e.g.
+  // -std=gnu99) the default for blocks depends on the target settings.
+  // However, blocks are not turned off when compiling Obj-C or Obj-C++ code.
+  if (!Options.ObjC1 && !Options.GNUMode)
+    Options.Blocks = 0;
+  
+  // Default to not accepting '$' in identifiers when preprocessing assembler,
+  // but do accept when preprocessing C.  FIXME: these defaults are right for
+  // darwin, are they right everywhere?
+  Options.DollarIdents = LK != langkind_asm_cpp;
+  if (DollarsInIdents.getPosition())  // Explicit setting overrides default.
+    Options.DollarIdents = DollarsInIdents;
+  
+  if (PascalStrings.getPosition())
+    Options.PascalStrings = PascalStrings;
+  Options.Microsoft = MSExtensions;
+  Options.WritableStrings = WritableStrings;
+  if (NoLaxVectorConversions.getPosition())
+      Options.LaxVectorConversions = 0;
+  Options.Exceptions = Exceptions;
+  if (EnableBlocks.getPosition())
+    Options.Blocks = EnableBlocks;
+
+  if (!AllowBuiltins)
+    Options.NoBuiltin = 1;
+  if (Freestanding)
+    Options.Freestanding = Options.NoBuiltin = 1;
+  
+  if (EnableHeinousExtensions)
+    Options.HeinousExtensions = 1;
+
+  if (AccessControl)
+    Options.AccessControl = 1;
+  
+  Options.MathErrno = MathErrno;
+
+  Options.InstantiationDepth = TemplateDepth;
+
+  // Override the default runtime if the user requested it.
+  if (NeXTRuntime)
+    Options.NeXTRuntime = 1;
+  else if (GNURuntime)
+    Options.NeXTRuntime = 0;
+
+  if (ObjCNonFragileABI)
+    Options.ObjCNonFragileABI = 1;
+
+  Options.ObjCSenderDispatch = ObjCSenderDispatch;
+  
+  if (EmitAllDecls)
+    Options.EmitAllDecls = 1;
+
+  // The __OPTIMIZE_SIZE__ define is tied to -Oz, which we don't
+  // support.
+  Options.OptimizeSize = 0;
+  
+  // -Os implies -O2
+  if (OptSize || OptLevel)
+    Options.Optimize = 1;
+
+  assert(PICLevel <= 2 && "Invalid value for -pic-level");
+  Options.PICLevel = PICLevel;
+
+  Options.GNUInline = !Options.C99;
+  // FIXME: This is affected by other options (-fno-inline). 
+  Options.NoInline = !OptSize && !OptLevel;
+
+  Options.Static = StaticDefine;
+
+  if (MainFileName.getPosition())
+    Options.setMainFileName(MainFileName.c_str());
+}
+
+//===----------------------------------------------------------------------===//
+// Target Triple Processing.
+//===----------------------------------------------------------------------===//
+
+static llvm::cl::opt<std::string>
+TargetTriple("triple",
+  llvm::cl::desc("Specify target triple (e.g. i686-apple-darwin9)"));
+
+static llvm::cl::opt<std::string>
+MacOSVersionMin("mmacosx-version-min", 
+                llvm::cl::desc("Specify target Mac OS X version (e.g. 10.5)"));
+
+// If -mmacosx-version-min=10.3.9 is specified, change the triple from being
+// something like powerpc-apple-darwin9 to powerpc-apple-darwin7
+
+// FIXME: We should have the driver do this instead.
+static void HandleMacOSVersionMin(std::string &Triple) {
+  std::string::size_type DarwinDashIdx = Triple.find("-darwin");
+  if (DarwinDashIdx == std::string::npos) {
+    fprintf(stderr, 
+            "-mmacosx-version-min only valid for darwin (Mac OS X) targets\n");
+    exit(1);
+  }
+  unsigned DarwinNumIdx = DarwinDashIdx + strlen("-darwin");
+  
+  // Remove the number.
+  Triple.resize(DarwinNumIdx);
+
+  // Validate that MacOSVersionMin is a 'version number', starting with 10.[3-9]
+  bool MacOSVersionMinIsInvalid = false;
+  int VersionNum = 0;
+  if (MacOSVersionMin.size() < 4 ||
+      MacOSVersionMin.substr(0, 3) != "10." ||
+      !isdigit(MacOSVersionMin[3])) {
+    MacOSVersionMinIsInvalid = true;
+  } else {
+    const char *Start = MacOSVersionMin.c_str()+3;
+    char *End = 0;
+    VersionNum = (int)strtol(Start, &End, 10);
+
+    // The version number must be in the range 0-9.
+    MacOSVersionMinIsInvalid = (unsigned)VersionNum > 9;
+    
+    // Turn MacOSVersionMin into a darwin number: e.g. 10.3.9 is 3 -> 7.
+    Triple += llvm::itostr(VersionNum+4);
+    
+    if (End[0] == '.' && isdigit(End[1]) && End[2] == '\0') {   // 10.4.7 is ok.
+      // Add the period piece (.7) to the end of the triple.  This gives us
+      // something like ...-darwin8.7
+      Triple += End;
+    } else if (End[0] != '\0') { // "10.4" is ok.  10.4x is not.
+      MacOSVersionMinIsInvalid = true;
+    }
+  }
+  
+  if (MacOSVersionMinIsInvalid) {
+    fprintf(stderr, 
+        "-mmacosx-version-min=%s is invalid, expected something like '10.4'.\n",
+            MacOSVersionMin.c_str());
+    exit(1);
+  }
+  else if (VersionNum <= 4 && 
+           !strncmp(Triple.c_str(), "x86_64", strlen("x86_64"))) {
+    fprintf(stderr, 
+        "-mmacosx-version-min=%s is invalid with -arch x86_64.\n",
+            MacOSVersionMin.c_str());
+    exit(1);
+  }
+
+}
+
+static llvm::cl::opt<std::string>
+IPhoneOSVersionMin("miphoneos-version-min", 
+                llvm::cl::desc("Specify target iPhone OS version (e.g. 2.0)"));
+
+// If -miphoneos-version-min=2.2 is specified, change the triple from being
+// something like armv6-apple-darwin10 to armv6-apple-darwin9.2.2. We use
+// 9 as the default major Darwin number, and encode the iPhone OS version
+// number in the minor version and revision.
+
+// FIXME: We should have the driver do this instead.
+static void HandleIPhoneOSVersionMin(std::string &Triple) {
+  std::string::size_type DarwinDashIdx = Triple.find("-darwin");
+  if (DarwinDashIdx == std::string::npos) {
+    fprintf(stderr, 
+            "-miphoneos-version-min only valid for darwin (Mac OS X) targets\n");
+    exit(1);
+  }
+  unsigned DarwinNumIdx = DarwinDashIdx + strlen("-darwin");
+  
+  // Remove the number.
+  Triple.resize(DarwinNumIdx);
+  
+  // Validate that IPhoneOSVersionMin is a 'version number', starting with [2-9].[0-9]
+  bool IPhoneOSVersionMinIsInvalid = false;
+  int VersionNum = 0;
+  if (IPhoneOSVersionMin.size() < 3 ||
+      !isdigit(IPhoneOSVersionMin[0])) {
+    IPhoneOSVersionMinIsInvalid = true;
+  } else {
+    const char *Start = IPhoneOSVersionMin.c_str();
+    char *End = 0;
+    VersionNum = (int)strtol(Start, &End, 10);
+    
+    // The version number must be in the range 0-9.
+    IPhoneOSVersionMinIsInvalid = (unsigned)VersionNum > 9;
+    
+    // Turn IPhoneOSVersionMin into a darwin number: e.g. 2.0 is 2 -> 9.2.
+    Triple += "9." + llvm::itostr(VersionNum);
+    
+    if (End[0] == '.' && isdigit(End[1]) && End[2] == '\0') {   // 2.2 is ok.
+      // Add the period piece (.2) to the end of the triple.  This gives us
+      // something like ...-darwin9.2.2
+      Triple += End;
+    } else if (End[0] != '\0') { // "2.2" is ok.  2x is not.
+      IPhoneOSVersionMinIsInvalid = true;
+    }
+  }
+  
+  if (IPhoneOSVersionMinIsInvalid) {
+    fprintf(stderr, 
+            "-miphoneos-version-min=%s is invalid, expected something like '2.0'.\n",
+            IPhoneOSVersionMin.c_str());
+    exit(1);
+  }
+}
+
+/// CreateTargetTriple - Process the various options that affect the target
+/// triple and build a final aggregate triple that we are compiling for.
+static std::string CreateTargetTriple() {
+  // Initialize base triple.  If a -triple option has been specified, use
+  // that triple.  Otherwise, default to the host triple.
+  std::string Triple = TargetTriple;
+  if (Triple.empty())
+    Triple = llvm::sys::getHostTriple();
+
+  // If -mmacosx-version-min=10.3.9 is specified, change the triple from being
+  // something like powerpc-apple-darwin9 to powerpc-apple-darwin7
+  if (!MacOSVersionMin.empty())
+    HandleMacOSVersionMin(Triple);
+  else if (!IPhoneOSVersionMin.empty())
+    HandleIPhoneOSVersionMin(Triple);;
+  
+  return Triple;
+}
+
+//===----------------------------------------------------------------------===//
+// SourceManager initialization.
+//===----------------------------------------------------------------------===//
+
+static bool InitializeSourceManager(Preprocessor &PP,
+                                    const std::string &InFile) {
+  // Figure out where to get and map in the main file.
+  SourceManager &SourceMgr = PP.getSourceManager();
+  FileManager &FileMgr = PP.getFileManager();
+
+  if (InFile != "-") {
+    const FileEntry *File = FileMgr.getFile(InFile);
+    if (File) SourceMgr.createMainFileID(File, SourceLocation());
+    if (SourceMgr.getMainFileID().isInvalid()) {
+      PP.getDiagnostics().Report(FullSourceLoc(), diag::err_fe_error_reading) 
+        << InFile.c_str();
+      return true;
+    }
+  } else {
+    llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN();
+
+    // If stdin was empty, SB is null.  Cons up an empty memory
+    // buffer now.
+    if (!SB) {
+      const char *EmptyStr = "";
+      SB = llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<stdin>");
+    }
+
+    SourceMgr.createMainFileIDForMemBuffer(SB);
+    if (SourceMgr.getMainFileID().isInvalid()) {
+      PP.getDiagnostics().Report(FullSourceLoc(), 
+                                 diag::err_fe_error_reading_stdin);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Initialization
+//===----------------------------------------------------------------------===//
+
+// FIXME: Preprocessor builtins to support.
+//   -A...    - Play with #assertions
+//   -undef   - Undefine all predefined macros
+
+static llvm::cl::list<std::string>
+D_macros("D", llvm::cl::value_desc("macro"), llvm::cl::Prefix,
+       llvm::cl::desc("Predefine the specified macro"));
+static llvm::cl::list<std::string>
+U_macros("U", llvm::cl::value_desc("macro"), llvm::cl::Prefix,
+         llvm::cl::desc("Undefine the specified macro"));
+
+static llvm::cl::list<std::string>
+ImplicitIncludes("include", llvm::cl::value_desc("file"),
+                 llvm::cl::desc("Include file before parsing"));
+static llvm::cl::list<std::string>
+ImplicitMacroIncludes("imacros", llvm::cl::value_desc("file"),
+                      llvm::cl::desc("Include macros from file before parsing"));
+
+static llvm::cl::opt<std::string>
+ImplicitIncludePTH("include-pth", llvm::cl::value_desc("file"),
+                   llvm::cl::desc("Include file before parsing"));
+
+
+//===----------------------------------------------------------------------===//
+// Preprocessor include path information.
+//===----------------------------------------------------------------------===//
+
+// This tool exports a large number of command line options to control how the
+// preprocessor searches for header files.  At root, however, the Preprocessor
+// object takes a very simple interface: a list of directories to search for
+// 
+// FIXME: -nostdinc++
+// FIXME: -imultilib
+//
+
+static llvm::cl::opt<bool>
+nostdinc("nostdinc", llvm::cl::desc("Disable standard #include directories"));
+
+// Various command line options.  These four add directories to each chain.
+static llvm::cl::list<std::string>
+F_dirs("F", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
+       llvm::cl::desc("Add directory to framework include search path"));
+static llvm::cl::list<std::string>
+I_dirs("I", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
+       llvm::cl::desc("Add directory to include search path"));
+static llvm::cl::list<std::string>
+idirafter_dirs("idirafter", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
+               llvm::cl::desc("Add directory to AFTER include search path"));
+static llvm::cl::list<std::string>
+iquote_dirs("iquote", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
+               llvm::cl::desc("Add directory to QUOTE include search path"));
+static llvm::cl::list<std::string>
+isystem_dirs("isystem", llvm::cl::value_desc("directory"), llvm::cl::Prefix,
+            llvm::cl::desc("Add directory to SYSTEM include search path"));
+
+// These handle -iprefix/-iwithprefix/-iwithprefixbefore.
+static llvm::cl::list<std::string>
+iprefix_vals("iprefix", llvm::cl::value_desc("prefix"), llvm::cl::Prefix,
+             llvm::cl::desc("Set the -iwithprefix/-iwithprefixbefore prefix"));
+static llvm::cl::list<std::string>
+iwithprefix_vals("iwithprefix", llvm::cl::value_desc("dir"), llvm::cl::Prefix,
+     llvm::cl::desc("Set directory to SYSTEM include search path with prefix"));
+static llvm::cl::list<std::string>
+iwithprefixbefore_vals("iwithprefixbefore", llvm::cl::value_desc("dir"),
+                       llvm::cl::Prefix,
+            llvm::cl::desc("Set directory to include search path with prefix"));
+
+static llvm::cl::opt<std::string>
+isysroot("isysroot", llvm::cl::value_desc("dir"), llvm::cl::init("/"),
+         llvm::cl::desc("Set the system root directory (usually /)"));
+
+// Finally, implement the code that groks the options above.
+
+/// InitializeIncludePaths - Process the -I options and set them in the
+/// HeaderSearch object.
+void InitializeIncludePaths(const char *Argv0, HeaderSearch &Headers,
+                            FileManager &FM, const LangOptions &Lang) {
+  InitHeaderSearch Init(Headers, Verbose, isysroot);
+
+  // Handle -I... and -F... options, walking the lists in parallel.
+  unsigned Iidx = 0, Fidx = 0;
+  while (Iidx < I_dirs.size() && Fidx < F_dirs.size()) {
+    if (I_dirs.getPosition(Iidx) < F_dirs.getPosition(Fidx)) {
+      Init.AddPath(I_dirs[Iidx], InitHeaderSearch::Angled, false, true, false);
+      ++Iidx;
+    } else {
+      Init.AddPath(F_dirs[Fidx], InitHeaderSearch::Angled, false, true, true);
+      ++Fidx;
+    }
+  }
+  
+  // Consume what's left from whatever list was longer.
+  for (; Iidx != I_dirs.size(); ++Iidx)
+    Init.AddPath(I_dirs[Iidx], InitHeaderSearch::Angled, false, true, false);
+  for (; Fidx != F_dirs.size(); ++Fidx)
+    Init.AddPath(F_dirs[Fidx], InitHeaderSearch::Angled, false, true, true);
+  
+  // Handle -idirafter... options.
+  for (unsigned i = 0, e = idirafter_dirs.size(); i != e; ++i)
+    Init.AddPath(idirafter_dirs[i], InitHeaderSearch::After,
+        false, true, false);
+  
+  // Handle -iquote... options.
+  for (unsigned i = 0, e = iquote_dirs.size(); i != e; ++i)
+    Init.AddPath(iquote_dirs[i], InitHeaderSearch::Quoted, false, true, false);
+  
+  // Handle -isystem... options.
+  for (unsigned i = 0, e = isystem_dirs.size(); i != e; ++i)
+    Init.AddPath(isystem_dirs[i], InitHeaderSearch::System, false, true, false);
+
+  // Walk the -iprefix/-iwithprefix/-iwithprefixbefore argument lists in
+  // parallel, processing the values in order of occurance to get the right
+  // prefixes.
+  {
+    std::string Prefix = "";  // FIXME: this isn't the correct default prefix.
+    unsigned iprefix_idx = 0;
+    unsigned iwithprefix_idx = 0;
+    unsigned iwithprefixbefore_idx = 0;
+    bool iprefix_done           = iprefix_vals.empty();
+    bool iwithprefix_done       = iwithprefix_vals.empty();
+    bool iwithprefixbefore_done = iwithprefixbefore_vals.empty();
+    while (!iprefix_done || !iwithprefix_done || !iwithprefixbefore_done) {
+      if (!iprefix_done &&
+          (iwithprefix_done || 
+           iprefix_vals.getPosition(iprefix_idx) < 
+           iwithprefix_vals.getPosition(iwithprefix_idx)) &&
+          (iwithprefixbefore_done || 
+           iprefix_vals.getPosition(iprefix_idx) < 
+           iwithprefixbefore_vals.getPosition(iwithprefixbefore_idx))) {
+        Prefix = iprefix_vals[iprefix_idx];
+        ++iprefix_idx;
+        iprefix_done = iprefix_idx == iprefix_vals.size();
+      } else if (!iwithprefix_done &&
+                 (iwithprefixbefore_done || 
+                  iwithprefix_vals.getPosition(iwithprefix_idx) < 
+                  iwithprefixbefore_vals.getPosition(iwithprefixbefore_idx))) {
+        Init.AddPath(Prefix+iwithprefix_vals[iwithprefix_idx], 
+                InitHeaderSearch::System, false, false, false);
+        ++iwithprefix_idx;
+        iwithprefix_done = iwithprefix_idx == iwithprefix_vals.size();
+      } else {
+        Init.AddPath(Prefix+iwithprefixbefore_vals[iwithprefixbefore_idx], 
+                InitHeaderSearch::Angled, false, false, false);
+        ++iwithprefixbefore_idx;
+        iwithprefixbefore_done = 
+          iwithprefixbefore_idx == iwithprefixbefore_vals.size();
+      }
+    }
+  }
+
+  Init.AddDefaultEnvVarPaths(Lang);
+
+  // Add the clang headers, which are relative to the clang binary.
+  llvm::sys::Path MainExecutablePath = 
+     llvm::sys::Path::GetMainExecutable(Argv0,
+                                    (void*)(intptr_t)InitializeIncludePaths);
+  if (!MainExecutablePath.isEmpty()) {
+    MainExecutablePath.eraseComponent();  // Remove /clang from foo/bin/clang
+    MainExecutablePath.eraseComponent();  // Remove /bin   from foo/bin
+
+    // Get foo/lib/clang/<version>/include    
+    MainExecutablePath.appendComponent("lib");
+    MainExecutablePath.appendComponent("clang");
+    MainExecutablePath.appendComponent(CLANG_VERSION_STRING);
+    MainExecutablePath.appendComponent("include");
+    
+    // We pass true to ignore sysroot so that we *always* look for clang headers
+    // relative to our executable, never relative to -isysroot.
+    Init.AddPath(MainExecutablePath.c_str(), InitHeaderSearch::System,
+                 false, false, false, true /*ignore sysroot*/);
+  }
+  
+  if (!nostdinc) 
+    Init.AddDefaultSystemIncludePaths(Lang);
+
+  // Now that we have collected all of the include paths, merge them all
+  // together and tell the preprocessor about them.
+  
+  Init.Realize();
+}
+
+void InitializePreprocessorInitOptions(PreprocessorInitOptions &InitOpts)
+{
+  // Add macros from the command line.
+  unsigned d = 0, D = D_macros.size();
+  unsigned u = 0, U = U_macros.size();
+  while (d < D || u < U) {
+    if (u == U || (d < D && D_macros.getPosition(d) < U_macros.getPosition(u)))
+      InitOpts.addMacroDef(D_macros[d++]);
+    else
+      InitOpts.addMacroUndef(U_macros[u++]);
+  }
+
+  // If -imacros are specified, include them now.  These are processed before
+  // any -include directives.
+  for (unsigned i = 0, e = ImplicitMacroIncludes.size(); i != e; ++i)
+    InitOpts.addMacroInclude(ImplicitMacroIncludes[i]);
+
+  if (!ImplicitIncludePTH.empty() || !ImplicitIncludes.empty()) {
+    // We want to add these paths to the predefines buffer in order, make a
+    // temporary vector to sort by their occurrence.
+    llvm::SmallVector<std::pair<unsigned, std::string*>, 8> OrderedPaths;
+
+    if (!ImplicitIncludePTH.empty())
+      OrderedPaths.push_back(std::make_pair(ImplicitIncludePTH.getPosition(),
+                                            &ImplicitIncludePTH));
+    for (unsigned i = 0, e = ImplicitIncludes.size(); i != e; ++i)
+      OrderedPaths.push_back(std::make_pair(ImplicitIncludes.getPosition(i),
+                                            &ImplicitIncludes[i]));
+    llvm::array_pod_sort(OrderedPaths.begin(), OrderedPaths.end());
+
+
+    // Now that they are ordered by position, add to the predefines buffer.
+    for (unsigned i = 0, e = OrderedPaths.size(); i != e; ++i) {
+      std::string *Ptr = OrderedPaths[i].second;
+      if (!ImplicitIncludes.empty() &&
+          Ptr >= &ImplicitIncludes[0] &&
+          Ptr <= &ImplicitIncludes[ImplicitIncludes.size()-1]) {
+        InitOpts.addInclude(*Ptr, false);
+      } else if (Ptr == &ImplicitIncludePTH) {
+        InitOpts.addInclude(*Ptr, true);
+      } else {
+        // We end up here when we're producing preprocessed output and
+        // we loaded a PCH file. In this case, just include the header
+        // file that was used to build the precompiled header.
+        assert(0);
+      }
+    }
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Driver PreprocessorFactory - For lazily generating preprocessors ...
+//===----------------------------------------------------------------------===//
+
+namespace {
+class VISIBILITY_HIDDEN DriverPreprocessorFactory : public PreprocessorFactory {
+  Diagnostic        &Diags;
+  const LangOptions &LangInfo;
+  TargetInfo        &Target;
+  SourceManager     &SourceMgr;
+  HeaderSearch      &HeaderInfo;
+  
+public:
+  DriverPreprocessorFactory(Diagnostic &diags, const LangOptions &opts,
+                            TargetInfo &target, SourceManager &SM,
+                            HeaderSearch &Headers)  
+  : Diags(diags), LangInfo(opts), Target(target),
+    SourceMgr(SM), HeaderInfo(Headers) {}
+  
+  
+  virtual ~DriverPreprocessorFactory() {}
+  
+  virtual Preprocessor* CreatePreprocessor() {
+    llvm::OwningPtr<PTHManager> PTHMgr;
+
+    // Use PTH?
+    if (!ImplicitIncludePTH.empty()) {
+      PTHMgr.reset(PTHManager::Create(ImplicitIncludePTH, &Diags, Diagnostic::Error));
+    }
+    
+    if (Diags.hasErrorOccurred())
+      exit(1);
+    
+    // Create the Preprocessor.
+    llvm::OwningPtr<Preprocessor> PP(new Preprocessor(Diags, LangInfo, Target,
+                                                      SourceMgr, HeaderInfo,
+                                                      PTHMgr.get()));
+    
+    // Note that this is different then passing PTHMgr to Preprocessor's ctor.
+    // That argument is used as the IdentifierInfoLookup argument to
+    // IdentifierTable's ctor.
+    if (PTHMgr) {
+      PTHMgr->setPreprocessor(PP.get());
+      PP->setPTHManager(PTHMgr.take());
+    }
+
+    PreprocessorInitOptions InitOpts;
+    InitializePreprocessorInitOptions(InitOpts);
+    if (InitializePreprocessor(*PP, InitOpts))
+      return 0;
+
+    return PP.take();
+  }
+};
+}
+
+//===----------------------------------------------------------------------===//
+// Code generation options
+//===----------------------------------------------------------------------===//
+
+static llvm::cl::opt<std::string>
+TargetCPU("mcpu",
+         llvm::cl::desc("Target a specific cpu type (-mcpu=help for details)"));
+
+static llvm::cl::list<std::string>
+TargetFeatures("target-feature", llvm::cl::desc("Target specific attributes"));
+
+/// ComputeTargetFeatures - Recompute the target feature list to only
+/// be the list of things that are enabled, based on the target cpu
+/// and feature list.
+static void ComputeFeatureMap(TargetInfo *Target,
+                              llvm::StringMap<bool> &Features) {
+  assert(Features.empty() && "invalid map"); 
+
+  // Initialize the feature map based on the target.
+  Target->getDefaultFeatures(TargetCPU, Features);
+
+  // Apply the user specified deltas.
+  for (llvm::cl::list<std::string>::iterator it = TargetFeatures.begin(), 
+         ie = TargetFeatures.end(); it != ie; ++it) {
+    const char *Name = it->c_str();
+    
+    // FIXME: Don't handle errors like this.
+    if (Name[0] != '-' && Name[0] != '+') {
+      fprintf(stderr, "error: clang-cc: invalid target feature string: %s\n", 
+              Name);
+      exit(1);
+    }
+    if (!Target->setFeatureEnabled(Features, Name + 1, (Name[0] == '+'))) {
+      fprintf(stderr, "error: clang-cc: invalid target feature name: %s\n", 
+              Name + 1);
+      exit(1);
+    }
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// ObjC Rewriter Options
+//===----------------------------------------------------------------------===//
+static llvm::cl::opt<bool>
+SilenceRewriteMacroWarning("Wno-rewrite-macros", llvm::cl::init(false),
+                           llvm::cl::desc("Silence ObjC rewriting warnings"));
+
+//===----------------------------------------------------------------------===//
+// Warning Options
+//===----------------------------------------------------------------------===//
+
+// This gets all -W options, including -Werror, -W[no-]system-headers, etc.  The
+// driver has stripped off -Wa,foo etc.  The driver has also translated -W to
+// -Wextra, so we don't need to worry about it.
+static llvm::cl::list<std::string>
+OptWarnings("W", llvm::cl::Prefix, llvm::cl::ValueOptional);
+
+static llvm::cl::opt<bool> OptPedantic("pedantic");
+static llvm::cl::opt<bool> OptPedanticErrors("pedantic-errors");
+static llvm::cl::opt<bool> OptNoWarnings("w");
+
+//===----------------------------------------------------------------------===//
+// Main driver
+//===----------------------------------------------------------------------===//
+
+static llvm::raw_ostream* ComputeOutFile(const std::string& InFile,
+                                         const char* Extension,
+                                         bool Binary,
+                                         llvm::sys::Path& OutPath) {
+  llvm::raw_ostream* Ret;
+  bool UseStdout = false;
+  std::string OutFile;
+  if (OutputFile == "-" || (OutputFile.empty() && InFile == "-")) {
+    UseStdout = true;
+  } else if (!OutputFile.empty()) {
+    OutFile = OutputFile;
+  } else if (Extension) {
+    llvm::sys::Path Path(InFile);
+    Path.eraseSuffix();
+    Path.appendSuffix(Extension);
+    OutFile = Path.toString();
+  } else {
+    UseStdout = true;
+  }
+
+  if (UseStdout) {
+    Ret = new llvm::raw_stdout_ostream();
+    if (Binary)
+      llvm::sys::Program::ChangeStdoutToBinary();
+  } else {
+    std::string Error;
+    Ret = new llvm::raw_fd_ostream(OutFile.c_str(), Binary, Error);
+    if (!Error.empty()) {
+      // FIXME: Don't fail this way.
+      llvm::cerr << "ERROR: " << Error << "\n";
+      ::exit(1);
+    }
+    OutPath = OutFile;
+  }
+
+  return Ret;
+}
+
+/// ProcessInputFile - Process a single input file with the specified state.
+///
+static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
+                             const std::string &InFile, ProgActions PA,
+                             const llvm::StringMap<bool> &Features) {
+  llvm::OwningPtr<llvm::raw_ostream> OS;
+  llvm::OwningPtr<ASTConsumer> Consumer;
+  llvm::sys::Path OutPath;
+
+  switch (PA) {
+/*    
+  case ASTPrintXML:
+    OS.reset(ComputeOutFile(InFile, "xml", false, OutPath));
+    Consumer.reset(CreateASTPrinterXML(OS.get()));
+    break;
+*/
+  case RewriteObjC:
+    OS.reset(ComputeOutFile(InFile, "cpp", true, OutPath));
+    Consumer.reset(CreateInlineRewriter(InFile, OS.get(), PP.getDiagnostics(),
+                                        PP.getLangOptions()));
+    break;
+  }
+
+
+  if (Consumer)
+  {
+    llvm::OwningPtr<ASTContext> ContextOwner;
+    ContextOwner.reset(new ASTContext(PP.getLangOptions(),
+                                      PP.getSourceManager(),
+                                      PP.getTargetInfo(),
+                                      PP.getIdentifierTable(),
+                                      PP.getSelectorTable(),
+                                      PP.getBuiltinInfo(),
+                                      /* FreeMemory = */ true,
+                                      /* size_reserve = */0));
+
+    ParseAST(PP, Consumer.get(), *ContextOwner.get(), /*Stats=*/false, true);
+  }
+
+  Consumer.reset();
+
+  // Always delete the output stream because we don't want to leak file
+  // handles.  Also, we don't want to try to erase an open file.
+  OS.reset();
+
+  if ((HadErrors || (PP.getDiagnostics().getNumErrors() != 0)) &&
+      !OutPath.isEmpty()) {
+    // If we had errors, try to erase the output file.
+    OutPath.eraseFromDisk();
+  }
+}
+
+static llvm::cl::list<std::string>
+InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input files>"));
+
+extern "C" int X86TargetMachineModule;
+int X86TargetMachineModule = 0;
+extern "C" int X86AsmPrinterForceLink;
+int X86AsmPrinterForceLink = 0;
+
+int main(int argc, char **argv) {
+  llvm::sys::PrintStackTraceOnErrorSignal();
+  llvm::PrettyStackTraceProgram X(argc, argv);
+  llvm::cl::ParseCommandLineOptions(argc, argv,
+                              "LLVM 'Clang' Compiler: http://clang.llvm.org\n");
+  
+  // If no input was specified, read from stdin.
+  if (InputFilenames.empty())
+    InputFilenames.push_back("-");
+
+  // Create the diagnostic client for reporting errors or for
+  // implementing -verify.
+  llvm::OwningPtr<DiagnosticClient> DiagClient;
+
+  // Print diagnostics to stderr by default.
+
+  // If -fmessage-length=N was not specified, determine whether this
+  // is a terminal and, if so, implicitly define -fmessage-length
+  // appropriately.
+  if (MessageLength.getNumOccurrences() == 0)
+    MessageLength.setValue(llvm::sys::Process::StandardErrColumns());
+
+  DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(),
+                                             !NoShowColumn,
+                                             !NoCaretDiagnostics,
+                                             !NoShowLocation,
+                                             PrintSourceRangeInfo,
+                                             PrintDiagnosticOption,
+                                             !NoDiagnosticsFixIt,
+                                             MessageLength));
+  
+  // Configure our handling of diagnostics.
+  Diagnostic Diags(DiagClient.get());
+  if (ProcessWarningOptions(Diags, OptWarnings, OptPedantic, OptPedanticErrors,
+                            OptNoWarnings))
+    return 1;
+
+  // -I- is a deprecated GCC feature, scan for it and reject it.
+  for (unsigned i = 0, e = I_dirs.size(); i != e; ++i) {
+    if (I_dirs[i] == "-") {
+      Diags.Report(FullSourceLoc(), diag::err_pp_I_dash_not_supported);      
+      I_dirs.erase(I_dirs.begin()+i);
+      --i;
+    }
+  }
+
+  // Get information about the target being compiled for.
+  std::string Triple = CreateTargetTriple();
+  llvm::OwningPtr<TargetInfo> Target(TargetInfo::CreateTargetInfo(Triple));
+  
+  if (Target == 0) {
+    Diags.Report(FullSourceLoc(), diag::err_fe_unknown_triple) 
+      << Triple.c_str();
+    return 1;
+  }
+  
+  llvm::OwningPtr<SourceManager> SourceMgr;
+  
+  // Create a file manager object to provide access to and cache the filesystem.
+  FileManager FileMgr;
+
+  // Compute the feature set, unfortunately this effects the language!
+  llvm::StringMap<bool> Features;
+  ComputeFeatureMap(Target.get(), Features);
+
+  for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
+    const std::string &InFile = InputFilenames[i];
+    
+    /// Create a SourceManager object.  This tracks and owns all the file
+    /// buffers allocated to a translation unit.
+    if (!SourceMgr)
+      SourceMgr.reset(new SourceManager());
+    else
+      SourceMgr->clearIDTables();
+    
+    // Initialize language options, inferring file types from input filenames.
+    LangOptions LangInfo;
+    DiagClient->setLangOptions(&LangInfo);
+    
+    InitializeBaseLanguage();
+    LangKind LK = GetLanguage(InFile);
+    InitializeLangOptions(LangInfo, LK);
+    InitializeLanguageStandard(LangInfo, LK, Target.get(), Features);
+          
+    // Process the -I options and set them in the HeaderInfo.
+    HeaderSearch HeaderInfo(FileMgr);
+    
+    
+    InitializeIncludePaths(argv[0], HeaderInfo, FileMgr, LangInfo);
+    
+    // Set up the preprocessor with these options.
+    DriverPreprocessorFactory PPFactory(Diags, LangInfo, *Target,
+                                        *SourceMgr.get(), HeaderInfo);
+    
+    llvm::OwningPtr<Preprocessor> PP(PPFactory.CreatePreprocessor());
+          
+    if (!PP)
+      continue;
+
+    if (InitializeSourceManager(*PP.get(), InFile))
+      continue;
+
+    // Process the source file.
+    ProcessInputFile(*PP, PPFactory, InFile, ProgAction, Features);
+    
+    HeaderInfo.ClearFileInfo();
+    DiagClient->setLangOptions(0);
+  }
+
+  if (Verbose)
+    fprintf(stderr, "clang version 1.0 based upon " PACKAGE_STRING
+            " hosted on " LLVM_HOSTTRIPLE "\n");
+
+  if (!NoCaretDiagnostics)
+    if (unsigned NumDiagnostics = Diags.getNumDiagnostics())
+      fprintf(stderr, "%d diagnostic%s generated.\n", NumDiagnostics,
+              (NumDiagnostics == 1 ? "" : "s"));
+  
+  // Managed static deconstruction. Useful for making things like
+  // -time-passes usable.
+  llvm::llvm_shutdown();
+
+  return HadErrors || (Diags.getNumErrors() != 0);
+}
Index: tools/min-clang-AST/RewriteInline.cpp
===================================================================
--- tools/min-clang-AST/RewriteInline.cpp	(revision 0)
+++ tools/min-clang-AST/RewriteInline.cpp	(revision 0)
@@ -0,0 +1,131 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Rewrite/Rewriter.h"
+#include "clang/ASTProcessing/ArtificialIdentifierPolicy.h"
+#include "clang/ASTProcessing/StmtEditor.h"
+#include "clang/ASTProcessing/StmtCollector.h"
+#include "clang/ASTProcessing/Inline.h"    
+#include "clang/ASTProcessing/InvariantIf.h"    
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Basic/SourceManager.h"
+
+using namespace clang;
+
+//--------------------------------------------------------- 
+namespace {
+
+//--------------------------------------------------------- 
+class RewriteInline : public ASTConsumer {
+  Rewriter Rewrite;
+  Diagnostic &Diags;
+  const LangOptions &LangOpts;
+  ASTContext *Ctx;
+  SourceManager *SM;
+  FileID MainFileID;
+  
+  std::string InFileName;
+  llvm::raw_ostream* OutFile;
+
+  std::string Preamble;
+
+public:
+  virtual void Initialize(ASTContext &context);
+
+  RewriteInline(std::string inFile, llvm::raw_ostream *OS,
+                Diagnostic &D, const LangOptions &LOpts)
+    : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(OS)
+  {}
+
+  ~RewriteInline() {}
+  
+  virtual void HandleTranslationUnit(ASTContext &C);
+};
+
+//--------------------------------------------------------- 
+void RewriteInline::Initialize(ASTContext &context) {
+  Ctx = &context;
+  SM = &Ctx->getSourceManager();
+  
+  // Get the ID and start/end of the main file.
+  MainFileID = SM->getMainFileID();
+  const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
+     
+  Rewrite.setSourceMgr(Ctx->getSourceManager(), Ctx->getLangOptions());
+  
+  // declaring objc_selector outside the parameter list removes a silly
+  // scope related warning...
+  Preamble += "/*This file is a rewritten one*/\n";
+}
+
+//--------------------------------------------------------- 
+void RewriteInline::HandleTranslationUnit(ASTContext &C) {
+  // Get the top-level buffer that this corresponds to.
+  
+  // Rewrite tabs if we care.
+  //RewriteTabs();
+  
+  if (Diags.hasErrorOccurred())
+    return;
+  
+  Rewrite.InsertText(SM->getLocForStartOfFile(MainFileID), 
+                     Preamble.c_str(), Preamble.size(), false);
+
+
+  for (DeclContext::decl_iterator 
+         D = C.getTranslationUnitDecl()->decls_begin(),
+         DEnd = C.getTranslationUnitDecl()->decls_end();
+       D != DEnd; 
+       ++D)
+  {
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) 
+    {
+      if (Stmt *Body = FD->getBody()) 
+      {
+        StmtCollector rewriter(*Ctx, ArtificialIdentifierPolicy("inlined"), Diags, *FD);
+        ASTProcessing::doInline(StmtEditor(rewriter), Body);
+        rewriter.setArtificialIdentifierPolicy(ArtificialIdentifierPolicy("splitted"));
+        ASTProcessing::splitInvariantIfs(StmtEditor(rewriter), Body);
+        rewriter.rewrite(Rewrite);
+      }
+    }
+  }
+
+
+  // Get the buffer corresponding to MainFileID.  If we haven't changed it, then
+  // we are done.
+  if (const RewriteBuffer *RewriteBuf = 
+      Rewrite.getRewriteBufferFor(MainFileID)) {
+    //printf("Changed:\n");
+    *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
+  } else {
+    fprintf(stderr, "No changes\n");
+  }
+
+  OutFile->flush();
+}
+
+
+} // anon NS
+
+namespace clang {
+
+ASTConsumer *CreateInlineRewriter(const std::string& InFile,
+                                       llvm::raw_ostream* OS,
+                                       Diagnostic &Diags, 
+                                       const LangOptions &LOpts) 
+{
+  return new RewriteInline(InFile, OS, Diags, LOpts);
+}
+
+}
\ No newline at end of file
