[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [creduce-dev] multifile creduce



On 10/19/2015 06:17 PM, John Regehr wrote:
I've pushed changes to C-Reduce that support reducing more than one file
at a time.  Use cases include:

- reductions for LTO bugs

- reducing a file + its transitive includes when, for whatever reason,
reducing the preprocessed file does not work

(As always, if you can reduce a preprocessed file, you should do so.)

To support the second case, I wrote a program that copies each
transitive include file for a C/C++ file into the cwd, renaming files as
necessary (there are 8 files called "errno.h" under /usr/include on one
of my machines) and also replacing each <foo>-style include with a
"foo"-style include.  The program is in scripts/localize_headers.  To
use it you need to modify a few variables up at the top.  Let me know if
you have either a good or a bad experience with this script.  I'm not
sure that it is very robust but it has worked for me.

Multifile reduction works by running each pass over all files that are
being reduced.  It is often the case that some files go to zero bytes.
C-Reduce could at this point try to delete such files, but it doesn't do
that yet.

I also beefed up C-Reduce's usage info.

clang-delta becomes pretty crashy on non-preprocessed files. I don't
really know what is going on, but these crashes are largely harmless.
Please don't kill us with bug reports about this.

I have done some work on reducing non-preprocessed files in my local copy of creduce but has been reluctant to resubmit the changes since they are tailored to my specific use case. The clang-delta crashes when working with non-preprocessed files are mainly of two different types. The first one is when it can not find the included files. In this setting the clang framework will get confused by types that are defined in the included files and get the source ranges wrong. The second one is when clang-delta finds the included files and identifies rewrite opportunities in them. Both of these problems causes clang-delta to crash during rewrite.

I have attached my changes. Note that they are neither complete nor water tight.

/Johan





Testing appreciated.  I've only tested on Linux so far.

John


>From 34ff7a96862b8573fb9f441a4387258b49efe981 Mon Sep 17 00:00:00 2001
From: Johan Bengtsson <johan.bengtsson@iar.com>
Date: Tue, 30 Sep 2014 11:21:53 +0200
Subject: [PATCH 1/5] Add basic support for reducing non preprocessed files

The clang parser library gets confused when it encounters types it does
not recognize and in non preprocessed code this is quite common (types
declared in header files). The patch tries to work around this problem
by supplying clang_delta with the default include path from the local
clang installation when creduce is given --non-pp option.
---
 clang_delta/ClangDelta.cpp            |  8 ++++++++
 clang_delta/TransformationManager.cpp | 21 +++++++++++++++++++++
 clang_delta/TransformationManager.h   |  5 +++++
 creduce/creduce.in                    |  4 +++-
 creduce/pass_clang.pm                 | 24 +++++++++++++++++++++---
 creduce/pass_clang_binsrch.pm         | 27 ++++++++++++++++++++++++---
 6 files changed, 82 insertions(+), 7 deletions(-)

diff --git a/clang_delta/ClangDelta.cpp b/clang_delta/ClangDelta.cpp
index 430697f..72e506d 100644
--- a/clang_delta/ClangDelta.cpp
+++ b/clang_delta/ClangDelta.cpp
@@ -76,6 +76,11 @@ static void PrintHelpMessage()
   llvm::outs() << "  --output=<filename>: ";
   llvm::outs() << "specify where to output the transformed source code ";
   llvm::outs() << "(default: stdout)\n";
+
+  llvm::outs() << "  --include-path=<path>: ";
+  llvm::outs() << "specify a colon-separated list of directories to search for ";
+  llvm::outs() <<" unresolved include files. (This option is useful when ";
+  llvm::outs() << "reducing files that are not fully preprocessed.)\n";
   llvm::outs() << "\n";
 }
 
@@ -143,6 +148,9 @@ static void HandleOneArgValue(const std::string &ArgValueStr, size_t SepPos)
   else if (!ArgName.compare("output")) {
     TransMgr->setOutputFileName(ArgValue);
   }
+  else if (!ArgName.compare("include-path")) {
+    TransMgr->setIncludePath(ArgValue);
+  }
   else {
     DieOnBadCmdArg("--" + ArgValueStr);
   }
diff --git a/clang_delta/TransformationManager.cpp b/clang_delta/TransformationManager.cpp
index d31f9bf..3f6e0af 100644
--- a/clang_delta/TransformationManager.cpp
+++ b/clang_delta/TransformationManager.cpp
@@ -134,6 +134,13 @@ bool TransformationManager::initializeCompilerInstance(std::string &ErrorMsg)
     TargetInfo::CreateTargetInfo(ClangInstance->getDiagnostics(),
                                  ClangInstance->getInvocation().TargetOpts);
   ClangInstance->setTarget(Target);
+
+  HeaderSearchOptions &HeaderSearchOpts = ClangInstance->getHeaderSearchOpts();
+
+  for (const std::string &dir : IncludePath) {
+    HeaderSearchOpts.AddPath(dir, clang::frontend::Angled, false, false);
+  }
+
   ClangInstance->createFileManager();
   ClangInstance->createSourceManager(ClangInstance->getFileManager());
   ClangInstance->createPreprocessor(TU_Complete);
@@ -320,6 +327,19 @@ void TransformationManager::outputNumTransformationInstances()
                << NumInstances << "\n";
 }
 
+
+void TransformationManager::setIncludePath(const std::string &path)
+{
+  std::size_t now = 0, next = 0;
+  const std::size_t npos = std::string::npos;
+  do {
+    next = path.find(':', now);
+    std::size_t len = (next == npos) ? npos : (next - now);
+    IncludePath.push_back(path.substr(now, len));
+    now = next + 1;
+  } while(next != std::string::npos);
+}
+
 TransformationManager::TransformationManager()
   : CurrentTransformationImpl(NULL),
     TransformationCounter(-1),
@@ -327,6 +347,7 @@ TransformationManager::TransformationManager()
     SrcFileName(""),
     OutputFileName(""),
     CurrentTransName(""),
+    IncludePath(),
     ClangInstance(NULL),
     QueryInstanceOnly(false)
 {
diff --git a/clang_delta/TransformationManager.h b/clang_delta/TransformationManager.h
index 248e089..639e40a 100644
--- a/clang_delta/TransformationManager.h
+++ b/clang_delta/TransformationManager.h
@@ -14,6 +14,7 @@
 #include <string>
 #include <map>
 #include <cassert>
+#include <vector>
 
 #include "llvm/Support/raw_ostream.h"
 
@@ -76,6 +77,8 @@ public:
     QueryInstanceOnly = Flag;
   }
 
+  void setIncludePath(const std::string &Path);
+
   bool getQueryInstanceFlag() {
     return QueryInstanceOnly;
   }
@@ -116,6 +119,8 @@ private:
 
   std::string CurrentTransName;
 
+  std::vector<std::string> IncludePath;
+
   clang::CompilerInstance *ClangInstance;
 
   bool QueryInstanceOnly;
diff --git a/creduce/creduce.in b/creduce/creduce.in
index 9040e48..942c42f 100644
--- a/creduce/creduce.in
+++ b/creduce/creduce.in
@@ -87,6 +87,7 @@ my $CACHE = 0;
 my $FUZZ = 0;
 my $CPP;
 my $TIMING = 0;
+my $NON_PP = 0;
 
 my @options = (
     # ["--add-pass",            "call",    0, \&process_foo,     "Also run the specified pass; requires three sub-arguments: pass sub-pass priority"],
@@ -104,6 +105,7 @@ my @options = (
     ["--sllooww",             "const",   1, \$SLLOOWW,         "Try harder to reduce, but perhaps take a long time to do so"],
     ["--verbose",             "const",   1, \$VERBOSE,         "Print debug information"],
     ["--timing",              "const",   1, \$TIMING,          "Print timestaps about reduction progress"],
+    ["--non-pp",              "const",   1, \$NON_PP,          "The file to reduce has not been preprocessed and may contain include directives" ],
 );
 
 my $help = creduce_config::PACKAGE_STRING . " -- C and C++ program reducer";
@@ -243,7 +245,7 @@ sub call_prereq_check ($) {
     (my $method) = @_;
     my $str = $method."::check_prereqs";
     no strict "refs";
-    &${str}() or die "prereqs not found for pass $method";
+    &${str}($NON_PP) or die "prereqs not found for pass $method";
     print "successfully checked prereqs for $method\n" if $VERBOSE;
 }
 
diff --git a/creduce/pass_clang.pm b/creduce/pass_clang.pm
index 410a479..1ab6b19 100644
--- a/creduce/pass_clang.pm
+++ b/creduce/pass_clang.pm
@@ -28,7 +28,24 @@ my $clang_delta = "clang_delta";
 
 my $ORIG_DIR;
 
-sub check_prereqs () {
+my $INCPATH_OPT = "";
+
+sub init_include_path() {
+    my $append = 0;
+    my @opts = ();
+    open INF, "clang -E -v - </dev/null 2>&1 |" or die;
+    while(<INF>) {
+	m/^\#include <\.\.\.> search starts here\:/ && do { $append = 1; next; };
+	m/^End of search list\./ && do { $append = 0; };
+	s/\s*(\S+)\s*/$1/;
+	push @opts, $_ if $append;
+    }
+    close INF;
+    $INCPATH_OPT="--include-path=" . join(':', @opts);
+}
+
+sub check_prereqs ($) {
+    my ($non_pp) = @_;
     $ORIG_DIR = getcwd();
     my $path;
     if ($FindBin::RealBin eq abs_path(bindir)) {
@@ -42,6 +59,7 @@ sub check_prereqs () {
     }
     if ((-e $path) && (-x $path)) {
 	$clang_delta = $path;
+	init_include_path() if $non_pp;
 	return 1;
     }
     # Check Windows
@@ -69,7 +87,7 @@ sub transform ($$$) {
     (my $cfile, my $which, my $state) = @_;
     my $index = ${$state};
     my $tmpfile = File::Temp::tmpnam();
-    my $cmd = qq{"$clang_delta" --transformation=$which --counter=$index $cfile};
+    my $cmd = qq{"$clang_delta" "$INCPATH_OPT" --transformation=$which --counter=$index $cfile};
     print "$cmd\n" if $VERBOSE;
     my $res = run_clang_delta ("$cmd > $tmpfile");
     if ($res==0) {
@@ -84,7 +102,7 @@ sub transform ($$$) {
             open  CRASH, ">>$crashfile";
             print CRASH "\n\n";
             print CRASH "\/\/ this should reproduce the crash:\n";
-            print CRASH "\/\/ $clang_delta --transformation=$which --counter=$index $crashfile\n";
+            print CRASH "\/\/ $clang_delta $INCPATH_OPT --transformation=$which --counter=$index $crashfile\n";
             close CRASH;
             print <<"EOT";
 
diff --git a/creduce/pass_clang_binsrch.pm b/creduce/pass_clang_binsrch.pm
index f5cfa35..b01bd61 100644
--- a/creduce/pass_clang_binsrch.pm
+++ b/creduce/pass_clang_binsrch.pm
@@ -28,9 +28,25 @@ my $clang_delta = "clang_delta";
 
 my $ORIG_DIR;
 
+my $INCPATH_OPT = "";
+
+sub init_include_path() {
+    my $append = 0;
+    my @opts = ();
+    open INF, "clang -E -v - </dev/null 2>&1 |" or die;
+    while(<INF>) {
+	m/^\#include <\.\.\.> search starts here\:/ && do { $append = 1; next; };
+	m/^End of search list\./ && do { $append = 0; };
+	s/\s*(\S+)\s*/$1/;
+	push @opts, $_ if $append;
+    }
+    close INF;
+    $INCPATH_OPT="--include-path=" . join(':', @opts);
+}
+
 sub count_instances ($$) {
     (my $cfile, my $which) = @_;
-    open INF, qq{"$clang_delta" --query-instances=$which $cfile |} or die;
+    open INF, qq{"$clang_delta" "$INCPATH_OPT" --query-instances=$which $cfile |} or die;
     my $line = <INF>;
     my $n = 0;
     if ($line =~ /Available transformation instances: ([0-9]+)$/) {
@@ -41,7 +57,9 @@ sub count_instances ($$) {
 }
 
 sub check_prereqs () {
+    my ($non_pp) = @_;
     $ORIG_DIR = getcwd();
+
     my $path;
     if ($FindBin::RealBin eq abs_path(bindir)) {
 	# This script is in the installation directory.
@@ -52,10 +70,13 @@ sub check_prereqs () {
 	# Use the `clang_delta' that is also in the build tree.
 	$path = "$FindBin::Bin/../clang_delta/clang_delta";
     }
+
     if ((-e $path) && (-x $path)) {
 	$clang_delta = $path;
+	init_include_path() if $non_pp;
 	return 1;
     }
+
     # Check Windows
     $path=$path . ".exe";
     if (($^O eq "MSWin32") && (-e $path) && (-x $path)) {
@@ -121,7 +142,7 @@ sub transform ($$$) {
 	
 	my $dec = $end - $index + 1;
 
-	my $cmd = qq{"$clang_delta" --transformation=$which --counter=$index --to-counter=$end $cfile};
+	my $cmd = qq{"$clang_delta" "$INCPATH_OPT" --transformation=$which --counter=$index --to-counter=$end $cfile};
 	print "$cmd\n" if $VERBOSE;
 	my $res = run_clang_delta ("$cmd > $tmpfile");
 
@@ -145,7 +166,7 @@ sub transform ($$$) {
 		open TMPF, ">>$crashfile_path";
 		print TMPF "\n\n";
 		print TMPF "\/\/ this should reproduce the crash:\n";
-		print TMPF "\/\/ $clang_delta --transformation=$which --counter=$index $crashfile_path\n";
+		print TMPF "\/\/ $clang_delta $INCPATH_OPT --transformation=$which --counter=$index $crashfile_path\n";
 		close TMPF;
 		print "\n\n=======================================\n\n";
 		print "OOPS: clang_delta crashed; please consider mailing\n";
-- 
1.9.1

>From 1316c3c3777a84387143d27a648002cc6c0387de Mon Sep 17 00:00:00 2001
From: Johan Bengtsson <johan.bengtsson@iar.com>
Date: Wed, 12 Aug 2015 13:30:39 +0200
Subject: [PATCH 2/5] Prevent transformation of constructs from included files

When reducing non-preprocessed files the transformations are faced with
declarations that are not part of the reduced file. The patch tries to
fix this problem by identifying these declarations and disqualify them
from reduction.
---
 clang_delta/BinOpSimplification.cpp        |  3 ++-
 clang_delta/CallExprToValue.cpp            |  3 +++
 clang_delta/ClassTemplateToClass.cpp       |  3 ++-
 clang_delta/CombineGlobalVarDecl.cpp       |  3 ++-
 clang_delta/EmptyStructToInt.cpp           |  3 ++-
 clang_delta/MoveGlobalVar.cpp              |  7 +++++++
 clang_delta/ParamToGlobal.cpp              |  5 +++++
 clang_delta/ParamToLocal.cpp               |  5 +++++
 clang_delta/ReducePointerLevel.cpp         |  3 +++
 clang_delta/RemoveArray.cpp                |  2 +-
 clang_delta/RemoveEnumMemberValue.cpp      |  3 ++-
 clang_delta/RemovePointer.cpp              |  3 +++
 clang_delta/RemoveUnusedEnumMember.cpp     |  2 +-
 clang_delta/RemoveUnusedStructField.cpp    |  3 +++
 clang_delta/RemoveUnusedVar.cpp            |  3 +++
 clang_delta/RenameFun.cpp                  | 16 ++++++++++++++++
 clang_delta/RenameParam.cpp                |  7 +++++--
 clang_delta/RenameVar.cpp                  | 12 ++++++++++--
 clang_delta/ReplaceOneLevelTypedefType.cpp |  2 +-
 clang_delta/ReplaceSimpleTypedef.cpp       | 20 ++++++++++++++++----
 clang_delta/ReplaceUndefinedFunction.cpp   |  2 +-
 clang_delta/ReturnVoid.cpp                 |  3 +++
 clang_delta/SimplifyStructUnionDecl.cpp    | 13 +++++++++++++
 clang_delta/Transformation.cpp             | 12 ++++++++++++
 clang_delta/Transformation.h               |  3 +++
 clang_delta/UnionToStruct.cpp              | 20 +++++++++++++-------
 26 files changed, 137 insertions(+), 24 deletions(-)

diff --git a/clang_delta/BinOpSimplification.cpp b/clang_delta/BinOpSimplification.cpp
index 6e109e7..97c540f 100644
--- a/clang_delta/BinOpSimplification.cpp
+++ b/clang_delta/BinOpSimplification.cpp
@@ -64,7 +64,8 @@ private:
 
 bool BSCollectionVisitor::VisitFunctionDecl(FunctionDecl *FD)
 {
-  if (!FD->isThisDeclarationADefinition())
+  if (ConsumerInstance->isInIncludedFile(FD) ||
+      !FD->isThisDeclarationADefinition())
     return true;
 
   ConsumerInstance->StmtVisitor->setCurrentFunctionDecl(FD);
diff --git a/clang_delta/CallExprToValue.cpp b/clang_delta/CallExprToValue.cpp
index df0d435..b28bd3e 100644
--- a/clang_delta/CallExprToValue.cpp
+++ b/clang_delta/CallExprToValue.cpp
@@ -56,6 +56,9 @@ private:
 
 bool CallExprToValueVisitor::VisitCallExpr(CallExpr *CE)
 {
+  if (ConsumerInstance->isInIncludedFile(CurrentFD))
+    return true;
+
   ConsumerInstance->ValidInstanceNum++;
   if (ConsumerInstance->TransformationCounter != 
       ConsumerInstance->ValidInstanceNum)
diff --git a/clang_delta/ClassTemplateToClass.cpp b/clang_delta/ClassTemplateToClass.cpp
index e6eb7d0..aab438c 100644
--- a/clang_delta/ClassTemplateToClass.cpp
+++ b/clang_delta/ClassTemplateToClass.cpp
@@ -143,7 +143,8 @@ bool ClassTemplateToClassASTVisitor::VisitClassTemplateDecl(
        ClassTemplateDecl *D)
 {
   ClassTemplateDecl *CanonicalD = D->getCanonicalDecl();
-  if (ConsumerInstance->VisitedDecls.count(CanonicalD))
+  if (ConsumerInstance->isInIncludedFile(CanonicalD) ||
+      ConsumerInstance->VisitedDecls.count(CanonicalD))
     return true;
 
   ConsumerInstance->VisitedDecls.insert(CanonicalD);
diff --git a/clang_delta/CombineGlobalVarDecl.cpp b/clang_delta/CombineGlobalVarDecl.cpp
index e1009ce..1c04e8b 100644
--- a/clang_delta/CombineGlobalVarDecl.cpp
+++ b/clang_delta/CombineGlobalVarDecl.cpp
@@ -54,8 +54,9 @@ bool CombineGlobalVarDecl::HandleTopLevelDecl(DeclGroupRef DGR)
 {
   DeclGroupRef::iterator DI = DGR.begin();
   VarDecl *VD = dyn_cast<VarDecl>(*DI);
-  if (!VD)
+  if (!VD || isInIncludedFile(VD))
     return true;
+
   SourceRange Range = VD->getSourceRange();
   if (Range.getBegin().isInvalid() || Range.getEnd().isInvalid())
     return true;
diff --git a/clang_delta/EmptyStructToInt.cpp b/clang_delta/EmptyStructToInt.cpp
index be4bf7d..ea7669e 100644
--- a/clang_delta/EmptyStructToInt.cpp
+++ b/clang_delta/EmptyStructToInt.cpp
@@ -77,7 +77,8 @@ private:
 
 bool EmptyStructToIntASTVisitor::VisitRecordDecl(RecordDecl *RD)
 {
-  if (!ConsumerInstance->isValidRecordDecl(RD))
+  if (ConsumerInstance->isInIncludedFile(RD) ||
+      !ConsumerInstance->isValidRecordDecl(RD))
     return true;
  
   const RecordDecl *CanonicalRD = dyn_cast<RecordDecl>(RD->getCanonicalDecl());
diff --git a/clang_delta/MoveGlobalVar.cpp b/clang_delta/MoveGlobalVar.cpp
index b067770..4a58499 100644
--- a/clang_delta/MoveGlobalVar.cpp
+++ b/clang_delta/MoveGlobalVar.cpp
@@ -47,6 +47,7 @@ bool MoveGlobalVar::HandleTopLevelDecl(DeclGroupRef D)
   TransAssert((I != D.end()) && "Bad DeclGroupRef!");
 
   const NamedDecl *ND = dyn_cast<NamedDecl>(*I);
+
   if (!TheFirstDecl && ND && isSpecialDecl(ND->getNameAsString()))
     return true;
 
@@ -87,6 +88,9 @@ void MoveGlobalVar::HandleTranslationUnit(ASTContext &Ctx)
 
 void MoveGlobalVar::handleFunctionDecl(const FunctionDecl *FD)
 {
+  if (isInIncludedFile(FD))
+    return;
+
   if (FD->getNameAsString() == "printf") {
     if (ThePrintfDecl || !TheFirstDecl || FD->isThisDeclarationADefinition())
       return;
@@ -102,6 +106,9 @@ void MoveGlobalVar::handleFunctionDecl(const FunctionDecl *FD)
 
 void MoveGlobalVar::handleOtherDecl(DeclGroupRef DGR)
 {
+  if(isInIncludedFile(*DGR.begin()))
+    return;
+
   if (!TheFirstFunctionDecl)
     return;
 
diff --git a/clang_delta/ParamToGlobal.cpp b/clang_delta/ParamToGlobal.cpp
index b724858..52d10c7 100644
--- a/clang_delta/ParamToGlobal.cpp
+++ b/clang_delta/ParamToGlobal.cpp
@@ -172,6 +172,11 @@ bool ParamToGlobal::isValidFuncDecl(FunctionDecl *FD)
 
   TransAssert(isa<FunctionDecl>(FD) && "Must be a FunctionDecl");
 
+  // Skip declarations from include files.
+  if (isInIncludedFile(FD)) {
+    return false;
+  }
+
   // Skip the case like foo(int, ...), because we cannot remove
   // the "int" there
   if (FD->isVariadic() && (FD->getNumParams() == 1)) {
diff --git a/clang_delta/ParamToLocal.cpp b/clang_delta/ParamToLocal.cpp
index f90d0f5..94f76de 100644
--- a/clang_delta/ParamToLocal.cpp
+++ b/clang_delta/ParamToLocal.cpp
@@ -169,6 +169,11 @@ bool ParamToLocal::isValidFuncDecl(FunctionDecl *FD)
 
   TransAssert(isa<FunctionDecl>(FD) && "Must be a FunctionDecl");
 
+  // Skip declarations from include files.
+  if (isInIncludedFile(FD)) {
+    return false;
+  }
+
   // Skip the case like foo(int, ...), because we cannot remove
   // the "int" there
   if (FD->isVariadic() && (FD->getNumParams() == 1)) {
diff --git a/clang_delta/ReducePointerLevel.cpp b/clang_delta/ReducePointerLevel.cpp
index ad01318..eec4628 100644
--- a/clang_delta/ReducePointerLevel.cpp
+++ b/clang_delta/ReducePointerLevel.cpp
@@ -118,6 +118,9 @@ bool PointerLevelCollectionVisitor::isVAArgField(DeclaratorDecl *DD)
 // I skipped IndirectFieldDecl for now
 bool PointerLevelCollectionVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD)
 {
+  if (ConsumerInstance->isInIncludedFile(DD))
+    return true;
+
   if (isVAArgField(DD))
     return true;
 
diff --git a/clang_delta/RemoveArray.cpp b/clang_delta/RemoveArray.cpp
index 54f6bbb..2c348b1 100644
--- a/clang_delta/RemoveArray.cpp
+++ b/clang_delta/RemoveArray.cpp
@@ -267,7 +267,7 @@ void RemoveArray::addOneArraySubscriptExpr(ArraySubscriptExpr *ASE,
 
 void RemoveArray::handleOneVarDecl(const VarDecl *VD)
 {
-  if (VD->getAnyInitializer())
+  if (isInIncludedFile(VD) || VD->getAnyInitializer())
     return;
 
   const Type *Ty = VD->getType().getTypePtr();
diff --git a/clang_delta/RemoveEnumMemberValue.cpp b/clang_delta/RemoveEnumMemberValue.cpp
index fcb6bc1..7d42519 100644
--- a/clang_delta/RemoveEnumMemberValue.cpp
+++ b/clang_delta/RemoveEnumMemberValue.cpp
@@ -47,7 +47,8 @@ private:
 
 bool RemoveEnumMemberValueAnalysisVisitor::VisitEnumConstantDecl(EnumConstantDecl *ECD)
 {
-  if (!ECD->getInitExpr())
+  if (ConsumerInstance->isInIncludedFile(ECD) ||
+      !ECD->getInitExpr())
     return true;
 
   ConsumerInstance->ValidInstanceNum++;
diff --git a/clang_delta/RemovePointer.cpp b/clang_delta/RemovePointer.cpp
index f60176b..6ea38ff 100644
--- a/clang_delta/RemovePointer.cpp
+++ b/clang_delta/RemovePointer.cpp
@@ -170,6 +170,9 @@ void RemovePointer::invalidateOneVarDecl(const DeclRefExpr *DRE)
 
 void RemovePointer::handleOneVarDecl(const VarDecl *VD)
 {
+  if (isInIncludedFile(VD))
+    return;
+
   if (dyn_cast<ParmVarDecl>(VD))
     return;
 
diff --git a/clang_delta/RemoveUnusedEnumMember.cpp b/clang_delta/RemoveUnusedEnumMember.cpp
index 283215b..3deeff3 100644
--- a/clang_delta/RemoveUnusedEnumMember.cpp
+++ b/clang_delta/RemoveUnusedEnumMember.cpp
@@ -47,7 +47,7 @@ private:
 
 bool RemoveUnusedEnumMemberAnalysisVisitor::VisitEnumDecl(EnumDecl *ED)
 {
-  if (ED != ED->getCanonicalDecl())
+  if (ConsumerInstance->isInIncludedFile(ED) || ED != ED->getCanonicalDecl())
     return true;
 
   EnumDecl::enumerator_iterator Previous = ED->enumerator_begin();
diff --git a/clang_delta/RemoveUnusedStructField.cpp b/clang_delta/RemoveUnusedStructField.cpp
index dfbe7ed..16e5375 100644
--- a/clang_delta/RemoveUnusedStructField.cpp
+++ b/clang_delta/RemoveUnusedStructField.cpp
@@ -66,6 +66,9 @@ private:
 
 bool RemoveUnusedStructFieldVisitor::VisitFieldDecl(FieldDecl *FD)
 {
+  if(ConsumerInstance->isInIncludedFile(FD))
+    return true;
+
   const RecordDecl *RD = FD->getParent();
   if (FD->isReferenced() || !RD->isStruct() ||
       ConsumerInstance->isSpecialRecordDecl(RD))
diff --git a/clang_delta/RemoveUnusedVar.cpp b/clang_delta/RemoveUnusedVar.cpp
index 459b0b0..eb7aeec 100644
--- a/clang_delta/RemoveUnusedVar.cpp
+++ b/clang_delta/RemoveUnusedVar.cpp
@@ -50,6 +50,9 @@ private:
 
 bool RemoveUnusedVarAnalysisVisitor::VisitVarDecl(VarDecl *VD)
 {
+  if (ConsumerInstance->isInIncludedFile(VD))
+    return true;
+
   if (VD->isReferenced() || dyn_cast<ParmVarDecl>(VD) || 
       VD->isStaticDataMember())
     return true;
diff --git a/clang_delta/RenameFun.cpp b/clang_delta/RenameFun.cpp
index 2ad67bf..3f69d77 100644
--- a/clang_delta/RenameFun.cpp
+++ b/clang_delta/RenameFun.cpp
@@ -76,6 +76,11 @@ bool RNFunCollectionVisitor::VisitFunctionDecl(FunctionDecl *FD)
   }
 
   const FunctionDecl *CanonicalFD = FD->getCanonicalDecl();
+
+  if (ConsumerInstance->isInIncludedFile(FD) ||
+      ConsumerInstance->isInIncludedFile(CanonicalFD))
+    return true;
+
   ConsumerInstance->addFun(CanonicalFD);
   if (!ConsumerInstance->hasValidPostfix(FD->getNameAsString()))
     ConsumerInstance->HasValidFuns = true;
@@ -91,6 +96,9 @@ bool RNFunCollectionVisitor::VisitCallExpr(CallExpr *CE)
 
   const FunctionDecl *CanonicalFD = FD->getCanonicalDecl();
 
+  if (ConsumerInstance->isInIncludedFile(CanonicalFD))
+    return true;
+
   // This case is handled by VisitFunctionDecl
   if (CanonicalFD->isDefined())
     return true;
@@ -108,6 +116,10 @@ bool RenameFunVisitor::VisitFunctionDecl(FunctionDecl *FD)
     return true;
 
   FunctionDecl *CanonicalDecl = FD->getCanonicalDecl();
+
+  if (ConsumerInstance->isInIncludedFile(CanonicalDecl))
+    return true;
+
   llvm::DenseMap<const FunctionDecl *, std::string>::iterator I = 
     ConsumerInstance->FunToNameMap.find(CanonicalDecl);
 
@@ -126,6 +138,10 @@ bool RenameFunVisitor::VisitDeclRefExpr(DeclRefExpr *DRE)
     return true;
 
   FunctionDecl *CanonicalDecl = FD->getCanonicalDecl();
+
+  if (ConsumerInstance->isInIncludedFile(CanonicalDecl))
+    return true;
+
   llvm::DenseMap<const FunctionDecl *, std::string>::iterator I = 
     ConsumerInstance->FunToNameMap.find(CanonicalDecl);
 
diff --git a/clang_delta/RenameParam.cpp b/clang_delta/RenameParam.cpp
index 87982b5..01d42e3 100644
--- a/clang_delta/RenameParam.cpp
+++ b/clang_delta/RenameParam.cpp
@@ -68,6 +68,9 @@ private:
 
 bool ExistingVarCollectionVisitor::VisitVarDecl(VarDecl *VD)
 {
+  if (ConsumerInstance->isInIncludedFile(VD))
+    return true;
+
   ParmVarDecl *PD = dyn_cast<ParmVarDecl>(VD);
   if (PD) {
     ConsumerInstance->validateParam(PD);
@@ -87,7 +90,7 @@ bool ExistingVarCollectionVisitor::VisitVarDecl(VarDecl *VD)
 
 bool RenameParamVisitor::VisitFunctionDecl(FunctionDecl *FD)
 {
-  if (FD->param_size() == 0)
+  if (ConsumerInstance->isInIncludedFile(FD) || FD->param_size() == 0)
     return true;
 
   FunctionDecl *CanonicalFD = FD->getCanonicalDecl();
@@ -120,7 +123,7 @@ bool RenameParamVisitor::VisitDeclRefExpr(DeclRefExpr *DRE)
   ValueDecl *OrigDecl = DRE->getDecl();
   ParmVarDecl *PD = dyn_cast<ParmVarDecl>(OrigDecl);
   
-  if (!PD)
+  if (!PD || ConsumerInstance->isInIncludedFile(PD))
     return true;
 
   llvm::DenseMap<ParmVarDecl *, std::string>::iterator I =
diff --git a/clang_delta/RenameVar.cpp b/clang_delta/RenameVar.cpp
index d323241..1a59649 100644
--- a/clang_delta/RenameVar.cpp
+++ b/clang_delta/RenameVar.cpp
@@ -68,18 +68,26 @@ private:
 
 bool RNVCollectionVisitor::VisitVarDecl(VarDecl *VD)
 {
+  if (ConsumerInstance->isInIncludedFile(VD))
+    return true;
+
   ParmVarDecl *PV = dyn_cast<ParmVarDecl>(VD);
   // Skip parameters
   if (PV)
     return true;
 
   VarDecl *CanonicalVD = VD->getCanonicalDecl();
-  ConsumerInstance->addVar(CanonicalVD);
+
+  if (!ConsumerInstance->isInIncludedFile(CanonicalVD))
+    ConsumerInstance->addVar(CanonicalVD);
   return true;
 }
 
 bool RenameVarVisitor::VisitVarDecl(VarDecl *VD)
 {
+  if (ConsumerInstance->isInIncludedFile(VD))
+    return true;
+
   VarDecl *CanonicalDecl = VD->getCanonicalDecl();
   llvm::DenseMap<VarDecl *, std::string>::iterator I = 
     ConsumerInstance->VarToNameMap.find(CanonicalDecl);
@@ -94,7 +102,7 @@ bool RenameVarVisitor::VisitDeclRefExpr(DeclRefExpr *DRE)
 {
   ValueDecl *OrigDecl = DRE->getDecl();
   VarDecl *VD = dyn_cast<VarDecl>(OrigDecl);
-  if (!VD)
+  if (!VD || ConsumerInstance->isInIncludedFile(VD))
     return true;
 
   VarDecl *CanonicalDecl = VD->getCanonicalDecl();
diff --git a/clang_delta/ReplaceOneLevelTypedefType.cpp b/clang_delta/ReplaceOneLevelTypedefType.cpp
index b7e30d3..a39fa6c 100644
--- a/clang_delta/ReplaceOneLevelTypedefType.cpp
+++ b/clang_delta/ReplaceOneLevelTypedefType.cpp
@@ -122,7 +122,7 @@ void ReplaceOneLevelTypedefType::handleOneTypedefTypeLoc(TypedefTypeLoc TLoc)
 {
   const TypedefType *TdefTy = TLoc.getTypePtr();
   const TypedefDecl *TdefD = dyn_cast<TypedefDecl>(TdefTy->getDecl());
-  if (!TdefD || TdefD->getLocStart().isInvalid())
+  if (!TdefD || TdefD->getLocStart().isInvalid() || isInIncludedFile(TdefD))
     return;
   const TypedefDecl *CanonicalD = 
     dyn_cast<TypedefDecl>(TdefD->getCanonicalDecl());
diff --git a/clang_delta/ReplaceSimpleTypedef.cpp b/clang_delta/ReplaceSimpleTypedef.cpp
index 39e34f9..33186d0 100644
--- a/clang_delta/ReplaceSimpleTypedef.cpp
+++ b/clang_delta/ReplaceSimpleTypedef.cpp
@@ -42,11 +42,10 @@ public:
     : ConsumerInstance(Instance)
   { }
 
-  bool VisitTypedefDecl(TypedefDecl *D);
+  bool VisitTypedefTypeLoc(TypedefTypeLoc Loc);
 
 private:
   ReplaceSimpleTypedef *ConsumerInstance;
-
 };
 
 class ReplaceSimpleTypedefRewriteVisitor : public
@@ -66,9 +65,19 @@ private:
 
 };
 
-bool ReplaceSimpleTypedefCollectionVisitor::VisitTypedefDecl(TypedefDecl *TdefD)
+bool ReplaceSimpleTypedefCollectionVisitor::VisitTypedefTypeLoc(TypedefTypeLoc Loc)
 {
-  TypedefDecl *CanonicalD = dyn_cast<TypedefDecl>(TdefD->getCanonicalDecl());
+  if (ConsumerInstance->isInIncludedFile(Loc.getBeginLoc()))
+    return true;
+
+  const TypedefType *TdefTy = Loc.getTypePtr();
+  const TypedefDecl *TdefD = dyn_cast<TypedefDecl>(TdefTy->getDecl());
+
+  if (!TdefD)
+    return true;
+
+  const TypedefDecl *CanonicalD = dyn_cast<TypedefDecl>(TdefD->getCanonicalDecl());
+
   if (!ConsumerInstance->VisitedTypedefDecls.count(CanonicalD)) {
     ConsumerInstance->handleOneTypedefDecl(CanonicalD);
     ConsumerInstance->VisitedTypedefDecls.insert(CanonicalD);
@@ -79,6 +88,9 @@ bool ReplaceSimpleTypedefCollectionVisitor::VisitTypedefDecl(TypedefDecl *TdefD)
 
 bool ReplaceSimpleTypedefRewriteVisitor::VisitTypedefTypeLoc(TypedefTypeLoc Loc)
 {
+  if (ConsumerInstance->isInIncludedFile(Loc.getBeginLoc()))
+    return true;
+
   const TypedefType *TdefTy = Loc.getTypePtr();
   const TypedefDecl *TdefD = dyn_cast<TypedefDecl>(TdefTy->getDecl());
   if (!TdefD || TdefD->getLocStart().isInvalid())
diff --git a/clang_delta/ReplaceUndefinedFunction.cpp b/clang_delta/ReplaceUndefinedFunction.cpp
index f03f7b3..0976923 100644
--- a/clang_delta/ReplaceUndefinedFunction.cpp
+++ b/clang_delta/ReplaceUndefinedFunction.cpp
@@ -65,7 +65,7 @@ private:
 
 bool ReplaceUndefFuncCollectionVisitor::VisitFunctionDecl(FunctionDecl *FD)
 {
-  if (FD->hasBody())
+  if (ConsumerInstance->isInIncludedFile(FD) || FD->hasBody())
     return true;
   ConsumerInstance->handleOneFunctionDecl(FD->getCanonicalDecl());
 
diff --git a/clang_delta/ReturnVoid.cpp b/clang_delta/ReturnVoid.cpp
index 2a4ddad..f9c8869 100644
--- a/clang_delta/ReturnVoid.cpp
+++ b/clang_delta/ReturnVoid.cpp
@@ -67,6 +67,9 @@ private:
 
 bool RVCollectionVisitor::VisitFunctionDecl(FunctionDecl *FD)
 {
+  if (ConsumerInstance->isInIncludedFile(FD))
+    return true;
+
   FunctionDecl *CanonicalDecl = FD->getCanonicalDecl();
   if (ConsumerInstance->isNonVoidReturnFunction(CanonicalDecl)) {
     ConsumerInstance->ValidInstanceNum++;
diff --git a/clang_delta/SimplifyStructUnionDecl.cpp b/clang_delta/SimplifyStructUnionDecl.cpp
index 869fcf9..642e786 100644
--- a/clang_delta/SimplifyStructUnionDecl.cpp
+++ b/clang_delta/SimplifyStructUnionDecl.cpp
@@ -52,12 +52,18 @@ private:
 
 bool SimplifyStructUnionDeclVisitor::VisitFunctionDecl(FunctionDecl *FD)
 {
+  if (ConsumerInstance->isInIncludedFile(FD))
+    return true;
+
   const Type *T = FD->getReturnType().getTypePtr();
   return ConsumerInstance->handleOneDeclarator(T);
 }
 
 bool SimplifyStructUnionDeclVisitor::VisitVarDecl(VarDecl *VD)
 {
+  if (ConsumerInstance->isInIncludedFile(VD))
+    return true;
+
   if (ConsumerInstance->CombinedVars.count(VD))
     return true;
 
@@ -67,6 +73,9 @@ bool SimplifyStructUnionDeclVisitor::VisitVarDecl(VarDecl *VD)
 
 bool SimplifyStructUnionDeclVisitor::VisitFieldDecl(FieldDecl *FD)
 {
+  if (ConsumerInstance->isInIncludedFile(FD))
+    return true;
+
   const Type *T = FD->getType().getTypePtr();
   return ConsumerInstance->handleOneDeclarator(T);
 }
@@ -80,6 +89,10 @@ void SimplifyStructUnionDecl::Initialize(ASTContext &context)
 bool SimplifyStructUnionDecl::HandleTopLevelDecl(DeclGroupRef DGR) 
 {
   DeclGroupRef::iterator DI = DGR.begin();
+
+  if (isInIncludedFile(*DI))
+    return true;
+
   const RecordDecl *RD = dyn_cast<RecordDecl>(*DI);
   if (RD) {
     addOneRecordDecl(RD, DGR);
diff --git a/clang_delta/Transformation.cpp b/clang_delta/Transformation.cpp
index 4ef8168..9dfc9b3 100644
--- a/clang_delta/Transformation.cpp
+++ b/clang_delta/Transformation.cpp
@@ -1038,6 +1038,18 @@ unsigned Transformation::getNumExplicitDecls(const CXXRecordDecl *CXXRD)
   return Num;
 }
 
+bool Transformation::isInIncludedFile(SourceLocation loc) const
+{
+  return SrcManager->getFileID(loc) != SrcManager->getMainFileID();
+}
+
+
+bool Transformation::isInIncludedFile(clang::Decl const *decl) const
+{
+  return isInIncludedFile(decl->getLocation());
+}
+
+
 Transformation::~Transformation(void)
 {
   RewriteUtils::Finalize();
diff --git a/clang_delta/Transformation.h b/clang_delta/Transformation.h
index 9fe81d3..c0675ef 100644
--- a/clang_delta/Transformation.h
+++ b/clang_delta/Transformation.h
@@ -270,6 +270,9 @@ protected:
 
   unsigned getNumExplicitDecls(const clang::CXXRecordDecl *CXXRD);
 
+  bool isInIncludedFile(clang::SourceLocation loc) const;
+  bool isInIncludedFile(clang::Decl const *decl) const;
+
   const std::string Name;
 
   int TransformationCounter;
diff --git a/clang_delta/UnionToStruct.cpp b/clang_delta/UnionToStruct.cpp
index 1802916..9a64508 100644
--- a/clang_delta/UnionToStruct.cpp
+++ b/clang_delta/UnionToStruct.cpp
@@ -67,28 +67,34 @@ private:
 
 bool UnionToStructCollectionVisitor::VisitFunctionDecl(FunctionDecl *FD)
 {
-  const Type *T = FD->getReturnType().getTypePtr();
-  ConsumerInstance->addOneDeclarator(FD, T);
+  if (!ConsumerInstance->isInIncludedFile(FD)) {
+    const Type *T = FD->getReturnType().getTypePtr();
+    ConsumerInstance->addOneDeclarator(FD, T);
+  }
   return true;
 }
 
 bool UnionToStructCollectionVisitor::VisitVarDecl(VarDecl *VD)
 {
-  const Type *T = VD->getType().getTypePtr();
-  ConsumerInstance->addOneDeclarator(VD, T);
+  if (!ConsumerInstance->isInIncludedFile(VD)) {
+    const Type *T = VD->getType().getTypePtr();
+    ConsumerInstance->addOneDeclarator(VD, T);
+  }
   return true;
 }
 
 bool UnionToStructCollectionVisitor::VisitFieldDecl(FieldDecl *FD)
 {
-  const Type *T = FD->getType().getTypePtr();
-  ConsumerInstance->addOneDeclarator(FD, T);
+  if (!ConsumerInstance->isInIncludedFile(FD)) {
+    const Type *T = FD->getType().getTypePtr();
+    ConsumerInstance->addOneDeclarator(FD, T);
+  }
   return true;
 }
 
 bool UnionToStructCollectionVisitor::VisitRecordDecl(RecordDecl *RD)
 {
-  if (RD->isUnion())
+  if (!ConsumerInstance->isInIncludedFile(RD) && RD->isUnion())
     ConsumerInstance->addOneRecord(RD);
 
   return true;
-- 
1.9.1