summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/IdentifierTable.h2
-rw-r--r--clang/include/clang/Lex/ExternalPreprocessorSource.h3
-rw-r--r--clang/include/clang/Lex/Preprocessor.h7
-rw-r--r--clang/include/clang/Serialization/ASTReader.h18
-rw-r--r--clang/lib/Lex/PPMacroExpansion.cpp15
-rw-r--r--clang/lib/Serialization/ASTReader.cpp51
6 files changed, 93 insertions, 3 deletions
diff --git a/clang/include/clang/Basic/IdentifierTable.h b/clang/include/clang/Basic/IdentifierTable.h
index 66c5deea547..0013bd937c4 100644
--- a/clang/include/clang/Basic/IdentifierTable.h
+++ b/clang/include/clang/Basic/IdentifierTable.h
@@ -71,7 +71,7 @@ class IdentifierInfo {
void operator=(const IdentifierInfo&); // NONASSIGNABLE.
friend class IdentifierTable;
-
+
public:
IdentifierInfo();
diff --git a/clang/include/clang/Lex/ExternalPreprocessorSource.h b/clang/include/clang/Lex/ExternalPreprocessorSource.h
index 791d3fe304e..dbf73890337 100644
--- a/clang/include/clang/Lex/ExternalPreprocessorSource.h
+++ b/clang/include/clang/Lex/ExternalPreprocessorSource.h
@@ -27,6 +27,9 @@ public:
/// \brief Read the set of macros defined by this external macro source.
virtual void ReadDefinedMacros() = 0;
+
+ /// \brief Read the definition for the given macro.
+ virtual void LoadMacroDefinition(IdentifierInfo *II) = 0;
};
}
diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h
index 87b62d0a9a7..7b138884e0b 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -262,6 +262,8 @@ private: // Cached tokens state.
/// allocation.
MacroInfoChain *MICache;
+ MacroInfo *getInfoForMacro(IdentifierInfo *II) const;
+
public:
Preprocessor(Diagnostic &diags, const LangOptions &opts,
const TargetInfo &target,
@@ -335,7 +337,10 @@ public:
/// getMacroInfo - Given an identifier, return the MacroInfo it is #defined to
/// or null if it isn't #define'd.
MacroInfo *getMacroInfo(IdentifierInfo *II) const {
- return II->hasMacroDefinition() ? Macros.find(II)->second : 0;
+ if (!II->hasMacroDefinition())
+ return 0;
+
+ return getInfoForMacro(II);
}
/// setMacroInfo - Specify a macro for this identifier.
diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h
index e855cc79488..9ac7c318529 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -488,6 +488,11 @@ private:
/// \brief The macro definitions we have already loaded.
llvm::SmallVector<MacroDefinition *, 16> MacroDefinitionsLoaded;
+ /// \brief Mapping from identifiers that represent macros whose definitions
+ /// have not yet been deserialized to the global offset where the macro
+ /// record resides.
+ llvm::DenseMap<IdentifierInfo *, uint64_t> UnreadMacroRecordOffsets;
+
/// \name CodeGen-relevant special data
/// \brief Fields containing data that is relevant to CodeGen.
//@{
@@ -1145,9 +1150,22 @@ public:
/// \brief Reads the macro record located at the given offset.
void ReadMacroRecord(PerFileData &F, uint64_t Offset);
+ /// \brief Note that the identifier is a macro whose record will be loaded
+ /// from the given AST file at the given (file-local) offset.
+ void SetIdentifierIsMacro(IdentifierInfo *II, PerFileData &F,
+ uint64_t Offset);
+
/// \brief Read the set of macros defined by this external macro source.
virtual void ReadDefinedMacros();
+ /// \brief Read the macro definition for this identifier.
+ virtual void LoadMacroDefinition(IdentifierInfo *II);
+
+ /// \brief Read the macro definition corresponding to this iterator
+ /// into the unread macro record offsets table.
+ void LoadMacroDefinition(
+ llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos);
+
/// \brief Retrieve the macro definition with the given ID.
MacroDefinition *getMacroDefinition(serialization::MacroID ID);
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp
index 68fc56f7b78..a9f4cacf6ce 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -20,12 +20,27 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/CodeCompletionHandler.h"
+#include "clang/Lex/ExternalPreprocessorSource.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
#include <ctime>
using namespace clang;
+MacroInfo *Preprocessor::getInfoForMacro(IdentifierInfo *II) const {
+ assert(II->hasMacroDefinition() && "Identifier is not a macro!");
+
+ llvm::DenseMap<IdentifierInfo*, MacroInfo*>::const_iterator Pos
+ = Macros.find(II);
+ if (Pos == Macros.end()) {
+ // Load this macro from the external source.
+ getExternalSource()->LoadMacroDefinition(II);
+ Pos = Macros.find(II);
+ }
+ assert(Pos != Macros.end() && "Identifier macro info is missing!");
+ return Pos->second;
+}
+
/// setMacroInfo - Specify a macro for this identifier.
///
void Preprocessor::setMacroInfo(IdentifierInfo *II, MacroInfo *MI) {
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index aa76765dc9d..22d3cbc68f7 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -682,7 +682,7 @@ public:
// definition.
if (hasMacroDefinition) {
uint32_t Offset = ReadUnalignedLE32(d);
- Reader.ReadMacroRecord(F, Offset);
+ Reader.SetIdentifierIsMacro(II, F, Offset);
DataLen -= 4;
}
@@ -1568,6 +1568,22 @@ void ASTReader::ReadMacroRecord(PerFileData &F, uint64_t Offset) {
}
}
+void ASTReader::SetIdentifierIsMacro(IdentifierInfo *II, PerFileData &F,
+ uint64_t Offset) {
+ // Note that this identifier has a macro definition.
+ II->setHasMacroDefinition(true);
+
+ // Adjust the offset based on our position in the chain.
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ if (Chain[I] == &F)
+ break;
+
+ Offset += Chain[I]->SizeInBits;
+ }
+
+ UnreadMacroRecordOffsets[II] = Offset;
+}
+
void ASTReader::ReadDefinedMacros() {
for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
PerFileData &F = *Chain[N - I - 1];
@@ -1629,6 +1645,39 @@ void ASTReader::ReadDefinedMacros() {
}
}
}
+
+ // Drain the unread macro-record offsets map.
+ while (!UnreadMacroRecordOffsets.empty())
+ LoadMacroDefinition(UnreadMacroRecordOffsets.begin());
+}
+
+void ASTReader::LoadMacroDefinition(
+ llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos) {
+ assert(Pos != UnreadMacroRecordOffsets.end() && "Unknown macro definition");
+ PerFileData *F = 0;
+ uint64_t Offset = Pos->second;
+ UnreadMacroRecordOffsets.erase(Pos);
+
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ if (Offset < Chain[I]->SizeInBits) {
+ F = Chain[I];
+ break;
+ }
+
+ Offset -= Chain[I]->SizeInBits;
+ }
+ if (!F) {
+ Error("Malformed macro record offset");
+ return;
+ }
+
+ ReadMacroRecord(*F, Offset);
+}
+
+void ASTReader::LoadMacroDefinition(IdentifierInfo *II) {
+ llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos
+ = UnreadMacroRecordOffsets.find(II);
+ LoadMacroDefinition(Pos);
}
MacroDefinition *ASTReader::getMacroDefinition(MacroID ID) {
OpenPOWER on IntegriCloud