]> granicus.if.org Git - clang/commitdiff
Implement handling of file entry/exit notifications from GNU
authorChris Lattner <sabre@nondot.org>
Wed, 4 Feb 2009 06:25:26 +0000 (06:25 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 4 Feb 2009 06:25:26 +0000 (06:25 +0000)
line markers, including maintenance of the virtual include stack.

For something like this:

# 42 "bar.c" 1
# 142 "bar2.c" 1

#warning zappa
# 92 "bar.c" 2
#warning gonzo
# 102 "foo.c" 2
#warning bonkta

we now produce these three warnings:

#1:
In file included from foo.c:3:
In file included from bar.c:42:
bar2.c:143:2: warning: #warning zappa
#warning zappa
 ^

#2:
In file included from foo.c:3:
bar.c:92:2: warning: #warning gonzo
#warning gonzo
 ^

#3:
foo.c:102:2: warning: #warning bonkta
#warning bonkta
 ^

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

include/clang/Basic/DiagnosticLexKinds.def
lib/Basic/SourceManager.cpp
lib/Lex/PPDirectives.cpp
test/Preprocessor/line-directive.c

index 8c9a82688a7c74beb3473213241f8f3f14ce615d..ad08ba976cb45264e8fc29cb79a849674174e6fa 100644 (file)
@@ -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")
 
index a77f8535e3c142aeb88d4f993a10006d316d8ecf..cc75b87c467fd8b0429773a149a01c4649817334 100644 (file)
@@ -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);
+      }
     }
   }
 
index 15487925f533c78af82cc0b0e56ce5f40200febf..00cb62384e3502f559e96c024c84deab740f0c5f 100644 (file)
@@ -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, 
index 062081c6bcd6f7bd79ba742c3e7da2fc9507e2bb..a1590fa33334d053e41df8d49b4cc6a6540e3961 100644 (file)
@@ -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
 
 
 
 # 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}}