]> granicus.if.org Git - clang/commitdiff
Correctly handle line table entries without filenames during AST serialization
authorHans Wennborg <hans@hanshq.net>
Mon, 4 Dec 2017 22:28:45 +0000 (22:28 +0000)
committerHans Wennborg <hans@hanshq.net>
Mon, 4 Dec 2017 22:28:45 +0000 (22:28 +0000)
The current code would hit an assert in ASTWriter when trying to write
out the filename for a line table entry that didn't have any. Fix this
by allowing the -1 sentinel value to round-trip through serialization.

Differential revision: https://reviews.llvm.org/D40746

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@319707 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp
test/PCH/line-directive-nofilename.c [new file with mode: 0644]
test/PCH/line-directive-nofilename.h [new file with mode: 0644]

index fa853e9ebb6602cf58b18cd8189b69c12f444e15..111ac4fcdaa4208aa4e1589a955f1bb76c8b3691 100644 (file)
@@ -1220,6 +1220,7 @@ bool ASTReader::ParseLineTable(ModuleFile &F,
 
   // Parse the file names
   std::map<int, int> FileIDs;
+  FileIDs[-1] = -1; // For unspecified filenames.
   for (unsigned I = 0; Record[Idx]; ++I) {
     // Extract the file name
     auto Filename = ReadPath(F, Record, Idx);
index 92b464ef91a9322f18050c15879083a912b06fb3..e9e379aab68556b7eaa2a987d522f5addf2894ee 100644 (file)
@@ -2363,12 +2363,13 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
 
     // Emit the needed file names.
     llvm::DenseMap<int, int> FilenameMap;
+    FilenameMap[-1] = -1; // For unspecified filenames.
     for (const auto &L : LineTable) {
       if (L.first.ID < 0)
         continue;
       for (auto &LE : L.second) {
         if (FilenameMap.insert(std::make_pair(LE.FilenameID,
-                                              FilenameMap.size())).second)
+                                              FilenameMap.size() - 1)).second)
           AddPath(LineTable.getFilename(LE.FilenameID), Record);
       }
     }
diff --git a/test/PCH/line-directive-nofilename.c b/test/PCH/line-directive-nofilename.c
new file mode 100644 (file)
index 0000000..0d2bcb7
--- /dev/null
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -emit-pch -o %t %S/line-directive-nofilename.h
+// RUN: not %clang_cc1 -include-pch %t -fsyntax-only %s 2>&1 | FileCheck %s
+
+// This causes an "error: redefinition" diagnostic. The notes will have the
+// locations of the declarations from the PCH file.
+double foo, bar;
+
+// CHECK: line-directive-nofilename.h:42:5: note: previous definition is here
+// CHECK: foobar.h:100:5: note: previous definition is here
diff --git a/test/PCH/line-directive-nofilename.h b/test/PCH/line-directive-nofilename.h
new file mode 100644 (file)
index 0000000..2e2d189
--- /dev/null
@@ -0,0 +1,5 @@
+#line 42
+int foo; // This should appear as at line-directive-nofilename.h:42
+
+#line 100 "foobar.h"
+int bar; // This should appear as at foobar.h:100