diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Basic/DiagnosticLexKinds.def | 2 | ||||
-rw-r--r-- | clang/lib/Basic/SourceManager.cpp | 44 | ||||
-rw-r--r-- | clang/lib/Lex/PPDirectives.cpp | 19 | ||||
-rw-r--r-- | clang/test/Preprocessor/line-directive.c | 9 |
4 files changed, 62 insertions, 12 deletions
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.def b/clang/include/clang/Basic/DiagnosticLexKinds.def index 8c9a82688a7..ad08ba976cb 100644 --- a/clang/include/clang/Basic/DiagnosticLexKinds.def +++ b/clang/include/clang/Basic/DiagnosticLexKinds.def @@ -274,6 +274,8 @@ DIAG(err_pp_linemarker_invalid_filename, ERROR, "invalid filename for line marker directive") DIAG(err_pp_linemarker_invalid_flag, ERROR, "invalid flag line marker directive") +DIAG(err_pp_linemarker_invalid_pop, ERROR, + "invalid line marker flag '2': cannot pop empty include stack") DIAG(ext_pp_line_too_big, EXTENSION, "C requires #line number to be less than %0, allowed as extension") diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index a77f8535e3c..cc75b87c467 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -76,13 +76,20 @@ struct LineEntry { /// Flags - Set the 0 if no flags, 1 if a system header, SrcMgr::CharacteristicKind FileKind; + /// IncludeOffset - This is the offset of the virtual include stack location, + /// which is manipulated by GNU linemarker directives. If this is 0 then + /// there is no virtual #includer. + unsigned IncludeOffset; + static LineEntry get(unsigned Offs, unsigned Line, int Filename, - SrcMgr::CharacteristicKind FileKind) { + SrcMgr::CharacteristicKind FileKind, + unsigned IncludeOffset) { LineEntry E; E.FileOffset = Offs; E.LineNo = Line; E.FilenameID = Filename; E.FileKind = FileKind; + E.IncludeOffset = IncludeOffset; return E; } }; @@ -164,6 +171,7 @@ void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset, "Adding line entries out of order!"); SrcMgr::CharacteristicKind Kind = SrcMgr::C_User; + unsigned IncludeOffset = 0; if (!Entries.empty()) { // If this is a '#line 4' after '#line 42 "foo.h"', make sure to remember @@ -171,12 +179,14 @@ void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset, if (FilenameID == -1) FilenameID = Entries.back().FilenameID; - // If we are after a line marker that switched us to system header mode, - // preserve it. + // If we are after a line marker that switched us to system header mode, or + // that set #include information, preserve it. Kind = Entries.back().FileKind; + IncludeOffset = Entries.back().IncludeOffset; } - Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, Kind)); + Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, Kind, + IncludeOffset)); } /// AddLineNote This is the same as the previous version of AddLineNote, but is @@ -195,10 +205,24 @@ void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset, 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) { + IncludeOffset = Offset-1; + } else if (EntryExit == 2) { + assert(!Entries.empty() && Entries.back().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)) + IncludeOffset = PrevEntry->IncludeOffset; + } - // TODO: Handle EntryExit. - - Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, FileKind)); + Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, FileKind, + IncludeOffset)); } @@ -831,6 +855,12 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const { LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1); // Note that column numbers are not molested by line markers. + + // Handle virtual #include manipulation. + if (Entry->IncludeOffset) { + IncludeLoc = getLocForStartOfFile(LocInfo.first); + IncludeLoc = IncludeLoc.getFileLocWithOffset(Entry->IncludeOffset); + } } } diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 15487925f53..00cb62384e3 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -676,6 +676,23 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, } else if (FlagVal == 2) { IsFileExit = true; + SourceManager &SM = PP.getSourceManager(); + // If we are leaving the current presumed file, check to make sure the + // presumed include stack isn't empty! + FileID CurFileID = + SM.getDecomposedInstantiationLoc(FlagTok.getLocation()).first; + PresumedLoc PLoc = SM.getPresumedLoc(FlagTok.getLocation()); + + // If there is no include loc (main file) or if the include loc is in a + // different physical file, then we aren't in a "1" line marker flag region. + SourceLocation IncLoc = PLoc.getIncludeLoc(); + if (IncLoc.isInvalid() || + SM.getDecomposedInstantiationLoc(IncLoc).first != CurFileID) { + PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_pop); + PP.DiscardUntilEndOfDirective(); + return true; + } + PP.Lex(FlagTok); if (FlagTok.is(tok::eom)) return false; if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP)) @@ -761,7 +778,7 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) { IsSystemHeader, IsExternCHeader, *this)) return; } - + // Create a line note with this information. SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID, IsFileEntry, IsFileExit, diff --git a/clang/test/Preprocessor/line-directive.c b/clang/test/Preprocessor/line-directive.c index 062081c6bcd..a1590fa3333 100644 --- a/clang/test/Preprocessor/line-directive.c +++ b/clang/test/Preprocessor/line-directive.c @@ -6,7 +6,7 @@ #line 0 // expected-error {{#line directive requires a positive integer argument}} #line 2147483648 // expected-warning {{C requires #line number to be less than 2147483648, allowed as extension}} #line 42 // ok -#line 42 'a' // expected-error {{nvalid filename for #line directive}} +#line 42 'a' // expected-error {{invalid filename for #line directive}} #line 42 "foo/bar/baz.h" // ok @@ -16,9 +16,10 @@ # 42 # 42 "foo" -# 42 "foo" 1 3 -# 42 "foo" 2 3 -# 42 "foo" 2 3 4 +# 42 "foo" 2 // expected-error {{invalid line marker flag '2': cannot pop empty include stack}} +# 42 "foo" 1 3 // enter +# 42 "foo" 2 3 // exit +# 42 "foo" 2 3 4 // expected-error {{invalid line marker flag '2': cannot pop empty include stack}} # 42 "foo" 3 4 # 'a' // expected-error {{invalid preprocessing directive}} |