summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/DiagnosticLexKinds.def2
-rw-r--r--clang/lib/Basic/SourceManager.cpp44
-rw-r--r--clang/lib/Lex/PPDirectives.cpp19
-rw-r--r--clang/test/Preprocessor/line-directive.c9
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}}
OpenPOWER on IntegriCloud