From: Chris Lattner Date: Wed, 4 Feb 2009 05:33:01 +0000 (+0000) Subject: make getFileCharacteristic linetable aware. line markers that X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6b3066780bda02e3117d71a18ca2f430ed1454af;p=clang make getFileCharacteristic linetable aware. line markers that play around with the 'is system header' bit now function correctly. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63720 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index e24e623899..565cb0e17e 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -495,11 +495,15 @@ public: unsigned getInstantiationLineNumber(SourceLocation Loc) const; unsigned getSpellingLineNumber(SourceLocation Loc) const; - // FIXME: This should handle #line. - SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const { - FileID FID = getFileID(getSpellingLoc(Loc)); - return getSLocEntry(FID).getFile().getFileCharacteristic(); - } + /// getFileCharacteristic - return the file characteristic of the specified + /// source location, indicating whether this is a normal file, a system + /// header, or an "implicit extern C" system header. + /// + /// This state can be modified with flags on GNU linemarker directives like: + /// # 4 "foo.h" 3 + /// which changes all source locations in the current file after that to be + /// considered to be from a system header. + SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const; /// getPresumedLoc - This method returns the "presumed" location of a /// SourceLocation specifies. A "presumed location" can be modified by #line diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index 275d520e04..a77f8535e3 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -82,6 +82,7 @@ struct LineEntry { E.FileOffset = Offs; E.LineNo = Line; E.FilenameID = Filename; + E.FileKind = FileKind; return E; } }; @@ -754,6 +755,37 @@ unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc) const { return getLineNumber(LocInfo.first, LocInfo.second); } +/// getFileCharacteristic - return the file characteristic of the specified +/// source location, indicating whether this is a normal file, a system +/// header, or an "implicit extern C" system header. +/// +/// This state can be modified with flags on GNU linemarker directives like: +/// # 4 "foo.h" 3 +/// which changes all source locations in the current file after that to be +/// considered to be from a system header. +SrcMgr::CharacteristicKind +SourceManager::getFileCharacteristic(SourceLocation Loc) const { + assert(!Loc.isInvalid() && "Can't get file characteristic of invalid loc!"); + std::pair LocInfo = getDecomposedInstantiationLoc(Loc); + const SrcMgr::FileInfo &FI = getSLocEntry(LocInfo.first).getFile(); + + // If there are no #line directives in this file, just return the whole-file + // state. + if (!FI.hasLineDirectives()) + return FI.getFileCharacteristic(); + + assert(LineTable && "Can't have linetable entries without a LineTable!"); + // See if there is a #line directive before the location. + const LineEntry *Entry = + LineTable->FindNearestLineEntry(LocInfo.first.ID, LocInfo.second); + + // If this is before the first line marker, use the file characteristic. + if (!Entry) + return FI.getFileCharacteristic(); + + return Entry->FileKind; +} + /// getPresumedLoc - This method returns the "presumed" location of a /// SourceLocation specifies. A "presumed location" can be modified by #line diff --git a/test/Preprocessor/line-directive.c b/test/Preprocessor/line-directive.c index 6946ad4854..0a4b582239 100644 --- a/test/Preprocessor/line-directive.c +++ b/test/Preprocessor/line-directive.c @@ -34,3 +34,23 @@ #error ABC // expected-error {{#error ABC}} #error DEF // expected-error {{#error DEF}} + +// Verify that linemarker diddling of the system header flag works. + +# 192 "glomp.h" // not a system header. +typedef int x; // expected-note {{previous definition is here}} +typedef int x; // expected-error {{redefinition of 'x'}} + +# 192 "glomp.h" 3 // System header. +typedef int y; // ok +typedef int y; // ok + +#line 42 "blonk.h" // doesn't change system headerness. + +typedef int z; // ok +typedef int z; // ok + +# 42 "blonk.h" // DOES change system headerness. + +typedef int w; // expected-note {{previous definition is here}} +typedef int w; // expected-error {{redefinition of 'w'}}