summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/SourceManager.h35
-rw-r--r--clang/lib/Basic/SourceManager.cpp76
-rw-r--r--clang/lib/Lex/PPDirectives.cpp38
3 files changed, 127 insertions, 22 deletions
diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h
index a58662443d1..d8c17e11da5 100644
--- a/clang/include/clang/Basic/SourceManager.h
+++ b/clang/include/clang/Basic/SourceManager.h
@@ -31,6 +31,7 @@ class SourceManager;
class FileManager;
class FileEntry;
class IdentifierTokenInfo;
+class LineTableInfo;
/// SrcMgr - Public enums and private classes that are part of the
/// SourceManager implementation.
@@ -224,7 +225,6 @@ namespace SrcMgr {
return E;
}
};
-
} // end SrcMgr namespace.
} // end clang namespace
@@ -275,6 +275,10 @@ class SourceManager {
/// is very common to look up many tokens from the same file.
mutable FileID LastFileIDLookup;
+ /// LineTable - This holds information for #line directives. It is referenced
+ /// by indices from SLocEntryTable.
+ LineTableInfo *LineTable;
+
/// LastLineNo - These ivars serve as a cache used in the getLineNumber
/// method which is used to speedup getLineNumber calls to nearby locations.
mutable FileID LastLineNoFileIDQuery;
@@ -292,23 +296,13 @@ class SourceManager {
explicit SourceManager(const SourceManager&);
void operator=(const SourceManager&);
public:
- SourceManager() : NumLinearScans(0), NumBinaryProbes(0) {
+ SourceManager() : LineTable(0), NumLinearScans(0), NumBinaryProbes(0) {
clearIDTables();
}
- ~SourceManager() {}
-
- void clearIDTables() {
- MainFileID = FileID();
- SLocEntryTable.clear();
- LastLineNoFileIDQuery = FileID();
- LastLineNoContentCache = 0;
- LastFileIDLookup = FileID();
-
- // Use up FileID #0 as an invalid instantiation.
- NextOffset = 0;
- createInstantiationLoc(SourceLocation(), SourceLocation(), 1);
- }
-
+ ~SourceManager();
+
+ void clearIDTables();
+
//===--------------------------------------------------------------------===//
// MainFileID creation and querying methods.
//===--------------------------------------------------------------------===//
@@ -553,6 +547,15 @@ public:
}
//===--------------------------------------------------------------------===//
+ // Line Table Manipulation Routines
+ //===--------------------------------------------------------------------===//
+
+ /// getLineTableFilenameID - Return the uniqued ID for the specified filename.
+ ///
+ unsigned getLineTableFilenameID(const char *Ptr, unsigned Len);
+
+
+ //===--------------------------------------------------------------------===//
// Other miscellaneous methods.
//===--------------------------------------------------------------------===//
diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp
index fcca97774df..42e6040b746 100644
--- a/clang/lib/Basic/SourceManager.cpp
+++ b/clang/lib/Basic/SourceManager.cpp
@@ -59,9 +59,85 @@ const llvm::MemoryBuffer *ContentCache::getBuffer() const {
}
//===--------------------------------------------------------------------===//
+// Line Table Implementation
+//===--------------------------------------------------------------------===//
+
+namespace clang {
+/// LineTableInfo - This class is used to hold and unique data used to
+/// represent #line information.
+class LineTableInfo {
+ /// FilenameIDs - This map is used to assign unique IDs to filenames in
+ /// #line directives. This allows us to unique the filenames that
+ /// frequently reoccur and reference them with indices. FilenameIDs holds
+ /// the mapping from string -> ID, and FilenamesByID holds the mapping of ID
+ /// to string.
+ llvm::StringMap<unsigned, llvm::BumpPtrAllocator> FilenameIDs;
+ std::vector<llvm::StringMapEntry<unsigned>*> FilenamesByID;
+public:
+ LineTableInfo() {
+ }
+
+ void clear() {
+ FilenameIDs.clear();
+ FilenamesByID.clear();
+ }
+
+ ~LineTableInfo() {}
+
+ unsigned getLineTableFilenameID(const char *Ptr, unsigned Len);
+
+};
+} // namespace clang
+
+
+
+
+unsigned LineTableInfo::getLineTableFilenameID(const char *Ptr, unsigned Len) {
+ // Look up the filename in the string table, returning the pre-existing value
+ // if it exists.
+ llvm::StringMapEntry<unsigned> &Entry =
+ FilenameIDs.GetOrCreateValue(Ptr, Ptr+Len, ~0U);
+ if (Entry.getValue() != ~0U)
+ return Entry.getValue();
+
+ // Otherwise, assign this the next available ID.
+ Entry.setValue(FilenamesByID.size());
+ FilenamesByID.push_back(&Entry);
+ return FilenamesByID.size()-1;
+}
+
+/// getLineTableFilenameID - Return the uniqued ID for the specified filename.
+///
+unsigned SourceManager::getLineTableFilenameID(const char *Ptr, unsigned Len) {
+ if (LineTable == 0)
+ LineTable = new LineTableInfo();
+ return LineTable->getLineTableFilenameID(Ptr, Len);
+}
+
+
+//===--------------------------------------------------------------------===//
// Private 'Create' methods.
//===--------------------------------------------------------------------===//
+SourceManager::~SourceManager() {
+ delete LineTable;
+}
+
+void SourceManager::clearIDTables() {
+ MainFileID = FileID();
+ SLocEntryTable.clear();
+ LastLineNoFileIDQuery = FileID();
+ LastLineNoContentCache = 0;
+ LastFileIDLookup = FileID();
+
+ if (LineTable)
+ LineTable->clear();
+
+ // Use up FileID #0 as an invalid instantiation.
+ NextOffset = 0;
+ createInstantiationLoc(SourceLocation(), SourceLocation(), 1);
+}
+
/// getOrCreateContentCache - Create or return a cached ContentCache for the
/// specified file.
const ContentCache *
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index 5b45ddd35e9..099dfb4aef0 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -621,6 +621,7 @@ void Preprocessor::HandleLineDirective(Token &Tok) {
if (LineNo >= LineLimit)
Diag(DigitTok, diag::ext_pp_line_too_big) << LineLimit;
+ int FilenameID = -1;
Token StrTok;
Lex(StrTok);
@@ -633,6 +634,18 @@ void Preprocessor::HandleLineDirective(Token &Tok) {
DiscardUntilEndOfDirective();
return;
} else {
+ // Parse and validate the string, converting it into a unique ID.
+ StringLiteralParser Literal(&StrTok, 1, *this);
+ assert(!Literal.AnyWide && "Didn't allow wide strings in");
+ if (Literal.hadError)
+ return DiscardUntilEndOfDirective();
+ if (Literal.Pascal) {
+ Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
+ return DiscardUntilEndOfDirective();
+ }
+ FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString(),
+ Literal.GetStringLength());
+
// Verify that there is nothing after the string, other than EOM.
CheckEndOfDirective("#line");
}
@@ -671,6 +684,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit,
// We must have 3 if there are still flags.
if (FlagVal != 3) {
PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
+ PP.DiscardUntilEndOfDirective();
return true;
}
@@ -684,6 +698,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit,
// We must have 4 if there is yet another flag.
if (FlagVal != 4) {
PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
+ PP.DiscardUntilEndOfDirective();
return true;
}
@@ -694,6 +709,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit,
// There are no more valid flags here.
PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
+ PP.DiscardUntilEndOfDirective();
return true;
}
@@ -717,22 +733,32 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) {
bool IsFileEntry = false, IsFileExit = false;
bool IsSystemHeader = false, IsExternCHeader = false;
-
+ int FilenameID = -1;
+
// If the StrTok is "eom", then it wasn't present. Otherwise, it must be a
// string followed by eom.
if (StrTok.is(tok::eom))
; // ok
else if (StrTok.isNot(tok::string_literal)) {
Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
- DiscardUntilEndOfDirective();
- return;
+ return DiscardUntilEndOfDirective();
} else {
+ // Parse and validate the string, converting it into a unique ID.
+ StringLiteralParser Literal(&StrTok, 1, *this);
+ assert(!Literal.AnyWide && "Didn't allow wide strings in");
+ if (Literal.hadError)
+ return DiscardUntilEndOfDirective();
+ if (Literal.Pascal) {
+ Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
+ return DiscardUntilEndOfDirective();
+ }
+ FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString(),
+ Literal.GetStringLength());
+
// If a filename was present, read any flags that are present.
if (ReadLineMarkerFlags(IsFileEntry, IsFileExit,
- IsSystemHeader, IsExternCHeader, *this)) {
- DiscardUntilEndOfDirective();
+ IsSystemHeader, IsExternCHeader, *this))
return;
- }
}
// FIXME: do something with the #line info.
OpenPOWER on IntegriCloud