summaryrefslogtreecommitdiffstats
path: root/clang/lib/Lex/MacroInfo.cpp
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-07-07 03:40:34 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-07-07 03:40:34 +0000
commit41fb2d95a3921948571ee58ce8d0fa905bb32394 (patch)
tree7da61b23638478b9a928f8516f241566302d892b /clang/lib/Lex/MacroInfo.cpp
parentc8f7e213b9f04664cc85f0deb66a4c9fe94ba03c (diff)
downloadbcm5719-llvm-41fb2d95a3921948571ee58ce8d0fa905bb32394.tar.gz
bcm5719-llvm-41fb2d95a3921948571ee58ce8d0fa905bb32394.zip
Make the Preprocessor more memory efficient and improve macro instantiation diagnostics.
When a macro instantiation occurs, reserve a SLocEntry chunk with length the full length of the macro definition source. Set the spelling location of this chunk to point to the start of the macro definition and any tokens that are lexed directly from the macro definition will get a location from this chunk with the appropriate offset. For any tokens that come from argument expansion, '##' paste operator, etc. have their instantiation location point at the appropriate place in the instantiated macro definition (the argument identifier and the '##' token respectively). This improves macro instantiation diagnostics: Before: t.c:5:9: error: invalid operands to binary expression ('struct S' and 'int') int y = M(/); ^~~~ t.c:5:11: note: instantiated from: int y = M(/); ^ After: t.c:5:9: error: invalid operands to binary expression ('struct S' and 'int') int y = M(/); ^~~~ t.c:3:20: note: instantiated from: \#define M(op) (foo op 3); ~~~ ^ ~ t.c:5:11: note: instantiated from: int y = M(/); ^ The memory savings for a candidate boost library that abuses the preprocessor are: - 32% less SLocEntries (37M -> 25M) - 30% reduction in PCH file size (900M -> 635M) - 50% reduction in memory usage for the SLocEntry table (1.6G -> 800M) llvm-svn: 134587
Diffstat (limited to 'clang/lib/Lex/MacroInfo.cpp')
-rw-r--r--clang/lib/Lex/MacroInfo.cpp32
1 files changed, 32 insertions, 0 deletions
diff --git a/clang/lib/Lex/MacroInfo.cpp b/clang/lib/Lex/MacroInfo.cpp
index 66d87a19386..0a16a256721 100644
--- a/clang/lib/Lex/MacroInfo.cpp
+++ b/clang/lib/Lex/MacroInfo.cpp
@@ -25,6 +25,7 @@ MacroInfo::MacroInfo(SourceLocation DefLoc) : Location(DefLoc) {
IsUsed = false;
IsAllowRedefinitionsWithoutWarning = false;
IsWarnIfUnused = false;
+ IsDefinitionLengthCached = false;
ArgumentList = 0;
NumArguments = 0;
@@ -43,11 +44,42 @@ MacroInfo::MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator) {
IsUsed = MI.IsUsed;
IsAllowRedefinitionsWithoutWarning = MI.IsAllowRedefinitionsWithoutWarning;
IsWarnIfUnused = MI.IsWarnIfUnused;
+ IsDefinitionLengthCached = MI.IsDefinitionLengthCached;
+ DefinitionLength = MI.DefinitionLength;
ArgumentList = 0;
NumArguments = 0;
setArgumentList(MI.ArgumentList, MI.NumArguments, PPAllocator);
}
+unsigned MacroInfo::getDefinitionLengthSlow(SourceManager &SM) const {
+ assert(!IsDefinitionLengthCached);
+ IsDefinitionLengthCached = true;
+
+ if (ReplacementTokens.empty())
+ return (DefinitionLength = 0);
+
+ const Token &firstToken = ReplacementTokens.front();
+ const Token &lastToken = ReplacementTokens.back();
+ SourceLocation macroStart = firstToken.getLocation();
+ SourceLocation macroEnd = lastToken.getLocation();
+ assert(macroStart.isValid() && macroEnd.isValid());
+ assert((macroStart.isFileID() || firstToken.is(tok::comment)) &&
+ "Macro defined in macro?");
+ assert((macroEnd.isFileID() || lastToken.is(tok::comment)) &&
+ "Macro defined in macro?");
+ std::pair<FileID, unsigned>
+ startInfo = SM.getDecomposedInstantiationLoc(macroStart);
+ std::pair<FileID, unsigned>
+ endInfo = SM.getDecomposedInstantiationLoc(macroEnd);
+ assert(startInfo.first == endInfo.first &&
+ "Macro definition spanning multiple FileIDs ?");
+ assert(startInfo.second <= endInfo.second);
+ DefinitionLength = endInfo.second - startInfo.second;
+ DefinitionLength += lastToken.getLength();
+
+ return DefinitionLength;
+}
+
/// isIdenticalTo - Return true if the specified macro definition is equal to
/// this macro in spelling, arguments, and whitespace. This is used to emit
/// duplicate definition warnings. This implements the rules in C99 6.10.3.
OpenPOWER on IntegriCloud