[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2018-01-15 Thread Cameron via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rC322503: [PCH] Serialize skipped preprocessor ranges 
(authored by cameron314, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D20124?vs=125333&id=129892#toc

Repository:
  rC Clang

https://reviews.llvm.org/D20124

Files:
  include/clang/Lex/PreprocessingRecord.h
  include/clang/Serialization/ASTBitCodes.h
  include/clang/Serialization/ASTReader.h
  include/clang/Serialization/Module.h
  lib/Lex/PPDirectives.cpp
  lib/Lex/PreprocessingRecord.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTWriter.cpp
  tools/libclang/CIndex.cpp
  unittests/libclang/LibclangTest.cpp

Index: include/clang/Lex/PreprocessingRecord.h
===
--- include/clang/Lex/PreprocessingRecord.h
+++ include/clang/Lex/PreprocessingRecord.h
@@ -297,6 +297,9 @@
 FileID FID) {
   return None;
 }
+
+/// \brief Read a preallocated skipped range from the external source.
+virtual SourceRange ReadSkippedRange(unsigned Index) = 0;
   };
   
   /// \brief A record of the steps taken while preprocessing a source file,
@@ -322,6 +325,8 @@
 /// \brief The set of ranges that were skipped by the preprocessor,
 std::vector SkippedRanges;
 
+bool SkippedRangesAllLoaded = true;
+
 /// \brief Global (loaded or local) ID for a preprocessed entity.
 /// Negative values are used to indicate preprocessed entities
 /// loaded from the external source while non-negative values are used to
@@ -377,6 +382,16 @@
 /// corresponds to the first newly-allocated entity.
 unsigned allocateLoadedEntities(unsigned NumEntities);
 
+/// \brief Allocate space for a new set of loaded preprocessed skipped
+/// ranges.
+///
+/// \returns The index into the set of loaded preprocessed ranges, which
+/// corresponds to the first newly-allocated range.
+unsigned allocateSkippedRanges(unsigned NumRanges);
+
+/// \brief Ensures that all external skipped ranges have been loaded.
+void ensureSkippedRangesLoaded();
+
 /// \brief Register a new macro definition.
 void RegisterMacroDefinition(MacroInfo *Macro, MacroDefinitionRecord *Def);
 
@@ -499,7 +514,8 @@
 MacroDefinitionRecord *findMacroDefinition(const MacroInfo *MI);
 
 /// \brief Retrieve all ranges that got skipped while preprocessing.
-const std::vector &getSkippedRanges() const {
+const std::vector &getSkippedRanges() {
+  ensureSkippedRangesLoaded();
   return SkippedRanges;
 }
 
Index: include/clang/Serialization/Module.h
===
--- include/clang/Serialization/Module.h
+++ include/clang/Serialization/Module.h
@@ -324,6 +324,12 @@
   const PPEntityOffset *PreprocessedEntityOffsets = nullptr;
   unsigned NumPreprocessedEntities = 0;
 
+  /// \brief Base ID for preprocessed skipped ranges local to this module.
+  unsigned BasePreprocessedSkippedRangeID = 0;
+
+  const PPSkippedRange *PreprocessedSkippedRangeOffsets = nullptr;
+  unsigned NumPreprocessedSkippedRanges = 0;
+
   // === Header search information ===
 
   /// \brief The number of local HeaderFileInfo structures.
Index: include/clang/Serialization/ASTBitCodes.h
===
--- include/clang/Serialization/ASTBitCodes.h
+++ include/clang/Serialization/ASTBitCodes.h
@@ -198,6 +198,25 @@
   }
 };
 
+/// \brief Source range of a skipped preprocessor region
+struct PPSkippedRange {
+  /// \brief Raw source location of beginning of range.
+  unsigned Begin;
+  /// \brief Raw source location of end of range.
+  unsigned End;
+
+  PPSkippedRange(SourceRange R)
+: Begin(R.getBegin().getRawEncoding()),
+  End(R.getEnd().getRawEncoding()) { }
+
+  SourceLocation getBegin() const {
+return SourceLocation::getFromRawEncoding(Begin);
+  }
+  SourceLocation getEnd() const {
+return SourceLocation::getFromRawEncoding(End);
+  }
+};
+
 /// \brief Source range/offset of a preprocessed entity.
 struct DeclOffset {
   /// \brief Raw source location.
@@ -627,6 +646,9 @@
 
   /// \brief The stack of open #ifs/#ifdefs recorded in a preamble.
   PP_CONDITIONAL_STACK = 62,
+
+  /// \brief A table of skipped ranges within the preprocessing record.
+  PPD_SKIPPED_RANGES = 63
 };
 
 /// \brief Record types used within a source manager block.
Index: include/clang/Serialization/ASTReader.h
===
--- include/clang/Serialization/ASTReader.h
+++ include/clang/Serialization/ASTReader.h
@@ -753,6 +753,13 @@
   /// added to the global preprocessing entity ID to produce a local ID.
   GlobalPreprocessedEntityMapType GlobalPreprocessedEntityMap;
 
+  

[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2018-01-15 Thread Cameron via Phabricator via cfe-commits
cameron314 added a comment.

Excellent, I'll rebase and commit. Thanks everyone for your patience!


https://reviews.llvm.org/D20124



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2018-01-12 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov accepted this revision.
ilya-biryukov added a comment.
This revision is now accepted and ready to land.

LGTM, sorry for the delay.


https://reviews.llvm.org/D20124



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2018-01-05 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv added a comment.

lgtm. Ilya?


https://reviews.llvm.org/D20124



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2017-12-14 Thread Cameron via Phabricator via cfe-commits
cameron314 added a comment.

Ping?
The patch is ready to go, just needs a final approval...


https://reviews.llvm.org/D20124



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2017-12-06 Thread Nikolai Kosjar via Phabricator via cfe-commits
nik added a comment.

In https://reviews.llvm.org/D20124#943592, @cameron314 wrote:

> Here's the final patch that fixes `clang_getSkippedRegions` with regions in 
> the preamble (as well as serializing the skipped regions in the PCH file).


Works fine for me, thanks! Test from the bug report is fixed by this one.

You should probably add "Fixes PR34971." to the summary.

@erikjv @ilya-biryukov - please review as you know the details here :)


https://reviews.llvm.org/D20124



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2017-12-04 Thread Cameron via Phabricator via cfe-commits
cameron314 updated this revision to Diff 125333.
cameron314 added a comment.

Here's the final patch that fixes `clang_getSkippedRegions` with regions in the 
preamble (as well as serializing the skipped regions in the PCH file).


https://reviews.llvm.org/D20124

Files:
  include/clang/Lex/PreprocessingRecord.h
  include/clang/Serialization/ASTBitCodes.h
  include/clang/Serialization/ASTReader.h
  include/clang/Serialization/Module.h
  lib/Lex/PPDirectives.cpp
  lib/Lex/PreprocessingRecord.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTWriter.cpp
  tools/libclang/CIndex.cpp
  unittests/libclang/LibclangTest.cpp

Index: unittests/libclang/LibclangTest.cpp
===
--- unittests/libclang/LibclangTest.cpp
+++ unittests/libclang/LibclangTest.cpp
@@ -572,3 +572,81 @@
   EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU));
   DisplayDiagnostics();
 }
+
+TEST_F(LibclangReparseTest, PreprocessorSkippedRanges) {
+  std::string Header = "header.h", Main = "main.cpp";
+  WriteFile(Header,
+"#ifdef MANGOS\n"
+"printf(\"mmm\");\n"
+"#endif");
+  WriteFile(Main,
+"#include \"header.h\"\n"
+"#ifdef GUAVA\n"
+"#endif\n"
+"#ifdef KIWIS\n"
+"printf(\"mmm!!\");\n"
+"#endif");
+
+  for (int i = 0; i != 3; ++i) {
+unsigned flags = TUFlags | CXTranslationUnit_PrecompiledPreamble;
+if (i == 2)
+  flags |= CXTranslationUnit_CreatePreambleOnFirstParse;
+
+// parse once
+ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0,
+ nullptr, 0, flags);
+if (i != 0) {
+  // reparse
+  ASSERT_TRUE(ReparseTU(0, nullptr /* No unsaved files. */));
+}
+
+// Check all ranges are there
+CXSourceRangeList *Ranges = clang_getAllSkippedRanges(ClangTU);
+EXPECT_EQ(3U, Ranges->count);
+
+CXSourceLocation cxl;
+unsigned line;
+cxl = clang_getRangeStart(Ranges->ranges[0]);
+clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+EXPECT_EQ(1U, line);
+cxl = clang_getRangeEnd(Ranges->ranges[0]);
+clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+EXPECT_EQ(3U, line);
+
+cxl = clang_getRangeStart(Ranges->ranges[1]);
+clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+EXPECT_EQ(2U, line);
+cxl = clang_getRangeEnd(Ranges->ranges[1]);
+clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+EXPECT_EQ(3U, line);
+
+cxl = clang_getRangeStart(Ranges->ranges[2]);
+clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+EXPECT_EQ(4U, line);
+cxl = clang_getRangeEnd(Ranges->ranges[2]);
+clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+EXPECT_EQ(6U, line);
+
+clang_disposeSourceRangeList(Ranges);
+
+// Check obtaining ranges by each file works
+CXFile cxf = clang_getFile(ClangTU, Header.c_str());
+Ranges = clang_getSkippedRanges(ClangTU, cxf);
+EXPECT_EQ(1U, Ranges->count);
+cxl = clang_getRangeStart(Ranges->ranges[0]);
+clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+EXPECT_EQ(1U, line);
+clang_disposeSourceRangeList(Ranges);
+
+cxf = clang_getFile(ClangTU, Main.c_str());
+Ranges = clang_getSkippedRanges(ClangTU, cxf);
+EXPECT_EQ(2U, Ranges->count);
+cxl = clang_getRangeStart(Ranges->ranges[0]);
+clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+EXPECT_EQ(2U, line);
+cxl = clang_getRangeStart(Ranges->ranges[1]);
+clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+EXPECT_EQ(4U, line);
+clang_disposeSourceRangeList(Ranges);
+  }
+}
Index: tools/libclang/CIndex.cpp
===
--- tools/libclang/CIndex.cpp
+++ tools/libclang/CIndex.cpp
@@ -8079,13 +8079,16 @@
   SourceManager &sm = Ctx.getSourceManager();
   FileEntry *fileEntry = static_cast(file);
   FileID wantedFileID = sm.translateFile(fileEntry);
+  bool isMainFile = wantedFileID == sm.getMainFileID();
 
   const std::vector &SkippedRanges = ppRec->getSkippedRanges();
   std::vector wantedRanges;
   for (std::vector::const_iterator i = SkippedRanges.begin(), ei = SkippedRanges.end();
i != ei; ++i) {
 if (sm.getFileID(i->getBegin()) == wantedFileID || sm.getFileID(i->getEnd()) == wantedFileID)
   wantedRanges.push_back(*i);
+else if (isMainFile && (astUnit->isInPreambleFileID(i->getBegin()) || astUnit->isInPreambleFileID(i->getEnd(
+  wantedRanges.push_back(*i);
   }
 
   skipped->count = wantedRanges.size();
Index: lib/Serialization/ASTWriter.cpp
===
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -1104,6 +1104,7 @@
   RECORD(UNUSED_FILESCOPED_DECLS);
   RECORD(PPD_ENTITIES_OFFSETS);
   RECORD(VTABLE_USES);
+  RECORD(PPD_SKIPPED_RANGES);
   RECORD(R

[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2017-12-01 Thread Cameron via Phabricator via cfe-commits
cameron314 added a comment.

Brilliant, didn't know `isInPreambleFileID` existed. All my tests pass for me 
now with that change, thanks :-)
I'll update the patch on Monday.


https://reviews.llvm.org/D20124



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2017-11-28 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv added a comment.

Maybe something like this works:

  --- a/tools/libclang/CIndex.cpp
  +++ b/tools/libclang/CIndex.cpp
  @@ -8090,6 +8090,7 @@ CXSourceRangeList 
*clang_getSkippedRanges(CXTranslationUnit TU, CXFile file) {
 SourceManager &sm = Ctx.getSourceManager();
 FileEntry *fileEntry = static_cast(file);
 FileID wantedFileID = sm.translateFile(fileEntry);
  +  bool isMainFile = wantedFileID == sm.getMainFileID();
   
 const std::vector &SkippedRanges = ppRec->getSkippedRanges();
 std::vector wantedRanges;
  @@ -8097,6 +8098,8 @@ CXSourceRangeList 
*clang_getSkippedRanges(CXTranslationUnit TU, CXFile file) {
  i != ei; ++i) {
   if (sm.getFileID(i->getBegin()) == wantedFileID || 
sm.getFileID(i->getEnd()) == wantedFileID)
 wantedRanges.push_back(*i);
  +else if (isMainFile && (astUnit->isInPreambleFileID(i->getBegin()) || 
astUnit->isInPreambleFileID(i->getEnd(
  +  wantedRanges.push_back(*i);
 }
   
 skipped->count = wantedRanges.size();


https://reviews.llvm.org/D20124



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2017-11-20 Thread Cameron via Phabricator via cfe-commits
cameron314 added a comment.

In https://reviews.llvm.org/D20124#928552, @ilya-biryukov wrote:

> Why do we store raw source locations in `PPSkippedRange`? Would storing 
> `SourceLocation` and using  `ASTWriter::AddSourceLocation` and `ASTReader:: 
> ReadSourceLocation` do the trick?


I followed the pattern used to store `PPEntityOffset`s; it allows the entire 
array to be written in one chunk. Using 
`AddSourceLocation`/`ReadSourceLocation` boils down to the same thing -- 
`AddSourceLocation` simply rotates by one bit, and `ReadSourceLocation` simply 
rotates back and calls `ASTReader::TranslateSourceLocation` (which I call from 
`AST::ReadSkippedRange` explicitly instead). So the source location translation 
path is exactly the same either way.

The thing is, the PCH created for the preamble is imported as a module, meaning 
the part of the source code that overlaps the preamble of the entry file has a 
different file ID from the entry file itself. Is there any way to force source 
locations in the preamble to map to the actual entry file instead of the 
module's version of the entry file?


https://reviews.llvm.org/D20124



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2017-11-17 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov added a comment.

In https://reviews.llvm.org/D20124#927967, @cameron314 wrote:

> Well, it seems like preamble PCH source location translation is fundamentally 
> broken. The entry file has a single, positive file ID. The preamble PCH is 
> treated as an imported module, so it has a negative file ID for the part that 
> overlaps the preamble of the entry file. That means locations in the preamble 
> part of the entry file can have two different file IDs depending on how they 
> are arrived at.
>
> I really don't know how to fix this. Any ideas?


Why do we store raw source locations in `PPSkippedRange`? Would storing 
`SourceLocation` and using  `ASTWriter::AddSourceLocation` and `ASTReader:: 
ReadSourceLocation` do the trick?


https://reviews.llvm.org/D20124



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2017-11-16 Thread Cameron via Phabricator via cfe-commits
cameron314 added a comment.

Well, it seems like preamble PCH source location translation is fundamentally 
broken. The entry file has a single, positive file ID. The preamble PCH is 
treated as an imported module, so it has a negative file ID for the part that 
overlaps the preamble of the entry file. That means locations in the preamble 
part of the entry file can have two different file IDs depending on how they 
are arrived at.

I really don't know how to fix this. Any ideas?


https://reviews.llvm.org/D20124



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2017-11-16 Thread Cameron via Phabricator via cfe-commits
cameron314 added a comment.

Alright, with my patch the `c-index-test` *does* correctly serialize and 
restore the skipped ranges; the problem is that it searches for only ranges 
matching the target file. When there's a preamble, it's seen as a different 
file than the main file, even though they're really one and the same in this 
case.

So my test, which uses `clang_getAllSkippedRanges`, passes, but `c-index-test`, 
which uses `clang_getSkippedRanges`, fails. I'll update my test to use both.

I'm trying to figure out how to fix this.


https://reviews.llvm.org/D20124



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2017-11-16 Thread Cameron via Phabricator via cfe-commits
cameron314 marked an inline comment as done.
cameron314 added a comment.

- Well that's odd, because the test definitely fails for me without the patch. 
I'm only a few days behind the trunk.
- I'm looking at your test case now. I can reproduce it even with the patch; 
I'm investigating what's happening.
- I've fixed the warning, thanks! Using MSVC on my end which doesn't emit that 
particular warning.


https://reviews.llvm.org/D20124



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2017-11-16 Thread Nikolai Kosjar via Phabricator via cfe-commits
nik added a comment.

Here are my observations:

- Your test case works fine for me even without having this change 
applied/build. Looks like this is already fixed in current trunk. Please 
confirm/test.
- Can you come up with another test case that fixes something that is not yet 
addressed in trunk?
- It does not fix https://bugs.llvm.org/show_bug.cgi?id=34971

Apart from that the patch applies cleanly and all tests pass (check-clang). 
However, some new warnings are emitted during building:

  
/home/nik/dev/llvm/trunk/source/tools/clang/include/clang/Lex/PreprocessingRecord.h:
 In constructor 
‘clang::PreprocessingRecord::PreprocessingRecord(clang::SourceManager&)’:
  
/home/nik/dev/llvm/trunk/source/tools/clang/include/clang/Lex/PreprocessingRecord.h:339:40:
 warning: ‘clang::PreprocessingRecord::ExternalSource’ will be initialized 
after [-Wreorder]
 ExternalPreprocessingRecordSource *ExternalSource;

^~
  
/home/nik/dev/llvm/trunk/source/tools/clang/include/clang/Lex/PreprocessingRecord.h:312:10:
 warning:   ‘bool clang::PreprocessingRecord::SkippedRangesAllLoaded’ 
[-Wreorder]
 bool SkippedRangesAllLoaded;
  ^~
  
/home/nik/dev/llvm/trunk/source/tools/clang/lib/Lex/PreprocessingRecord.cpp:36:1:
 warning:   when initialized here [-Wreorder]




Comment at: lib/Lex/PreprocessingRecord.cpp:339
+
+
 void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,

Remove excess new line.


https://reviews.llvm.org/D20124



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2017-11-15 Thread Cameron via Phabricator via cfe-commits
cameron314 updated this revision to Diff 123044.
cameron314 added a comment.

Fully rebased, with a test.


https://reviews.llvm.org/D20124

Files:
  include/clang/Lex/PreprocessingRecord.h
  include/clang/Serialization/ASTBitCodes.h
  include/clang/Serialization/ASTReader.h
  include/clang/Serialization/Module.h
  lib/Lex/PPDirectives.cpp
  lib/Lex/PreprocessingRecord.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTWriter.cpp
  unittests/libclang/LibclangTest.cpp

Index: unittests/libclang/LibclangTest.cpp
===
--- unittests/libclang/LibclangTest.cpp
+++ unittests/libclang/LibclangTest.cpp
@@ -572,3 +572,52 @@
   EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU));
   DisplayDiagnostics();
 }
+
+TEST_F(LibclangReparseTest, PreprocessorSkippedRanges) {
+  std::string Header = "header.h", Main = "main.cpp";
+  WriteFile(Header,
+"#ifdef MANGOS\n"
+"printf(\"mmm\");\n"
+"#endif");
+  WriteFile(Main,
+"#include \"header.h\"\n"
+"#ifdef KIWIS\n"
+"printf(\"mmm!!\");\n"
+"#endif");
+
+  unsigned flags = TUFlags |
+CXTranslationUnit_PrecompiledPreamble;//|
+  //CXTranslationUnit_CreatePreambleOnFirstParse;
+  for (int i = 0; i != 5; ++i) {
+if (i == 0) {
+  // first parse
+  ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0,
+   nullptr, 0, flags);
+}
+else {
+  // reparse
+  ASSERT_TRUE(ReparseTU(0, nullptr /* No unsaved files. */));
+}
+
+CXSourceRangeList *Ranges = clang_getAllSkippedRanges(ClangTU);
+EXPECT_EQ(2U, Ranges->count);
+
+CXSourceLocation cxl;
+unsigned line;
+cxl = clang_getRangeStart(Ranges->ranges[0]);
+clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+EXPECT_EQ(1U, line);
+cxl = clang_getRangeEnd(Ranges->ranges[0]);
+clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+EXPECT_EQ(3U, line);
+
+cxl = clang_getRangeStart(Ranges->ranges[1]);
+clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+EXPECT_EQ(2U, line);
+cxl = clang_getRangeEnd(Ranges->ranges[1]);
+clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
+EXPECT_EQ(4U, line);
+
+clang_disposeSourceRangeList(Ranges);
+  }
+}
Index: lib/Serialization/ASTWriter.cpp
===
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -1104,6 +1104,7 @@
   RECORD(UNUSED_FILESCOPED_DECLS);
   RECORD(PPD_ENTITIES_OFFSETS);
   RECORD(VTABLE_USES);
+  RECORD(PPD_SKIPPED_RANGES);
   RECORD(REFERENCED_SELECTOR_POOL);
   RECORD(TU_UPDATE_LEXICAL);
   RECORD(SEMA_DECL_REFS);
@@ -2725,6 +2726,26 @@
 Stream.EmitRecordWithBlob(PPEOffsetAbbrev, Record,
   bytes(PreprocessedEntityOffsets));
   }
+
+  // Write the skipped region table for the preprocessing record.
+  ArrayRef SkippedRanges = PPRec.getSkippedRanges();
+  if (SkippedRanges.size() > 0) {
+std::vector SerializedSkippedRanges;
+SerializedSkippedRanges.reserve(SkippedRanges.size());
+for (auto const& Range : SkippedRanges)
+  SerializedSkippedRanges.emplace_back(Range);
+
+using namespace llvm;
+auto Abbrev = std::make_shared();
+Abbrev->Add(BitCodeAbbrevOp(PPD_SKIPPED_RANGES));
+Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+unsigned PPESkippedRangeAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
+
+Record.clear();
+Record.push_back(PPD_SKIPPED_RANGES);
+Stream.EmitRecordWithBlob(PPESkippedRangeAbbrev, Record,
+  bytes(SerializedSkippedRanges));
+  }
 }
 
 unsigned ASTWriter::getLocalOrImportedSubmoduleID(Module *Mod) {
Index: lib/Serialization/ASTReader.cpp
===
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -3214,6 +3214,24 @@
   break;
 }
 
+case PPD_SKIPPED_RANGES: {
+  F.PreprocessedSkippedRangeOffsets = (const PPSkippedRange*)Blob.data();
+  assert(Blob.size() % sizeof(PPSkippedRange) == 0);
+  F.NumPreprocessedSkippedRanges = Blob.size() / sizeof(PPSkippedRange);
+
+  if (!PP.getPreprocessingRecord())
+PP.createPreprocessingRecord();
+  if (!PP.getPreprocessingRecord()->getExternalSource())
+PP.getPreprocessingRecord()->SetExternalSource(*this);
+  F.BasePreprocessedSkippedRangeID = PP.getPreprocessingRecord()
+  ->allocateSkippedRanges(F.NumPreprocessedSkippedRanges);
+  
+  if (F.NumPreprocessedSkippedRanges > 0)
+GlobalSkippedRangeMap.insert(
+std::make_pair(F.BasePreprocessedSkippedRangeID, &F));
+  break;
+}
+
 case DECL_UPDATE_OFFSETS:
   if (Record.size() % 2 != 0) {
 Error("invalid DECL_UPDATE_OFFSETS block in AST file");
@@ -5379,6 +5397,20 @@
  Mod.FileSo

[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2017-11-07 Thread Cameron via Phabricator via cfe-commits
cameron314 added a comment.

I'll rebase the patch and add a test. Thanks for looking at this!


Repository:
  rL LLVM

https://reviews.llvm.org/D20124



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2017-11-03 Thread Erik Verbruggen via Phabricator via cfe-commits
erikjv added a comment.

The patch has aged a bit since upload, so does it still apply? And, can you add 
a testcase please?


Repository:
  rL LLVM

https://reviews.llvm.org/D20124



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20124: [PCH] Serialize skipped preprocessor ranges

2016-05-10 Thread Cameron via cfe-commits
cameron314 created this revision.
cameron314 added a reviewer: rsmith.
cameron314 added a subscriber: cfe-commits.
cameron314 set the repository for this revision to rL LLVM.

This fixes, for example, libclang's `clang_getAllSkippedRanges` returning zero 
ranges after reparsing a translation unit.

Repository:
  rL LLVM

http://reviews.llvm.org/D20124

Files:
  include/clang/Lex/PreprocessingRecord.h
  include/clang/Serialization/ASTBitCodes.h
  include/clang/Serialization/ASTReader.h
  include/clang/Serialization/Module.h
  lib/Lex/PreprocessingRecord.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTWriter.cpp
  lib/Serialization/Module.cpp

Index: lib/Serialization/Module.cpp
===
--- lib/Serialization/Module.cpp
+++ lib/Serialization/Module.cpp
@@ -31,6 +31,8 @@
 LocalNumMacros(0), MacroOffsets(nullptr),
 BasePreprocessedEntityID(0),
 PreprocessedEntityOffsets(nullptr), NumPreprocessedEntities(0),
+BasePreprocessedSkippedRangeID(0),
+PreprocessedSkippedRangeOffsets(nullptr), NumPreprocessedSkippedRanges(0),
 LocalNumHeaderFileInfos(0), 
 HeaderFileInfoTableData(nullptr), HeaderFileInfoTable(nullptr),
 LocalNumSubmodules(0), BaseSubmoduleID(0),
Index: lib/Serialization/ASTWriter.cpp
===
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -953,6 +953,7 @@
   RECORD(UNUSED_FILESCOPED_DECLS);
   RECORD(PPD_ENTITIES_OFFSETS);
   RECORD(VTABLE_USES);
+  RECORD(PPD_SKIPPED_RANGES);
   RECORD(REFERENCED_SELECTOR_POOL);
   RECORD(TU_UPDATE_LEXICAL);
   RECORD(SEMA_DECL_REFS);
@@ -2408,6 +2409,26 @@
 Stream.EmitRecordWithBlob(PPEOffsetAbbrev, Record,
   bytes(PreprocessedEntityOffsets));
   }
+
+  // Write the skipped region table for the preprocessing record.
+  const std::vector &SkippedRanges = PPRec.getSkippedRanges();
+  if (SkippedRanges.size() > 0) {
+std::vector SerializedSkippedRanges;
+SerializedSkippedRanges.reserve(SkippedRanges.size());
+for (auto const& Range : SkippedRanges)
+  SerializedSkippedRanges.emplace_back(Range);
+
+using namespace llvm;
+BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+Abbrev->Add(BitCodeAbbrevOp(PPD_SKIPPED_RANGES));
+Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+unsigned PPESkippedRangeAbbrev = Stream.EmitAbbrev(Abbrev);
+
+Record.clear();
+Record.push_back(PPD_SKIPPED_RANGES);
+Stream.EmitRecordWithBlob(PPESkippedRangeAbbrev, Record,
+  bytes(SerializedSkippedRanges));
+  }
 }
 
 unsigned ASTWriter::getLocalOrImportedSubmoduleID(Module *Mod) {
Index: lib/Serialization/ASTReader.cpp
===
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -3020,6 +3020,24 @@
 
   break;
 }
+
+case PPD_SKIPPED_RANGES: {
+  F.PreprocessedSkippedRangeOffsets = (const PPSkippedRange*)Blob.data();
+  assert(Blob.size() % sizeof(PPSkippedRange) == 0);
+  F.NumPreprocessedSkippedRanges = Blob.size() / sizeof(PPSkippedRange);
+
+  if (!PP.getPreprocessingRecord())
+PP.createPreprocessingRecord();
+  if (!PP.getPreprocessingRecord()->getExternalSource())
+PP.getPreprocessingRecord()->SetExternalSource(*this);
+  F.BasePreprocessedSkippedRangeID = PP.getPreprocessingRecord()
+->allocateSkippedRanges(F.NumPreprocessedSkippedRanges);
+  
+  if (F.NumPreprocessedSkippedRanges > 0)
+GlobalSkippedRangeMap.insert(
+std::make_pair(F.BasePreprocessedSkippedRangeID, &F));
+  break;
+}
 
 case DECL_UPDATE_OFFSETS: {
   if (Record.size() % 2 != 0) {
@@ -4874,6 +4892,20 @@
  Mod.FileSortedDecls + Mod.NumFileSortedDecls));
 }
 
+SourceRange ASTReader::ReadSkippedRange(unsigned GlobalIndex) {
+  auto I = GlobalSkippedRangeMap.find(GlobalIndex);
+  assert(I != GlobalSkippedRangeMap.end() &&
+"Corrupted global skipped range map");
+  ModuleFile *M = I->second;
+  unsigned LocalIndex = GlobalIndex - M->BasePreprocessedSkippedRangeID;
+  assert(LocalIndex < M->NumPreprocessedSkippedRanges);
+  PPSkippedRange RawRange = M->PreprocessedSkippedRangeOffsets[LocalIndex];
+  SourceRange Range(TranslateSourceLocation(*M, RawRange.getBegin()),
+TranslateSourceLocation(*M, RawRange.getEnd()));
+  assert(Range.isValid());
+  return Range;
+}
+
 PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
   PreprocessedEntityID PPID = Index+1;
   std::pair PPInfo = getModulePreprocessedEntity(Index);
Index: lib/Lex/PreprocessingRecord.cpp
===
--- lib/Lex/PreprocessingRecord.cpp
+++ lib/Lex/PreprocessingRecord.cpp
@@ -40,7 +40,8 @@
 
 PreprocessingRecord::PreprocessingRecord(SourceManager &SM)
   : SourceMgr(