diff options
author | Alexander Kornienko <alexfh@google.com> | 2012-08-29 00:20:03 +0000 |
---|---|---|
committer | Alexander Kornienko <alexfh@google.com> | 2012-08-29 00:20:03 +0000 |
commit | 8a64bb58c3b24d7d97895e435bbc0965c99bd3be (patch) | |
tree | b0d399833553c6fe52395e6b517a5e55579de82a /include/clang/Lex | |
parent | ec2a396c6f11b4017e30f1865f7b62c5a42425b8 (diff) |
Keep history of macro definitions and #undefs
Summary:
Summary: Keep history of macro definitions and #undefs with corresponding source locations, so that we can later find out all macros active in a specified source location. We don't save the history in PCH (no need currently). Memory overhead is about sizeof(void*)*3*<number of macro definitions and #undefs>+<in-memory size of all #undef'd macros>
I've run a test on a file composed of 109 .h files from boost 1.49 on x86-64 linux.
Stats before this patch:
*** Preprocessor Stats:
73222 directives found:
19171 #define.
4345 #undef.
#include/#include_next/#import:
5233 source files entered.
27 max include stack depth
19210 #if/#ifndef/#ifdef.
2384 #else/#elif.
6891 #endif.
408 #pragma.
14466 #if/#ifndef#ifdef regions skipped
80023/451669/1270 obj/fn/builtin macros expanded, 85724 on the fast path.
127145 token paste (##) operations performed, 11008 on the fast path.
Preprocessor Memory: 5874615B total
BumpPtr: 4399104
Macro Expanded Tokens: 417768
Predefines Buffer: 8135
Macros: 1048576
#pragma push_macro Info: 0
Poison Reasons: 1024
Comment Handlers: 8
Stats with this patch:
...
Preprocessor Memory: 7541687B total
BumpPtr: 6066176
Macro Expanded Tokens: 417768
Predefines Buffer: 8135
Macros: 1048576
#pragma push_macro Info: 0
Poison Reasons: 1024
Comment Handlers: 8
In my test increase in memory usage is about 1.7Mb, which is ~28% of initial preprocessor's memory usage and about 0.8% of clang's total VMM allocation.
As for CPU overhead, it should only be noticeable when iterating over all macros, and should mostly consist of couple extra dereferences and one comparison per macro + skipping of #undef'd macros. It's less trivial to measure, though, as the preprocessor consumes a very small fraction of compilation time.
Reviewers: doug.gregor, klimek, rsmith, djasper
Reviewed By: doug.gregor
CC: cfe-commits, chandlerc
Differential Revision: http://llvm-reviews.chandlerc.com/D28
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162810 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang/Lex')
-rw-r--r-- | include/clang/Lex/MacroInfo.h | 29 | ||||
-rw-r--r-- | include/clang/Lex/Preprocessor.h | 11 |
2 files changed, 35 insertions, 5 deletions
diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index cbd201f849..ba3c30d16a 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -32,6 +32,12 @@ class MacroInfo { SourceLocation Location; /// EndLocation - The location of the last token in the macro. SourceLocation EndLocation; + /// \brief The location where the macro was #undef'd, or an invalid location + /// for macros that haven't been undefined. + SourceLocation UndefLocation; + /// \brief Previous definition, the identifier of this macro was defined to, + /// or NULL. + MacroInfo *PreviousDefinition; /// Arguments - The list of arguments for a function-like macro. This can be /// empty, for, e.g. "#define X()". In a C99-style variadic macro, this @@ -128,10 +134,31 @@ public: /// setDefinitionEndLoc - Set the location of the last token in the macro. /// void setDefinitionEndLoc(SourceLocation EndLoc) { EndLocation = EndLoc; } + /// getDefinitionEndLoc - Return the location of the last token in the macro. /// SourceLocation getDefinitionEndLoc() const { return EndLocation; } - + + /// \brief Set the location where macro was undefined. Can only be set once. + void setUndefLoc(SourceLocation UndefLoc) { + assert(UndefLocation.isInvalid() && "UndefLocation is already set!"); + assert(UndefLoc.isValid() && "Invalid UndefLoc!"); + UndefLocation = UndefLoc; + } + + /// \brief Get the location where macro was undefined. + SourceLocation getUndefLoc() const { return UndefLocation; } + + /// \brief Set previous definition of the macro with the same name. Can only + /// be set once. + void setPreviousDefinition(MacroInfo *PreviousDef) { + assert(!PreviousDefinition && "PreviousDefiniton is already set!"); + PreviousDefinition = PreviousDef; + } + + /// \brief Get previous definition of the macro with the same name. + MacroInfo *getPreviousDefinition() { return PreviousDefinition; } + /// \brief Get length in characters of the macro definition. unsigned getDefinitionLength(SourceManager &SM) const { if (IsDefinitionLengthCached) diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 2d2a31f611..fca5796068 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -274,8 +274,9 @@ class Preprocessor : public RefCountedBase<Preprocessor> { }; SmallVector<MacroExpandsInfo, 2> DelayedMacroExpandsCallbacks; - /// Macros - For each IdentifierInfo with 'HasMacro' set, we keep a mapping - /// to the actual definition of the macro. + /// Macros - For each IdentifierInfo that was associated with a macro, we + /// keep a mapping to the history of all macro definitions and #undefs in + /// the reverse order (the latest one is in the head of the list). llvm::DenseMap<IdentifierInfo*, MacroInfo*> Macros; /// \brief Macros that we want to warn because they are not used at the end @@ -470,8 +471,10 @@ public: void setMacroInfo(IdentifierInfo *II, MacroInfo *MI, bool LoadedFromAST = false); - /// macro_iterator/macro_begin/macro_end - This allows you to walk the current - /// state of the macro table. This visits every currently-defined macro. + /// macro_iterator/macro_begin/macro_end - This allows you to walk the macro + /// history table. Currently defined macros have + /// IdentifierInfo::hasMacroDefinition() set and an empty + /// MacroInfo::getUndefLoc() at the head of the list. typedef llvm::DenseMap<IdentifierInfo*, MacroInfo*>::const_iterator macro_iterator; macro_iterator macro_begin(bool IncludeExternalMacros = true) const; |