cpp11-migrate: Add a class to support include directives modifications

The IncludeDirectives class helps with detecting and modifying #include
directives. For now it allows the users to add angled-includes in a source file.
This is a start for this class that will evolve in the future to add more
functionality.

This should fix the reverted commit r189037 (buildbot failures on Windows).

llvm-svn: 189354
diff --git a/clang-tools-extra/cpp11-migrate/Core/IncludeDirectives.h b/clang-tools-extra/cpp11-migrate/Core/IncludeDirectives.h
new file mode 100644
index 0000000..c1c5a7a
--- /dev/null
+++ b/clang-tools-extra/cpp11-migrate/Core/IncludeDirectives.h
@@ -0,0 +1,141 @@
+//===-- Core/IncludeDirectives.h - Include directives handling --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file declares the IncludeDirectives class that helps with
+/// detecting and modifying \#include directives.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef CPP11_MIGRATE_INCLUDE_DIRECTIVES_H
+#define CPP11_MIGRATE_INCLUDE_DIRECTIVES_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Tooling/Refactoring.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include <vector>
+
+namespace clang {
+class Preprocessor;
+} // namespace clang
+
+/// \brief Support for include directives handling.
+///
+/// This class should be created with a \c clang::CompilerInstance before the
+/// file is preprocessed in order to collect the inclusion information. It can
+/// be queried as long as the compiler instance is valid.
+class IncludeDirectives {
+public:
+  IncludeDirectives(clang::CompilerInstance &CI);
+
+  /// \brief Add an angled include to a the given file.
+  ///
+  /// \param File A file accessible by a SourceManager
+  /// \param Include The include file as it should be written in the code.
+  ///
+  /// \returns
+  /// \li A null Replacement (check using \c Replacement::isApplicable()), if
+  ///     the \c Include is already visible from \c File.
+  /// \li Otherwise, a non-null Replacement that, when applied, inserts an
+  ///     \c \#include into \c File.
+  clang::tooling::Replacement addAngledInclude(llvm::StringRef File,
+                                               llvm::StringRef Include);
+  clang::tooling::Replacement addAngledInclude(const clang::FileEntry *File,
+                                               llvm::StringRef Include);
+
+  /// \brief Check if \p Include is included by \p File or any of the files
+  /// \p File includes.
+  bool hasInclude(const clang::FileEntry *File, llvm::StringRef Include) const;
+
+private:
+  friend class IncludeDirectivesPPCallback;
+
+  /// \brief Contains information about an inclusion.
+  class Entry {
+  public:
+    Entry(clang::SourceLocation HashLoc, const clang::FileEntry *IncludedFile,
+          bool Angled)
+        : HashLoc(HashLoc), IncludedFile(IncludedFile), Angled(Angled) {}
+
+    /// \brief The location of the '#'.
+    clang::SourceLocation getHashLocation() const { return HashLoc; }
+
+    /// \brief The file included by this include directive.
+    const clang::FileEntry *getIncludedFile() const { return IncludedFile; }
+
+    /// \brief \c true if the include use angle brackets, \c false otherwise
+    /// when using of quotes.
+    bool isAngled() const { return Angled; }
+
+  private:
+    clang::SourceLocation HashLoc;
+    const clang::FileEntry *IncludedFile;
+    bool Angled;
+  };
+
+  // A list of entries.
+  typedef std::vector<Entry> EntryVec;
+
+  // A list of source locations.
+  typedef std::vector<clang::SourceLocation> LocationVec;
+
+  // Associates files to their includes.
+  typedef llvm::DenseMap<const clang::FileEntry *, EntryVec> FileToEntriesMap;
+
+  // Associates headers to their include guards if any. The location is the
+  // location of the hash from the #define.
+  typedef llvm::DenseMap<const clang::FileEntry *, clang::SourceLocation>
+  HeaderToGuardMap;
+
+  /// \brief Type used by \c lookForInclude() to keep track of the files that
+  /// have already been processed.
+  typedef llvm::SmallPtrSet<const clang::FileEntry *, 32> SeenFilesSet;
+
+  /// \brief Recursively look if an include is included by \p File or any of the
+  /// headers \p File includes.
+  ///
+  /// \param File The file where to start the search.
+  /// \param IncludeLocs These are the hash locations of the \#include
+  /// directives we are looking for.
+  /// \param Seen Used to avoid visiting a same file more than once during the
+  /// recursion.
+  bool lookForInclude(const clang::FileEntry *File,
+                      const LocationVec &IncludeLocs, SeenFilesSet &Seen) const;
+
+  /// \brief Find the end of a file header and returns a pair (FileOffset,
+  /// NewLineFlags).
+  ///
+  /// Source files often contain a file header (copyright, license, explanation
+  /// of the file content). An \#include should preferrably be put after this.
+  std::pair<unsigned, unsigned>
+  findFileHeaderEndOffset(clang::FileID FID) const;
+
+  /// \brief Finds the offset where an angled include should be added and
+  /// returns a pair (FileOffset, NewLineFlags).
+  std::pair<unsigned, unsigned>
+  angledIncludeInsertionOffset(clang::FileID FID) const;
+
+  /// \brief Find the location of an include directive that can be used to
+  /// insert an inclusion after.
+  ///
+  /// If no such include exists returns a null SourceLocation.
+  clang::SourceLocation angledIncludeHintLoc(clang::FileID FID) const;
+
+  clang::CompilerInstance &CI;
+  clang::SourceManager &Sources;
+  FileToEntriesMap FileToEntries;
+  // maps include filename as written in the source code to the source locations
+  // where it appears
+  llvm::StringMap<LocationVec> IncludeAsWrittenToLocationsMap;
+  HeaderToGuardMap HeaderToGuard;
+};
+
+#endif // CPP11_MIGRATE_INCLUDE_DIRECTIVES_H