Updated to Clang 3.5a.
Change-Id: I8127eb568f674c2e72635b639a3295381fe8af82
diff --git a/lib/Serialization/ASTCommon.h b/lib/Serialization/ASTCommon.h
index ef81e69..524a9c2 100644
--- a/lib/Serialization/ASTCommon.h
+++ b/lib/Serialization/ASTCommon.h
@@ -26,8 +26,12 @@
UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
UPD_CXX_ADDED_ANONYMOUS_NAMESPACE,
UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
+ UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION,
+ UPD_CXX_RESOLVED_EXCEPTION_SPEC,
UPD_CXX_DEDUCED_RETURN_TYPE,
- UPD_DECL_MARKED_USED
+ UPD_DECL_MARKED_USED,
+ UPD_MANGLING_NUMBER,
+ UPD_STATIC_LOCAL_NUMBER
};
TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT);
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 4d1b4b9..ff0b1dd 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -49,6 +49,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SaveAndRestore.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
#include <algorithm>
#include <cstdio>
@@ -59,6 +60,75 @@
using namespace clang::serialization::reader;
using llvm::BitstreamCursor;
+
+//===----------------------------------------------------------------------===//
+// ChainedASTReaderListener implementation
+//===----------------------------------------------------------------------===//
+
+bool
+ChainedASTReaderListener::ReadFullVersionInformation(StringRef FullVersion) {
+ return First->ReadFullVersionInformation(FullVersion) ||
+ Second->ReadFullVersionInformation(FullVersion);
+}
+bool ChainedASTReaderListener::ReadLanguageOptions(const LangOptions &LangOpts,
+ bool Complain) {
+ return First->ReadLanguageOptions(LangOpts, Complain) ||
+ Second->ReadLanguageOptions(LangOpts, Complain);
+}
+bool
+ChainedASTReaderListener::ReadTargetOptions(const TargetOptions &TargetOpts,
+ bool Complain) {
+ return First->ReadTargetOptions(TargetOpts, Complain) ||
+ Second->ReadTargetOptions(TargetOpts, Complain);
+}
+bool ChainedASTReaderListener::ReadDiagnosticOptions(
+ const DiagnosticOptions &DiagOpts, bool Complain) {
+ return First->ReadDiagnosticOptions(DiagOpts, Complain) ||
+ Second->ReadDiagnosticOptions(DiagOpts, Complain);
+}
+bool
+ChainedASTReaderListener::ReadFileSystemOptions(const FileSystemOptions &FSOpts,
+ bool Complain) {
+ return First->ReadFileSystemOptions(FSOpts, Complain) ||
+ Second->ReadFileSystemOptions(FSOpts, Complain);
+}
+
+bool ChainedASTReaderListener::ReadHeaderSearchOptions(
+ const HeaderSearchOptions &HSOpts, bool Complain) {
+ return First->ReadHeaderSearchOptions(HSOpts, Complain) ||
+ Second->ReadHeaderSearchOptions(HSOpts, Complain);
+}
+bool ChainedASTReaderListener::ReadPreprocessorOptions(
+ const PreprocessorOptions &PPOpts, bool Complain,
+ std::string &SuggestedPredefines) {
+ return First->ReadPreprocessorOptions(PPOpts, Complain,
+ SuggestedPredefines) ||
+ Second->ReadPreprocessorOptions(PPOpts, Complain, SuggestedPredefines);
+}
+void ChainedASTReaderListener::ReadCounter(const serialization::ModuleFile &M,
+ unsigned Value) {
+ First->ReadCounter(M, Value);
+ Second->ReadCounter(M, Value);
+}
+bool ChainedASTReaderListener::needsInputFileVisitation() {
+ return First->needsInputFileVisitation() ||
+ Second->needsInputFileVisitation();
+}
+bool ChainedASTReaderListener::needsSystemInputFileVisitation() {
+ return First->needsSystemInputFileVisitation() ||
+ Second->needsSystemInputFileVisitation();
+}
+void ChainedASTReaderListener::visitModuleFile(StringRef Filename) {
+ First->visitModuleFile(Filename);
+ Second->visitModuleFile(Filename);
+}
+bool ChainedASTReaderListener::visitInputFile(StringRef Filename,
+ bool isSystem,
+ bool isOverridden) {
+ return First->visitInputFile(Filename, isSystem, isOverridden) ||
+ Second->visitInputFile(Filename, isSystem, isOverridden);
+}
+
//===----------------------------------------------------------------------===//
// PCH validator implementation
//===----------------------------------------------------------------------===//
@@ -140,7 +210,6 @@
CHECK_TARGET_OPT(Triple, "target");
CHECK_TARGET_OPT(CPU, "target CPU");
CHECK_TARGET_OPT(ABI, "target ABI");
- CHECK_TARGET_OPT(CXXABI, "target C++ ABI");
CHECK_TARGET_OPT(LinkerVersion, "target linker version");
#undef CHECK_TARGET_OPT
@@ -401,19 +470,19 @@
std::pair<unsigned, unsigned>
ASTSelectorLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
- using namespace clang::io;
- unsigned KeyLen = ReadUnalignedLE16(d);
- unsigned DataLen = ReadUnalignedLE16(d);
+ using namespace llvm::support;
+ unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d);
+ unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d);
return std::make_pair(KeyLen, DataLen);
}
ASTSelectorLookupTrait::internal_key_type
ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) {
- using namespace clang::io;
+ using namespace llvm::support;
SelectorTable &SelTable = Reader.getContext().Selectors;
- unsigned N = ReadUnalignedLE16(d);
- IdentifierInfo *FirstII
- = Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));
+ unsigned N = endian::readNext<uint16_t, little, unaligned>(d);
+ IdentifierInfo *FirstII = Reader.getLocalIdentifier(
+ F, endian::readNext<uint32_t, little, unaligned>(d));
if (N == 0)
return SelTable.getNullarySelector(FirstII);
else if (N == 1)
@@ -422,7 +491,8 @@
SmallVector<IdentifierInfo *, 16> Args;
Args.push_back(FirstII);
for (unsigned I = 1; I != N; ++I)
- Args.push_back(Reader.getLocalIdentifier(F, ReadUnalignedLE32(d)));
+ Args.push_back(Reader.getLocalIdentifier(
+ F, endian::readNext<uint32_t, little, unaligned>(d)));
return SelTable.getSelector(N, Args.data());
}
@@ -430,13 +500,16 @@
ASTSelectorLookupTrait::data_type
ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d,
unsigned DataLen) {
- using namespace clang::io;
+ using namespace llvm::support;
data_type Result;
- Result.ID = Reader.getGlobalSelectorID(F, ReadUnalignedLE32(d));
- unsigned NumInstanceMethodsAndBits = ReadUnalignedLE16(d);
- unsigned NumFactoryMethodsAndBits = ReadUnalignedLE16(d);
+ Result.ID = Reader.getGlobalSelectorID(
+ F, endian::readNext<uint32_t, little, unaligned>(d));
+ unsigned NumInstanceMethodsAndBits =
+ endian::readNext<uint16_t, little, unaligned>(d);
+ unsigned NumFactoryMethodsAndBits =
+ endian::readNext<uint16_t, little, unaligned>(d);
Result.InstanceBits = NumInstanceMethodsAndBits & 0x3;
Result.FactoryBits = NumFactoryMethodsAndBits & 0x3;
unsigned NumInstanceMethods = NumInstanceMethodsAndBits >> 2;
@@ -444,15 +517,15 @@
// Load instance methods
for (unsigned I = 0; I != NumInstanceMethods; ++I) {
- if (ObjCMethodDecl *Method
- = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d)))
+ if (ObjCMethodDecl *Method = Reader.GetLocalDeclAs<ObjCMethodDecl>(
+ F, endian::readNext<uint32_t, little, unaligned>(d)))
Result.Instance.push_back(Method);
}
// Load factory methods
for (unsigned I = 0; I != NumFactoryMethods; ++I) {
- if (ObjCMethodDecl *Method
- = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d)))
+ if (ObjCMethodDecl *Method = Reader.GetLocalDeclAs<ObjCMethodDecl>(
+ F, endian::readNext<uint32_t, little, unaligned>(d)))
Result.Factory.push_back(Method);
}
@@ -465,9 +538,9 @@
std::pair<unsigned, unsigned>
ASTIdentifierLookupTraitBase::ReadKeyDataLength(const unsigned char*& d) {
- using namespace clang::io;
- unsigned DataLen = ReadUnalignedLE16(d);
- unsigned KeyLen = ReadUnalignedLE16(d);
+ using namespace llvm::support;
+ unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d);
+ unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d);
return std::make_pair(KeyLen, DataLen);
}
@@ -490,8 +563,8 @@
IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
const unsigned char* d,
unsigned DataLen) {
- using namespace clang::io;
- unsigned RawID = ReadUnalignedLE32(d);
+ using namespace llvm::support;
+ unsigned RawID = endian::readNext<uint32_t, little, unaligned>(d);
bool IsInteresting = RawID & 0x01;
// Wipe out the "is interesting" bit.
@@ -517,8 +590,8 @@
return II;
}
- unsigned ObjCOrBuiltinID = ReadUnalignedLE16(d);
- unsigned Bits = ReadUnalignedLE16(d);
+ unsigned ObjCOrBuiltinID = endian::readNext<uint16_t, little, unaligned>(d);
+ unsigned Bits = endian::readNext<uint16_t, little, unaligned>(d);
bool CPlusPlusOperatorKeyword = Bits & 0x01;
Bits >>= 1;
bool HasRevertedTokenIDToIdentifier = Bits & 0x01;
@@ -567,11 +640,13 @@
// If this identifier is a macro, deserialize the macro
// definition.
if (hadMacroDefinition) {
- uint32_t MacroDirectivesOffset = ReadUnalignedLE32(d);
+ uint32_t MacroDirectivesOffset =
+ endian::readNext<uint32_t, little, unaligned>(d);
DataLen -= 4;
SmallVector<uint32_t, 8> LocalMacroIDs;
if (hasSubmoduleMacros) {
- while (uint32_t LocalMacroID = ReadUnalignedLE32(d)) {
+ while (uint32_t LocalMacroID =
+ endian::readNext<uint32_t, little, unaligned>(d)) {
DataLen -= 4;
LocalMacroIDs.push_back(LocalMacroID);
}
@@ -579,11 +654,34 @@
}
if (F.Kind == MK_Module) {
+ // Macro definitions are stored from newest to oldest, so reverse them
+ // before registering them.
+ llvm::SmallVector<unsigned, 8> MacroSizes;
for (SmallVectorImpl<uint32_t>::iterator
- I = LocalMacroIDs.begin(), E = LocalMacroIDs.end(); I != E; ++I) {
- MacroID MacID = Reader.getGlobalMacroID(F, *I);
- Reader.addPendingMacroFromModule(II, &F, MacID, F.DirectImportLoc);
+ I = LocalMacroIDs.begin(), E = LocalMacroIDs.end(); I != E; /**/) {
+ unsigned Size = 1;
+
+ static const uint32_t HasOverridesFlag = 0x80000000U;
+ if (I + 1 != E && (I[1] & HasOverridesFlag))
+ Size += 1 + (I[1] & ~HasOverridesFlag);
+
+ MacroSizes.push_back(Size);
+ I += Size;
}
+
+ SmallVectorImpl<uint32_t>::iterator I = LocalMacroIDs.end();
+ for (SmallVectorImpl<unsigned>::reverse_iterator SI = MacroSizes.rbegin(),
+ SE = MacroSizes.rend();
+ SI != SE; ++SI) {
+ I -= *SI;
+
+ uint32_t LocalMacroID = *I;
+ llvm::ArrayRef<uint32_t> Overrides;
+ if (*SI != 1)
+ Overrides = llvm::makeArrayRef(&I[2], *SI - 2);
+ Reader.addPendingMacroFromModule(II, &F, LocalMacroID, Overrides);
+ }
+ assert(I == LocalMacroIDs.begin());
} else {
Reader.addPendingMacroFromPCH(II, &F, MacroDirectivesOffset);
}
@@ -596,7 +694,8 @@
if (DataLen > 0) {
SmallVector<uint32_t, 4> DeclIDs;
for (; DataLen > 0; DataLen -= 4)
- DeclIDs.push_back(Reader.getGlobalDeclID(F, ReadUnalignedLE32(d)));
+ DeclIDs.push_back(Reader.getGlobalDeclID(
+ F, endian::readNext<uint32_t, little, unaligned>(d)));
Reader.SetGloballyVisibleDecls(II, DeclIDs);
}
@@ -664,34 +763,37 @@
std::pair<unsigned, unsigned>
ASTDeclContextNameLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
- using namespace clang::io;
- unsigned KeyLen = ReadUnalignedLE16(d);
- unsigned DataLen = ReadUnalignedLE16(d);
+ using namespace llvm::support;
+ unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d);
+ unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d);
return std::make_pair(KeyLen, DataLen);
}
ASTDeclContextNameLookupTrait::internal_key_type
ASTDeclContextNameLookupTrait::ReadKey(const unsigned char* d, unsigned) {
- using namespace clang::io;
+ using namespace llvm::support;
DeclNameKey Key;
Key.Kind = (DeclarationName::NameKind)*d++;
switch (Key.Kind) {
case DeclarationName::Identifier:
- Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));
+ Key.Data = (uint64_t)Reader.getLocalIdentifier(
+ F, endian::readNext<uint32_t, little, unaligned>(d));
break;
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
Key.Data =
- (uint64_t)Reader.getLocalSelector(F, ReadUnalignedLE32(d))
- .getAsOpaquePtr();
+ (uint64_t)Reader.getLocalSelector(
+ F, endian::readNext<uint32_t, little, unaligned>(
+ d)).getAsOpaquePtr();
break;
case DeclarationName::CXXOperatorName:
Key.Data = *d++; // OverloadedOperatorKind
break;
case DeclarationName::CXXLiteralOperatorName:
- Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));
+ Key.Data = (uint64_t)Reader.getLocalIdentifier(
+ F, endian::readNext<uint32_t, little, unaligned>(d));
break;
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
@@ -708,8 +810,8 @@
ASTDeclContextNameLookupTrait::ReadData(internal_key_type,
const unsigned char* d,
unsigned DataLen) {
- using namespace clang::io;
- unsigned NumDecls = ReadUnalignedLE16(d);
+ using namespace llvm::support;
+ unsigned NumDecls = endian::readNext<uint16_t, little, unaligned>(d);
LE32DeclID *Start = reinterpret_cast<LE32DeclID *>(
const_cast<unsigned char *>(d));
return std::make_pair(Start, Start + NumDecls);
@@ -1262,16 +1364,18 @@
std::pair<unsigned, unsigned>
HeaderFileInfoTrait::ReadKeyDataLength(const unsigned char*& d) {
- unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d);
+ using namespace llvm::support;
+ unsigned KeyLen = (unsigned) endian::readNext<uint16_t, little, unaligned>(d);
unsigned DataLen = (unsigned) *d++;
return std::make_pair(KeyLen, DataLen);
}
HeaderFileInfoTrait::internal_key_type
HeaderFileInfoTrait::ReadKey(const unsigned char *d, unsigned) {
+ using namespace llvm::support;
internal_key_type ikey;
- ikey.Size = off_t(clang::io::ReadUnalignedLE64(d));
- ikey.ModTime = time_t(clang::io::ReadUnalignedLE64(d));
+ ikey.Size = off_t(endian::readNext<uint64_t, little, unaligned>(d));
+ ikey.ModTime = time_t(endian::readNext<uint64_t, little, unaligned>(d));
ikey.Filename = (const char *)d;
return ikey;
}
@@ -1280,7 +1384,7 @@
HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
unsigned DataLen) {
const unsigned char *End = d + DataLen;
- using namespace clang::io;
+ using namespace llvm::support;
HeaderFileInfo HFI;
unsigned Flags = *d++;
HFI.HeaderRole = static_cast<ModuleMap::ModuleHeaderRole>
@@ -1290,10 +1394,11 @@
HFI.DirInfo = (Flags >> 2) & 0x03;
HFI.Resolved = (Flags >> 1) & 0x01;
HFI.IndexHeaderMapHeader = Flags & 0x01;
- HFI.NumIncludes = ReadUnalignedLE16(d);
- HFI.ControllingMacroID = Reader.getGlobalIdentifierID(M,
- ReadUnalignedLE32(d));
- if (unsigned FrameworkOffset = ReadUnalignedLE32(d)) {
+ HFI.NumIncludes = endian::readNext<uint16_t, little, unaligned>(d);
+ HFI.ControllingMacroID = Reader.getGlobalIdentifierID(
+ M, endian::readNext<uint32_t, little, unaligned>(d));
+ if (unsigned FrameworkOffset =
+ endian::readNext<uint32_t, little, unaligned>(d)) {
// The framework offset is 1 greater than the actual offset,
// since 0 is used as an indicator for "no framework name".
StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1);
@@ -1301,7 +1406,7 @@
}
if (d != End) {
- uint32_t LocalSMID = ReadUnalignedLE32(d);
+ uint32_t LocalSMID = endian::readNext<uint32_t, little, unaligned>(d);
if (LocalSMID) {
// This header is part of a module. Associate it with the module to enable
// implicit module import.
@@ -1323,12 +1428,19 @@
return HFI;
}
-void ASTReader::addPendingMacroFromModule(IdentifierInfo *II,
- ModuleFile *M,
- GlobalMacroID GMacID,
- SourceLocation ImportLoc) {
+void
+ASTReader::addPendingMacroFromModule(IdentifierInfo *II, ModuleFile *M,
+ GlobalMacroID GMacID,
+ llvm::ArrayRef<SubmoduleID> Overrides) {
assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard");
- PendingMacroIDs[II].push_back(PendingMacroInfo(M, GMacID, ImportLoc));
+ SubmoduleID *OverrideData = 0;
+ if (!Overrides.empty()) {
+ OverrideData = new (Context) SubmoduleID[Overrides.size() + 1];
+ OverrideData[0] = Overrides.size();
+ for (unsigned I = 0; I != Overrides.size(); ++I)
+ OverrideData[I + 1] = getGlobalSubmoduleID(*M, Overrides[I]);
+ }
+ PendingMacroIDs[II].push_back(PendingMacroInfo(M, GMacID, OverrideData));
}
void ASTReader::addPendingMacroFromPCH(IdentifierInfo *II,
@@ -1477,6 +1589,59 @@
IdentifierGeneration[II] = CurrentGeneration;
}
+struct ASTReader::ModuleMacroInfo {
+ SubmoduleID SubModID;
+ MacroInfo *MI;
+ SubmoduleID *Overrides;
+ // FIXME: Remove this.
+ ModuleFile *F;
+
+ bool isDefine() const { return MI; }
+
+ SubmoduleID getSubmoduleID() const { return SubModID; }
+
+ llvm::ArrayRef<SubmoduleID> getOverriddenSubmodules() const {
+ if (!Overrides)
+ return llvm::ArrayRef<SubmoduleID>();
+ return llvm::makeArrayRef(Overrides + 1, *Overrides);
+ }
+
+ DefMacroDirective *import(Preprocessor &PP, SourceLocation ImportLoc) const {
+ if (!MI)
+ return 0;
+ return PP.AllocateDefMacroDirective(MI, ImportLoc, /*isImported=*/true);
+ }
+};
+
+ASTReader::ModuleMacroInfo *
+ASTReader::getModuleMacro(const PendingMacroInfo &PMInfo) {
+ ModuleMacroInfo Info;
+
+ uint32_t ID = PMInfo.ModuleMacroData.MacID;
+ if (ID & 1) {
+ // Macro undefinition.
+ Info.SubModID = getGlobalSubmoduleID(*PMInfo.M, ID >> 1);
+ Info.MI = 0;
+ } else {
+ // Macro definition.
+ GlobalMacroID GMacID = getGlobalMacroID(*PMInfo.M, ID >> 1);
+ assert(GMacID);
+
+ // If this macro has already been loaded, don't do so again.
+ // FIXME: This is highly dubious. Multiple macro definitions can have the
+ // same MacroInfo (and hence the same GMacID) due to #pragma push_macro etc.
+ if (MacrosLoaded[GMacID - NUM_PREDEF_MACRO_IDS])
+ return 0;
+
+ Info.MI = getMacro(GMacID);
+ Info.SubModID = Info.MI->getOwningModuleID();
+ }
+ Info.Overrides = PMInfo.ModuleMacroData.Overrides;
+ Info.F = PMInfo.M;
+
+ return new (Context) ModuleMacroInfo(Info);
+}
+
void ASTReader::resolvePendingMacro(IdentifierInfo *II,
const PendingMacroInfo &PMInfo) {
assert(II);
@@ -1486,42 +1651,21 @@
PMInfo.PCHMacroData.MacroDirectivesOffset);
return;
}
-
+
// Module Macro.
- GlobalMacroID GMacID = PMInfo.ModuleMacroData.GMacID;
- SourceLocation ImportLoc =
- SourceLocation::getFromRawEncoding(PMInfo.ModuleMacroData.ImportLoc);
-
- assert(GMacID);
- // If this macro has already been loaded, don't do so again.
- if (MacrosLoaded[GMacID - NUM_PREDEF_MACRO_IDS])
+ ModuleMacroInfo *MMI = getModuleMacro(PMInfo);
+ if (!MMI)
return;
- MacroInfo *MI = getMacro(GMacID);
- SubmoduleID SubModID = MI->getOwningModuleID();
- MacroDirective *MD = PP.AllocateDefMacroDirective(MI, ImportLoc,
- /*isImported=*/true);
-
- // Determine whether this macro definition is visible.
- bool Hidden = false;
- Module *Owner = 0;
- if (SubModID) {
- if ((Owner = getSubmodule(SubModID))) {
- if (Owner->NameVisibility == Module::Hidden) {
- // The owning module is not visible, and this macro definition
- // should not be, either.
- Hidden = true;
-
- // Note that this macro definition was hidden because its owning
- // module is not yet visible.
- HiddenNamesMap[Owner].push_back(HiddenName(II, MD));
- }
- }
+ Module *Owner = getSubmodule(MMI->getSubmoduleID());
+ if (Owner && Owner->NameVisibility == Module::Hidden) {
+ // Macros in the owning module are hidden. Just remember this macro to
+ // install if we make this module visible.
+ HiddenNamesMap[Owner].HiddenMacros.insert(std::make_pair(II, MMI));
+ } else {
+ installImportedMacro(II, MMI, Owner);
}
-
- if (!Hidden)
- installImportedMacro(II, MD, Owner);
}
void ASTReader::installPCHMacroDirectives(IdentifierInfo *II,
@@ -1606,34 +1750,181 @@
return PrevInSystem && NewInSystem;
}
-void ASTReader::installImportedMacro(IdentifierInfo *II, MacroDirective *MD,
- Module *Owner) {
- assert(II && MD);
+void ASTReader::removeOverriddenMacros(IdentifierInfo *II,
+ AmbiguousMacros &Ambig,
+ llvm::ArrayRef<SubmoduleID> Overrides) {
+ for (unsigned OI = 0, ON = Overrides.size(); OI != ON; ++OI) {
+ SubmoduleID OwnerID = Overrides[OI];
- DefMacroDirective *DefMD = cast<DefMacroDirective>(MD);
+ // If this macro is not yet visible, remove it from the hidden names list.
+ Module *Owner = getSubmodule(OwnerID);
+ HiddenNames &Hidden = HiddenNamesMap[Owner];
+ HiddenMacrosMap::iterator HI = Hidden.HiddenMacros.find(II);
+ if (HI != Hidden.HiddenMacros.end()) {
+ auto SubOverrides = HI->second->getOverriddenSubmodules();
+ Hidden.HiddenMacros.erase(HI);
+ removeOverriddenMacros(II, Ambig, SubOverrides);
+ }
+
+ // If this macro is already in our list of conflicts, remove it from there.
+ Ambig.erase(
+ std::remove_if(Ambig.begin(), Ambig.end(), [&](DefMacroDirective *MD) {
+ return MD->getInfo()->getOwningModuleID() == OwnerID;
+ }),
+ Ambig.end());
+ }
+}
+
+ASTReader::AmbiguousMacros *
+ASTReader::removeOverriddenMacros(IdentifierInfo *II,
+ llvm::ArrayRef<SubmoduleID> Overrides) {
MacroDirective *Prev = PP.getMacroDirective(II);
- if (Prev) {
- MacroDirective::DefInfo PrevDef = Prev->getDefinition();
- MacroInfo *PrevMI = PrevDef.getMacroInfo();
- MacroInfo *NewMI = DefMD->getInfo();
- if (NewMI != PrevMI && !PrevMI->isIdenticalTo(*NewMI, PP,
- /*Syntactically=*/true)) {
- // Before marking the macros as ambiguous, check if this is a case where
- // both macros are in system headers. If so, we trust that the system
- // did not get it wrong. This also handles cases where Clang's own
- // headers have a different spelling of certain system macros:
- // #define LONG_MAX __LONG_MAX__ (clang's limits.h)
- // #define LONG_MAX 0x7fffffffffffffffL (system's limits.h)
- if (!areDefinedInSystemModules(PrevMI, NewMI, Owner, *this)) {
- PrevDef.getDirective()->setAmbiguous(true);
- DefMD->setAmbiguous(true);
- }
+ if (!Prev && Overrides.empty())
+ return 0;
+
+ DefMacroDirective *PrevDef = Prev ? Prev->getDefinition().getDirective() : 0;
+ if (PrevDef && PrevDef->isAmbiguous()) {
+ // We had a prior ambiguity. Check whether we resolve it (or make it worse).
+ AmbiguousMacros &Ambig = AmbiguousMacroDefs[II];
+ Ambig.push_back(PrevDef);
+
+ removeOverriddenMacros(II, Ambig, Overrides);
+
+ if (!Ambig.empty())
+ return &Ambig;
+
+ AmbiguousMacroDefs.erase(II);
+ } else {
+ // There's no ambiguity yet. Maybe we're introducing one.
+ llvm::SmallVector<DefMacroDirective*, 1> Ambig;
+ if (PrevDef)
+ Ambig.push_back(PrevDef);
+
+ removeOverriddenMacros(II, Ambig, Overrides);
+
+ if (!Ambig.empty()) {
+ AmbiguousMacros &Result = AmbiguousMacroDefs[II];
+ Result.swap(Ambig);
+ return &Result;
}
}
-
+
+ // We ended up with no ambiguity.
+ return 0;
+}
+
+void ASTReader::installImportedMacro(IdentifierInfo *II, ModuleMacroInfo *MMI,
+ Module *Owner) {
+ assert(II && Owner);
+
+ SourceLocation ImportLoc = Owner->MacroVisibilityLoc;
+ if (ImportLoc.isInvalid()) {
+ // FIXME: If we made macros from this module visible but didn't provide a
+ // source location for the import, we don't have a location for the macro.
+ // Use the location at which the containing module file was first imported
+ // for now.
+ ImportLoc = MMI->F->DirectImportLoc;
+ assert(ImportLoc.isValid() && "no import location for a visible macro?");
+ }
+
+ llvm::SmallVectorImpl<DefMacroDirective*> *Prev =
+ removeOverriddenMacros(II, MMI->getOverriddenSubmodules());
+
+
+ // Create a synthetic macro definition corresponding to the import (or null
+ // if this was an undefinition of the macro).
+ DefMacroDirective *MD = MMI->import(PP, ImportLoc);
+
+ // If there's no ambiguity, just install the macro.
+ if (!Prev) {
+ if (MD)
+ PP.appendMacroDirective(II, MD);
+ else
+ PP.appendMacroDirective(II, PP.AllocateUndefMacroDirective(ImportLoc));
+ return;
+ }
+ assert(!Prev->empty());
+
+ if (!MD) {
+ // We imported a #undef that didn't remove all prior definitions. The most
+ // recent prior definition remains, and we install it in the place of the
+ // imported directive.
+ MacroInfo *NewMI = Prev->back()->getInfo();
+ Prev->pop_back();
+ MD = PP.AllocateDefMacroDirective(NewMI, ImportLoc, /*Imported*/true);
+ }
+
+ // We're introducing a macro definition that creates or adds to an ambiguity.
+ // We can resolve that ambiguity if this macro is token-for-token identical to
+ // all of the existing definitions.
+ MacroInfo *NewMI = MD->getInfo();
+ assert(NewMI && "macro definition with no MacroInfo?");
+ while (!Prev->empty()) {
+ MacroInfo *PrevMI = Prev->back()->getInfo();
+ assert(PrevMI && "macro definition with no MacroInfo?");
+
+ // Before marking the macros as ambiguous, check if this is a case where
+ // both macros are in system headers. If so, we trust that the system
+ // did not get it wrong. This also handles cases where Clang's own
+ // headers have a different spelling of certain system macros:
+ // #define LONG_MAX __LONG_MAX__ (clang's limits.h)
+ // #define LONG_MAX 0x7fffffffffffffffL (system's limits.h)
+ //
+ // FIXME: Remove the defined-in-system-headers check. clang's limits.h
+ // overrides the system limits.h's macros, so there's no conflict here.
+ if (NewMI != PrevMI &&
+ !PrevMI->isIdenticalTo(*NewMI, PP, /*Syntactically=*/true) &&
+ !areDefinedInSystemModules(PrevMI, NewMI, Owner, *this))
+ break;
+
+ // The previous definition is the same as this one (or both are defined in
+ // system modules so we can assume they're equivalent); we don't need to
+ // track it any more.
+ Prev->pop_back();
+ }
+
+ if (!Prev->empty())
+ MD->setAmbiguous(true);
+
PP.appendMacroDirective(II, MD);
}
+ASTReader::InputFileInfo
+ASTReader::readInputFileInfo(ModuleFile &F, unsigned ID) {
+ // Go find this input file.
+ BitstreamCursor &Cursor = F.InputFilesCursor;
+ SavedStreamPosition SavedPosition(Cursor);
+ Cursor.JumpToBit(F.InputFileOffsets[ID-1]);
+
+ unsigned Code = Cursor.ReadCode();
+ RecordData Record;
+ StringRef Blob;
+
+ unsigned Result = Cursor.readRecord(Code, Record, &Blob);
+ assert(static_cast<InputFileRecordTypes>(Result) == INPUT_FILE &&
+ "invalid record type for input file");
+ (void)Result;
+
+ std::string Filename;
+ off_t StoredSize;
+ time_t StoredTime;
+ bool Overridden;
+
+ assert(Record[0] == ID && "Bogus stored ID or offset");
+ StoredSize = static_cast<off_t>(Record[1]);
+ StoredTime = static_cast<time_t>(Record[2]);
+ Overridden = static_cast<bool>(Record[3]);
+ Filename = Blob;
+ MaybeAddSystemRootToFilename(F, Filename);
+
+ InputFileInfo R = { std::move(Filename), StoredSize, StoredTime, Overridden };
+ return R;
+}
+
+std::string ASTReader::getInputFileName(ModuleFile &F, unsigned int ID) {
+ return readInputFileInfo(F, ID).Filename;
+}
+
InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
// If this ID is bogus, just return an empty input file.
if (ID == 0 || ID > F.InputFilesLoaded.size())
@@ -1643,107 +1934,113 @@
if (F.InputFilesLoaded[ID-1].getFile())
return F.InputFilesLoaded[ID-1];
+ if (F.InputFilesLoaded[ID-1].isNotFound())
+ return InputFile();
+
// Go find this input file.
BitstreamCursor &Cursor = F.InputFilesCursor;
SavedStreamPosition SavedPosition(Cursor);
Cursor.JumpToBit(F.InputFileOffsets[ID-1]);
- unsigned Code = Cursor.ReadCode();
- RecordData Record;
- StringRef Blob;
- switch ((InputFileRecordTypes)Cursor.readRecord(Code, Record, &Blob)) {
- case INPUT_FILE: {
- unsigned StoredID = Record[0];
- assert(ID == StoredID && "Bogus stored ID or offset");
- (void)StoredID;
- off_t StoredSize = (off_t)Record[1];
- time_t StoredTime = (time_t)Record[2];
- bool Overridden = (bool)Record[3];
-
- // Get the file entry for this input file.
- StringRef OrigFilename = Blob;
- std::string Filename = OrigFilename;
- MaybeAddSystemRootToFilename(F, Filename);
- const FileEntry *File
- = Overridden? FileMgr.getVirtualFile(Filename, StoredSize, StoredTime)
- : FileMgr.getFile(Filename, /*OpenFile=*/false);
-
- // If we didn't find the file, resolve it relative to the
- // original directory from which this AST file was created.
- if (File == 0 && !F.OriginalDir.empty() && !CurrentDir.empty() &&
- F.OriginalDir != CurrentDir) {
- std::string Resolved = resolveFileRelativeToOriginalDir(Filename,
- F.OriginalDir,
- CurrentDir);
- if (!Resolved.empty())
- File = FileMgr.getFile(Resolved);
- }
-
- // For an overridden file, create a virtual file with the stored
- // size/timestamp.
- if (Overridden && File == 0) {
- File = FileMgr.getVirtualFile(Filename, StoredSize, StoredTime);
- }
-
- if (File == 0) {
- if (Complain) {
- std::string ErrorStr = "could not find file '";
- ErrorStr += Filename;
- ErrorStr += "' referenced by AST file";
- Error(ErrorStr.c_str());
- }
- return InputFile();
- }
+ InputFileInfo FI = readInputFileInfo(F, ID);
+ off_t StoredSize = FI.StoredSize;
+ time_t StoredTime = FI.StoredTime;
+ bool Overridden = FI.Overridden;
+ StringRef Filename = FI.Filename;
- // Check if there was a request to override the contents of the file
- // that was part of the precompiled header. Overridding such a file
- // can lead to problems when lexing using the source locations from the
- // PCH.
- SourceManager &SM = getSourceManager();
- if (!Overridden && SM.isFileOverridden(File)) {
- if (Complain)
- Error(diag::err_fe_pch_file_overridden, Filename);
- // After emitting the diagnostic, recover by disabling the override so
- // that the original file will be used.
- SM.disableFileContentsOverride(File);
- // The FileEntry is a virtual file entry with the size of the contents
- // that would override the original contents. Set it to the original's
- // size/time.
- FileMgr.modifyFileEntry(const_cast<FileEntry*>(File),
- StoredSize, StoredTime);
+ const FileEntry *File
+ = Overridden? FileMgr.getVirtualFile(Filename, StoredSize, StoredTime)
+ : FileMgr.getFile(Filename, /*OpenFile=*/false);
+
+ // If we didn't find the file, resolve it relative to the
+ // original directory from which this AST file was created.
+ if (File == 0 && !F.OriginalDir.empty() && !CurrentDir.empty() &&
+ F.OriginalDir != CurrentDir) {
+ std::string Resolved = resolveFileRelativeToOriginalDir(Filename,
+ F.OriginalDir,
+ CurrentDir);
+ if (!Resolved.empty())
+ File = FileMgr.getFile(Resolved);
+ }
+
+ // For an overridden file, create a virtual file with the stored
+ // size/timestamp.
+ if (Overridden && File == 0) {
+ File = FileMgr.getVirtualFile(Filename, StoredSize, StoredTime);
+ }
+
+ if (File == 0) {
+ if (Complain) {
+ std::string ErrorStr = "could not find file '";
+ ErrorStr += Filename;
+ ErrorStr += "' referenced by AST file";
+ Error(ErrorStr.c_str());
}
+ // Record that we didn't find the file.
+ F.InputFilesLoaded[ID-1] = InputFile::getNotFound();
+ return InputFile();
+ }
- bool IsOutOfDate = false;
+ // Check if there was a request to override the contents of the file
+ // that was part of the precompiled header. Overridding such a file
+ // can lead to problems when lexing using the source locations from the
+ // PCH.
+ SourceManager &SM = getSourceManager();
+ if (!Overridden && SM.isFileOverridden(File)) {
+ if (Complain)
+ Error(diag::err_fe_pch_file_overridden, Filename);
+ // After emitting the diagnostic, recover by disabling the override so
+ // that the original file will be used.
+ SM.disableFileContentsOverride(File);
+ // The FileEntry is a virtual file entry with the size of the contents
+ // that would override the original contents. Set it to the original's
+ // size/time.
+ FileMgr.modifyFileEntry(const_cast<FileEntry*>(File),
+ StoredSize, StoredTime);
+ }
- // For an overridden file, there is nothing to validate.
- if (!Overridden && (StoredSize != File->getSize()
+ bool IsOutOfDate = false;
+
+ // For an overridden file, there is nothing to validate.
+ if (!Overridden && (StoredSize != File->getSize()
#if !defined(LLVM_ON_WIN32)
- // In our regression testing, the Windows file system seems to
- // have inconsistent modification times that sometimes
- // erroneously trigger this error-handling path.
- || StoredTime != File->getModificationTime()
+ // In our regression testing, the Windows file system seems to
+ // have inconsistent modification times that sometimes
+ // erroneously trigger this error-handling path.
+ || StoredTime != File->getModificationTime()
#endif
- )) {
- if (Complain) {
- Error(diag::err_fe_pch_file_modified, Filename, F.FileName);
- if (Context.getLangOpts().Modules && !Diags.isDiagnosticInFlight()) {
- Diag(diag::note_module_cache_path)
- << PP.getHeaderSearchInfo().getModuleCachePath();
- }
+ )) {
+ if (Complain) {
+ // Build a list of the PCH imports that got us here (in reverse).
+ SmallVector<ModuleFile *, 4> ImportStack(1, &F);
+ while (ImportStack.back()->ImportedBy.size() > 0)
+ ImportStack.push_back(ImportStack.back()->ImportedBy[0]);
+
+ // The top-level PCH is stale.
+ StringRef TopLevelPCHName(ImportStack.back()->FileName);
+ Error(diag::err_fe_pch_file_modified, Filename, TopLevelPCHName);
+
+ // Print the import stack.
+ if (ImportStack.size() > 1 && !Diags.isDiagnosticInFlight()) {
+ Diag(diag::note_pch_required_by)
+ << Filename << ImportStack[0]->FileName;
+ for (unsigned I = 1; I < ImportStack.size(); ++I)
+ Diag(diag::note_pch_required_by)
+ << ImportStack[I-1]->FileName << ImportStack[I]->FileName;
}
- IsOutOfDate = true;
+ if (!Diags.isDiagnosticInFlight())
+ Diag(diag::note_pch_rebuild_required) << TopLevelPCHName;
}
- InputFile IF = InputFile(File, Overridden, IsOutOfDate);
-
- // Note that we've loaded this input file.
- F.InputFilesLoaded[ID-1] = IF;
- return IF;
- }
+ IsOutOfDate = true;
}
- return InputFile();
+ InputFile IF = InputFile(File, Overridden, IsOutOfDate);
+
+ // Note that we've loaded this input file.
+ F.InputFilesLoaded[ID-1] = IF;
+ return IF;
}
const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) {
@@ -1808,20 +2105,54 @@
case llvm::BitstreamEntry::Error:
Error("malformed block record in AST file");
return Failure;
- case llvm::BitstreamEntry::EndBlock:
- // Validate all of the non-system input files.
- if (!DisableValidation) {
+ case llvm::BitstreamEntry::EndBlock: {
+ // Validate input files.
+ const HeaderSearchOptions &HSOpts =
+ PP.getHeaderSearchInfo().getHeaderSearchOpts();
+
+ // All user input files reside at the index range [0, Record[1]), and
+ // system input files reside at [Record[1], Record[0]).
+ // Record is the one from INPUT_FILE_OFFSETS.
+ unsigned NumInputs = Record[0];
+ unsigned NumUserInputs = Record[1];
+
+ if (!DisableValidation &&
+ (!HSOpts.ModulesValidateOncePerBuildSession ||
+ F.InputFilesValidationTimestamp <= HSOpts.BuildSessionTimestamp)) {
bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0;
- // All user input files reside at the index range [0, Record[1]).
- // Record is the one from INPUT_FILE_OFFSETS.
- for (unsigned I = 0, N = Record[1]; I < N; ++I) {
+
+ // If we are reading a module, we will create a verification timestamp,
+ // so we verify all input files. Otherwise, verify only user input
+ // files.
+
+ unsigned N = NumUserInputs;
+ if (ValidateSystemInputs ||
+ (HSOpts.ModulesValidateOncePerBuildSession && F.Kind == MK_Module))
+ N = NumInputs;
+
+ for (unsigned I = 0; I < N; ++I) {
InputFile IF = getInputFile(F, I+1, Complain);
if (!IF.getFile() || IF.isOutOfDate())
return OutOfDate;
}
}
+
+ if (Listener)
+ Listener->visitModuleFile(F.FileName);
+
+ if (Listener && Listener->needsInputFileVisitation()) {
+ unsigned N = Listener->needsSystemInputFileVisitation() ? NumInputs
+ : NumUserInputs;
+ for (unsigned I = 0; I < N; ++I) {
+ bool IsSystem = I >= NumUserInputs;
+ InputFileInfo FI = readInputFileInfo(F, I+1);
+ Listener->visitInputFile(FI.Filename, IsSystem, FI.Overridden);
+ }
+ }
+
return Success;
-
+ }
+
case llvm::BitstreamEntry::SubBlock:
switch (Entry.ID) {
case INPUT_FILES_BLOCK_ID:
@@ -1854,8 +2185,8 @@
case METADATA: {
if (Record[0] != VERSION_MAJOR && !DisableValidation) {
if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0)
- Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old
- : diag::warn_pch_version_too_new);
+ Diag(Record[0] < VERSION_MAJOR? diag::err_pch_version_too_old
+ : diag::err_pch_version_too_new);
return VersionMismatch;
}
@@ -1871,7 +2202,7 @@
StringRef ASTBranch = Blob;
if (StringRef(CurBranch) != ASTBranch && !DisableValidation) {
if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0)
- Diag(diag::warn_pch_different_branch) << ASTBranch << CurBranch;
+ Diag(diag::err_pch_different_branch) << ASTBranch << CurBranch;
return VersionMismatch;
}
break;
@@ -1916,7 +2247,7 @@
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
if (Listener && &F == *ModuleMgr.begin() &&
ParseLanguageOptions(Record, Complain, *Listener) &&
- !DisableValidation)
+ !DisableValidation && !AllowConfigurationMismatch)
return ConfigurationMismatch;
break;
}
@@ -1925,7 +2256,7 @@
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
if (Listener && &F == *ModuleMgr.begin() &&
ParseTargetOptions(Record, Complain, *Listener) &&
- !DisableValidation)
+ !DisableValidation && !AllowConfigurationMismatch)
return ConfigurationMismatch;
break;
}
@@ -1934,7 +2265,7 @@
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
if (Listener && &F == *ModuleMgr.begin() &&
ParseDiagnosticOptions(Record, Complain, *Listener) &&
- !DisableValidation)
+ !DisableValidation && !AllowConfigurationMismatch)
return ConfigurationMismatch;
break;
}
@@ -1943,7 +2274,7 @@
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
if (Listener && &F == *ModuleMgr.begin() &&
ParseFileSystemOptions(Record, Complain, *Listener) &&
- !DisableValidation)
+ !DisableValidation && !AllowConfigurationMismatch)
return ConfigurationMismatch;
break;
}
@@ -1952,7 +2283,7 @@
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
if (Listener && &F == *ModuleMgr.begin() &&
ParseHeaderSearchOptions(Record, Complain, *Listener) &&
- !DisableValidation)
+ !DisableValidation && !AllowConfigurationMismatch)
return ConfigurationMismatch;
break;
}
@@ -1962,7 +2293,7 @@
if (Listener && &F == *ModuleMgr.begin() &&
ParsePreprocessorOptions(Record, Complain, *Listener,
SuggestedPredefines) &&
- !DisableValidation)
+ !DisableValidation && !AllowConfigurationMismatch)
return ConfigurationMismatch;
break;
}
@@ -2035,14 +2366,7 @@
return true;
}
break;
-
- case DECL_UPDATES_BLOCK_ID:
- if (Stream.SkipBlock()) {
- Error("malformed block record in AST file");
- return true;
- }
- break;
-
+
case PREPROCESSOR_BLOCK_ID:
F.MacroCursor = Stream;
if (!PP.getExternalSource())
@@ -2191,6 +2515,12 @@
DeclContext *TU = Context.getTranslationUnitDecl();
F.DeclContextInfos[TU].NameLookupTableData = Table;
TU->setHasExternalVisibleStorage(true);
+ } else if (Decl *D = DeclsLoaded[ID - NUM_PREDEF_DECL_IDS]) {
+ auto *DC = cast<DeclContext>(D);
+ DC->getPrimaryContext()->setHasExternalVisibleStorage(true);
+ auto *&LookupTable = F.DeclContextInfos[DC].NameLookupTableData;
+ delete LookupTable;
+ LookupTable = Table;
} else
PendingVisibleUpdates[ID].push_back(std::make_pair(Table, &F));
break;
@@ -2237,9 +2567,9 @@
break;
}
- case EXTERNAL_DEFINITIONS:
+ case EAGERLY_DESERIALIZED_DECLS:
for (unsigned I = 0, N = Record.size(); I != N; ++I)
- ExternalDefinitions.push_back(getGlobalDeclID(F, Record[I]));
+ EagerlyDeserializedDecls.push_back(getGlobalDeclID(F, Record[I]));
break;
case SPECIAL_TYPES:
@@ -2365,7 +2695,7 @@
F.SLocEntryOffsets = (const uint32_t *)Blob.data();
F.LocalNumSLocEntries = Record[0];
unsigned SLocSpaceSize = Record[1];
- llvm::tie(F.SLocEntryBaseID, F.SLocEntryBaseOffset) =
+ std::tie(F.SLocEntryBaseID, F.SLocEntryBaseOffset) =
SourceMgr.AllocateLoadedSLocEntries(F.LocalNumSLocEntries,
SLocSpaceSize);
// Make our entry in the range map. BaseID is negative and growing, so
@@ -2384,9 +2714,9 @@
// Initialize the remapping table.
// Invalid stays invalid.
- F.SLocRemap.insert(std::make_pair(0U, 0));
+ F.SLocRemap.insertOrReplace(std::make_pair(0U, 0));
// This module. Base was 2 when being compiled.
- F.SLocRemap.insert(std::make_pair(2U,
+ F.SLocRemap.insertOrReplace(std::make_pair(2U,
static_cast<int>(F.SLocEntryBaseOffset - 2)));
TotalNumSLocEntries += F.LocalNumSLocEntries;
@@ -2397,7 +2727,13 @@
// Additional remapping information.
const unsigned char *Data = (const unsigned char*)Blob.data();
const unsigned char *DataEnd = Data + Blob.size();
-
+
+ // If we see this entry before SOURCE_LOCATION_OFFSETS, add placeholders.
+ if (F.SLocRemap.find(0) == F.SLocRemap.end()) {
+ F.SLocRemap.insert(std::make_pair(0U, 0));
+ F.SLocRemap.insert(std::make_pair(2U, 1));
+ }
+
// Continuous range maps we may be updating in our module.
ContinuousRangeMap<uint32_t, int, 2>::Builder SLocRemap(F.SLocRemap);
ContinuousRangeMap<uint32_t, int, 2>::Builder
@@ -2414,7 +2750,8 @@
ContinuousRangeMap<uint32_t, int, 2>::Builder TypeRemap(F.TypeRemap);
while(Data < DataEnd) {
- uint16_t Len = io::ReadUnalignedLE16(Data);
+ using namespace llvm::support;
+ uint16_t Len = endian::readNext<uint16_t, little, unaligned>(Data);
StringRef Name = StringRef((const char*)Data, Len);
Data += Len;
ModuleFile *OM = ModuleMgr.lookup(Name);
@@ -2423,15 +2760,23 @@
return true;
}
- uint32_t SLocOffset = io::ReadUnalignedLE32(Data);
- uint32_t IdentifierIDOffset = io::ReadUnalignedLE32(Data);
- uint32_t MacroIDOffset = io::ReadUnalignedLE32(Data);
- uint32_t PreprocessedEntityIDOffset = io::ReadUnalignedLE32(Data);
- uint32_t SubmoduleIDOffset = io::ReadUnalignedLE32(Data);
- uint32_t SelectorIDOffset = io::ReadUnalignedLE32(Data);
- uint32_t DeclIDOffset = io::ReadUnalignedLE32(Data);
- uint32_t TypeIndexOffset = io::ReadUnalignedLE32(Data);
-
+ uint32_t SLocOffset =
+ endian::readNext<uint32_t, little, unaligned>(Data);
+ uint32_t IdentifierIDOffset =
+ endian::readNext<uint32_t, little, unaligned>(Data);
+ uint32_t MacroIDOffset =
+ endian::readNext<uint32_t, little, unaligned>(Data);
+ uint32_t PreprocessedEntityIDOffset =
+ endian::readNext<uint32_t, little, unaligned>(Data);
+ uint32_t SubmoduleIDOffset =
+ endian::readNext<uint32_t, little, unaligned>(Data);
+ uint32_t SelectorIDOffset =
+ endian::readNext<uint32_t, little, unaligned>(Data);
+ uint32_t DeclIDOffset =
+ endian::readNext<uint32_t, little, unaligned>(Data);
+ uint32_t TypeIndexOffset =
+ endian::readNext<uint32_t, little, unaligned>(Data);
+
// Source location offset is mapped to OM->SLocEntryBaseOffset.
SLocRemap.insert(std::make_pair(SLocOffset,
static_cast<int>(OM->SLocEntryBaseOffset - SLocOffset)));
@@ -2569,6 +2914,7 @@
Error("invalid DECL_UPDATE_OFFSETS block in AST file");
return true;
}
+ // FIXME: If we've already loaded the decl, perform the updates now.
for (unsigned I = 0, N = Record.size(); I != N; I += 2)
DeclUpdateOffsets[getGlobalDeclID(F, Record[I])]
.push_back(std::make_pair(&F, Record[I+1]));
@@ -2690,9 +3036,11 @@
// If we aren't loading a module (which has its own exports), make
// all of the imported modules visible.
// FIXME: Deal with macros-only imports.
- for (unsigned I = 0, N = Record.size(); I != N; ++I) {
- if (unsigned GlobalID = getGlobalSubmoduleID(F, Record[I]))
- ImportedModules.push_back(GlobalID);
+ for (unsigned I = 0, N = Record.size(); I != N; /**/) {
+ unsigned GlobalID = getGlobalSubmoduleID(F, Record[I++]);
+ SourceLocation Loc = ReadSourceLocation(F, Record, I);
+ if (GlobalID)
+ ImportedModules.push_back(ImportedSubmodule(GlobalID, Loc));
}
}
break;
@@ -2791,30 +3139,25 @@
}
void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner) {
- for (unsigned I = 0, N = Names.size(); I != N; ++I) {
- switch (Names[I].getKind()) {
- case HiddenName::Declaration: {
- Decl *D = Names[I].getDecl();
- bool wasHidden = D->Hidden;
- D->Hidden = false;
+ for (unsigned I = 0, N = Names.HiddenDecls.size(); I != N; ++I) {
+ Decl *D = Names.HiddenDecls[I];
+ bool wasHidden = D->Hidden;
+ D->Hidden = false;
- if (wasHidden && SemaObj) {
- if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D)) {
- moveMethodToBackOfGlobalList(*SemaObj, Method);
- }
+ if (wasHidden && SemaObj) {
+ if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D)) {
+ moveMethodToBackOfGlobalList(*SemaObj, Method);
}
- break;
- }
- case HiddenName::MacroVisibility: {
- std::pair<IdentifierInfo *, MacroDirective *> Macro = Names[I].getMacro();
- installImportedMacro(Macro.first, Macro.second, Owner);
- break;
- }
}
}
+
+ for (HiddenMacrosMap::const_iterator I = Names.HiddenMacros.begin(),
+ E = Names.HiddenMacros.end();
+ I != E; ++I)
+ installImportedMacro(I->first, I->second, Owner);
}
-void ASTReader::makeModuleVisible(Module *Mod,
+void ASTReader::makeModuleVisible(Module *Mod,
Module::NameVisibilityKind NameVisibility,
SourceLocation ImportLoc,
bool Complain) {
@@ -2829,15 +3172,18 @@
// there is nothing more to do.
continue;
}
-
+
if (!Mod->isAvailable()) {
// Modules that aren't available cannot be made visible.
continue;
}
// Update the module's name visibility.
+ if (NameVisibility >= Module::MacrosVisible &&
+ Mod->NameVisibility < Module::MacrosVisible)
+ Mod->MacroVisibilityLoc = ImportLoc;
Mod->NameVisibility = NameVisibility;
-
+
// If we've already deserialized any names from this module,
// mark them as visible.
HiddenNamesMapType::iterator Hidden = HiddenNamesMap.find(Mod);
@@ -2899,6 +3245,17 @@
!hasGlobalIndex() && TriedLoadingGlobalIndex;
}
+static void updateModuleTimestamp(ModuleFile &MF) {
+ // Overwrite the timestamp file contents so that file's mtime changes.
+ std::string TimestampFilename = MF.getTimestampFilename();
+ std::string ErrorInfo;
+ llvm::raw_fd_ostream OS(TimestampFilename.c_str(), ErrorInfo,
+ llvm::sys::fs::F_Text);
+ if (!ErrorInfo.empty())
+ return;
+ OS << "Timestamp file\n";
+}
+
ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
ModuleKind Type,
SourceLocation ImportLoc,
@@ -3057,6 +3414,21 @@
PreviousGeneration);
}
+ if (PP.getHeaderSearchInfo()
+ .getHeaderSearchOpts()
+ .ModulesValidateOncePerBuildSession) {
+ // Now we are certain that the module and all modules it depends on are
+ // up to date. Create or update timestamp files for modules that are
+ // located in the module cache (not for PCH files that could be anywhere
+ // in the filesystem).
+ for (unsigned I = 0, N = Loaded.size(); I != N; ++I) {
+ ImportedModule &M = Loaded[I];
+ if (M.Mod->Kind == MK_Module) {
+ updateModuleTimestamp(*M.Mod);
+ }
+ }
+ }
+
return Success;
}
@@ -3177,7 +3549,7 @@
case AST_BLOCK_ID:
if (!HaveReadControlBlock) {
if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0)
- Diag(diag::warn_pch_version_too_old);
+ Diag(diag::err_pch_version_too_old);
return VersionMismatch;
}
@@ -3323,12 +3695,14 @@
Context.setcudaConfigureCallDecl(
cast<FunctionDecl>(GetDecl(CUDASpecialDeclRefs[0])));
}
-
+
// Re-export any modules that were imported by a non-module AST file.
- for (unsigned I = 0, N = ImportedModules.size(); I != N; ++I) {
- if (Module *Imported = getSubmodule(ImportedModules[I]))
+ // FIXME: This does not make macro-only imports visible again. It also doesn't
+ // make #includes mapped to module imports visible.
+ for (auto &Import : ImportedModules) {
+ if (Module *Imported = getSubmodule(Import.ID))
makeModuleVisible(Imported, Module::AllVisible,
- /*ImportLoc=*/SourceLocation(),
+ /*ImportLoc=*/Import.ImportLoc,
/*Complain=*/false);
}
ImportedModules.clear();
@@ -3381,7 +3755,7 @@
DiagnosticsEngine &Diags) {
// Open the AST file.
std::string ErrStr;
- OwningPtr<llvm::MemoryBuffer> Buffer;
+ std::unique_ptr<llvm::MemoryBuffer> Buffer;
Buffer.reset(FileMgr.getBufferForFile(ASTFileName, &ErrStr));
if (!Buffer) {
Diags.Report(diag::err_fe_unable_to_read_pch_file) << ASTFileName << ErrStr;
@@ -3448,17 +3822,17 @@
{
}
- virtual bool ReadLanguageOptions(const LangOptions &LangOpts,
- bool Complain) {
+ bool ReadLanguageOptions(const LangOptions &LangOpts,
+ bool Complain) override {
return checkLanguageOptions(ExistingLangOpts, LangOpts, 0);
}
- virtual bool ReadTargetOptions(const TargetOptions &TargetOpts,
- bool Complain) {
+ bool ReadTargetOptions(const TargetOptions &TargetOpts,
+ bool Complain) override {
return checkTargetOptions(ExistingTargetOpts, TargetOpts, 0);
}
- virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
- bool Complain,
- std::string &SuggestedPredefines) {
+ bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
+ bool Complain,
+ std::string &SuggestedPredefines) override {
return checkPreprocessorOptions(ExistingPPOpts, PPOpts, 0, FileMgr,
SuggestedPredefines, ExistingLangOpts);
}
@@ -3470,7 +3844,7 @@
ASTReaderListener &Listener) {
// Open the AST file.
std::string ErrStr;
- OwningPtr<llvm::MemoryBuffer> Buffer;
+ std::unique_ptr<llvm::MemoryBuffer> Buffer;
Buffer.reset(FileMgr.getBufferForFile(Filename, &ErrStr));
if (!Buffer) {
return true;
@@ -3496,6 +3870,7 @@
return true;
bool NeedsInputFiles = Listener.needsInputFileVisitation();
+ bool NeedsSystemInputFiles = Listener.needsSystemInputFileVisitation();
BitstreamCursor InputFilesCursor;
if (NeedsInputFiles) {
InputFilesCursor = Stream;
@@ -3582,6 +3957,10 @@
for (unsigned I = 0; I != NumInputFiles; ++I) {
// Go find this input file.
bool isSystemFile = I >= NumUserFiles;
+
+ if (isSystemFile && !NeedsSystemInputFiles)
+ break; // the rest are system input files
+
BitstreamCursor &Cursor = InputFilesCursor;
SavedStreamPosition SavedPosition(Cursor);
Cursor.JumpToBit(InputFileOffs[I]);
@@ -3592,7 +3971,8 @@
bool shouldContinue = false;
switch ((InputFileRecordTypes)Cursor.readRecord(Code, Record, &Blob)) {
case INPUT_FILE:
- shouldContinue = Listener.visitInputFile(Blob, isSystemFile);
+ bool Overridden = static_cast<bool>(Record[3]);
+ shouldContinue = Listener.visitInputFile(Blob, isSystemFile, Overridden);
break;
}
if (!shouldContinue)
@@ -3663,15 +4043,17 @@
}
StringRef Name = Blob;
- SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[0]);
- SubmoduleID Parent = getGlobalSubmoduleID(F, Record[1]);
- bool IsFramework = Record[2];
- bool IsExplicit = Record[3];
- bool IsSystem = Record[4];
- bool InferSubmodules = Record[5];
- bool InferExplicitSubmodules = Record[6];
- bool InferExportWildcard = Record[7];
- bool ConfigMacrosExhaustive = Record[8];
+ unsigned Idx = 0;
+ SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[Idx++]);
+ SubmoduleID Parent = getGlobalSubmoduleID(F, Record[Idx++]);
+ bool IsFramework = Record[Idx++];
+ bool IsExplicit = Record[Idx++];
+ bool IsSystem = Record[Idx++];
+ bool IsExternC = Record[Idx++];
+ bool InferSubmodules = Record[Idx++];
+ bool InferExplicitSubmodules = Record[Idx++];
+ bool InferExportWildcard = Record[Idx++];
+ bool ConfigMacrosExhaustive = Record[Idx++];
Module *ParentModule = 0;
if (Parent)
@@ -3707,6 +4089,7 @@
CurrentModule->IsFromModuleFile = true;
CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem;
+ CurrentModule->IsExternC = IsExternC;
CurrentModule->InferSubmodules = InferSubmodules;
CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules;
CurrentModule->InferExportWildcard = InferExportWildcard;
@@ -4004,7 +4387,6 @@
TargetOpts.Triple = ReadString(Record, Idx);
TargetOpts.CPU = ReadString(Record, Idx);
TargetOpts.ABI = ReadString(Record, Idx);
- TargetOpts.CXXABI = ReadString(Record, Idx);
TargetOpts.LinkerVersion = ReadString(Record, Idx);
for (unsigned N = Record[Idx++]; N; --N) {
TargetOpts.FeaturesAsWritten.push_back(ReadString(Record, Idx));
@@ -4068,6 +4450,7 @@
HSOpts.ResourceDir = ReadString(Record, Idx);
HSOpts.ModuleCachePath = ReadString(Record, Idx);
+ HSOpts.ModuleUserBuildPath = ReadString(Record, Idx);
HSOpts.DisableModuleHash = Record[Idx++];
HSOpts.UseBuiltinIncludes = Record[Idx++];
HSOpts.UseStandardSystemIncludes = Record[Idx++];
@@ -4548,6 +4931,16 @@
return DT;
}
+ case TYPE_ADJUSTED: {
+ if (Record.size() != 2) {
+ Error("Incorrect encoding of adjusted type");
+ return QualType();
+ }
+ QualType OriginalTy = readType(*Loc.F, Record, Idx);
+ QualType AdjustedTy = readType(*Loc.F, Record, Idx);
+ return Context.getAdjustedType(OriginalTy, AdjustedTy);
+ }
+
case TYPE_BLOCK_POINTER: {
if (Record.size() != 1) {
Error("Incorrect encoding of block pointer type");
@@ -4671,23 +5064,8 @@
EPI.HasTrailingReturn = Record[Idx++];
EPI.TypeQuals = Record[Idx++];
EPI.RefQualifier = static_cast<RefQualifierKind>(Record[Idx++]);
- ExceptionSpecificationType EST =
- static_cast<ExceptionSpecificationType>(Record[Idx++]);
- EPI.ExceptionSpecType = EST;
- SmallVector<QualType, 2> Exceptions;
- if (EST == EST_Dynamic) {
- EPI.NumExceptions = Record[Idx++];
- for (unsigned I = 0; I != EPI.NumExceptions; ++I)
- Exceptions.push_back(readType(*Loc.F, Record, Idx));
- EPI.Exceptions = Exceptions.data();
- } else if (EST == EST_ComputedNoexcept) {
- EPI.NoexceptExpr = ReadExpr(*Loc.F);
- } else if (EST == EST_Uninstantiated) {
- EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);
- EPI.ExceptionSpecTemplate = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);
- } else if (EST == EST_Unevaluated) {
- EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);
- }
+ SmallVector<QualType, 8> ExceptionStorage;
+ readExceptionSpec(*Loc.F, ExceptionStorage, EPI, Record, Idx);
return Context.getFunctionType(ResultType, ParamTypes, EPI);
}
@@ -4837,9 +5215,9 @@
unsigned Idx = 0;
QualType Parm = readType(*Loc.F, Record, Idx);
QualType Replacement = readType(*Loc.F, Record, Idx);
- return
- Context.getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm),
- Replacement);
+ return Context.getSubstTemplateTypeParmType(
+ cast<TemplateTypeParmType>(Parm),
+ Context.getCanonicalType(Replacement));
}
case TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK: {
@@ -4942,6 +5320,29 @@
llvm_unreachable("Invalid TypeCode!");
}
+void ASTReader::readExceptionSpec(ModuleFile &ModuleFile,
+ SmallVectorImpl<QualType> &Exceptions,
+ FunctionProtoType::ExtProtoInfo &EPI,
+ const RecordData &Record, unsigned &Idx) {
+ ExceptionSpecificationType EST =
+ static_cast<ExceptionSpecificationType>(Record[Idx++]);
+ EPI.ExceptionSpecType = EST;
+ if (EST == EST_Dynamic) {
+ EPI.NumExceptions = Record[Idx++];
+ for (unsigned I = 0; I != EPI.NumExceptions; ++I)
+ Exceptions.push_back(readType(ModuleFile, Record, Idx));
+ EPI.Exceptions = Exceptions.data();
+ } else if (EST == EST_ComputedNoexcept) {
+ EPI.NoexceptExpr = ReadExpr(ModuleFile);
+ } else if (EST == EST_Uninstantiated) {
+ EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx);
+ EPI.ExceptionSpecTemplate =
+ ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx);
+ } else if (EST == EST_Unevaluated) {
+ EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx);
+ }
+}
+
class clang::TypeLocReader : public TypeLocVisitor<TypeLocReader> {
ASTReader &Reader;
ModuleFile &F;
@@ -4997,6 +5398,9 @@
void TypeLocReader::VisitDecayedTypeLoc(DecayedTypeLoc TL) {
// nothing to do
}
+void TypeLocReader::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
+ // nothing to do
+}
void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
TL.setCaretLoc(ReadSourceLocation(Record, Idx));
}
@@ -5046,8 +5450,8 @@
TL.setLParenLoc(ReadSourceLocation(Record, Idx));
TL.setRParenLoc(ReadSourceLocation(Record, Idx));
TL.setLocalRangeEnd(ReadSourceLocation(Record, Idx));
- for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
- TL.setArg(i, ReadDeclAs<ParmVarDecl>(Record, Idx));
+ for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i) {
+ TL.setParam(i, ReadDeclAs<ParmVarDecl>(Record, Idx));
}
}
void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
@@ -5924,15 +6328,23 @@
ASTConsumer *Consumer) {
assert(ImplD && Consumer);
- for (ObjCImplDecl::method_iterator
- I = ImplD->meth_begin(), E = ImplD->meth_end(); I != E; ++I)
- Consumer->HandleInterestingDecl(DeclGroupRef(*I));
+ for (auto *I : ImplD->methods())
+ Consumer->HandleInterestingDecl(DeclGroupRef(I));
Consumer->HandleInterestingDecl(DeclGroupRef(ImplD));
}
void ASTReader::PassInterestingDeclsToConsumer() {
assert(Consumer);
+
+ if (PassingDeclsToConsumer)
+ return;
+
+ // Guard variable to avoid recursively redoing the process of passing
+ // decls to consumer.
+ SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer,
+ true);
+
while (!InterestingDecls.empty()) {
Decl *D = InterestingDecls.front();
InterestingDecls.pop_front();
@@ -5954,12 +6366,12 @@
if (!Consumer)
return;
- for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) {
+ for (unsigned I = 0, N = EagerlyDeserializedDecls.size(); I != N; ++I) {
// Force deserialization of this decl, which will cause it to be queued for
// passing to the consumer.
- GetDecl(ExternalDefinitions[I]);
+ GetDecl(EagerlyDeserializedDecls[I]);
}
- ExternalDefinitions.clear();
+ EagerlyDeserializedDecls.clear();
PassInterestingDeclsToConsumer();
}
@@ -6211,7 +6623,7 @@
public:
explicit ASTIdentifierIterator(const ASTReader &Reader);
- virtual StringRef Next();
+ StringRef Next() override;
};
}
@@ -7298,6 +7710,7 @@
I = CommentsCursors.begin(),
E = CommentsCursors.end();
I != E; ++I) {
+ Comments.clear();
BitstreamCursor &Cursor = I->first;
serialization::ModuleFile &F = *I->second;
SavedStreamPosition SavedPosition(Cursor);
@@ -7306,7 +7719,7 @@
while (true) {
llvm::BitstreamEntry Entry =
Cursor.advanceSkippingSubblocks(BitstreamCursor::AF_DontPopBlockAtEnd);
-
+
switch (Entry.Kind) {
case llvm::BitstreamEntry::SubBlock: // Handled for us already.
case llvm::BitstreamEntry::Error:
@@ -7336,9 +7749,9 @@
}
}
}
- NextCursor:;
+ NextCursor:
+ Context.Comments.addDeserializedComments(Comments);
}
- Context.Comments.addCommentsToFront(Comments);
}
void ASTReader::finishPendingActions() {
@@ -7352,14 +7765,14 @@
TopLevelDeclsMap TopLevelDecls;
while (!PendingIdentifierInfos.empty()) {
- // FIXME: std::move
IdentifierInfo *II = PendingIdentifierInfos.back().first;
- SmallVector<uint32_t, 4> DeclIDs = PendingIdentifierInfos.back().second;
+ SmallVector<uint32_t, 4> DeclIDs =
+ std::move(PendingIdentifierInfos.back().second);
PendingIdentifierInfos.pop_back();
SetGloballyVisibleDecls(II, DeclIDs, &TopLevelDecls[II]);
}
-
+
// Load pending declaration chains.
for (unsigned I = 0; I != PendingDeclChains.size(); ++I) {
loadPendingDeclChain(PendingDeclChains[I]);
@@ -7382,14 +7795,14 @@
SmallVector<PendingMacroInfo, 2> GlobalIDs;
GlobalIDs.swap(PendingMacroIDs.begin()[I].second);
// Initialize the macro history from chained-PCHs ahead of module imports.
- for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs;
+ for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs;
++IDIdx) {
const PendingMacroInfo &Info = GlobalIDs[IDIdx];
if (Info.M->Kind != MK_Module)
resolvePendingMacro(II, Info);
}
// Handle module imports.
- for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs;
+ for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs;
++IDIdx) {
const PendingMacroInfo &Info = GlobalIDs[IDIdx];
if (Info.M->Kind == MK_Module)
@@ -7430,16 +7843,14 @@
llvm::SmallVector<const NamedDecl*, 4> Candidates;
for (DeclContext::lookup_iterator I = R.begin(), E = R.end();
!Found && I != E; ++I) {
- for (Decl::redecl_iterator RI = (*I)->redecls_begin(),
- RE = (*I)->redecls_end();
- RI != RE; ++RI) {
- if ((*RI)->getLexicalDeclContext() == CanonDef) {
+ for (auto RI : (*I)->redecls()) {
+ if (RI->getLexicalDeclContext() == CanonDef) {
// This declaration is present in the canonical definition. If it's
// in the same redecl chain, it's the one we're looking for.
- if ((*RI)->getCanonicalDecl() == DCanon)
+ if (RI->getCanonicalDecl() == DCanon)
Found = true;
else
- Candidates.push_back(cast<NamedDecl>(*RI));
+ Candidates.push_back(cast<NamedDecl>(RI));
break;
}
}
@@ -7480,44 +7891,35 @@
const_cast<TagType*>(TagT)->decl = TD;
}
- if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(*D)) {
- for (CXXRecordDecl::redecl_iterator R = RD->redecls_begin(),
- REnd = RD->redecls_end();
- R != REnd; ++R)
- cast<CXXRecordDecl>(*R)->DefinitionData = RD->DefinitionData;
+ if (auto RD = dyn_cast<CXXRecordDecl>(*D)) {
+ for (auto R : RD->redecls())
+ cast<CXXRecordDecl>(R)->DefinitionData = RD->DefinitionData;
}
continue;
}
- if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(*D)) {
+ if (auto ID = dyn_cast<ObjCInterfaceDecl>(*D)) {
// Make sure that the ObjCInterfaceType points at the definition.
const_cast<ObjCInterfaceType *>(cast<ObjCInterfaceType>(ID->TypeForDecl))
->Decl = ID;
- for (ObjCInterfaceDecl::redecl_iterator R = ID->redecls_begin(),
- REnd = ID->redecls_end();
- R != REnd; ++R)
+ for (auto R : ID->redecls())
R->Data = ID->Data;
continue;
}
- if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(*D)) {
- for (ObjCProtocolDecl::redecl_iterator R = PD->redecls_begin(),
- REnd = PD->redecls_end();
- R != REnd; ++R)
+ if (auto PD = dyn_cast<ObjCProtocolDecl>(*D)) {
+ for (auto R : PD->redecls())
R->Data = PD->Data;
continue;
}
- RedeclarableTemplateDecl *RTD
- = cast<RedeclarableTemplateDecl>(*D)->getCanonicalDecl();
- for (RedeclarableTemplateDecl::redecl_iterator R = RTD->redecls_begin(),
- REnd = RTD->redecls_end();
- R != REnd; ++R)
+ auto RTD = cast<RedeclarableTemplateDecl>(*D)->getCanonicalDecl();
+ for (auto R : RTD->redecls())
R->Common = RTD->Common;
}
PendingDefinitions.clear();
@@ -7553,20 +7955,10 @@
}
--NumCurrentElementsDeserializing;
- if (NumCurrentElementsDeserializing == 0 &&
- Consumer && !PassingDeclsToConsumer) {
- // Guard variable to avoid recursively redoing the process of passing
- // decls to consumer.
- SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer,
- true);
-
- while (!InterestingDecls.empty()) {
- // We are not in recursive loading, so it's safe to pass the "interesting"
- // decls to the consumer.
- Decl *D = InterestingDecls.front();
- InterestingDecls.pop_front();
- PassInterestingDeclToConsumer(D);
- }
+ if (NumCurrentElementsDeserializing == 0 && Consumer) {
+ // We are not in recursive loading, so it's safe to pass the "interesting"
+ // decls to the consumer.
+ PassInterestingDeclsToConsumer();
}
}
@@ -7587,13 +7979,18 @@
ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context,
StringRef isysroot, bool DisableValidation,
- bool AllowASTWithCompilerErrors, bool UseGlobalIndex)
+ bool AllowASTWithCompilerErrors,
+ bool AllowConfigurationMismatch,
+ bool ValidateSystemInputs,
+ bool UseGlobalIndex)
: Listener(new PCHValidator(PP, *this)), DeserializationListener(0),
SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
Diags(PP.getDiagnostics()), SemaObj(0), PP(PP), Context(Context),
Consumer(0), ModuleMgr(PP.getFileManager()),
isysroot(isysroot), DisableValidation(DisableValidation),
AllowASTWithCompilerErrors(AllowASTWithCompilerErrors),
+ AllowConfigurationMismatch(AllowConfigurationMismatch),
+ ValidateSystemInputs(ValidateSystemInputs),
UseGlobalIndex(UseGlobalIndex), TriedLoadingGlobalIndex(false),
CurrentGeneration(0), CurrSwitchCaseStmts(&SwitchCaseStmts),
NumSLocEntriesRead(0), TotalNumSLocEntries(0),
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index b8102d8..7d95072 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -356,11 +356,14 @@
}
void ASTDeclReader::VisitDecl(Decl *D) {
- if (D->isTemplateParameter()) {
+ if (D->isTemplateParameter() || D->isTemplateParameterPack() ||
+ isa<ParmVarDecl>(D)) {
// We don't want to deserialize the DeclContext of a template
- // parameter immediately, because the template parameter might be
- // used in the formulation of its DeclContext. Use the translation
- // unit DeclContext as a placeholder.
+ // parameter or of a parameter of a function template immediately. These
+ // entities might be used in the formulation of its DeclContext (for
+ // example, a function parameter can be used in decltype() in trailing
+ // return type of the function). Use the translation unit DeclContext as a
+ // placeholder.
GlobalDeclID SemaDCIDForTemplateParmDecl = ReadDeclID(Record, Idx);
GlobalDeclID LexicalDCIDForTemplateParmDecl = ReadDeclID(Record, Idx);
Reader.addPendingDeclContextInfo(D,
@@ -409,7 +412,7 @@
// Note that this declaration was hidden because its owning module is
// not yet visible.
- Reader.HiddenNamesMap[Owner].push_back(D);
+ Reader.HiddenNamesMap[Owner].HiddenDecls.push_back(D);
}
}
}
@@ -709,8 +712,8 @@
MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]);
MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
MD->SetRelatedResultType(Record[Idx++]);
- MD->setResultType(Reader.readType(F, Record, Idx));
- MD->setResultTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
+ MD->setReturnType(Reader.readType(F, Record, Idx));
+ MD->setReturnTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
MD->DeclEndLoc = ReadSourceLocation(Record, Idx);
unsigned NumParams = Record[Idx++];
SmallVector<ParmVarDecl *, 16> Params;
@@ -755,6 +758,7 @@
Data.SuperClassLoc = ReadSourceLocation(Record, Idx);
Data.EndLoc = ReadSourceLocation(Record, Idx);
+ Data.HasDesignatedInitializers = Record[Idx++];
// Read the directly referenced protocols and their SourceLocations.
unsigned NumProtocols = Record[Idx++];
@@ -798,8 +802,6 @@
IVD->setNextIvar(0);
bool synth = Record[Idx++];
IVD->setSynthesize(synth);
- bool backingIvarReferencedInAccessor = Record[Idx++];
- IVD->setBackingIvarReferencedInAccessor(backingIvarReferencedInAccessor);
}
void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
@@ -907,8 +909,8 @@
D->setIvarRBraceLoc(ReadSourceLocation(Record, Idx));
D->setHasNonZeroConstructors(Record[Idx++]);
D->setHasDestructors(Record[Idx++]);
- llvm::tie(D->IvarInitializers, D->NumIvarInitializers)
- = Reader.ReadCXXCtorInitializers(F, Record, Idx);
+ std::tie(D->IvarInitializers, D->NumIvarInitializers) =
+ Reader.ReadCXXCtorInitializers(F, Record, Idx);
}
@@ -971,7 +973,7 @@
VD->setCachedLinkage(VarLinkage);
// Reconstruct the one piece of the IdentifierNamespace that we need.
- if (VarLinkage != NoLinkage &&
+ if (VD->getStorageClass() == SC_Extern && VarLinkage != NoLinkage &&
VD->getLexicalDeclContext()->isFunctionOrMethod())
VD->setLocalExternDecl();
@@ -1186,6 +1188,7 @@
Data.HasProtectedFields = Record[Idx++];
Data.HasPublicFields = Record[Idx++];
Data.HasMutableFields = Record[Idx++];
+ Data.HasVariantMembers = Record[Idx++];
Data.HasOnlyCMembers = Record[Idx++];
Data.HasInClassInitializer = Record[Idx++];
Data.HasUninitializedReferenceMember = Record[Idx++];
@@ -1345,10 +1348,12 @@
void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
VisitCXXMethodDecl(D);
-
+
+ if (auto *CD = ReadDeclAs<CXXConstructorDecl>(Record, Idx))
+ D->setInheritedConstructor(CD);
D->IsExplicitSpecified = Record[Idx++];
- llvm::tie(D->CtorInitializers, D->NumCtorInitializers)
- = Reader.ReadCXXCtorInitializers(F, Record, Idx);
+ std::tie(D->CtorInitializers, D->NumCtorInitializers) =
+ Reader.ReadCXXCtorInitializers(F, Record, Idx);
}
void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
@@ -1981,7 +1986,8 @@
if (isa<FileScopeAsmDecl>(D) ||
isa<ObjCProtocolDecl>(D) ||
- isa<ObjCImplDecl>(D))
+ isa<ObjCImplDecl>(D) ||
+ isa<ImportDecl>(D))
return true;
if (VarDecl *Var = dyn_cast<VarDecl>(D))
return Var->isFileVarDecl() &&
@@ -2605,12 +2611,10 @@
// There are updates. This means the context has external visible
// storage, even if the original stored version didn't.
LookupDC->setHasExternalVisibleStorage(true);
- DeclContextVisibleUpdates &U = I->second;
- for (DeclContextVisibleUpdates::iterator UI = U.begin(), UE = U.end();
- UI != UE; ++UI) {
- DeclContextInfo &Info = UI->second->DeclContextInfos[DC];
+ for (const auto &Update : I->second) {
+ DeclContextInfo &Info = Update.second->DeclContextInfos[DC];
delete Info.NameLookupTableData;
- Info.NameLookupTableData = UI->first;
+ Info.NameLookupTableData = Update.first;
}
PendingVisibleUpdates.erase(I);
}
@@ -2642,6 +2646,7 @@
DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID);
if (UpdI != DeclUpdateOffsets.end()) {
FileOffsetsTy &UpdateOffsets = UpdI->second;
+ bool WasInteresting = isConsumerInterestedIn(D, false);
for (FileOffsetsTy::iterator
I = UpdateOffsets.begin(), E = UpdateOffsets.end(); I != E; ++I) {
ModuleFile *F = I->first;
@@ -2654,33 +2659,23 @@
unsigned RecCode = Cursor.readRecord(Code, Record);
(void)RecCode;
assert(RecCode == DECL_UPDATES && "Expected DECL_UPDATES record!");
-
+
unsigned Idx = 0;
ASTDeclReader Reader(*this, *F, ID, 0, Record, Idx);
Reader.UpdateDecl(D, *F, Record);
+
+ // We might have made this declaration interesting. If so, remember that
+ // we need to hand it off to the consumer.
+ if (!WasInteresting &&
+ isConsumerInterestedIn(D, Reader.hasPendingBody())) {
+ InterestingDecls.push_back(D);
+ WasInteresting = true;
+ }
}
}
}
namespace {
- struct CompareLocalRedeclarationsInfoToID {
- bool operator()(const LocalRedeclarationsInfo &X, DeclID Y) {
- return X.FirstID < Y;
- }
-
- bool operator()(DeclID X, const LocalRedeclarationsInfo &Y) {
- return X < Y.FirstID;
- }
-
- bool operator()(const LocalRedeclarationsInfo &X,
- const LocalRedeclarationsInfo &Y) {
- return X.FirstID < Y.FirstID;
- }
- bool operator()(DeclID X, DeclID Y) {
- return X < Y;
- }
- };
-
/// \brief Module visitor class that finds all of the redeclarations of a
///
class RedeclChainVisitor {
@@ -2724,10 +2719,11 @@
// Perform a binary search to find the local redeclarations for this
// declaration (if any).
+ const LocalRedeclarationsInfo Compare = { ID, 0 };
const LocalRedeclarationsInfo *Result
= std::lower_bound(M.RedeclarationsMap,
M.RedeclarationsMap + M.LocalNumRedeclarationsInMap,
- ID, CompareLocalRedeclarationsInfoToID());
+ Compare);
if (Result == M.RedeclarationsMap + M.LocalNumRedeclarationsInMap ||
Result->FirstID != ID) {
// If we have a previously-canonical singleton declaration that was
@@ -2802,24 +2798,6 @@
}
namespace {
- struct CompareObjCCategoriesInfo {
- bool operator()(const ObjCCategoriesInfo &X, DeclID Y) {
- return X.DefinitionID < Y;
- }
-
- bool operator()(DeclID X, const ObjCCategoriesInfo &Y) {
- return X < Y.DefinitionID;
- }
-
- bool operator()(const ObjCCategoriesInfo &X,
- const ObjCCategoriesInfo &Y) {
- return X.DefinitionID < Y.DefinitionID;
- }
- bool operator()(DeclID X, DeclID Y) {
- return X < Y;
- }
- };
-
/// \brief Given an ObjC interface, goes through the modules and links to the
/// interface all the categories for it.
class ObjCCategoriesVisitor {
@@ -2881,15 +2859,12 @@
Tail(0)
{
// Populate the name -> category map with the set of known categories.
- for (ObjCInterfaceDecl::known_categories_iterator
- Cat = Interface->known_categories_begin(),
- CatEnd = Interface->known_categories_end();
- Cat != CatEnd; ++Cat) {
+ for (auto *Cat : Interface->known_categories()) {
if (Cat->getDeclName())
- NameCategoryMap[Cat->getDeclName()] = *Cat;
+ NameCategoryMap[Cat->getDeclName()] = Cat;
// Keep track of the tail of the category list.
- Tail = *Cat;
+ Tail = Cat;
}
}
@@ -2912,10 +2887,11 @@
// Perform a binary search to find the local redeclarations for this
// declaration (if any).
+ const ObjCCategoriesInfo Compare = { LocalID, 0 };
const ObjCCategoriesInfo *Result
= std::lower_bound(M.ObjCCategoriesMap,
M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap,
- LocalID, CompareObjCCategoriesInfo());
+ Compare);
if (Result == M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap ||
Result->DefinitionID != LocalID) {
// We didn't find anything. If the class definition is in this module
@@ -2979,6 +2955,36 @@
Reader.ReadSourceLocation(ModuleFile, Record, Idx));
break;
+ case UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION: {
+ FunctionDecl *FD = cast<FunctionDecl>(D);
+ if (Reader.PendingBodies[FD])
+ // FIXME: Maybe check for ODR violations.
+ break;
+
+ if (Record[Idx++])
+ FD->setImplicitlyInline();
+ FD->setInnerLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
+ if (auto *CD = dyn_cast<CXXConstructorDecl>(FD))
+ std::tie(CD->CtorInitializers, CD->NumCtorInitializers) =
+ Reader.ReadCXXCtorInitializers(ModuleFile, Record, Idx);
+ // Store the offset of the body so we can lazily load it later.
+ Reader.PendingBodies[FD] = GetCurrentCursorOffset();
+ HasPendingBody = true;
+ assert(Idx == Record.size() && "lazy body must be last");
+ break;
+ }
+
+ case UPD_CXX_RESOLVED_EXCEPTION_SPEC: {
+ auto *FD = cast<FunctionDecl>(D);
+ auto *FPT = FD->getType()->castAs<FunctionProtoType>();
+ auto EPI = FPT->getExtProtoInfo();
+ SmallVector<QualType, 8> ExceptionStorage;
+ Reader.readExceptionSpec(ModuleFile, ExceptionStorage, EPI, Record, Idx);
+ FD->setType(Reader.Context.getFunctionType(FPT->getReturnType(),
+ FPT->getParamTypes(), EPI));
+ break;
+ }
+
case UPD_CXX_DEDUCED_RETURN_TYPE: {
FunctionDecl *FD = cast<FunctionDecl>(D);
Reader.Context.adjustDeducedFunctionResultType(
@@ -2992,6 +2998,14 @@
D->Used = true;
break;
}
+
+ case UPD_MANGLING_NUMBER:
+ Reader.Context.setManglingNumber(cast<NamedDecl>(D), Record[Idx++]);
+ break;
+
+ case UPD_STATIC_LOCAL_NUMBER:
+ Reader.Context.setStaticLocalNumber(cast<VarDecl>(D), Record[Idx++]);
+ break;
}
}
}
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index 1115e8f..9a201d0 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -399,13 +399,11 @@
S->getCapturedDecl()->setBody(S->getCapturedStmt());
// Captures
- for (CapturedStmt::capture_iterator I = S->capture_begin(),
- E = S->capture_end();
- I != E; ++I) {
- I->VarAndKind.setPointer(ReadDeclAs<VarDecl>(Record, Idx));
- I->VarAndKind
+ for (auto &I : S->captures()) {
+ I.VarAndKind.setPointer(ReadDeclAs<VarDecl>(Record, Idx));
+ I.VarAndKind
.setInt(static_cast<CapturedStmt::VariableCaptureKind>(Record[Idx++]));
- I->Loc = ReadSourceLocation(Record, Idx);
+ I.Loc = ReadSourceLocation(Record, Idx);
}
}
@@ -1484,33 +1482,15 @@
E->NamingClass = ReadDeclAs<CXXRecordDecl>(Record, Idx);
}
-void ASTStmtReader::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
- VisitExpr(E);
- E->UTT = (UnaryTypeTrait)Record[Idx++];
- E->Value = (bool)Record[Idx++];
- SourceRange Range = ReadSourceRange(Record, Idx);
- E->Loc = Range.getBegin();
- E->RParen = Range.getEnd();
- E->QueriedType = GetTypeSourceInfo(Record, Idx);
-}
-
-void ASTStmtReader::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
- VisitExpr(E);
- E->BTT = (BinaryTypeTrait)Record[Idx++];
- E->Value = (bool)Record[Idx++];
- SourceRange Range = ReadSourceRange(Record, Idx);
- E->Loc = Range.getBegin();
- E->RParen = Range.getEnd();
- E->LhsType = GetTypeSourceInfo(Record, Idx);
- E->RhsType = GetTypeSourceInfo(Record, Idx);
-}
-
void ASTStmtReader::VisitTypeTraitExpr(TypeTraitExpr *E) {
VisitExpr(E);
E->TypeTraitExprBits.NumArgs = Record[Idx++];
E->TypeTraitExprBits.Kind = Record[Idx++];
E->TypeTraitExprBits.Value = Record[Idx++];
-
+ SourceRange Range = ReadSourceRange(Record, Idx);
+ E->Loc = Range.getBegin();
+ E->RParenLoc = Range.getEnd();
+
TypeSourceInfo **Args = E->getTypeSourceInfos();
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
Args[I] = GetTypeSourceInfo(Record, Idx);
@@ -1691,6 +1671,15 @@
OMPClause *OMPClauseReader::readClause() {
OMPClause *C;
switch (Record[Idx++]) {
+ case OMPC_if:
+ C = new (Context) OMPIfClause();
+ break;
+ case OMPC_num_threads:
+ C = new (Context) OMPNumThreadsClause();
+ break;
+ case OMPC_safelen:
+ C = new (Context) OMPSafelenClause();
+ break;
case OMPC_default:
C = new (Context) OMPDefaultClause();
break;
@@ -1703,6 +1692,9 @@
case OMPC_shared:
C = OMPSharedClause::CreateEmpty(Context, Record[Idx++]);
break;
+ case OMPC_copyin:
+ C = OMPCopyinClause::CreateEmpty(Context, Record[Idx++]);
+ break;
}
Visit(C);
C->setLocStart(Reader->ReadSourceLocation(Record, Idx));
@@ -1711,6 +1703,21 @@
return C;
}
+void OMPClauseReader::VisitOMPIfClause(OMPIfClause *C) {
+ C->setCondition(Reader->Reader.ReadSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+}
+
+void OMPClauseReader::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
+ C->setNumThreads(Reader->Reader.ReadSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+}
+
+void OMPClauseReader::VisitOMPSafelenClause(OMPSafelenClause *C) {
+ C->setSafelen(Reader->Reader.ReadSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+}
+
void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) {
C->setDefaultKind(
static_cast<OpenMPDefaultClauseKind>(Record[Idx++]));
@@ -1748,12 +1755,20 @@
C->setVarRefs(Vars);
}
+void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *C) {
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setVarRefs(Vars);
+}
+
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
- VisitStmt(E);
- ++Idx;
E->setLocStart(ReadSourceLocation(Record, Idx));
E->setLocEnd(ReadSourceLocation(Record, Idx));
OMPClauseReader ClauseReader(this, Reader.getContext(), Record, Idx);
@@ -1765,6 +1780,16 @@
}
void ASTStmtReader::VisitOMPParallelDirective(OMPParallelDirective *D) {
+ VisitStmt(D);
+ // The NumClauses field was read in ReadStmtFromStream.
+ ++Idx;
+ VisitOMPExecutableDirective(D);
+}
+
+void ASTStmtReader::VisitOMPSimdDirective(OMPSimdDirective *D) {
+ VisitStmt(D);
+ // Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream.
+ Idx += 2;
VisitOMPExecutableDirective(D);
}
@@ -2240,13 +2265,22 @@
DeclarationNameInfo(),
0);
break;
+
case STMT_OMP_PARALLEL_DIRECTIVE:
S =
OMPParallelDirective::CreateEmpty(Context,
Record[ASTStmtReader::NumStmtFields],
Empty);
break;
-
+
+ case STMT_OMP_SIMD_DIRECTIVE: {
+ unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
+ unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+ S = OMPSimdDirective::CreateEmpty(Context, NumClauses,
+ CollapsedNum, Empty);
+ break;
+ }
+
case EXPR_CXX_OPERATOR_CALL:
S = new (Context) CXXOperatorCallExpr(Context, Empty);
break;
@@ -2254,11 +2288,11 @@
case EXPR_CXX_MEMBER_CALL:
S = new (Context) CXXMemberCallExpr(Context, Empty);
break;
-
+
case EXPR_CXX_CONSTRUCT:
S = new (Context) CXXConstructExpr(Empty);
break;
-
+
case EXPR_CXX_TEMPORARY_OBJECT:
S = new (Context) CXXTemporaryObjectExpr(Empty);
break;
@@ -2393,14 +2427,6 @@
? Record[ASTStmtReader::NumExprFields + 1]
: 0);
break;
-
- case EXPR_CXX_UNARY_TYPE_TRAIT:
- S = new (Context) UnaryTypeTraitExpr(Empty);
- break;
-
- case EXPR_BINARY_TYPE_TRAIT:
- S = new (Context) BinaryTypeTraitExpr(Empty);
- break;
case EXPR_TYPE_TRAIT:
S = TypeTraitExpr::CreateDeserialized(Context,
@@ -2491,7 +2517,7 @@
StmtStack.push_back(S);
}
Done:
- assert(StmtStack.size() > PrevNumStmts && "Read too many sub stmts!");
+ assert(StmtStack.size() > PrevNumStmts && "Read too many sub-stmts!");
assert(StmtStack.size() == PrevNumStmts + 1 && "Extra expressions on stack!");
return StmtStack.pop_back_val();
}
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 405488c..e4b5cdb 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclLookups.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
@@ -45,6 +46,7 @@
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/Support/EndianStream.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
@@ -113,6 +115,12 @@
Code = TYPE_DECAYED;
}
+void ASTTypeWriter::VisitAdjustedType(const AdjustedType *T) {
+ Writer.AddTypeRef(T->getOriginalType(), Record);
+ Writer.AddTypeRef(T->getAdjustedType(), Record);
+ Code = TYPE_ADJUSTED;
+}
+
void ASTTypeWriter::VisitBlockPointerType(const BlockPointerType *T) {
Writer.AddTypeRef(T->getPointeeType(), Record);
Code = TYPE_BLOCK_POINTER;
@@ -173,7 +181,7 @@
}
void ASTTypeWriter::VisitFunctionType(const FunctionType *T) {
- Writer.AddTypeRef(T->getResultType(), Record);
+ Writer.AddTypeRef(T->getReturnType(), Record);
FunctionType::ExtInfo C = T->getExtInfo();
Record.push_back(C.getNoReturn());
Record.push_back(C.getHasRegParm());
@@ -188,15 +196,8 @@
Code = TYPE_FUNCTION_NO_PROTO;
}
-void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
- VisitFunctionType(T);
- Record.push_back(T->getNumArgs());
- for (unsigned I = 0, N = T->getNumArgs(); I != N; ++I)
- Writer.AddTypeRef(T->getArgType(I), Record);
- Record.push_back(T->isVariadic());
- Record.push_back(T->hasTrailingReturn());
- Record.push_back(T->getTypeQuals());
- Record.push_back(static_cast<unsigned>(T->getRefQualifier()));
+static void addExceptionSpec(ASTWriter &Writer, const FunctionProtoType *T,
+ ASTWriter::RecordDataImpl &Record) {
Record.push_back(T->getExceptionSpecType());
if (T->getExceptionSpecType() == EST_Dynamic) {
Record.push_back(T->getNumExceptions());
@@ -210,6 +211,18 @@
} else if (T->getExceptionSpecType() == EST_Unevaluated) {
Writer.AddDeclRef(T->getExceptionSpecDecl(), Record);
}
+}
+
+void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
+ VisitFunctionType(T);
+ Record.push_back(T->getNumParams());
+ for (unsigned I = 0, N = T->getNumParams(); I != N; ++I)
+ Writer.AddTypeRef(T->getParamType(I), Record);
+ Record.push_back(T->isVariadic());
+ Record.push_back(T->hasTrailingReturn());
+ Record.push_back(T->getTypeQuals());
+ Record.push_back(static_cast<unsigned>(T->getRefQualifier()));
+ addExceptionSpec(Writer, T, Record);
Code = TYPE_FUNCTION_PROTO;
}
@@ -395,9 +408,8 @@
void ASTTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) {
Writer.AddTypeRef(T->getBaseType(), Record);
Record.push_back(T->getNumProtocols());
- for (ObjCObjectType::qual_iterator I = T->qual_begin(),
- E = T->qual_end(); I != E; ++I)
- Writer.AddDeclRef(*I, Record);
+ for (const auto *I : T->quals())
+ Writer.AddDeclRef(I, Record);
Code = TYPE_OBJC_OBJECT;
}
@@ -455,6 +467,9 @@
void TypeLocWriter::VisitDecayedTypeLoc(DecayedTypeLoc TL) {
// nothing to do
}
+void TypeLocWriter::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
+ // nothing to do
+}
void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
Writer.AddSourceLocation(TL.getCaretLoc(), Record);
}
@@ -503,8 +518,8 @@
Writer.AddSourceLocation(TL.getLParenLoc(), Record);
Writer.AddSourceLocation(TL.getRParenLoc(), Record);
Writer.AddSourceLocation(TL.getLocalRangeEnd(), Record);
- for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
- Writer.AddDeclRef(TL.getArg(i), Record);
+ for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i)
+ Writer.AddDeclRef(TL.getParam(i), Record);
}
void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
VisitFunctionTypeLoc(TL);
@@ -764,10 +779,8 @@
RECORD(EXPR_CXX_UNRESOLVED_CONSTRUCT);
RECORD(EXPR_CXX_UNRESOLVED_MEMBER);
RECORD(EXPR_CXX_UNRESOLVED_LOOKUP);
- RECORD(EXPR_CXX_UNARY_TYPE_TRAIT);
RECORD(EXPR_CXX_NOEXCEPT);
RECORD(EXPR_OPAQUE_VALUE);
- RECORD(EXPR_BINARY_TYPE_TRAIT);
RECORD(EXPR_PACK_EXPANSION);
RECORD(EXPR_SIZEOF_PACK);
RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK);
@@ -806,7 +819,7 @@
RECORD(DECL_OFFSET);
RECORD(IDENTIFIER_OFFSET);
RECORD(IDENTIFIER_TABLE);
- RECORD(EXTERNAL_DEFINITIONS);
+ RECORD(EAGERLY_DESERIALIZED_DECLS);
RECORD(SPECIAL_TYPES);
RECORD(STATISTICS);
RECORD(TENTATIVE_DEFINITIONS);
@@ -1040,7 +1053,6 @@
// Imports
if (Chain) {
serialization::ModuleManager &Mgr = Chain->getModuleManager();
- SmallVector<char, 128> ModulePaths;
Record.clear();
for (ModuleManager::ModuleIterator M = Mgr.begin(), MEnd = Mgr.end();
@@ -1097,7 +1109,6 @@
AddString(TargetOpts.Triple, Record);
AddString(TargetOpts.CPU, Record);
AddString(TargetOpts.ABI, Record);
- AddString(TargetOpts.CXXABI, Record);
AddString(TargetOpts.LinkerVersion, Record);
Record.push_back(TargetOpts.FeaturesAsWritten.size());
for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size(); I != N; ++I) {
@@ -1156,6 +1167,7 @@
AddString(HSOpts.ResourceDir, Record);
AddString(HSOpts.ModuleCachePath, Record);
+ AddString(HSOpts.ModuleUserBuildPath, Record);
Record.push_back(HSOpts.DisableModuleHash);
Record.push_back(HSOpts.UseBuiltinIncludes);
Record.push_back(HSOpts.UseStandardSystemIncludes);
@@ -1294,33 +1306,6 @@
SortedFiles.push_front(Entry);
}
- // If we have an isysroot for a Darwin SDK, include its SDKSettings.plist in
- // the set of (non-system) input files. This is simple heuristic for
- // detecting whether the system headers may have changed, because it is too
- // expensive to stat() all of the system headers.
- FileManager &FileMgr = SourceMgr.getFileManager();
- if (!HSOpts.Sysroot.empty() && !Chain) {
- llvm::SmallString<128> SDKSettingsFileName(HSOpts.Sysroot);
- llvm::sys::path::append(SDKSettingsFileName, "SDKSettings.plist");
- if (const FileEntry *SDKSettingsFile = FileMgr.getFile(SDKSettingsFileName)) {
- InputFileEntry Entry = { SDKSettingsFile, false, false };
- SortedFiles.push_front(Entry);
- }
- }
-
- // Add the compiler's own module.map in the set of (non-system) input files.
- // This is a simple heuristic for detecting whether the compiler's headers
- // have changed, because we don't want to stat() all of them.
- if (Modules && !Chain) {
- SmallString<128> P = StringRef(HSOpts.ResourceDir);
- llvm::sys::path::append(P, "include");
- llvm::sys::path::append(P, "module.map");
- if (const FileEntry *ModuleMapFile = FileMgr.getFile(P)) {
- InputFileEntry Entry = { ModuleMapFile, false, false };
- SortedFiles.push_front(Entry);
- }
- }
-
unsigned UserFilesNum = 0;
// Write out all of the input files.
std::vector<uint32_t> InputFileOffsets;
@@ -1357,7 +1342,7 @@
// Ask the file manager to fixup the relative path for us. This will
// honor the working directory.
- FileMgr.FixupRelativePath(FilePath);
+ SourceMgr.getFileManager().FixupRelativePath(FilePath);
// FIXME: This call to make_absolute shouldn't be necessary, the
// call to FixupRelativePath should always return an absolute path.
@@ -1481,26 +1466,31 @@
std::pair<unsigned,unsigned>
EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) {
+ using namespace llvm::support;
+ endian::Writer<little> Writer(Out);
unsigned KeyLen = strlen(key.Filename) + 1 + 8 + 8;
- clang::io::Emit16(Out, KeyLen);
+ Writer.write<uint16_t>(KeyLen);
unsigned DataLen = 1 + 2 + 4 + 4;
if (Data.isModuleHeader)
DataLen += 4;
- clang::io::Emit8(Out, DataLen);
+ Writer.write<uint8_t>(DataLen);
return std::make_pair(KeyLen, DataLen);
}
void EmitKey(raw_ostream& Out, key_type_ref key, unsigned KeyLen) {
- clang::io::Emit64(Out, key.FE->getSize());
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
+ LE.write<uint64_t>(key.FE->getSize());
KeyLen -= 8;
- clang::io::Emit64(Out, key.FE->getModificationTime());
+ LE.write<uint64_t>(key.FE->getModificationTime());
KeyLen -= 8;
Out.write(key.Filename, KeyLen);
}
void EmitData(raw_ostream &Out, key_type_ref key,
data_type_ref Data, unsigned DataLen) {
- using namespace clang::io;
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
uint64_t Start = Out.tell(); (void)Start;
unsigned char Flags = (Data.HeaderRole << 6)
@@ -1509,13 +1499,13 @@
| (Data.DirInfo << 2)
| (Data.Resolved << 1)
| Data.IndexHeaderMapHeader;
- Emit8(Out, (uint8_t)Flags);
- Emit16(Out, (uint16_t) Data.NumIncludes);
+ LE.write<uint8_t>(Flags);
+ LE.write<uint16_t>(Data.NumIncludes);
if (!Data.ControllingMacro)
- Emit32(Out, (uint32_t)Data.ControllingMacroID);
+ LE.write<uint32_t>(Data.ControllingMacroID);
else
- Emit32(Out, (uint32_t)Writer.getIdentifierRef(Data.ControllingMacro));
+ LE.write<uint32_t>(Writer.getIdentifierRef(Data.ControllingMacro));
unsigned Offset = 0;
if (!Data.Framework.empty()) {
@@ -1532,11 +1522,11 @@
} else
Offset = Pos->second;
}
- Emit32(Out, Offset);
+ LE.write<uint32_t>(Offset);
if (Data.isModuleHeader) {
Module *Mod = HS.findModuleForHeader(key.FE).getModule();
- Emit32(Out, Writer.getExistingSubmoduleID(Mod));
+ LE.write<uint32_t>(Writer.getExistingSubmoduleID(Mod));
}
assert(Out.tell() - Start == DataLen && "Wrong data length");
@@ -1568,10 +1558,10 @@
// Use HeaderSearch's getFileInfo to make sure we get the HeaderFileInfo
// from the external source if it was not provided already.
- const HeaderFileInfo &HFI = HS.getFileInfo(File);
- if (HFI.External && Chain)
- continue;
- if (HFI.isModuleHeader && !HFI.isCompilingModuleHeader)
+ HeaderFileInfo HFI;
+ if (!HS.tryGetFileInfo(File, HFI) ||
+ (HFI.External && Chain) ||
+ (HFI.isModuleHeader && !HFI.isCompilingModuleHeader))
continue;
// Turn the file name into an absolute path, if it isn't already.
@@ -1594,9 +1584,10 @@
SmallString<4096> TableData;
uint32_t BucketOffset;
{
+ using namespace llvm::support;
llvm::raw_svector_ostream Out(TableData);
// Make sure that no bucket is at offset 0
- clang::io::Emit32(Out, 0);
+ endian::Writer<little>(Out).write<uint32_t>(0);
BucketOffset = Generator.Emit(Out, GeneratorTrait);
}
@@ -1851,12 +1842,14 @@
}
static void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) {
- clang::io::Emit32(Out, Key);
+ using namespace llvm::support;
+ endian::Writer<little>(Out).write<uint32_t>(Key);
}
static void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data,
unsigned) {
- clang::io::Emit32(Out, Data.MacroDirectivesOffset);
+ using namespace llvm::support;
+ endian::Writer<little>(Out).write<uint32_t>(Data.MacroDirectivesOffset);
}
};
} // end anonymous namespace
@@ -1946,8 +1939,6 @@
// Emit the macro directives in reverse source order.
for (; MD; MD = MD->getPrevious()) {
- if (MD->isHidden())
- continue;
if (shouldIgnoreMacro(MD, IsModule, PP))
continue;
@@ -2054,9 +2045,10 @@
SmallString<4096> MacroTable;
uint32_t BucketOffset;
{
+ using namespace llvm::support;
llvm::raw_svector_ostream Out(MacroTable);
// Make sure that no bucket is at offset 0
- clang::io::Emit32(Out, 0);
+ endian::Writer<little>(Out).write<uint32_t>(0);
BucketOffset = Generator.Emit(Out);
}
@@ -2227,9 +2219,7 @@
// other consumers of this information.
SourceManager &SrcMgr = PP->getSourceManager();
ModuleMap &ModMap = PP->getHeaderSearchInfo().getModuleMap();
- for (ASTContext::import_iterator I = Context->local_import_begin(),
- IEnd = Context->local_import_end();
- I != IEnd; ++I) {
+ for (const auto *I : Context->local_imports()) {
if (Module *ImportedFrom
= ModMap.inferModuleFromLocation(FullSourceLoc(I->getLocation(),
SrcMgr))) {
@@ -2248,7 +2238,8 @@
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExternC
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferSubmodules...
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit...
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild...
@@ -2336,6 +2327,7 @@
Record.push_back(Mod->IsFramework);
Record.push_back(Mod->IsExplicit);
Record.push_back(Mod->IsSystem);
+ Record.push_back(Mod->IsExternC);
Record.push_back(Mod->InferSubmodules);
Record.push_back(Mod->InferExplicitSubmodules);
Record.push_back(Mod->InferExportWildcard);
@@ -2618,9 +2610,8 @@
RecordData Record;
Record.push_back(DECL_CONTEXT_LEXICAL);
SmallVector<KindDeclIDPair, 64> Decls;
- for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
- D != DEnd; ++D)
- Decls.push_back(std::make_pair((*D)->getKind(), GetDeclRef(*D)));
+ for (const auto *D : DC->decls())
+ Decls.push_back(std::make_pair(D->getKind(), GetDeclRef(D)));
++NumLexicalDeclContexts;
Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, data(Decls));
@@ -2728,8 +2719,10 @@
std::pair<unsigned,unsigned>
EmitKeyDataLength(raw_ostream& Out, Selector Sel,
data_type_ref Methods) {
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4);
- clang::io::Emit16(Out, KeyLen);
+ LE.write<uint16_t>(KeyLen);
unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts
for (const ObjCMethodList *Method = &Methods.Instance; Method;
Method = Method->getNext())
@@ -2739,27 +2732,31 @@
Method = Method->getNext())
if (Method->Method)
DataLen += 4;
- clang::io::Emit16(Out, DataLen);
+ LE.write<uint16_t>(DataLen);
return std::make_pair(KeyLen, DataLen);
}
void EmitKey(raw_ostream& Out, Selector Sel, unsigned) {
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
uint64_t Start = Out.tell();
assert((Start >> 32) == 0 && "Selector key offset too large");
Writer.SetSelectorOffset(Sel, Start);
unsigned N = Sel.getNumArgs();
- clang::io::Emit16(Out, N);
+ LE.write<uint16_t>(N);
if (N == 0)
N = 1;
for (unsigned I = 0; I != N; ++I)
- clang::io::Emit32(Out,
- Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I)));
+ LE.write<uint32_t>(
+ Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I)));
}
void EmitData(raw_ostream& Out, key_type_ref,
data_type_ref Methods, unsigned DataLen) {
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
uint64_t Start = Out.tell(); (void)Start;
- clang::io::Emit32(Out, Methods.ID);
+ LE.write<uint32_t>(Methods.ID);
unsigned NumInstanceMethods = 0;
for (const ObjCMethodList *Method = &Methods.Instance; Method;
Method = Method->getNext())
@@ -2779,16 +2776,16 @@
unsigned FactoryBits = Methods.Factory.getBits();
assert(FactoryBits < 4);
unsigned NumFactoryMethodsAndBits = (NumFactoryMethods << 2) | FactoryBits;
- clang::io::Emit16(Out, NumInstanceMethodsAndBits);
- clang::io::Emit16(Out, NumFactoryMethodsAndBits);
+ LE.write<uint16_t>(NumInstanceMethodsAndBits);
+ LE.write<uint16_t>(NumFactoryMethodsAndBits);
for (const ObjCMethodList *Method = &Methods.Instance; Method;
Method = Method->getNext())
if (Method->Method)
- clang::io::Emit32(Out, Writer.getDeclID(Method->Method));
+ LE.write<uint32_t>(Writer.getDeclID(Method->Method));
for (const ObjCMethodList *Method = &Methods.Factory; Method;
Method = Method->getNext())
if (Method->Method)
- clang::io::Emit32(Out, Writer.getDeclID(Method->Method));
+ LE.write<uint32_t>(Writer.getDeclID(Method->Method));
assert(Out.tell() - Start == DataLen && "Data length is wrong");
}
@@ -2857,10 +2854,11 @@
SmallString<4096> MethodPool;
uint32_t BucketOffset;
{
+ using namespace llvm::support;
ASTMethodPoolTrait Trait(*this);
llvm::raw_svector_ostream Out(MethodPool);
// Make sure that no bucket is at offset 0
- clang::io::Emit32(Out, 0);
+ endian::Writer<little>(Out).write<uint32_t>(0);
BucketOffset = Generator.Emit(Out, Trait);
}
@@ -2959,83 +2957,101 @@
return false;
}
- DefMacroDirective *getFirstPublicSubmoduleMacro(MacroDirective *MD,
- SubmoduleID &ModID) {
+ typedef llvm::SmallVectorImpl<SubmoduleID> OverriddenList;
+
+ MacroDirective *
+ getFirstPublicSubmoduleMacro(MacroDirective *MD, SubmoduleID &ModID) {
ModID = 0;
- if (DefMacroDirective *DefMD = getPublicSubmoduleMacro(MD, ModID))
- if (!shouldIgnoreMacro(DefMD, IsModule, PP))
- return DefMD;
+ llvm::SmallVector<SubmoduleID, 1> Overridden;
+ if (MacroDirective *NextMD = getPublicSubmoduleMacro(MD, ModID, Overridden))
+ if (!shouldIgnoreMacro(NextMD, IsModule, PP))
+ return NextMD;
return 0;
}
- DefMacroDirective *getNextPublicSubmoduleMacro(DefMacroDirective *MD,
- SubmoduleID &ModID) {
- if (DefMacroDirective *
- DefMD = getPublicSubmoduleMacro(MD->getPrevious(), ModID))
- if (!shouldIgnoreMacro(DefMD, IsModule, PP))
- return DefMD;
+ MacroDirective *
+ getNextPublicSubmoduleMacro(MacroDirective *MD, SubmoduleID &ModID,
+ OverriddenList &Overridden) {
+ if (MacroDirective *NextMD =
+ getPublicSubmoduleMacro(MD->getPrevious(), ModID, Overridden))
+ if (!shouldIgnoreMacro(NextMD, IsModule, PP))
+ return NextMD;
return 0;
}
/// \brief Traverses the macro directives history and returns the latest
- /// macro that is public and not undefined in the same submodule.
- /// A macro that is defined in submodule A and undefined in submodule B,
+ /// public macro definition or undefinition that is not in ModID.
+ /// A macro that is defined in submodule A and undefined in submodule B
/// will still be considered as defined/exported from submodule A.
- DefMacroDirective *getPublicSubmoduleMacro(MacroDirective *MD,
- SubmoduleID &ModID) {
+ /// ModID is updated to the module containing the returned directive.
+ ///
+ /// FIXME: This process breaks down if a module defines a macro, imports
+ /// another submodule that changes the macro, then changes the
+ /// macro again itself.
+ MacroDirective *getPublicSubmoduleMacro(MacroDirective *MD,
+ SubmoduleID &ModID,
+ OverriddenList &Overridden) {
if (!MD)
return 0;
+ Overridden.clear();
SubmoduleID OrigModID = ModID;
- bool isUndefined = false;
- Optional<bool> isPublic;
+ Optional<bool> IsPublic;
for (; MD; MD = MD->getPrevious()) {
- if (MD->isHidden())
- continue;
-
SubmoduleID ThisModID = getSubmoduleID(MD);
if (ThisModID == 0) {
- isUndefined = false;
- isPublic = Optional<bool>();
+ IsPublic = Optional<bool>();
continue;
}
- if (ThisModID != ModID){
+ if (ThisModID != ModID) {
ModID = ThisModID;
- isUndefined = false;
- isPublic = Optional<bool>();
+ IsPublic = Optional<bool>();
}
+
+ // If this is a definition from a submodule import, that submodule's
+ // definition is overridden by the definition or undefinition that we
+ // started with.
+ // FIXME: This should only apply to macros defined in OrigModID.
+ // We can't do that currently, because a #include of a different submodule
+ // of the same module just leaks through macros instead of providing new
+ // DefMacroDirectives for them.
+ if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) {
+ // Figure out which submodule the macro was originally defined within.
+ SubmoduleID SourceID = DefMD->getInfo()->getOwningModuleID();
+ if (!SourceID) {
+ SourceLocation DefLoc = DefMD->getInfo()->getDefinitionLoc();
+ if (DefLoc == MD->getLocation())
+ SourceID = ThisModID;
+ else
+ SourceID = Writer.inferSubmoduleIDFromLocation(DefLoc);
+ }
+ if (SourceID != OrigModID)
+ Overridden.push_back(SourceID);
+ }
+
// We are looking for a definition in a different submodule than the one
// that we started with. If a submodule has re-definitions of the same
// macro, only the last definition will be used as the "exported" one.
if (ModID == OrigModID)
continue;
- if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) {
- if (!isUndefined && (!isPublic.hasValue() || isPublic.getValue()))
- return DefMD;
- continue;
+ // The latest visibility directive for a name in a submodule affects all
+ // the directives that come before it.
+ if (VisibilityMacroDirective *VisMD =
+ dyn_cast<VisibilityMacroDirective>(MD)) {
+ if (!IsPublic.hasValue())
+ IsPublic = VisMD->isPublic();
+ } else if (!IsPublic.hasValue() || IsPublic.getValue()) {
+ // FIXME: If we find an imported macro, we should include its list of
+ // overrides in our export.
+ return MD;
}
-
- if (isa<UndefMacroDirective>(MD)) {
- isUndefined = true;
- continue;
- }
-
- VisibilityMacroDirective *VisMD = cast<VisibilityMacroDirective>(MD);
- if (!isPublic.hasValue())
- isPublic = VisMD->isPublic();
}
return 0;
}
SubmoduleID getSubmoduleID(MacroDirective *MD) {
- if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) {
- MacroInfo *MI = DefMD->getInfo();
- if (unsigned ID = MI->getOwningModuleID())
- return ID;
- return Writer.inferSubmoduleIDFromLocation(MI->getDefinitionLoc());
- }
return Writer.inferSubmoduleIDFromLocation(MD->getLocation());
}
@@ -3066,11 +3082,18 @@
DataLen += 4; // MacroDirectives offset.
if (IsModule) {
SubmoduleID ModID;
- for (DefMacroDirective *
- DefMD = getFirstPublicSubmoduleMacro(Macro, ModID);
- DefMD; DefMD = getNextPublicSubmoduleMacro(DefMD, ModID)) {
- DataLen += 4; // MacroInfo ID.
+ llvm::SmallVector<SubmoduleID, 4> Overridden;
+ for (MacroDirective *
+ MD = getFirstPublicSubmoduleMacro(Macro, ModID);
+ MD; MD = getNextPublicSubmoduleMacro(MD, ModID, Overridden)) {
+ // Previous macro's overrides.
+ if (!Overridden.empty())
+ DataLen += 4 * (1 + Overridden.size());
+ DataLen += 4; // MacroInfo ID or ModuleID.
}
+ // Previous macro's overrides.
+ if (!Overridden.empty())
+ DataLen += 4 * (1 + Overridden.size());
DataLen += 4;
}
}
@@ -3080,11 +3103,14 @@
D != DEnd; ++D)
DataLen += sizeof(DeclID);
}
- clang::io::Emit16(Out, DataLen);
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
+
+ LE.write<uint16_t>(DataLen);
// We emit the key length after the data length so that every
// string is preceded by a 16-bit length. This matches the PTH
// format for storing identifiers.
- clang::io::Emit16(Out, KeyLen);
+ LE.write<uint16_t>(KeyLen);
return std::make_pair(KeyLen, DataLen);
}
@@ -3096,18 +3122,31 @@
Out.write(II->getNameStart(), KeyLen);
}
+ static void emitMacroOverrides(raw_ostream &Out,
+ llvm::ArrayRef<SubmoduleID> Overridden) {
+ if (!Overridden.empty()) {
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
+ LE.write<uint32_t>(Overridden.size() | 0x80000000U);
+ for (unsigned I = 0, N = Overridden.size(); I != N; ++I)
+ LE.write<uint32_t>(Overridden[I]);
+ }
+ }
+
void EmitData(raw_ostream& Out, IdentifierInfo* II,
IdentID ID, unsigned) {
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
MacroDirective *Macro = 0;
if (!isInterestingIdentifier(II, Macro)) {
- clang::io::Emit32(Out, ID << 1);
+ LE.write<uint32_t>(ID << 1);
return;
}
- clang::io::Emit32(Out, (ID << 1) | 0x01);
+ LE.write<uint32_t>((ID << 1) | 0x01);
uint32_t Bits = (uint32_t)II->getObjCOrBuiltinID();
assert((Bits & 0xffff) == Bits && "ObjCOrBuiltinID too big for ASTReader.");
- clang::io::Emit16(Out, Bits);
+ LE.write<uint16_t>(Bits);
Bits = 0;
bool HadMacroDefinition = hadMacroDefinition(II, Macro);
Bits = (Bits << 1) | unsigned(HadMacroDefinition);
@@ -3116,21 +3155,30 @@
Bits = (Bits << 1) | unsigned(II->isPoisoned());
Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier());
Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword());
- clang::io::Emit16(Out, Bits);
+ LE.write<uint16_t>(Bits);
if (HadMacroDefinition) {
- clang::io::Emit32(Out, Writer.getMacroDirectivesOffset(II));
+ LE.write<uint32_t>(Writer.getMacroDirectivesOffset(II));
if (IsModule) {
// Write the IDs of macros coming from different submodules.
SubmoduleID ModID;
- for (DefMacroDirective *
- DefMD = getFirstPublicSubmoduleMacro(Macro, ModID);
- DefMD; DefMD = getNextPublicSubmoduleMacro(DefMD, ModID)) {
- MacroID InfoID = Writer.getMacroID(DefMD->getInfo());
- assert(InfoID);
- clang::io::Emit32(Out, InfoID);
+ llvm::SmallVector<SubmoduleID, 4> Overridden;
+ for (MacroDirective *
+ MD = getFirstPublicSubmoduleMacro(Macro, ModID);
+ MD; MD = getNextPublicSubmoduleMacro(MD, ModID, Overridden)) {
+ MacroID InfoID = 0;
+ emitMacroOverrides(Out, Overridden);
+ if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) {
+ InfoID = Writer.getMacroID(DefMD->getInfo());
+ assert(InfoID);
+ LE.write<uint32_t>(InfoID << 1);
+ } else {
+ assert(isa<UndefMacroDirective>(MD));
+ LE.write<uint32_t>((ModID << 1) | 1);
+ }
}
- clang::io::Emit32(Out, 0);
+ emitMacroOverrides(Out, Overridden);
+ LE.write<uint32_t>(0);
}
}
@@ -3145,7 +3193,7 @@
for (SmallVectorImpl<Decl *>::reverse_iterator D = Decls.rbegin(),
DEnd = Decls.rend();
D != DEnd; ++D)
- clang::io::Emit32(Out, Writer.getDeclID(getMostRecentLocalDecl(*D)));
+ LE.write<uint32_t>(Writer.getDeclID(getMostRecentLocalDecl(*D)));
}
/// \brief Returns the most recent local decl or the given decl if there are
@@ -3214,10 +3262,11 @@
SmallString<4096> IdentifierTable;
uint32_t BucketOffset;
{
+ using namespace llvm::support;
ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule);
llvm::raw_svector_ostream Out(IdentifierTable);
// Make sure that no bucket is at offset 0
- clang::io::Emit32(Out, 0);
+ endian::Writer<little>(Out).write<uint32_t>(0);
BucketOffset = Generator.Emit(Out, Trait);
}
@@ -3306,6 +3355,8 @@
std::pair<unsigned,unsigned>
EmitKeyDataLength(raw_ostream& Out, DeclarationName Name,
data_type_ref Lookup) {
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
unsigned KeyLen = 1;
switch (Name.getNameKind()) {
case DeclarationName::Identifier:
@@ -3324,35 +3375,35 @@
case DeclarationName::CXXUsingDirective:
break;
}
- clang::io::Emit16(Out, KeyLen);
+ LE.write<uint16_t>(KeyLen);
// 2 bytes for num of decls and 4 for each DeclID.
unsigned DataLen = 2 + 4 * Lookup.size();
- clang::io::Emit16(Out, DataLen);
+ LE.write<uint16_t>(DataLen);
return std::make_pair(KeyLen, DataLen);
}
void EmitKey(raw_ostream& Out, DeclarationName Name, unsigned) {
- using namespace clang::io;
-
- Emit8(Out, Name.getNameKind());
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
+ LE.write<uint8_t>(Name.getNameKind());
switch (Name.getNameKind()) {
case DeclarationName::Identifier:
- Emit32(Out, Writer.getIdentifierRef(Name.getAsIdentifierInfo()));
+ LE.write<uint32_t>(Writer.getIdentifierRef(Name.getAsIdentifierInfo()));
return;
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
- Emit32(Out, Writer.getSelectorRef(Name.getObjCSelector()));
+ LE.write<uint32_t>(Writer.getSelectorRef(Name.getObjCSelector()));
return;
case DeclarationName::CXXOperatorName:
assert(Name.getCXXOverloadedOperator() < NUM_OVERLOADED_OPERATORS &&
"Invalid operator?");
- Emit8(Out, Name.getCXXOverloadedOperator());
+ LE.write<uint8_t>(Name.getCXXOverloadedOperator());
return;
case DeclarationName::CXXLiteralOperatorName:
- Emit32(Out, Writer.getIdentifierRef(Name.getCXXLiteralIdentifier()));
+ LE.write<uint32_t>(Writer.getIdentifierRef(Name.getCXXLiteralIdentifier()));
return;
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
@@ -3366,17 +3417,110 @@
void EmitData(raw_ostream& Out, key_type_ref,
data_type Lookup, unsigned DataLen) {
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
uint64_t Start = Out.tell(); (void)Start;
- clang::io::Emit16(Out, Lookup.size());
+ LE.write<uint16_t>(Lookup.size());
for (DeclContext::lookup_iterator I = Lookup.begin(), E = Lookup.end();
I != E; ++I)
- clang::io::Emit32(Out, Writer.GetDeclRef(*I));
+ LE.write<uint32_t>(Writer.GetDeclRef(*I));
assert(Out.tell() - Start == DataLen && "Data length is wrong");
}
};
} // end anonymous namespace
+uint32_t
+ASTWriter::GenerateNameLookupTable(const DeclContext *DC,
+ llvm::SmallVectorImpl<char> &LookupTable) {
+ assert(!DC->LookupPtr.getInt() && "must call buildLookups first");
+ assert(DC == DC->getPrimaryContext() && "only primary DC has lookup table");
+
+ OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> Generator;
+ ASTDeclContextNameLookupTrait Trait(*this);
+
+ // Create the on-disk hash table representation.
+ DeclarationName ConstructorName;
+ DeclarationName ConversionName;
+ SmallVector<NamedDecl *, 8> ConstructorDecls;
+ SmallVector<NamedDecl *, 4> ConversionDecls;
+
+ auto AddLookupResult = [&](DeclarationName Name,
+ DeclContext::lookup_result Result) {
+ if (Result.empty())
+ return;
+
+ // Different DeclarationName values of certain kinds are mapped to
+ // identical serialized keys, because we don't want to use type
+ // identifiers in the keys (since type ids are local to the module).
+ switch (Name.getNameKind()) {
+ case DeclarationName::CXXConstructorName:
+ // There may be different CXXConstructorName DeclarationName values
+ // in a DeclContext because a UsingDecl that inherits constructors
+ // has the DeclarationName of the inherited constructors.
+ if (!ConstructorName)
+ ConstructorName = Name;
+ ConstructorDecls.append(Result.begin(), Result.end());
+ return;
+ case DeclarationName::CXXConversionFunctionName:
+ if (!ConversionName)
+ ConversionName = Name;
+ ConversionDecls.append(Result.begin(), Result.end());
+ return;
+ default:
+ break;
+ }
+
+ Generator.insert(Name, Result, Trait);
+ };
+
+ SmallVector<DeclarationName, 16> ExternalNames;
+ for (auto &Lookup : *DC->getLookupPtr()) {
+ if (Lookup.second.hasExternalDecls() ||
+ DC->NeedToReconcileExternalVisibleStorage) {
+ // We don't know for sure what declarations are found by this name,
+ // because the external source might have a different set from the set
+ // that are in the lookup map, and we can't update it now without
+ // risking invalidating our lookup iterator. So add it to a queue to
+ // deal with later.
+ ExternalNames.push_back(Lookup.first);
+ continue;
+ }
+
+ AddLookupResult(Lookup.first, Lookup.second.getLookupResult());
+ }
+
+ // Add the names we needed to defer. Note, this shouldn't add any new decls
+ // to the list we need to serialize: any new declarations we find here should
+ // be imported from an external source.
+ // FIXME: What if the external source isn't an ASTReader?
+ for (const auto &Name : ExternalNames)
+ // FIXME: const_cast since OnDiskHashTable wants a non-const lookup result.
+ AddLookupResult(Name, const_cast<DeclContext*>(DC)->lookup(Name));
+
+ // Add the constructors.
+ if (!ConstructorDecls.empty()) {
+ Generator.insert(ConstructorName,
+ DeclContext::lookup_result(ConstructorDecls.begin(),
+ ConstructorDecls.end()),
+ Trait);
+ }
+ // Add the conversion functions.
+ if (!ConversionDecls.empty()) {
+ Generator.insert(ConversionName,
+ DeclContext::lookup_result(ConversionDecls.begin(),
+ ConversionDecls.end()),
+ Trait);
+ }
+
+ // Create the on-disk hash table in a buffer.
+ llvm::raw_svector_ostream Out(LookupTable);
+ // Make sure that no bucket is at offset 0
+ using namespace llvm::support;
+ endian::Writer<little>(Out).write<uint32_t>(0);
+ return Generator.Emit(Out, Trait);
+}
+
/// \brief Write the block containing all of the declaration IDs
/// visible from the given DeclContext.
///
@@ -3407,50 +3551,9 @@
if (!Map || Map->empty())
return 0;
- OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> Generator;
- ASTDeclContextNameLookupTrait Trait(*this);
-
- // Create the on-disk hash table representation.
- DeclarationName ConversionName;
- SmallVector<NamedDecl *, 4> ConversionDecls;
- for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
- D != DEnd; ++D) {
- DeclarationName Name = D->first;
- DeclContext::lookup_result Result = D->second.getLookupResult();
- if (!Result.empty()) {
- if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
- // Hash all conversion function names to the same name. The actual
- // type information in conversion function name is not used in the
- // key (since such type information is not stable across different
- // modules), so the intended effect is to coalesce all of the conversion
- // functions under a single key.
- if (!ConversionName)
- ConversionName = Name;
- ConversionDecls.append(Result.begin(), Result.end());
- continue;
- }
-
- Generator.insert(Name, Result, Trait);
- }
- }
-
- // Add the conversion functions
- if (!ConversionDecls.empty()) {
- Generator.insert(ConversionName,
- DeclContext::lookup_result(ConversionDecls.begin(),
- ConversionDecls.end()),
- Trait);
- }
-
// Create the on-disk hash table in a buffer.
SmallString<4096> LookupTable;
- uint32_t BucketOffset;
- {
- llvm::raw_svector_ostream Out(LookupTable);
- // Make sure that no bucket is at offset 0
- clang::io::Emit32(Out, 0);
- BucketOffset = Generator.Emit(Out, Trait);
- }
+ uint32_t BucketOffset = GenerateNameLookupTable(DC, LookupTable);
// Write the lookup table
RecordData Record;
@@ -3471,33 +3574,13 @@
/// (in C++), for namespaces, and for classes with forward-declared unscoped
/// enumeration members (in C++11).
void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) {
- StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr());
+ StoredDeclsMap *Map = DC->getLookupPtr();
if (!Map || Map->empty())
return;
- OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> Generator;
- ASTDeclContextNameLookupTrait Trait(*this);
-
- // Create the hash table.
- for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
- D != DEnd; ++D) {
- DeclarationName Name = D->first;
- DeclContext::lookup_result Result = D->second.getLookupResult();
- // For any name that appears in this table, the results are complete, i.e.
- // they overwrite results from previous PCHs. Merging is always a mess.
- if (!Result.empty())
- Generator.insert(Name, Result, Trait);
- }
-
// Create the on-disk hash table in a buffer.
SmallString<4096> LookupTable;
- uint32_t BucketOffset;
- {
- llvm::raw_svector_ostream Out(LookupTable);
- // Make sure that no bucket is at offset 0
- clang::io::Emit32(Out, 0);
- BucketOffset = Generator.Emit(Out, Trait);
- }
+ uint32_t BucketOffset = GenerateNameLookupTable(DC, LookupTable);
// Write the lookup table
RecordData Record;
@@ -3799,9 +3882,7 @@
}
ASTWriter::~ASTWriter() {
- for (FileDeclIDsTy::iterator
- I = FileDeclIDs.begin(), E = FileDeclIDs.end(); I != E; ++I)
- delete I->second;
+ llvm::DeleteContainerSeconds(FileDeclIDs);
}
void ASTWriter::WriteAST(Sema &SemaRef,
@@ -4032,11 +4113,9 @@
// translation unit that do not come from other AST files.
const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
SmallVector<KindDeclIDPair, 64> NewGlobalDecls;
- for (DeclContext::decl_iterator I = TU->noload_decls_begin(),
- E = TU->noload_decls_end();
- I != E; ++I) {
- if (!(*I)->isFromASTFile())
- NewGlobalDecls.push_back(std::make_pair((*I)->getKind(), GetDeclRef(*I)));
+ for (const auto *I : TU->noload_decls()) {
+ if (!I->isFromASTFile())
+ NewGlobalDecls.push_back(std::make_pair(I->getKind(), GetDeclRef(I)));
}
llvm::BitCodeAbbrev *Abv = new llvm::BitCodeAbbrev();
@@ -4059,14 +4138,25 @@
// If the translation unit has an anonymous namespace, and we don't already
// have an update block for it, write it as an update block.
+ // FIXME: Why do we not do this if there's already an update block?
if (NamespaceDecl *NS = TU->getAnonymousNamespace()) {
ASTWriter::UpdateRecord &Record = DeclUpdates[TU];
- if (Record.empty()) {
- Record.push_back(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE);
- Record.push_back(reinterpret_cast<uint64_t>(NS));
- }
+ if (Record.empty())
+ Record.push_back(DeclUpdate(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, NS));
}
+ // Add update records for all mangling numbers and static local numbers.
+ // These aren't really update records, but this is a convenient way of
+ // tagging this rare extra data onto the declarations.
+ for (const auto &Number : Context.MangleNumbers)
+ if (!Number.first->isFromASTFile())
+ DeclUpdates[Number.first].push_back(DeclUpdate(UPD_MANGLING_NUMBER,
+ Number.second));
+ for (const auto &Number : Context.StaticLocalNumbers)
+ if (!Number.first->isFromASTFile())
+ DeclUpdates[Number.first].push_back(DeclUpdate(UPD_STATIC_LOCAL_NUMBER,
+ Number.second));
+
// Make sure visible decls, added to DeclContexts previously loaded from
// an AST file, are registered for serialization.
for (SmallVectorImpl<const Decl *>::iterator
@@ -4090,9 +4180,6 @@
}
}
- // Resolve any declaration pointers within the declaration updates block.
- ResolveDeclUpdatesBlocks();
-
// Form the record of special types.
RecordData SpecialTypes;
AddTypeRef(Context.getRawCFConstantStringType(), SpecialTypes);
@@ -4104,30 +4191,6 @@
AddTypeRef(Context.ObjCSelRedefinitionType, SpecialTypes);
AddTypeRef(Context.getucontext_tType(), SpecialTypes);
- // Keep writing types and declarations until all types and
- // declarations have been written.
- Stream.EnterSubblock(DECLTYPES_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE);
- WriteDeclsBlockAbbrevs();
- for (DeclsToRewriteTy::iterator I = DeclsToRewrite.begin(),
- E = DeclsToRewrite.end();
- I != E; ++I)
- DeclTypesToEmit.push(const_cast<Decl*>(*I));
- while (!DeclTypesToEmit.empty()) {
- DeclOrType DOT = DeclTypesToEmit.front();
- DeclTypesToEmit.pop();
- if (DOT.isType())
- WriteType(DOT.getType());
- else
- WriteDecl(Context, DOT.getDecl());
- }
- Stream.ExitBlock();
-
- DoneWritingDeclsAndTypes = true;
-
- WriteFileDeclIDsMap();
- WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
- WriteComments();
-
if (Chain) {
// Write the mapping information describing our module dependencies and how
// each of those modules were mapped into our own offset/ID space, so that
@@ -4154,17 +4217,19 @@
for (ModuleManager::ModuleConstIterator M = Chain->ModuleMgr.begin(),
MEnd = Chain->ModuleMgr.end();
M != MEnd; ++M) {
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
StringRef FileName = (*M)->FileName;
- io::Emit16(Out, FileName.size());
+ LE.write<uint16_t>(FileName.size());
Out.write(FileName.data(), FileName.size());
- io::Emit32(Out, (*M)->SLocEntryBaseOffset);
- io::Emit32(Out, (*M)->BaseIdentifierID);
- io::Emit32(Out, (*M)->BaseMacroID);
- io::Emit32(Out, (*M)->BasePreprocessedEntityID);
- io::Emit32(Out, (*M)->BaseSubmoduleID);
- io::Emit32(Out, (*M)->BaseSelectorID);
- io::Emit32(Out, (*M)->BaseDeclID);
- io::Emit32(Out, (*M)->BaseTypeIndex);
+ LE.write<uint32_t>((*M)->SLocEntryBaseOffset);
+ LE.write<uint32_t>((*M)->BaseIdentifierID);
+ LE.write<uint32_t>((*M)->BaseMacroID);
+ LE.write<uint32_t>((*M)->BasePreprocessedEntityID);
+ LE.write<uint32_t>((*M)->BaseSubmoduleID);
+ LE.write<uint32_t>((*M)->BaseSelectorID);
+ LE.write<uint32_t>((*M)->BaseDeclID);
+ LE.write<uint32_t>((*M)->BaseTypeIndex);
}
}
Record.clear();
@@ -4172,6 +4237,41 @@
Stream.EmitRecordWithBlob(ModuleOffsetMapAbbrev, Record,
Buffer.data(), Buffer.size());
}
+
+ RecordData DeclUpdatesOffsetsRecord;
+
+ // Keep writing types, declarations, and declaration update records
+ // until we've emitted all of them.
+ Stream.EnterSubblock(DECLTYPES_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE);
+ WriteDeclsBlockAbbrevs();
+ for (DeclsToRewriteTy::iterator I = DeclsToRewrite.begin(),
+ E = DeclsToRewrite.end();
+ I != E; ++I)
+ DeclTypesToEmit.push(const_cast<Decl*>(*I));
+ do {
+ WriteDeclUpdatesBlocks(DeclUpdatesOffsetsRecord);
+ while (!DeclTypesToEmit.empty()) {
+ DeclOrType DOT = DeclTypesToEmit.front();
+ DeclTypesToEmit.pop();
+ if (DOT.isType())
+ WriteType(DOT.getType());
+ else
+ WriteDecl(Context, DOT.getDecl());
+ }
+ } while (!DeclUpdates.empty());
+ Stream.ExitBlock();
+
+ DoneWritingDeclsAndTypes = true;
+
+ // These things can only be done once we've written out decls and types.
+ WriteTypeDeclOffsets();
+ if (!DeclUpdatesOffsetsRecord.empty())
+ Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord);
+ WriteCXXBaseSpecifiersOffsets();
+ WriteFileDeclIDsMap();
+ WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
+
+ WriteComments();
WritePreprocessor(PP, isModule);
WriteHeaderSearch(PP.getHeaderSearchInfo(), isysroot);
WriteSelectors(SemaRef);
@@ -4179,12 +4279,8 @@
WriteIdentifierTable(PP, SemaRef.IdResolver, isModule);
WriteFPPragmaOptions(SemaRef.getFPOptions());
WriteOpenCLExtensions(SemaRef);
-
- WriteTypeDeclOffsets();
WritePragmaDiagnosticMappings(Context.getDiagnostics(), isModule);
- WriteCXXBaseSpecifiersOffsets();
-
// If we're emitting a module, write out the submodule information.
if (WritingModule)
WriteSubmodules(WritingModule);
@@ -4192,8 +4288,8 @@
Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes);
// Write the record containing external, unnamed definitions.
- if (!ExternalDefinitions.empty())
- Stream.EmitRecord(EXTERNAL_DEFINITIONS, ExternalDefinitions);
+ if (!EagerlyDeserializedDecls.empty())
+ Stream.EmitRecord(EAGERLY_DESERIALIZED_DECLS, EagerlyDeserializedDecls);
// Write the record containing tentative definitions.
if (!TentativeDefinitions.empty())
@@ -4258,27 +4354,41 @@
if (!WritingModule) {
// Write the submodules that were imported, if any.
- RecordData ImportedModules;
- for (ASTContext::import_iterator I = Context.local_import_begin(),
- IEnd = Context.local_import_end();
- I != IEnd; ++I) {
+ struct ModuleInfo {
+ uint64_t ID;
+ Module *M;
+ ModuleInfo(uint64_t ID, Module *M) : ID(ID), M(M) {}
+ };
+ llvm::SmallVector<ModuleInfo, 64> Imports;
+ for (const auto *I : Context.local_imports()) {
assert(SubmoduleIDs.find(I->getImportedModule()) != SubmoduleIDs.end());
- ImportedModules.push_back(SubmoduleIDs[I->getImportedModule()]);
+ Imports.push_back(ModuleInfo(SubmoduleIDs[I->getImportedModule()],
+ I->getImportedModule()));
}
- if (!ImportedModules.empty()) {
- // Sort module IDs.
- llvm::array_pod_sort(ImportedModules.begin(), ImportedModules.end());
-
- // Unique module IDs.
- ImportedModules.erase(std::unique(ImportedModules.begin(),
- ImportedModules.end()),
- ImportedModules.end());
-
+
+ if (!Imports.empty()) {
+ auto Cmp = [](const ModuleInfo &A, const ModuleInfo &B) {
+ return A.ID < B.ID;
+ };
+
+ // Sort and deduplicate module IDs.
+ std::sort(Imports.begin(), Imports.end(), Cmp);
+ Imports.erase(std::unique(Imports.begin(), Imports.end(), Cmp),
+ Imports.end());
+
+ RecordData ImportedModules;
+ for (const auto &Import : Imports) {
+ ImportedModules.push_back(Import.ID);
+ // FIXME: If the module has macros imported then later has declarations
+ // imported, this location won't be the right one as a location for the
+ // declaration imports.
+ AddSourceLocation(Import.M->MacroVisibilityLoc, ImportedModules);
+ }
+
Stream.EmitRecord(IMPORTED_MODULES, ImportedModules);
}
}
- WriteDeclUpdatesBlocks();
WriteDeclReplacementsBlock();
WriteRedeclarations();
WriteMergedDecls();
@@ -4295,64 +4405,79 @@
Stream.ExitBlock();
}
-/// \brief Go through the declaration update blocks and resolve declaration
-/// pointers into declaration IDs.
-void ASTWriter::ResolveDeclUpdatesBlocks() {
- for (DeclUpdateMap::iterator
- I = DeclUpdates.begin(), E = DeclUpdates.end(); I != E; ++I) {
- const Decl *D = I->first;
- UpdateRecord &URec = I->second;
-
- if (isRewritten(D))
- continue; // The decl will be written completely
-
- unsigned Idx = 0, N = URec.size();
- while (Idx < N) {
- switch ((DeclUpdateKind)URec[Idx++]) {
- case UPD_CXX_ADDED_IMPLICIT_MEMBER:
- case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
- case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE:
- URec[Idx] = GetDeclRef(reinterpret_cast<Decl *>(URec[Idx]));
- ++Idx;
- break;
-
- case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER:
- case UPD_DECL_MARKED_USED:
- ++Idx;
- break;
-
- case UPD_CXX_DEDUCED_RETURN_TYPE:
- URec[Idx] = GetOrCreateTypeID(
- QualType::getFromOpaquePtr(reinterpret_cast<void *>(URec[Idx])));
- ++Idx;
- break;
- }
- }
- }
-}
-
-void ASTWriter::WriteDeclUpdatesBlocks() {
+void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
if (DeclUpdates.empty())
return;
- RecordData OffsetsRecord;
- Stream.EnterSubblock(DECL_UPDATES_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE);
- for (DeclUpdateMap::iterator
- I = DeclUpdates.begin(), E = DeclUpdates.end(); I != E; ++I) {
- const Decl *D = I->first;
- UpdateRecord &URec = I->second;
+ DeclUpdateMap LocalUpdates;
+ LocalUpdates.swap(DeclUpdates);
+ for (auto &DeclUpdate : LocalUpdates) {
+ const Decl *D = DeclUpdate.first;
if (isRewritten(D))
continue; // The decl will be written completely,no need to store updates.
- uint64_t Offset = Stream.GetCurrentBitNo();
- Stream.EmitRecord(DECL_UPDATES, URec);
-
OffsetsRecord.push_back(GetDeclRef(D));
- OffsetsRecord.push_back(Offset);
+ OffsetsRecord.push_back(Stream.GetCurrentBitNo());
+
+ bool HasUpdatedBody = false;
+ RecordData Record;
+ for (auto &Update : DeclUpdate.second) {
+ DeclUpdateKind Kind = (DeclUpdateKind)Update.getKind();
+
+ Record.push_back(Kind);
+ switch (Kind) {
+ case UPD_CXX_ADDED_IMPLICIT_MEMBER:
+ case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
+ case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE:
+ Record.push_back(GetDeclRef(Update.getDecl()));
+ break;
+
+ case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER:
+ AddSourceLocation(Update.getLoc(), Record);
+ break;
+
+ case UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION:
+ // An updated body is emitted last, so that the reader doesn't need
+ // to skip over the lazy body to reach statements for other records.
+ Record.pop_back();
+ HasUpdatedBody = true;
+ break;
+
+ case UPD_CXX_RESOLVED_EXCEPTION_SPEC:
+ addExceptionSpec(
+ *this,
+ cast<FunctionDecl>(D)->getType()->castAs<FunctionProtoType>(),
+ Record);
+ break;
+
+ case UPD_CXX_DEDUCED_RETURN_TYPE:
+ Record.push_back(GetOrCreateTypeID(Update.getType()));
+ break;
+
+ case UPD_DECL_MARKED_USED:
+ break;
+
+ case UPD_MANGLING_NUMBER:
+ case UPD_STATIC_LOCAL_NUMBER:
+ Record.push_back(Update.getNumber());
+ break;
+ }
+ }
+
+ if (HasUpdatedBody) {
+ const FunctionDecl *Def = cast<FunctionDecl>(D);
+ Record.push_back(UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION);
+ Record.push_back(Def->isInlined());
+ AddSourceLocation(Def->getInnerLocStart(), Record);
+ AddFunctionDefinition(Def, Record);
+ }
+
+ Stream.EmitRecord(DECL_UPDATES, Record);
+
+ // Flush any statements that were written as part of this update record.
+ FlushStmts();
}
- Stream.ExitBlock();
- Stream.EmitRecord(DECL_UPDATE_OFFSETS, OffsetsRecord);
}
void ASTWriter::WriteDeclReplacementsBlock() {
@@ -4648,7 +4773,7 @@
assert(SM.isLocalSourceLocation(FileLoc));
FileID FID;
unsigned Offset;
- llvm::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc);
+ std::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc);
if (FID.isInvalid())
return;
assert(SM.getSLocEntry(FID).isFile());
@@ -5084,6 +5209,7 @@
Record.push_back(Data.HasProtectedFields);
Record.push_back(Data.HasPublicFields);
Record.push_back(Data.HasMutableFields);
+ Record.push_back(Data.HasVariantMembers);
Record.push_back(Data.HasOnlyCMembers);
Record.push_back(Data.HasInClassInitializer);
Record.push_back(Data.HasUninitializedReferenceMember);
@@ -5266,9 +5392,7 @@
// A decl coming from PCH was modified.
assert(RD->isCompleteDefinition());
- UpdateRecord &Record = DeclUpdates[RD];
- Record.push_back(UPD_CXX_ADDED_IMPLICIT_MEMBER);
- Record.push_back(reinterpret_cast<uint64_t>(D));
+ DeclUpdates[RD].push_back(DeclUpdate(UPD_CXX_ADDED_IMPLICIT_MEMBER, D));
}
void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
@@ -5279,9 +5403,8 @@
if (!(!D->isFromASTFile() && TD->isFromASTFile()))
return; // Not a source specialization added to a template from PCH.
- UpdateRecord &Record = DeclUpdates[TD];
- Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION);
- Record.push_back(reinterpret_cast<uint64_t>(D));
+ DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
+ D));
}
void ASTWriter::AddedCXXTemplateSpecialization(
@@ -5292,9 +5415,8 @@
if (!(!D->isFromASTFile() && TD->isFromASTFile()))
return; // Not a source specialization added to a template from PCH.
- UpdateRecord &Record = DeclUpdates[TD];
- Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION);
- Record.push_back(reinterpret_cast<uint64_t>(D));
+ DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
+ D));
}
void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
@@ -5305,9 +5427,17 @@
if (!(!D->isFromASTFile() && TD->isFromASTFile()))
return; // Not a source specialization added to a template from PCH.
- UpdateRecord &Record = DeclUpdates[TD];
- Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION);
- Record.push_back(reinterpret_cast<uint64_t>(D));
+ DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
+ D));
+}
+
+void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) {
+ assert(!WritingAST && "Already writing the AST!");
+ FD = FD->getCanonicalDecl();
+ if (!FD->isFromASTFile())
+ return; // Not a function declared in PCH and defined outside.
+
+ DeclUpdates[FD].push_back(UPD_CXX_RESOLVED_EXCEPTION_SPEC);
}
void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) {
@@ -5316,9 +5446,7 @@
if (!FD->isFromASTFile())
return; // Not a function declared in PCH and defined outside.
- UpdateRecord &Record = DeclUpdates[FD];
- Record.push_back(UPD_CXX_DEDUCED_RETURN_TYPE);
- Record.push_back(reinterpret_cast<uint64_t>(ReturnType.getAsOpaquePtr()));
+ DeclUpdates[FD].push_back(DeclUpdate(UPD_CXX_DEDUCED_RETURN_TYPE, ReturnType));
}
void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
@@ -5331,6 +5459,17 @@
RewriteDecl(D);
}
+void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {
+ assert(!WritingAST && "Already writing the AST!");
+ if (!D->isFromASTFile())
+ return;
+
+ // Since the actual instantiation is delayed, this really means that we need
+ // to update the instantiation location.
+ DeclUpdates[D].push_back(
+ DeclUpdate(UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION));
+}
+
void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) {
assert(!WritingAST && "Already writing the AST!");
if (!D->isFromASTFile())
@@ -5338,10 +5477,9 @@
// Since the actual instantiation is delayed, this really means that we need
// to update the instantiation location.
- UpdateRecord &Record = DeclUpdates[D];
- Record.push_back(UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER);
- AddSourceLocation(
- D->getMemberSpecializationInfo()->getPointOfInstantiation(), Record);
+ DeclUpdates[D].push_back(
+ DeclUpdate(UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
+ D->getMemberSpecializationInfo()->getPointOfInstantiation()));
}
void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
@@ -5375,6 +5513,5 @@
if (!D->isFromASTFile())
return;
- UpdateRecord &Record = DeclUpdates[D];
- Record.push_back(UPD_DECL_MARKED_USED);
+ DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_USED));
}
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 55f830a..14304ab 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -130,6 +130,14 @@
void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
+
+ void AddFunctionDefinition(const FunctionDecl *FD) {
+ assert(FD->doesThisDeclarationHaveABody());
+ if (auto *CD = dyn_cast<CXXConstructorDecl>(FD))
+ Writer.AddCXXCtorInitializers(CD->CtorInitializers,
+ CD->NumCtorInitializers, Record);
+ Writer.AddStmt(FD->getBody());
+ }
};
}
@@ -168,6 +176,24 @@
Record.push_back(D->getAccess());
Record.push_back(D->isModulePrivate());
Record.push_back(Writer.inferSubmoduleIDFromLocation(D->getLocation()));
+
+ // If this declaration injected a name into a context different from its
+ // lexical context, and that context is an imported namespace, we need to
+ // update its visible declarations to include this name.
+ //
+ // This happens when we instantiate a class with a friend declaration or a
+ // function with a local extern declaration, for instance.
+ if (D->isOutOfLine()) {
+ auto *DC = D->getDeclContext();
+ while (auto *NS = dyn_cast<NamespaceDecl>(DC->getRedeclContext())) {
+ if (!NS->isFromASTFile())
+ break;
+ Writer.AddUpdatedDeclContext(NS->getPrimaryContext());
+ if (!NS->isInlineNamespace())
+ break;
+ DC = NS->getParent();
+ }
+ }
}
void ASTDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
@@ -414,9 +440,8 @@
}
Record.push_back(D->param_size());
- for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
- P != PEnd; ++P)
- Writer.AddDeclRef(*P, Record);
+ for (auto P : D->params())
+ Writer.AddDeclRef(P, Record);
Code = serialization::DECL_FUNCTION;
}
@@ -451,13 +476,12 @@
// FIXME: stable encoding for in/out/inout/bycopy/byref/oneway
Record.push_back(D->getObjCDeclQualifier());
Record.push_back(D->hasRelatedResultType());
- Writer.AddTypeRef(D->getResultType(), Record);
- Writer.AddTypeSourceInfo(D->getResultTypeSourceInfo(), Record);
+ Writer.AddTypeRef(D->getReturnType(), Record);
+ Writer.AddTypeSourceInfo(D->getReturnTypeSourceInfo(), Record);
Writer.AddSourceLocation(D->getLocEnd(), Record);
Record.push_back(D->param_size());
- for (ObjCMethodDecl::param_iterator P = D->param_begin(),
- PEnd = D->param_end(); P != PEnd; ++P)
- Writer.AddDeclRef(*P, Record);
+ for (const auto *P : D->params())
+ Writer.AddDeclRef(P, Record);
Record.push_back(D->SelLocsKind);
unsigned NumStoredSelLocs = D->getNumStoredSelLocs();
@@ -489,17 +513,14 @@
Writer.AddDeclRef(D->getSuperClass(), Record);
Writer.AddSourceLocation(D->getSuperClassLoc(), Record);
Writer.AddSourceLocation(D->getEndOfDefinitionLoc(), Record);
+ Record.push_back(Data.HasDesignatedInitializers);
// Write out the protocols that are directly referenced by the @interface.
Record.push_back(Data.ReferencedProtocols.size());
- for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(),
- PEnd = D->protocol_end();
- P != PEnd; ++P)
- Writer.AddDeclRef(*P, Record);
- for (ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
- PLEnd = D->protocol_loc_end();
- PL != PLEnd; ++PL)
- Writer.AddSourceLocation(*PL, Record);
+ for (const auto *P : D->protocols())
+ Writer.AddDeclRef(P, Record);
+ for (const auto &PL : D->protocol_locs())
+ Writer.AddSourceLocation(PL, Record);
// Write out the protocols that are transitively referenced.
Record.push_back(Data.AllReferencedProtocols.size());
@@ -528,7 +549,6 @@
// FIXME: stable encoding for @public/@private/@protected/@package
Record.push_back(D->getAccessControl());
Record.push_back(D->getSynthesize());
- Record.push_back(D->getBackingIvarReferencedInAccessor());
if (!D->hasAttrs() &&
!D->isImplicit() &&
@@ -551,13 +571,10 @@
Record.push_back(D->isThisDeclarationADefinition());
if (D->isThisDeclarationADefinition()) {
Record.push_back(D->protocol_size());
- for (ObjCProtocolDecl::protocol_iterator
- I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
- Writer.AddDeclRef(*I, Record);
- for (ObjCProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
- PLEnd = D->protocol_loc_end();
- PL != PLEnd; ++PL)
- Writer.AddSourceLocation(*PL, Record);
+ for (const auto *I : D->protocols())
+ Writer.AddDeclRef(I, Record);
+ for (const auto &PL : D->protocol_locs())
+ Writer.AddSourceLocation(PL, Record);
}
Code = serialization::DECL_OBJC_PROTOCOL;
@@ -575,13 +592,10 @@
Writer.AddSourceLocation(D->getIvarRBraceLoc(), Record);
Writer.AddDeclRef(D->getClassInterface(), Record);
Record.push_back(D->protocol_size());
- for (ObjCCategoryDecl::protocol_iterator
- I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
- Writer.AddDeclRef(*I, Record);
- for (ObjCCategoryDecl::protocol_loc_iterator
- PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
- PL != PLEnd; ++PL)
- Writer.AddSourceLocation(*PL, Record);
+ for (const auto *I : D->protocols())
+ Writer.AddDeclRef(I, Record);
+ for (const auto &PL : D->protocol_locs())
+ Writer.AddSourceLocation(PL, Record);
Code = serialization::DECL_OBJC_CATEGORY;
}
@@ -688,10 +702,8 @@
VisitValueDecl(D);
Record.push_back(D->getChainingSize());
- for (IndirectFieldDecl::chain_iterator
- P = D->chain_begin(),
- PEnd = D->chain_end(); P != PEnd; ++P)
- Writer.AddDeclRef(*P, Record);
+ for (const auto *P : D->chain())
+ Writer.AddDeclRef(P, Record);
Code = serialization::DECL_INDIRECTFIELD;
}
@@ -833,9 +845,7 @@
Record.push_back(D->isConversionFromLambda());
Record.push_back(D->capturesCXXThis());
Record.push_back(D->getNumCaptures());
- for (BlockDecl::capture_iterator
- i = D->capture_begin(), e = D->capture_end(); i != e; ++i) {
- const BlockDecl::Capture &capture = *i;
+ for (const auto &capture : D->captures()) {
Writer.AddDeclRef(capture.getVariable(), Record);
unsigned flags = 0;
@@ -911,9 +921,8 @@
Decl *Parent = cast<Decl>(
D->getParent()->getRedeclContext()->getPrimaryContext());
if (Parent->isFromASTFile() || isa<TranslationUnitDecl>(Parent)) {
- ASTWriter::UpdateRecord &Record = Writer.DeclUpdates[Parent];
- Record.push_back(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE);
- Writer.AddDeclRef(D, Record);
+ Writer.DeclUpdates[Parent].push_back(
+ ASTWriter::DeclUpdate(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, D));
}
}
}
@@ -1021,6 +1030,7 @@
void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
VisitCXXMethodDecl(D);
+ Writer.AddDeclRef(D->getInheritedConstructor(), Record);
Record.push_back(D->IsExplicitSpecified);
Writer.AddCXXCtorInitializers(D->CtorInitializers, D->NumCtorInitializers,
Record);
@@ -1429,10 +1439,8 @@
void ASTDeclWriter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
Record.push_back(D->varlist_size());
VisitDecl(D);
- for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(),
- E = D->varlist_end();
- I != E; ++I)
- Writer.AddStmt(*I);
+ for (auto *I : D->varlists())
+ Writer.AddStmt(I);
Code = serialization::DECL_OMP_THREADPRIVATE;
}
@@ -1817,8 +1825,10 @@
// An ObjCMethodDecl is never considered as "required" because its
// implementation container always is.
- // File scoped assembly or obj-c implementation must be seen.
- if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplDecl>(D))
+ // File scoped assembly or obj-c implementation must be seen. ImportDecl is
+ // used by codegen to determine the set of imported modules to search for
+ // inputs for automatic linking.
+ if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplDecl>(D) || isa<ImportDecl>(D))
return true;
return Context.DeclMustBeEmitted(D);
@@ -1906,10 +1916,16 @@
// Flush C++ base specifiers, if there are any.
FlushCXXBaseSpecifiers();
- // Note "external" declarations so that we can add them to a record in the
- // AST file later.
- //
- // FIXME: This should be renamed, the predicate is much more complicated.
+ // Note declarations that should be deserialized eagerly so that we can add
+ // them to a record in the AST file later.
if (isRequiredDecl(D, Context))
- ExternalDefinitions.push_back(ID);
+ EagerlyDeserializedDecls.push_back(ID);
+}
+
+void ASTWriter::AddFunctionDefinition(const FunctionDecl *FD,
+ RecordData &Record) {
+ ClearSwitchCaseIDs();
+
+ ASTDeclWriter W(*this, FD->getASTContext(), Record);
+ W.AddFunctionDefinition(FD);
}
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index 072fc98..dd44a69 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -71,9 +71,8 @@
void ASTStmtWriter::VisitCompoundStmt(CompoundStmt *S) {
VisitStmt(S);
Record.push_back(S->size());
- for (CompoundStmt::body_iterator CS = S->body_begin(), CSEnd = S->body_end();
- CS != CSEnd; ++CS)
- Writer.AddStmt(*CS);
+ for (auto *CS : S->body())
+ Writer.AddStmt(CS);
Writer.AddSourceLocation(S->getLBracLoc(), Record);
Writer.AddSourceLocation(S->getRBracLoc(), Record);
Code = serialization::STMT_COMPOUND;
@@ -300,24 +299,20 @@
Writer.AddDeclRef(S->getCapturedRecordDecl(), Record);
// Capture inits
- for (CapturedStmt::capture_init_iterator I = S->capture_init_begin(),
- E = S->capture_init_end();
- I != E; ++I)
- Writer.AddStmt(*I);
+ for (auto *I : S->capture_inits())
+ Writer.AddStmt(I);
// Body
Writer.AddStmt(S->getCapturedStmt());
// Captures
- for (CapturedStmt::capture_iterator I = S->capture_begin(),
- E = S->capture_end();
- I != E; ++I) {
- if (I->capturesThis())
+ for (const auto &I : S->captures()) {
+ if (I.capturesThis())
Writer.AddDeclRef(0, Record);
else
- Writer.AddDeclRef(I->getCapturedVar(), Record);
- Record.push_back(I->getCaptureKind());
- Writer.AddSourceLocation(I->getLocation(), Record);
+ Writer.AddDeclRef(I.getCapturedVar(), Record);
+ Record.push_back(I.getCaptureKind());
+ Writer.AddSourceLocation(I.getLocation(), Record);
}
Code = serialization::STMT_CAPTURED;
@@ -1486,30 +1481,12 @@
Code = serialization::EXPR_CXX_UNRESOLVED_LOOKUP;
}
-void ASTStmtWriter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
- VisitExpr(E);
- Record.push_back(E->getTrait());
- Record.push_back(E->getValue());
- Writer.AddSourceRange(E->getSourceRange(), Record);
- Writer.AddTypeSourceInfo(E->getQueriedTypeSourceInfo(), Record);
- Code = serialization::EXPR_CXX_UNARY_TYPE_TRAIT;
-}
-
-void ASTStmtWriter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
- VisitExpr(E);
- Record.push_back(E->getTrait());
- Record.push_back(E->getValue());
- Writer.AddSourceRange(E->getSourceRange(), Record);
- Writer.AddTypeSourceInfo(E->getLhsTypeSourceInfo(), Record);
- Writer.AddTypeSourceInfo(E->getRhsTypeSourceInfo(), Record);
- Code = serialization::EXPR_BINARY_TYPE_TRAIT;
-}
-
void ASTStmtWriter::VisitTypeTraitExpr(TypeTraitExpr *E) {
VisitExpr(E);
Record.push_back(E->TypeTraitExprBits.NumArgs);
Record.push_back(E->TypeTraitExprBits.Kind); // FIXME: Stable encoding
Record.push_back(E->TypeTraitExprBits.Value);
+ Writer.AddSourceRange(E->getSourceRange(), Record);
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
Writer.AddTypeSourceInfo(E->getArg(I), Record);
Code = serialization::EXPR_TYPE_TRAIT;
@@ -1697,6 +1674,21 @@
Writer->Writer.AddSourceLocation(C->getLocEnd(), Record);
}
+void OMPClauseWriter::VisitOMPIfClause(OMPIfClause *C) {
+ Writer->Writer.AddStmt(C->getCondition());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+}
+
+void OMPClauseWriter::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
+ Writer->Writer.AddStmt(C->getNumThreads());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+}
+
+void OMPClauseWriter::VisitOMPSafelenClause(OMPSafelenClause *C) {
+ Writer->Writer.AddStmt(C->getSafelen());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+}
+
void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) {
Record.push_back(C->getDefaultKind());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
@@ -1706,36 +1698,35 @@
void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {
Record.push_back(C->varlist_size());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
- for (OMPPrivateClause::varlist_iterator I = C->varlist_begin(),
- E = C->varlist_end();
- I != E; ++I)
- Writer->Writer.AddStmt(*I);
+ for (auto *I : C->varlists())
+ Writer->Writer.AddStmt(I);
}
void OMPClauseWriter::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) {
Record.push_back(C->varlist_size());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
- for (OMPFirstprivateClause::varlist_iterator I = C->varlist_begin(),
- E = C->varlist_end();
- I != E; ++I)
- Writer->Writer.AddStmt(*I);
+ for (auto *I : C->varlists())
+ Writer->Writer.AddStmt(I);
}
void OMPClauseWriter::VisitOMPSharedClause(OMPSharedClause *C) {
Record.push_back(C->varlist_size());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
- for (OMPSharedClause::varlist_iterator I = C->varlist_begin(),
- E = C->varlist_end();
- I != E; ++I)
- Writer->Writer.AddStmt(*I);
+ for (auto *I : C->varlists())
+ Writer->Writer.AddStmt(I);
+}
+
+void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) {
+ Record.push_back(C->varlist_size());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+ for (auto *I : C->varlists())
+ Writer->Writer.AddStmt(I);
}
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
void ASTStmtWriter::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
- VisitStmt(E);
- Record.push_back(E->getNumClauses());
Writer.AddSourceLocation(E->getLocStart(), Record);
Writer.AddSourceLocation(E->getLocEnd(), Record);
OMPClauseWriter ClauseWriter(this, Record);
@@ -1746,10 +1737,20 @@
}
void ASTStmtWriter::VisitOMPParallelDirective(OMPParallelDirective *D) {
+ VisitStmt(D);
+ Record.push_back(D->getNumClauses());
VisitOMPExecutableDirective(D);
Code = serialization::STMT_OMP_PARALLEL_DIRECTIVE;
}
+void ASTStmtWriter::VisitOMPSimdDirective(OMPSimdDirective *D) {
+ VisitStmt(D);
+ Record.push_back(D->getNumClauses());
+ Record.push_back(D->getCollapsedNumber());
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_SIMD_DIRECTIVE;
+}
+
//===----------------------------------------------------------------------===//
// ASTWriter Implementation
//===----------------------------------------------------------------------===//
@@ -1812,7 +1813,7 @@
ParentStmtInserterRAII ParentStmtInserter(S, ParentStmts);
#endif
- // Redirect ASTWriter::AddStmt to collect sub stmts.
+ // Redirect ASTWriter::AddStmt to collect sub-stmts.
SmallVector<Stmt *, 16> SubStmts;
CollectedStmts = &SubStmts;
@@ -1825,16 +1826,16 @@
SourceManager &SrcMgr
= DeclIDs.begin()->first->getASTContext().getSourceManager();
S->dump(SrcMgr);
- llvm_unreachable("Unhandled sub statement writing AST file");
+ llvm_unreachable("Unhandled sub-statement writing AST file");
}
#endif
// Revert ASTWriter::AddStmt.
CollectedStmts = &StmtsToEmit;
- // Write the sub stmts in reverse order, last to first. When reading them back
+ // Write the sub-stmts in reverse order, last to first. When reading them back
// we will read them in correct order by "pop"ing them from the Stmts stack.
- // This simplifies reading and allows to store a variable number of sub stmts
+ // This simplifies reading and allows to store a variable number of sub-stmts
// without knowing it in advance.
while (!SubStmts.empty())
WriteSubStmt(SubStmts.pop_back_val(), SubStmtEntries, ParentStmts);
@@ -1851,7 +1852,7 @@
// We expect to be the only consumer of the two temporary statement maps,
// assert that they are empty.
- assert(SubStmtEntries.empty() && "unexpected entries in sub stmt map");
+ assert(SubStmtEntries.empty() && "unexpected entries in sub-stmt map");
assert(ParentStmts.empty() && "unexpected entries in parent stmt map");
for (unsigned I = 0, N = StmtsToEmit.size(); I != N; ++I) {
diff --git a/lib/Serialization/CMakeLists.txt b/lib/Serialization/CMakeLists.txt
index 3c68b64..d885db2 100644
--- a/lib/Serialization/CMakeLists.txt
+++ b/lib/Serialization/CMakeLists.txt
@@ -1,8 +1,10 @@
-set(LLVM_LINK_COMPONENTS bitreader)
+set(LLVM_LINK_COMPONENTS
+ BitReader
+ Support
+ )
+
add_clang_library(clangSerialization
- ASTCommon.h
- ASTReaderInternals.h
ASTCommon.cpp
ASTReader.cpp
ASTReaderDecl.cpp
@@ -14,23 +16,14 @@
GlobalModuleIndex.cpp
Module.cpp
ModuleManager.cpp
- )
-add_dependencies(clangSerialization
- ClangAttrClasses
- ClangAttrList
- ClangAttrParsedAttrList
- ClangAttrPCHRead
- ClangAttrPCHWrite
- ClangCommentNodes
- ClangDeclNodes
- ClangDiagnosticCommon
- ClangDiagnosticLex
- ClangDiagnosticSema
- ClangDiagnosticSerialization
- ClangStmtNodes
- )
+ ADDITIONAL_HEADERS
+ ASTCommon.h
+ ASTReaderInternals.h
-target_link_libraries(clangSerialization
+ LINK_LIBS
+ clangAST
+ clangBasic
+ clangLex
clangSema
)
diff --git a/lib/Serialization/GlobalModuleIndex.cpp b/lib/Serialization/GlobalModuleIndex.cpp
index fb647b0..14b149f 100644
--- a/lib/Serialization/GlobalModuleIndex.cpp
+++ b/lib/Serialization/GlobalModuleIndex.cpp
@@ -82,9 +82,9 @@
static std::pair<unsigned, unsigned>
ReadKeyDataLength(const unsigned char*& d) {
- using namespace clang::io;
- unsigned KeyLen = ReadUnalignedLE16(d);
- unsigned DataLen = ReadUnalignedLE16(d);
+ using namespace llvm::support;
+ unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d);
+ unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d);
return std::make_pair(KeyLen, DataLen);
}
@@ -101,11 +101,11 @@
static data_type ReadData(const internal_key_type& k,
const unsigned char* d,
unsigned DataLen) {
- using namespace clang::io;
+ using namespace llvm::support;
data_type Result;
while (DataLen > 0) {
- unsigned ID = ReadUnalignedLE32(d);
+ unsigned ID = endian::readNext<uint32_t, little, unaligned>(d);
Result.push_back(ID);
DataLen -= 4;
}
@@ -228,7 +228,7 @@
IndexPath += Path;
llvm::sys::path::append(IndexPath, IndexFileName);
- llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
+ std::unique_ptr<llvm::MemoryBuffer> Buffer;
if (llvm::MemoryBuffer::getFile(IndexPath.c_str(), Buffer) !=
llvm::errc::success)
return std::make_pair((GlobalModuleIndex *)0, EC_NotFound);
@@ -247,8 +247,9 @@
Cursor.Read(8) != 'I') {
return std::make_pair((GlobalModuleIndex *)0, EC_IOError);
}
-
- return std::make_pair(new GlobalModuleIndex(Buffer.take(), Cursor), EC_None);
+
+ return std::make_pair(new GlobalModuleIndex(Buffer.release(), Cursor),
+ EC_None);
}
void
@@ -458,8 +459,8 @@
unsigned DataLen) {
// The first bit indicates whether this identifier is interesting.
// That's all we care about.
- using namespace clang::io;
- unsigned RawID = ReadUnalignedLE32(d);
+ using namespace llvm::support;
+ unsigned RawID = endian::readNext<uint32_t, little, unaligned>(d);
bool IsInteresting = RawID & 0x01;
return std::make_pair(k, IsInteresting);
}
@@ -468,7 +469,7 @@
bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
// Open the module file.
- OwningPtr<llvm::MemoryBuffer> Buffer;
+ std::unique_ptr<llvm::MemoryBuffer> Buffer;
std::string ErrorStr;
Buffer.reset(FileMgr.getBufferForFile(File, &ErrorStr, /*isVolatile=*/true));
if (!Buffer) {
@@ -592,10 +593,10 @@
if (State == ASTBlock && Code == IDENTIFIER_TABLE && Record[0] > 0) {
typedef OnDiskChainedHashTable<InterestingASTIdentifierLookupTrait>
InterestingIdentifierTable;
- llvm::OwningPtr<InterestingIdentifierTable>
- Table(InterestingIdentifierTable::Create(
- (const unsigned char *)Blob.data() + Record[0],
- (const unsigned char *)Blob.data()));
+ std::unique_ptr<InterestingIdentifierTable> Table(
+ InterestingIdentifierTable::Create(
+ (const unsigned char *)Blob.data() + Record[0],
+ (const unsigned char *)Blob.data()));
for (InterestingIdentifierTable::data_iterator D = Table->data_begin(),
DEnd = Table->data_end();
D != DEnd; ++D) {
@@ -630,10 +631,12 @@
std::pair<unsigned,unsigned>
EmitKeyDataLength(raw_ostream& Out, key_type_ref Key, data_type_ref Data) {
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
unsigned KeyLen = Key.size();
unsigned DataLen = Data.size() * 4;
- clang::io::Emit16(Out, KeyLen);
- clang::io::Emit16(Out, DataLen);
+ LE.write<uint16_t>(KeyLen);
+ LE.write<uint16_t>(DataLen);
return std::make_pair(KeyLen, DataLen);
}
@@ -643,8 +646,9 @@
void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data,
unsigned DataLen) {
+ using namespace llvm::support;
for (unsigned I = 0, N = Data.size(); I != N; ++I)
- clang::io::Emit32(Out, Data[I]);
+ endian::Writer<little>(Out).write<uint32_t>(Data[I]);
}
};
@@ -706,9 +710,10 @@
SmallString<4096> IdentifierTable;
uint32_t BucketOffset;
{
+ using namespace llvm::support;
llvm::raw_svector_ostream Out(IdentifierTable);
// Make sure that no bucket is at offset 0
- clang::io::Emit32(Out, 0);
+ endian::Writer<little>(Out).write<uint32_t>(0);
BucketOffset = Generator.Emit(Out, Trait);
}
@@ -807,13 +812,12 @@
return EC_IOError;
// Remove the old index file. It isn't relevant any more.
- bool OldIndexExisted;
- llvm::sys::fs::remove(IndexPath.str(), OldIndexExisted);
+ llvm::sys::fs::remove(IndexPath.str());
// Rename the newly-written index file to the proper name.
if (llvm::sys::fs::rename(IndexTmpPath.str(), IndexPath.str())) {
// Rename failed; just remove the
- llvm::sys::fs::remove(IndexTmpPath.str(), OldIndexExisted);
+ llvm::sys::fs::remove(IndexTmpPath.str());
return EC_IOError;
}
@@ -835,7 +839,7 @@
End = Idx.key_end();
}
- virtual StringRef Next() {
+ StringRef Next() override {
if (Current == End)
return StringRef();
diff --git a/lib/Serialization/ModuleManager.cpp b/lib/Serialization/ModuleManager.cpp
index 9c4b3d9..3513eba 100644
--- a/lib/Serialization/ModuleManager.cpp
+++ b/lib/Serialization/ModuleManager.cpp
@@ -86,6 +86,16 @@
NewModule = true;
ModuleEntry = New;
+ New->InputFilesValidationTimestamp = 0;
+ if (New->Kind == MK_Module) {
+ std::string TimestampFilename = New->getTimestampFilename();
+ vfs::Status Status;
+ // A cached stat value would be fine as well.
+ if (!FileMgr.getNoncachedStatValue(TimestampFilename, Status))
+ New->InputFilesValidationTimestamp =
+ Status.getLastModificationTime().toEpochTime();
+ }
+
// Load the contents of the module
if (llvm::MemoryBuffer *Buffer = lookupBuffer(FileName)) {
// The buffer was already provided for us.
@@ -124,22 +134,6 @@
return NewModule? NewlyLoaded : AlreadyLoaded;
}
-namespace {
- /// \brief Predicate that checks whether a module file occurs within
- /// the given set.
- class IsInModuleFileSet : public std::unary_function<ModuleFile *, bool> {
- llvm::SmallPtrSet<ModuleFile *, 4> &Removed;
-
- public:
- IsInModuleFileSet(llvm::SmallPtrSet<ModuleFile *, 4> &Removed)
- : Removed(Removed) { }
-
- bool operator()(ModuleFile *MF) const {
- return Removed.count(MF);
- }
- };
-}
-
void ModuleManager::removeModules(ModuleIterator first, ModuleIterator last,
ModuleMap *modMap) {
if (first == last)
@@ -149,9 +143,10 @@
llvm::SmallPtrSet<ModuleFile *, 4> victimSet(first, last);
// Remove any references to the now-destroyed modules.
- IsInModuleFileSet checkInSet(victimSet);
for (unsigned i = 0, n = Chain.size(); i != n; ++i) {
- Chain[i]->ImportedBy.remove_if(checkInSet);
+ Chain[i]->ImportedBy.remove_if([&](ModuleFile *MF) {
+ return victimSet.count(MF);
+ });
}
// Delete the modules and erase them from the various structures.