Index: clang/lib/Basic/SourceManager.cpp =================================================================== --- clang/lib/Basic/SourceManager.cpp +++ clang/lib/Basic/SourceManager.cpp @@ -207,28 +207,28 @@ SrcMgr::CharacteristicKind FileKind) { std::vector &Entries = LineEntries[FID]; - // An unspecified FilenameID means use the last filename if available, or the - // main source file otherwise. - if (FilenameID == -1 && !Entries.empty()) - FilenameID = Entries.back().FilenameID; - assert((Entries.empty() || Entries.back().FileOffset < Offset) && "Adding line entries out of order!"); unsigned IncludeOffset = 0; - if (EntryExit == 0) { // No #include stack change. - IncludeOffset = Entries.empty() ? 0 : Entries.back().IncludeOffset; - } else if (EntryExit == 1) { + if (EntryExit == 1) { + // Push #include IncludeOffset = Offset-1; - } else if (EntryExit == 2) { - assert(!Entries.empty() && Entries.back().IncludeOffset && + } else { + const auto *PrevEntry = Entries.empty() ? nullptr : &Entries.back(); + if (EntryExit == 2) { + // Pop #include + assert(PrevEntry && PrevEntry->IncludeOffset && "PPDirectives should have caught case when popping empty include stack"); - - // Get the include loc of the last entries' include loc as our include loc. - IncludeOffset = 0; - if (const LineEntry *PrevEntry = - FindNearestLineEntry(FID, Entries.back().IncludeOffset)) + PrevEntry = FindNearestLineEntry(FID, PrevEntry->IncludeOffset); + } + if (PrevEntry) { IncludeOffset = PrevEntry->IncludeOffset; + if (FilenameID == -1) + // An unspecified FilenameID means use the previous (or containing) + // filename if available, or the main source file otherwise. + FilenameID = PrevEntry->FilenameID; + } } Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, FileKind, Index: clang/lib/Lex/PPDirectives.cpp =================================================================== --- clang/lib/Lex/PPDirectives.cpp +++ clang/lib/Lex/PPDirectives.cpp @@ -1451,11 +1451,14 @@ DiscardUntilEndOfDirective(); return; } - FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString()); // If a filename was present, read any flags that are present. if (ReadLineMarkerFlags(IsFileEntry, IsFileExit, FileKind, *this)) return; + + // Exiting to an empty string means pop to including file + if (!IsFileExit || Literal.GetString().size()) + FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString()); } // Create a line note with this information. Index: clang/test/Preprocessor/line-directive.c =================================================================== --- clang/test/Preprocessor/line-directive.c +++ clang/test/Preprocessor/line-directive.c @@ -1,6 +1,15 @@ // RUN: %clang_cc1 -std=c99 -fsyntax-only -verify -pedantic %s // RUN: not %clang_cc1 -E %s 2>&1 | grep 'blonk.c:92:2: error: ABC' // RUN: not %clang_cc1 -E %s 2>&1 | grep 'blonk.c:93:2: error: DEF' +// RUN: not %clang_cc1 -E %s 2>&1 | grep 'line-directive.c:11:2: error: MAIN7' +// RUN: not %clang_cc1 -E %s 2>&1 | grep 'enter-1:118:2: error: ENTER1' +// RUN: not %clang_cc1 -E %s 2>&1 | grep 'main:121:2: error: MAIN2' + +// a push/pop before any other line control +# 10 "enter-0" 1 +# 11 "" 2 // pop to main file +#error MAIN7 +// expected-error@-1{{MAIN7}} #line 'a' // expected-error {{#line directive requires a positive integer argument}} #line 0 // expected-warning {{#line directive with zero argument is a GNU extension}} @@ -103,4 +112,12 @@ #line 0 "line-directive.c" // expected-warning {{#line directive with zero argument is a GNU extension}} undefined t; // expected-error {{unknown type name 'undefined'}} - +# 115 "main" +# 116 "enter-1" 1 +# 117 "enter-2" 1 +# 118 "" 2 // pop to enter-1 +#error ENTER1 +// expected-error@-1{{ENTER1}} +# 121 "" 2 // pop to "main" +#error MAIN2 +// expected-error@-1{{MAIN}}