aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp4476
1 files changed, 1585 insertions, 2891 deletions
diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp
index 1722572f1a27..490b8cb10a48 100644
--- a/contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp
+++ b/contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp
@@ -10,15 +10,14 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Basic/OpenMPKinds.h"
-#include "clang/Serialization/ASTRecordReader.h"
#include "ASTCommon.h"
#include "ASTReaderInternals.h"
-#include "clang/AST/AbstractTypeReader.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
+#include "clang/AST/ASTStructuralEquivalence.h"
#include "clang/AST/ASTUnresolvedSet.h"
+#include "clang/AST/AbstractTypeReader.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
@@ -31,8 +30,9 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/NestedNameSpecifier.h"
-#include "clang/AST/OpenMPClause.h"
+#include "clang/AST/ODRDiagsEmitter.h"
#include "clang/AST/ODRHash.h"
+#include "clang/AST/OpenMPClause.h"
#include "clang/AST/RawCommentList.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
@@ -42,7 +42,9 @@
#include "clang/AST/UnresolvedSet.h"
#include "clang/Basic/CommentOptions.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticError.h"
#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
@@ -51,6 +53,7 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/ObjCRuntime.h"
+#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PragmaKinds.h"
#include "clang/Basic/Sanitizers.h"
@@ -76,6 +79,7 @@
#include "clang/Sema/Weak.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ASTDeserializationListener.h"
+#include "clang/Serialization/ASTRecordReader.h"
#include "clang/Serialization/ContinuousRangeMap.h"
#include "clang/Serialization/GlobalModuleIndex.h"
#include "clang/Serialization/InMemoryModuleCache.h"
@@ -93,8 +97,6 @@
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/None.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -103,7 +105,6 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Bitstream/BitstreamReader.h"
#include "llvm/Support/Casting.h"
@@ -118,9 +119,11 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SaveAndRestore.h"
+#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/Triple.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
@@ -131,6 +134,7 @@
#include <limits>
#include <map>
#include <memory>
+#include <optional>
#include <string>
#include <system_error>
#include <tuple>
@@ -141,7 +145,6 @@ using namespace clang;
using namespace clang::serialization;
using namespace clang::serialization::reader;
using llvm::BitstreamCursor;
-using llvm::RoundingMode;
//===----------------------------------------------------------------------===//
// ChainedASTReaderListener implementation
@@ -205,11 +208,12 @@ bool ChainedASTReaderListener::ReadHeaderSearchOptions(
}
bool ChainedASTReaderListener::ReadPreprocessorOptions(
- const PreprocessorOptions &PPOpts, bool Complain,
+ const PreprocessorOptions &PPOpts, bool ReadMacros, bool Complain,
std::string &SuggestedPredefines) {
- return First->ReadPreprocessorOptions(PPOpts, Complain,
+ return First->ReadPreprocessorOptions(PPOpts, ReadMacros, Complain,
SuggestedPredefines) ||
- Second->ReadPreprocessorOptions(PPOpts, Complain, SuggestedPredefines);
+ Second->ReadPreprocessorOptions(PPOpts, ReadMacros, Complain,
+ SuggestedPredefines);
}
void ChainedASTReaderListener::ReadCounter(const serialization::ModuleFile &M,
@@ -274,12 +278,17 @@ static bool checkLanguageOptions(const LangOptions &LangOpts,
const LangOptions &ExistingLangOpts,
DiagnosticsEngine *Diags,
bool AllowCompatibleDifferences = true) {
-#define LANGOPT(Name, Bits, Default, Description) \
- if (ExistingLangOpts.Name != LangOpts.Name) { \
- if (Diags) \
- Diags->Report(diag::err_pch_langopt_mismatch) \
- << Description << LangOpts.Name << ExistingLangOpts.Name; \
- return true; \
+#define LANGOPT(Name, Bits, Default, Description) \
+ if (ExistingLangOpts.Name != LangOpts.Name) { \
+ if (Diags) { \
+ if (Bits == 1) \
+ Diags->Report(diag::err_pch_langopt_mismatch) \
+ << Description << LangOpts.Name << ExistingLangOpts.Name; \
+ else \
+ Diags->Report(diag::err_pch_langopt_value_mismatch) \
+ << Description; \
+ } \
+ return true; \
}
#define VALUE_LANGOPT(Name, Bits, Default, Description) \
@@ -312,7 +321,7 @@ static bool checkLanguageOptions(const LangOptions &LangOpts,
#define BENIGN_LANGOPT(Name, Bits, Default, Description)
#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
-#define BENIGN_VALUE_LANGOPT(Name, Type, Bits, Default, Description)
+#define BENIGN_VALUE_LANGOPT(Name, Bits, Default, Description)
#include "clang/Basic/LangOptions.def"
if (ExistingLangOpts.ModuleFeatures != LangOpts.ModuleFeatures) {
@@ -499,14 +508,17 @@ static bool isExtHandlingFromDiagsError(DiagnosticsEngine &Diags) {
}
static bool checkDiagnosticMappings(DiagnosticsEngine &StoredDiags,
- DiagnosticsEngine &Diags,
- bool IsSystem, bool Complain) {
+ DiagnosticsEngine &Diags, bool IsSystem,
+ bool SystemHeaderWarningsInModule,
+ bool Complain) {
// Top-level options
if (IsSystem) {
if (Diags.getSuppressSystemWarnings())
return false;
- // If -Wsystem-headers was not enabled before, be conservative
- if (StoredDiags.getSuppressSystemWarnings()) {
+ // If -Wsystem-headers was not enabled before, and it was not explicit,
+ // be conservative
+ if (StoredDiags.getSuppressSystemWarnings() &&
+ !SystemHeaderWarningsInModule) {
if (Complain)
Diags.Report(diag::err_pch_diagopt_mismatch) << "-Wsystem-headers";
return true;
@@ -555,7 +567,8 @@ static Module *getTopImportImplicitModule(ModuleManager &ModuleMgr,
StringRef ModuleName = TopImport->ModuleName;
assert(!ModuleName.empty() && "diagnostic options read before module name");
- Module *M = PP.getHeaderSearchInfo().lookupModule(ModuleName);
+ Module *M =
+ PP.getHeaderSearchInfo().lookupModule(ModuleName, TopImport->ImportLoc);
assert(M && "missing module");
return M;
}
@@ -577,10 +590,17 @@ bool PCHValidator::ReadDiagnosticOptions(
if (!TopM)
return false;
+ Module *Importer = PP.getCurrentModule();
+
+ DiagnosticOptions &ExistingOpts = ExistingDiags.getDiagnosticOptions();
+ bool SystemHeaderWarningsInModule =
+ Importer && llvm::is_contained(ExistingOpts.SystemHeaderWarningsModules,
+ Importer->Name);
+
// FIXME: if the diagnostics are incompatible, save a DiagnosticOptions that
// contains the union of their flags.
return checkDiagnosticMappings(*Diags, ExistingDiags, TopM->IsSystem,
- Complain);
+ SystemHeaderWarningsInModule, Complain);
}
/// Collect the macro definitions provided by the given preprocessor
@@ -621,79 +641,119 @@ collectMacroDefinitions(const PreprocessorOptions &PPOpts,
}
}
+enum OptionValidation {
+ OptionValidateNone,
+ OptionValidateContradictions,
+ OptionValidateStrictMatches,
+};
+
/// Check the preprocessor options deserialized from the control block
/// against the preprocessor options in an existing preprocessor.
///
/// \param Diags If non-null, produce diagnostics for any mismatches incurred.
-/// \param Validate If true, validate preprocessor options. If false, allow
-/// macros defined by \p ExistingPPOpts to override those defined by
-/// \p PPOpts in SuggestedPredefines.
-static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
- const PreprocessorOptions &ExistingPPOpts,
- DiagnosticsEngine *Diags,
- FileManager &FileMgr,
- std::string &SuggestedPredefines,
- const LangOptions &LangOpts,
- bool Validate = true) {
- // Check macro definitions.
- MacroDefinitionsMap ASTFileMacros;
- collectMacroDefinitions(PPOpts, ASTFileMacros);
- MacroDefinitionsMap ExistingMacros;
- SmallVector<StringRef, 4> ExistingMacroNames;
- collectMacroDefinitions(ExistingPPOpts, ExistingMacros, &ExistingMacroNames);
-
- for (unsigned I = 0, N = ExistingMacroNames.size(); I != N; ++I) {
- // Dig out the macro definition in the existing preprocessor options.
- StringRef MacroName = ExistingMacroNames[I];
- std::pair<StringRef, bool> Existing = ExistingMacros[MacroName];
-
- // Check whether we know anything about this macro name or not.
- llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/>>::iterator Known =
- ASTFileMacros.find(MacroName);
- if (!Validate || Known == ASTFileMacros.end()) {
- // FIXME: Check whether this identifier was referenced anywhere in the
- // AST file. If so, we should reject the AST file. Unfortunately, this
- // information isn't in the control block. What shall we do about it?
-
- if (Existing.second) {
- SuggestedPredefines += "#undef ";
- SuggestedPredefines += MacroName.str();
- SuggestedPredefines += '\n';
- } else {
- SuggestedPredefines += "#define ";
- SuggestedPredefines += MacroName.str();
- SuggestedPredefines += ' ';
- SuggestedPredefines += Existing.first.str();
- SuggestedPredefines += '\n';
+/// \param Validation If set to OptionValidateNone, ignore differences in
+/// preprocessor options. If set to OptionValidateContradictions,
+/// require that options passed both in the AST file and on the command
+/// line (-D or -U) match, but tolerate options missing in one or the
+/// other. If set to OptionValidateContradictions, require that there
+/// are no differences in the options between the two.
+static bool checkPreprocessorOptions(
+ const PreprocessorOptions &PPOpts,
+ const PreprocessorOptions &ExistingPPOpts, bool ReadMacros,
+ DiagnosticsEngine *Diags, FileManager &FileMgr,
+ std::string &SuggestedPredefines, const LangOptions &LangOpts,
+ OptionValidation Validation = OptionValidateContradictions) {
+ if (ReadMacros) {
+ // Check macro definitions.
+ MacroDefinitionsMap ASTFileMacros;
+ collectMacroDefinitions(PPOpts, ASTFileMacros);
+ MacroDefinitionsMap ExistingMacros;
+ SmallVector<StringRef, 4> ExistingMacroNames;
+ collectMacroDefinitions(ExistingPPOpts, ExistingMacros,
+ &ExistingMacroNames);
+
+ // Use a line marker to enter the <command line> file, as the defines and
+ // undefines here will have come from the command line.
+ SuggestedPredefines += "# 1 \"<command line>\" 1\n";
+
+ for (unsigned I = 0, N = ExistingMacroNames.size(); I != N; ++I) {
+ // Dig out the macro definition in the existing preprocessor options.
+ StringRef MacroName = ExistingMacroNames[I];
+ std::pair<StringRef, bool> Existing = ExistingMacros[MacroName];
+
+ // Check whether we know anything about this macro name or not.
+ llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/>>::iterator Known =
+ ASTFileMacros.find(MacroName);
+ if (Validation == OptionValidateNone || Known == ASTFileMacros.end()) {
+ if (Validation == OptionValidateStrictMatches) {
+ // If strict matches are requested, don't tolerate any extra defines
+ // on the command line that are missing in the AST file.
+ if (Diags) {
+ Diags->Report(diag::err_pch_macro_def_undef) << MacroName << true;
+ }
+ return true;
+ }
+ // FIXME: Check whether this identifier was referenced anywhere in the
+ // AST file. If so, we should reject the AST file. Unfortunately, this
+ // information isn't in the control block. What shall we do about it?
+
+ if (Existing.second) {
+ SuggestedPredefines += "#undef ";
+ SuggestedPredefines += MacroName.str();
+ SuggestedPredefines += '\n';
+ } else {
+ SuggestedPredefines += "#define ";
+ SuggestedPredefines += MacroName.str();
+ SuggestedPredefines += ' ';
+ SuggestedPredefines += Existing.first.str();
+ SuggestedPredefines += '\n';
+ }
+ continue;
+ }
+
+ // If the macro was defined in one but undef'd in the other, we have a
+ // conflict.
+ if (Existing.second != Known->second.second) {
+ if (Diags) {
+ Diags->Report(diag::err_pch_macro_def_undef)
+ << MacroName << Known->second.second;
+ }
+ return true;
+ }
+
+ // If the macro was #undef'd in both, or if the macro bodies are
+ // identical, it's fine.
+ if (Existing.second || Existing.first == Known->second.first) {
+ ASTFileMacros.erase(Known);
+ continue;
}
- continue;
- }
- // If the macro was defined in one but undef'd in the other, we have a
- // conflict.
- if (Existing.second != Known->second.second) {
+ // The macro bodies differ; complain.
if (Diags) {
- Diags->Report(diag::err_pch_macro_def_undef)
- << MacroName << Known->second.second;
+ Diags->Report(diag::err_pch_macro_def_conflict)
+ << MacroName << Known->second.first << Existing.first;
}
return true;
}
- // If the macro was #undef'd in both, or if the macro bodies are identical,
- // it's fine.
- if (Existing.second || Existing.first == Known->second.first)
- continue;
+ // Leave the <command line> file and return to <built-in>.
+ SuggestedPredefines += "# 1 \"<built-in>\" 2\n";
- // The macro bodies differ; complain.
- if (Diags) {
- Diags->Report(diag::err_pch_macro_def_conflict)
- << MacroName << Known->second.first << Existing.first;
+ if (Validation == OptionValidateStrictMatches) {
+ // If strict matches are requested, don't tolerate any extra defines in
+ // the AST file that are missing on the command line.
+ for (const auto &MacroName : ASTFileMacros.keys()) {
+ if (Diags) {
+ Diags->Report(diag::err_pch_macro_def_undef) << MacroName << false;
+ }
+ return true;
+ }
}
- return true;
}
// Check whether we're using predefines.
- if (PPOpts.UsePredefines != ExistingPPOpts.UsePredefines && Validate) {
+ if (PPOpts.UsePredefines != ExistingPPOpts.UsePredefines &&
+ Validation != OptionValidateNone) {
if (Diags) {
Diags->Report(diag::err_pch_undef) << ExistingPPOpts.UsePredefines;
}
@@ -702,7 +762,8 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
// Detailed record is important since it is used for the module cache hash.
if (LangOpts.Modules &&
- PPOpts.DetailedRecord != ExistingPPOpts.DetailedRecord && Validate) {
+ PPOpts.DetailedRecord != ExistingPPOpts.DetailedRecord &&
+ Validation != OptionValidateNone) {
if (Diags) {
Diags->Report(diag::err_pch_pp_detailed_record) << PPOpts.DetailedRecord;
}
@@ -726,8 +787,7 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
if (File == ExistingPPOpts.ImplicitPCHInclude)
continue;
- if (std::find(PPOpts.Includes.begin(), PPOpts.Includes.end(), File)
- != PPOpts.Includes.end())
+ if (llvm::is_contained(PPOpts.Includes, File))
continue;
SuggestedPredefines += "#include \"";
@@ -737,9 +797,7 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
for (unsigned I = 0, N = ExistingPPOpts.MacroIncludes.size(); I != N; ++I) {
StringRef File = ExistingPPOpts.MacroIncludes[I];
- if (std::find(PPOpts.MacroIncludes.begin(), PPOpts.MacroIncludes.end(),
- File)
- != PPOpts.MacroIncludes.end())
+ if (llvm::is_contained(PPOpts.MacroIncludes, File))
continue;
SuggestedPredefines += "#__include_macros \"";
@@ -751,28 +809,22 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
}
bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
- bool Complain,
+ bool ReadMacros, bool Complain,
std::string &SuggestedPredefines) {
const PreprocessorOptions &ExistingPPOpts = PP.getPreprocessorOpts();
- return checkPreprocessorOptions(PPOpts, ExistingPPOpts,
- Complain? &Reader.Diags : nullptr,
- PP.getFileManager(),
- SuggestedPredefines,
- PP.getLangOpts());
+ return checkPreprocessorOptions(
+ PPOpts, ExistingPPOpts, ReadMacros, Complain ? &Reader.Diags : nullptr,
+ PP.getFileManager(), SuggestedPredefines, PP.getLangOpts());
}
bool SimpleASTReaderListener::ReadPreprocessorOptions(
- const PreprocessorOptions &PPOpts,
- bool Complain,
- std::string &SuggestedPredefines) {
- return checkPreprocessorOptions(PPOpts,
- PP.getPreprocessorOpts(),
- nullptr,
- PP.getFileManager(),
- SuggestedPredefines,
- PP.getLangOpts(),
- false);
+ const PreprocessorOptions &PPOpts, bool ReadMacros, bool Complain,
+ std::string &SuggestedPredefines) {
+ return checkPreprocessorOptions(PPOpts, PP.getPreprocessorOpts(), ReadMacros,
+ nullptr, PP.getFileManager(),
+ SuggestedPredefines, PP.getLangOpts(),
+ OptionValidateNone);
}
/// Check the header search options deserialized from the control block
@@ -860,9 +912,10 @@ ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) {
using namespace llvm::support;
SelectorTable &SelTable = Reader.getContext().Selectors;
- unsigned N = endian::readNext<uint16_t, little, unaligned>(d);
+ unsigned N =
+ endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d);
IdentifierInfo *FirstII = Reader.getLocalIdentifier(
- F, endian::readNext<uint32_t, little, unaligned>(d));
+ F, endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d));
if (N == 0)
return SelTable.getNullarySelector(FirstII);
else if (N == 1)
@@ -872,7 +925,7 @@ ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) {
Args.push_back(FirstII);
for (unsigned I = 1; I != N; ++I)
Args.push_back(Reader.getLocalIdentifier(
- F, endian::readNext<uint32_t, little, unaligned>(d)));
+ F, endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d)));
return SelTable.getSelector(N, Args.data());
}
@@ -885,9 +938,11 @@ ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d,
data_type Result;
Result.ID = Reader.getGlobalSelectorID(
- F, endian::readNext<uint32_t, little, unaligned>(d));
- unsigned FullInstanceBits = endian::readNext<uint16_t, little, unaligned>(d);
- unsigned FullFactoryBits = endian::readNext<uint16_t, little, unaligned>(d);
+ F, endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d));
+ unsigned FullInstanceBits =
+ endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d);
+ unsigned FullFactoryBits =
+ endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d);
Result.InstanceBits = FullInstanceBits & 0x3;
Result.InstanceHasMoreThanOneDecl = (FullInstanceBits >> 2) & 0x1;
Result.FactoryBits = FullFactoryBits & 0x3;
@@ -898,14 +953,16 @@ ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d,
// Load instance methods
for (unsigned I = 0; I != NumInstanceMethods; ++I) {
if (ObjCMethodDecl *Method = Reader.GetLocalDeclAs<ObjCMethodDecl>(
- F, endian::readNext<uint32_t, little, unaligned>(d)))
+ F,
+ endian::readNext<uint32_t, llvm::endianness::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, endian::readNext<uint32_t, little, unaligned>(d)))
+ F,
+ endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d)))
Result.Factory.push_back(Method);
}
@@ -946,7 +1003,8 @@ static bool readBit(unsigned &Bits) {
IdentID ASTIdentifierLookupTrait::ReadIdentifierID(const unsigned char *d) {
using namespace llvm::support;
- unsigned RawID = endian::readNext<uint32_t, little, unaligned>(d);
+ unsigned RawID =
+ endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d);
return Reader.getGlobalIdentifierID(F, RawID >> 1);
}
@@ -964,7 +1022,8 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
unsigned DataLen) {
using namespace llvm::support;
- unsigned RawID = endian::readNext<uint32_t, little, unaligned>(d);
+ unsigned RawID =
+ endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d);
bool IsInteresting = RawID & 0x01;
// Wipe out the "is interesting" bit.
@@ -987,8 +1046,10 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
return II;
}
- unsigned ObjCOrBuiltinID = endian::readNext<uint16_t, little, unaligned>(d);
- unsigned Bits = endian::readNext<uint16_t, little, unaligned>(d);
+ unsigned ObjCOrBuiltinID =
+ endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d);
+ unsigned Bits =
+ endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d);
bool CPlusPlusOperatorKeyword = readBit(Bits);
bool HasRevertedTokenIDToIdentifier = readBit(Bits);
bool Poisoned = readBit(Bits);
@@ -1017,7 +1078,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
// definition.
if (HadMacroDefinition) {
uint32_t MacroDirectivesOffset =
- endian::readNext<uint32_t, little, unaligned>(d);
+ endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d);
DataLen -= 4;
Reader.addPendingMacro(II, &F, MacroDirectivesOffset);
@@ -1031,7 +1092,8 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
SmallVector<uint32_t, 4> DeclIDs;
for (; DataLen > 0; DataLen -= 4)
DeclIDs.push_back(Reader.getGlobalDeclID(
- F, endian::readNext<uint32_t, little, unaligned>(d)));
+ F,
+ endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d)));
Reader.SetGloballyVisibleDecls(II, DeclIDs);
}
@@ -1100,7 +1162,8 @@ ModuleFile *
ASTDeclContextNameLookupTrait::ReadFileRef(const unsigned char *&d) {
using namespace llvm::support;
- uint32_t ModuleFileID = endian::readNext<uint32_t, little, unaligned>(d);
+ uint32_t ModuleFileID =
+ endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d);
return Reader.getLocalModuleFile(F, ModuleFileID);
}
@@ -1120,15 +1183,18 @@ ASTDeclContextNameLookupTrait::ReadKey(const unsigned char *d, unsigned) {
case DeclarationName::CXXLiteralOperatorName:
case DeclarationName::CXXDeductionGuideName:
Data = (uint64_t)Reader.getLocalIdentifier(
- F, endian::readNext<uint32_t, little, unaligned>(d));
+ F, endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d));
break;
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
Data =
- (uint64_t)Reader.getLocalSelector(
- F, endian::readNext<uint32_t, little, unaligned>(
- d)).getAsOpaquePtr();
+ (uint64_t)Reader
+ .getLocalSelector(
+ F,
+ endian::readNext<uint32_t, llvm::endianness::little, unaligned>(
+ d))
+ .getAsOpaquePtr();
break;
case DeclarationName::CXXOperatorName:
Data = *d++; // OverloadedOperatorKind
@@ -1151,7 +1217,8 @@ void ASTDeclContextNameLookupTrait::ReadDataInto(internal_key_type,
using namespace llvm::support;
for (unsigned NumDecls = DataLen / 4; NumDecls; --NumDecls) {
- uint32_t LocalID = endian::readNext<uint32_t, little, unaligned>(d);
+ uint32_t LocalID =
+ endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d);
Val.insert(Reader.getGlobalDeclID(F, LocalID));
}
}
@@ -1197,7 +1264,7 @@ bool ASTReader::ReadLexicalDeclContextStorage(ModuleFile &M,
auto &Lex = LexicalDecls[DC];
if (!Lex.first) {
Lex = std::make_pair(
- &M, llvm::makeArrayRef(
+ &M, llvm::ArrayRef(
reinterpret_cast<const llvm::support::unaligned_uint32_t *>(
Blob.data()),
Blob.size() / 4));
@@ -1263,7 +1330,29 @@ void ASTReader::Error(unsigned DiagID, StringRef Arg1, StringRef Arg2,
}
void ASTReader::Error(llvm::Error &&Err) const {
- Error(toString(std::move(Err)));
+ llvm::Error RemainingErr =
+ handleErrors(std::move(Err), [this](const DiagnosticError &E) {
+ auto Diag = E.getDiagnostic().second;
+
+ // Ideally we'd just emit it, but have to handle a possible in-flight
+ // diagnostic. Note that the location is currently ignored as well.
+ auto NumArgs = Diag.getStorage()->NumDiagArgs;
+ assert(NumArgs <= 3 && "Can only have up to 3 arguments");
+ StringRef Arg1, Arg2, Arg3;
+ switch (NumArgs) {
+ case 3:
+ Arg3 = Diag.getStringArg(2);
+ [[fallthrough]];
+ case 2:
+ Arg2 = Diag.getStringArg(1);
+ [[fallthrough]];
+ case 1:
+ Arg1 = Diag.getStringArg(0);
+ }
+ Error(Diag.getDiagID(), Arg1, Arg2, Arg3);
+ });
+ if (RemainingErr)
+ Error(toString(std::move(RemainingErr)));
}
//===----------------------------------------------------------------------===//
@@ -1271,9 +1360,7 @@ void ASTReader::Error(llvm::Error &&Err) const {
//===----------------------------------------------------------------------===//
/// Read the line table in the source manager block.
-/// \returns true if there was an error.
-bool ASTReader::ParseLineTable(ModuleFile &F,
- const RecordData &Record) {
+void ASTReader::ParseLineTable(ModuleFile &F, const RecordData &Record) {
unsigned Idx = 0;
LineTableInfo &LineTable = SourceMgr.getLineTable();
@@ -1290,10 +1377,7 @@ bool ASTReader::ParseLineTable(ModuleFile &F,
// Parse the line entries
std::vector<LineEntry> Entries;
while (Idx < Record.size()) {
- int FID = Record[Idx++];
- assert(FID >= 0 && "Serialized line entries for non-local file.");
- // Remap FileID from 1-based old view.
- FID += F.SLocEntryBaseID - 1;
+ FileID FID = ReadFileID(F, Record, Idx);
// Extract the line entries
unsigned NumEntries = Record[Idx++];
@@ -1310,14 +1394,12 @@ bool ASTReader::ParseLineTable(ModuleFile &F,
Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID,
FileKind, IncludeOffset));
}
- LineTable.AddEntry(FileID::get(FID), Entries);
+ LineTable.AddEntry(FID, Entries);
}
-
- return false;
}
/// Read a source manager block
-bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) {
+llvm::Error ASTReader::ReadSourceManagerBlock(ModuleFile &F) {
using namespace SrcMgr;
BitstreamCursor &SLocEntryCursor = F.SLocEntryCursor;
@@ -1329,36 +1411,29 @@ bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) {
SLocEntryCursor = F.Stream;
// The stream itself is going to skip over the source manager block.
- if (llvm::Error Err = F.Stream.SkipBlock()) {
- Error(std::move(Err));
- return true;
- }
+ if (llvm::Error Err = F.Stream.SkipBlock())
+ return Err;
// Enter the source manager block.
- if (llvm::Error Err =
- SLocEntryCursor.EnterSubBlock(SOURCE_MANAGER_BLOCK_ID)) {
- Error(std::move(Err));
- return true;
- }
+ if (llvm::Error Err = SLocEntryCursor.EnterSubBlock(SOURCE_MANAGER_BLOCK_ID))
+ return Err;
F.SourceManagerBlockStartOffset = SLocEntryCursor.GetCurrentBitNo();
RecordData Record;
while (true) {
Expected<llvm::BitstreamEntry> MaybeE =
SLocEntryCursor.advanceSkippingSubblocks();
- if (!MaybeE) {
- Error(MaybeE.takeError());
- return true;
- }
+ if (!MaybeE)
+ return MaybeE.takeError();
llvm::BitstreamEntry E = MaybeE.get();
switch (E.Kind) {
case llvm::BitstreamEntry::SubBlock: // Handled for us already.
case llvm::BitstreamEntry::Error:
- Error("malformed block record in AST file");
- return true;
+ return llvm::createStringError(std::errc::illegal_byte_sequence,
+ "malformed block record in AST file");
case llvm::BitstreamEntry::EndBlock:
- return false;
+ return llvm::Error::success();
case llvm::BitstreamEntry::Record:
// The interesting case.
break;
@@ -1369,10 +1444,8 @@ bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) {
StringRef Blob;
Expected<unsigned> MaybeRecord =
SLocEntryCursor.readRecord(E.ID, Record, &Blob);
- if (!MaybeRecord) {
- Error(MaybeRecord.takeError());
- return true;
- }
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
switch (MaybeRecord.get()) {
default: // Default behavior: ignore.
break;
@@ -1381,44 +1454,82 @@ bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) {
case SM_SLOC_BUFFER_ENTRY:
case SM_SLOC_EXPANSION_ENTRY:
// Once we hit one of the source location entries, we're done.
- return false;
+ return llvm::Error::success();
}
}
}
-/// If a header file is not found at the path that we expect it to be
-/// and the PCH file was moved from its original location, try to resolve the
-/// file by assuming that header+PCH were moved together and the header is in
-/// the same place relative to the PCH.
-static std::string
-resolveFileRelativeToOriginalDir(const std::string &Filename,
- const std::string &OriginalDir,
- const std::string &CurrDir) {
- assert(OriginalDir != CurrDir &&
- "No point trying to resolve the file if the PCH dir didn't change");
+llvm::Expected<SourceLocation::UIntTy>
+ASTReader::readSLocOffset(ModuleFile *F, unsigned Index) {
+ BitstreamCursor &Cursor = F->SLocEntryCursor;
+ SavedStreamPosition SavedPosition(Cursor);
+ if (llvm::Error Err = Cursor.JumpToBit(F->SLocEntryOffsetsBase +
+ F->SLocEntryOffsets[Index]))
+ return std::move(Err);
- using namespace llvm::sys;
+ Expected<llvm::BitstreamEntry> MaybeEntry = Cursor.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
+ if (Entry.Kind != llvm::BitstreamEntry::Record)
+ return llvm::createStringError(
+ std::errc::illegal_byte_sequence,
+ "incorrectly-formatted source location entry in AST file");
- SmallString<128> filePath(Filename);
- fs::make_absolute(filePath);
- assert(path::is_absolute(OriginalDir));
- SmallString<128> currPCHPath(CurrDir);
+ RecordData Record;
+ StringRef Blob;
+ Expected<unsigned> MaybeSLOC = Cursor.readRecord(Entry.ID, Record, &Blob);
+ if (!MaybeSLOC)
+ return MaybeSLOC.takeError();
- path::const_iterator fileDirI = path::begin(path::parent_path(filePath)),
- fileDirE = path::end(path::parent_path(filePath));
- path::const_iterator origDirI = path::begin(OriginalDir),
- origDirE = path::end(OriginalDir);
- // Skip the common path components from filePath and OriginalDir.
- while (fileDirI != fileDirE && origDirI != origDirE &&
- *fileDirI == *origDirI) {
- ++fileDirI;
- ++origDirI;
+ switch (MaybeSLOC.get()) {
+ default:
+ return llvm::createStringError(
+ std::errc::illegal_byte_sequence,
+ "incorrectly-formatted source location entry in AST file");
+ case SM_SLOC_FILE_ENTRY:
+ case SM_SLOC_BUFFER_ENTRY:
+ case SM_SLOC_EXPANSION_ENTRY:
+ return F->SLocEntryBaseOffset + Record[0];
}
- for (; origDirI != origDirE; ++origDirI)
- path::append(currPCHPath, "..");
- path::append(currPCHPath, fileDirI, fileDirE);
- path::append(currPCHPath, path::filename(Filename));
- return std::string(currPCHPath.str());
+}
+
+int ASTReader::getSLocEntryID(SourceLocation::UIntTy SLocOffset) {
+ auto SLocMapI =
+ GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset - SLocOffset - 1);
+ assert(SLocMapI != GlobalSLocOffsetMap.end() &&
+ "Corrupted global sloc offset map");
+ ModuleFile *F = SLocMapI->second;
+
+ bool Invalid = false;
+
+ auto It = llvm::upper_bound(
+ llvm::index_range(0, F->LocalNumSLocEntries), SLocOffset,
+ [&](SourceLocation::UIntTy Offset, std::size_t LocalIndex) {
+ int ID = F->SLocEntryBaseID + LocalIndex;
+ std::size_t Index = -ID - 2;
+ if (!SourceMgr.SLocEntryOffsetLoaded[Index]) {
+ assert(!SourceMgr.SLocEntryLoaded[Index]);
+ auto MaybeEntryOffset = readSLocOffset(F, LocalIndex);
+ if (!MaybeEntryOffset) {
+ Error(MaybeEntryOffset.takeError());
+ Invalid = true;
+ return true;
+ }
+ SourceMgr.LoadedSLocEntryTable[Index] =
+ SrcMgr::SLocEntry::getOffsetOnly(*MaybeEntryOffset);
+ SourceMgr.SLocEntryOffsetLoaded[Index] = true;
+ }
+ return Offset < SourceMgr.LoadedSLocEntryTable[Index].getOffset();
+ });
+
+ if (Invalid)
+ return 0;
+
+ // The iterator points to the first entry with start offset greater than the
+ // offset of interest. The previous entry must contain the offset of interest.
+ return F->SLocEntryBaseID + *std::prev(It);
}
bool ASTReader::ReadSLocEntry(int ID) {
@@ -1453,18 +1564,25 @@ bool ASTReader::ReadSLocEntry(int ID) {
unsigned RecCode = MaybeRecCode.get();
if (RecCode == SM_SLOC_BUFFER_BLOB_COMPRESSED) {
- if (!llvm::zlib::isAvailable()) {
- Error("zlib is not available");
+ // Inspect the first byte to differentiate zlib (\x78) and zstd
+ // (little-endian 0xFD2FB528).
+ const llvm::compression::Format F =
+ Blob.size() > 0 && Blob.data()[0] == 0x78
+ ? llvm::compression::Format::Zlib
+ : llvm::compression::Format::Zstd;
+ if (const char *Reason = llvm::compression::getReasonIfUnsupported(F)) {
+ Error(Reason);
return nullptr;
}
- SmallString<0> Uncompressed;
- if (llvm::Error E =
- llvm::zlib::uncompress(Blob, Uncompressed, Record[0])) {
+ SmallVector<uint8_t, 0> Decompressed;
+ if (llvm::Error E = llvm::compression::decompress(
+ F, llvm::arrayRefFromStringRef(Blob), Decompressed, Record[0])) {
Error("could not decompress embedded file contents: " +
llvm::toString(std::move(E)));
return nullptr;
}
- return llvm::MemoryBuffer::getMemBufferCopy(Uncompressed, Name);
+ return llvm::MemoryBuffer::getMemBufferCopy(
+ llvm::toStringRef(Decompressed), Name);
} else if (RecCode == SM_SLOC_BUFFER_BLOB) {
return llvm::MemoryBuffer::getMemBuffer(Blob.drop_back(1), Name, true);
} else {
@@ -1515,7 +1633,7 @@ bool ASTReader::ReadSLocEntry(int ID) {
// we will also try to fail gracefully by setting up the SLocEntry.
unsigned InputID = Record[4];
InputFile IF = getInputFile(*F, InputID);
- Optional<FileEntryRef> File = IF.getFile();
+ OptionalFileEntryRef File = IF.getFile();
bool OverriddenBuffer = IF.isOverridden();
// Note that we only check if a File was returned. If it was out-of-date
@@ -1543,8 +1661,8 @@ bool ASTReader::ReadSLocEntry(int ID) {
if (NumFileDecls && ContextObj) {
const DeclID *FirstDecl = F->FileSortedDecls + Record[6];
assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?");
- FileDeclIDs[FID] = FileDeclsInfo(F, llvm::makeArrayRef(FirstDecl,
- NumFileDecls));
+ FileDeclIDs[FID] =
+ FileDeclsInfo(F, llvm::ArrayRef(FirstDecl, NumFileDecls));
}
const SrcMgr::ContentCache &ContentCache =
@@ -1574,20 +1692,24 @@ bool ASTReader::ReadSLocEntry(int ID) {
auto Buffer = ReadBuffer(SLocEntryCursor, Name);
if (!Buffer)
return true;
- SourceMgr.createFileID(std::move(Buffer), FileCharacter, ID,
- BaseOffset + Offset, IncludeLoc);
+ FileID FID = SourceMgr.createFileID(std::move(Buffer), FileCharacter, ID,
+ BaseOffset + Offset, IncludeLoc);
+ if (Record[3]) {
+ auto &FileInfo =
+ const_cast<SrcMgr::FileInfo &>(SourceMgr.getSLocEntry(FID).getFile());
+ FileInfo.setHasLineDirectives();
+ }
break;
}
case SM_SLOC_EXPANSION_ENTRY: {
- SourceLocation SpellingLoc = ReadSourceLocation(*F, Record[1]);
- SourceMgr.createExpansionLoc(SpellingLoc,
- ReadSourceLocation(*F, Record[2]),
- ReadSourceLocation(*F, Record[3]),
- Record[5],
- Record[4],
- ID,
- BaseOffset + Record[0]);
+ LocSeq::State Seq;
+ SourceLocation SpellingLoc = ReadSourceLocation(*F, Record[1], Seq);
+ SourceLocation ExpansionBegin = ReadSourceLocation(*F, Record[2], Seq);
+ SourceLocation ExpansionEnd = ReadSourceLocation(*F, Record[3], Seq);
+ SourceMgr.createExpansionLoc(SpellingLoc, ExpansionBegin, ExpansionEnd,
+ Record[5], Record[4], ID,
+ BaseOffset + Record[0]);
break;
}
}
@@ -1632,13 +1754,11 @@ SourceLocation ASTReader::getImportLocation(ModuleFile *F) {
/// Enter a subblock of the specified BlockID with the specified cursor. Read
/// the abbreviations that are at the top of the block and then leave the cursor
/// pointing into the block.
-bool ASTReader::ReadBlockAbbrevs(BitstreamCursor &Cursor, unsigned BlockID,
- uint64_t *StartOfBlockOffset) {
- if (llvm::Error Err = Cursor.EnterSubBlock(BlockID)) {
- // FIXME this drops errors on the floor.
- consumeError(std::move(Err));
- return true;
- }
+llvm::Error ASTReader::ReadBlockAbbrevs(BitstreamCursor &Cursor,
+ unsigned BlockID,
+ uint64_t *StartOfBlockOffset) {
+ if (llvm::Error Err = Cursor.EnterSubBlock(BlockID))
+ return Err;
if (StartOfBlockOffset)
*StartOfBlockOffset = Cursor.GetCurrentBitNo();
@@ -1646,40 +1766,70 @@ bool ASTReader::ReadBlockAbbrevs(BitstreamCursor &Cursor, unsigned BlockID,
while (true) {
uint64_t Offset = Cursor.GetCurrentBitNo();
Expected<unsigned> MaybeCode = Cursor.ReadCode();
- if (!MaybeCode) {
- // FIXME this drops errors on the floor.
- consumeError(MaybeCode.takeError());
- return true;
- }
+ if (!MaybeCode)
+ return MaybeCode.takeError();
unsigned Code = MaybeCode.get();
// We expect all abbrevs to be at the start of the block.
if (Code != llvm::bitc::DEFINE_ABBREV) {
- if (llvm::Error Err = Cursor.JumpToBit(Offset)) {
- // FIXME this drops errors on the floor.
- consumeError(std::move(Err));
- return true;
- }
- return false;
- }
- if (llvm::Error Err = Cursor.ReadAbbrevRecord()) {
- // FIXME this drops errors on the floor.
- consumeError(std::move(Err));
- return true;
+ if (llvm::Error Err = Cursor.JumpToBit(Offset))
+ return Err;
+ return llvm::Error::success();
}
+ if (llvm::Error Err = Cursor.ReadAbbrevRecord())
+ return Err;
}
}
-Token ASTReader::ReadToken(ModuleFile &F, const RecordDataImpl &Record,
+Token ASTReader::ReadToken(ModuleFile &M, const RecordDataImpl &Record,
unsigned &Idx) {
Token Tok;
Tok.startToken();
- Tok.setLocation(ReadSourceLocation(F, Record, Idx));
- Tok.setLength(Record[Idx++]);
- if (IdentifierInfo *II = getLocalIdentifier(F, Record[Idx++]))
- Tok.setIdentifierInfo(II);
+ Tok.setLocation(ReadSourceLocation(M, Record, Idx));
Tok.setKind((tok::TokenKind)Record[Idx++]);
Tok.setFlag((Token::TokenFlags)Record[Idx++]);
+
+ if (Tok.isAnnotation()) {
+ Tok.setAnnotationEndLoc(ReadSourceLocation(M, Record, Idx));
+ switch (Tok.getKind()) {
+ case tok::annot_pragma_loop_hint: {
+ auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
+ Info->PragmaName = ReadToken(M, Record, Idx);
+ Info->Option = ReadToken(M, Record, Idx);
+ unsigned NumTokens = Record[Idx++];
+ SmallVector<Token, 4> Toks;
+ Toks.reserve(NumTokens);
+ for (unsigned I = 0; I < NumTokens; ++I)
+ Toks.push_back(ReadToken(M, Record, Idx));
+ Info->Toks = llvm::ArrayRef(Toks).copy(PP.getPreprocessorAllocator());
+ Tok.setAnnotationValue(static_cast<void *>(Info));
+ break;
+ }
+ case tok::annot_pragma_pack: {
+ auto *Info = new (PP.getPreprocessorAllocator()) Sema::PragmaPackInfo;
+ Info->Action = static_cast<Sema::PragmaMsStackAction>(Record[Idx++]);
+ auto SlotLabel = ReadString(Record, Idx);
+ Info->SlotLabel =
+ llvm::StringRef(SlotLabel).copy(PP.getPreprocessorAllocator());
+ Info->Alignment = ReadToken(M, Record, Idx);
+ Tok.setAnnotationValue(static_cast<void *>(Info));
+ break;
+ }
+ // Some annotation tokens do not use the PtrData field.
+ case tok::annot_pragma_openmp:
+ case tok::annot_pragma_openmp_end:
+ case tok::annot_pragma_unused:
+ case tok::annot_pragma_openacc:
+ case tok::annot_pragma_openacc_end:
+ break;
+ default:
+ llvm_unreachable("missing deserialization code for annotation token");
+ }
+ } else {
+ Tok.setLength(Record[Idx++]);
+ if (IdentifierInfo *II = getLocalIdentifier(M, Record[Idx++]))
+ Tok.setIdentifierInfo(II);
+ }
return Tok;
}
@@ -1698,6 +1848,7 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) {
RecordData Record;
SmallVector<IdentifierInfo*, 16> MacroParams;
MacroInfo *Macro = nullptr;
+ llvm::MutableArrayRef<Token> MacroTokens;
while (true) {
// Advance to the next record, but if we get to the end of the block, don't
@@ -1752,7 +1903,8 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) {
MI->setDefinitionEndLoc(ReadSourceLocation(F, Record, NextIndex));
MI->setIsUsed(Record[NextIndex++]);
MI->setUsedForHeaderGuard(Record[NextIndex++]);
-
+ MacroTokens = MI->allocateTokens(Record[NextIndex++],
+ PP.getPreprocessorAllocator());
if (RecType == PP_MACRO_FUNCTION_LIKE) {
// Decode function-like macro info.
bool isC99VarArgs = Record[NextIndex++];
@@ -1797,10 +1949,14 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) {
// If we see a TOKEN before a PP_MACRO_*, then the file is
// erroneous, just pretend we didn't see this.
if (!Macro) break;
+ if (MacroTokens.empty()) {
+ Error("unexpected number of macro tokens for a macro in AST file");
+ return Macro;
+ }
unsigned Idx = 0;
- Token Tok = ReadToken(F, Record, Idx);
- Macro->AddTokenToBody(Tok);
+ MacroTokens[0] = ReadToken(F, Record, Idx);
+ MacroTokens = MacroTokens.drop_front();
break;
}
}
@@ -1821,15 +1977,30 @@ ASTReader::getGlobalPreprocessedEntityID(ModuleFile &M,
return LocalID + I->second;
}
+const FileEntry *HeaderFileInfoTrait::getFile(const internal_key_type &Key) {
+ FileManager &FileMgr = Reader.getFileManager();
+ if (!Key.Imported) {
+ if (auto File = FileMgr.getFile(Key.Filename))
+ return *File;
+ return nullptr;
+ }
+
+ std::string Resolved = std::string(Key.Filename);
+ Reader.ResolveImportedPath(M, Resolved);
+ if (auto File = FileMgr.getFile(Resolved))
+ return *File;
+ return nullptr;
+}
+
unsigned HeaderFileInfoTrait::ComputeHash(internal_key_ref ikey) {
return llvm::hash_combine(ikey.Size, ikey.ModTime);
}
HeaderFileInfoTrait::internal_key_type
-HeaderFileInfoTrait::GetInternalKey(const FileEntry *FE) {
- internal_key_type ikey = {FE->getSize(),
- M.HasTimestamps ? FE->getModificationTime() : 0,
- FE->getName(), /*Imported*/ false};
+HeaderFileInfoTrait::GetInternalKey(external_key_type ekey) {
+ internal_key_type ikey = {ekey.getSize(),
+ M.HasTimestamps ? ekey.getModificationTime() : 0,
+ ekey.getName(), /*Imported*/ false};
return ikey;
}
@@ -1841,23 +2012,8 @@ bool HeaderFileInfoTrait::EqualKey(internal_key_ref a, internal_key_ref b) {
return true;
// Determine whether the actual files are equivalent.
- FileManager &FileMgr = Reader.getFileManager();
- auto GetFile = [&](const internal_key_type &Key) -> const FileEntry* {
- if (!Key.Imported) {
- if (auto File = FileMgr.getFile(Key.Filename))
- return *File;
- return nullptr;
- }
-
- std::string Resolved = std::string(Key.Filename);
- Reader.ResolveImportedPath(M, Resolved);
- if (auto File = FileMgr.getFile(Resolved))
- return *File;
- return nullptr;
- };
-
- const FileEntry *FEA = GetFile(a);
- const FileEntry *FEB = GetFile(b);
+ const FileEntry *FEA = getFile(a);
+ const FileEntry *FEB = getFile(b);
return FEA && FEA == FEB;
}
@@ -1871,8 +2027,10 @@ HeaderFileInfoTrait::ReadKey(const unsigned char *d, unsigned) {
using namespace llvm::support;
internal_key_type ikey;
- ikey.Size = off_t(endian::readNext<uint64_t, little, unaligned>(d));
- ikey.ModTime = time_t(endian::readNext<uint64_t, little, unaligned>(d));
+ ikey.Size =
+ off_t(endian::readNext<uint64_t, llvm::endianness::little, unaligned>(d));
+ ikey.ModTime = time_t(
+ endian::readNext<uint64_t, llvm::endianness::little, unaligned>(d));
ikey.Filename = (const char *)d;
ikey.Imported = true;
return ikey;
@@ -1886,19 +2044,23 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
const unsigned char *End = d + DataLen;
HeaderFileInfo HFI;
unsigned Flags = *d++;
+
+ bool Included = (Flags >> 6) & 0x01;
+ if (Included)
+ if (const FileEntry *FE = getFile(key))
+ // Not using \c Preprocessor::markIncluded(), since that would attempt to
+ // deserialize this header file info again.
+ Reader.getPreprocessor().getIncludedFiles().insert(FE);
+
// FIXME: Refactor with mergeHeaderFileInfo in HeaderSearch.cpp.
HFI.isImport |= (Flags >> 5) & 0x01;
HFI.isPragmaOnce |= (Flags >> 4) & 0x01;
HFI.DirInfo = (Flags >> 1) & 0x07;
HFI.IndexHeaderMapHeader = Flags & 0x01;
- // FIXME: Find a better way to handle this. Maybe just store a
- // "has been included" flag?
- HFI.NumIncludes = std::max(endian::readNext<uint16_t, little, unaligned>(d),
- HFI.NumIncludes);
HFI.ControllingMacroID = Reader.getGlobalIdentifierID(
- M, endian::readNext<uint32_t, little, unaligned>(d));
+ M, endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d));
if (unsigned FrameworkOffset =
- endian::readNext<uint32_t, little, unaligned>(d)) {
+ endian::readNext<uint32_t, llvm::endianness::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);
@@ -1908,9 +2070,10 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
assert((End - d) % 4 == 0 &&
"Wrong data length in HeaderFileInfo deserialization");
while (d != End) {
- uint32_t LocalSMID = endian::readNext<uint32_t, little, unaligned>(d);
- auto HeaderRole = static_cast<ModuleMap::ModuleHeaderRole>(LocalSMID & 3);
- LocalSMID >>= 2;
+ uint32_t LocalSMID =
+ endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d);
+ auto HeaderRole = static_cast<ModuleMap::ModuleHeaderRole>(LocalSMID & 7);
+ LocalSMID >>= 3;
// This header is part of a module. Associate it with the module to enable
// implicit module import.
@@ -1923,11 +2086,12 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
std::string Filename = std::string(key.Filename);
if (key.Imported)
Reader.ResolveImportedPath(M, Filename);
- // FIXME: NameAsWritten
- Module::Header H = {std::string(key.Filename), "",
- *FileMgr.getFile(Filename)};
- ModMap.addHeader(Mod, H, HeaderRole, /*Imported*/true);
- HFI.isModuleHeader |= !(HeaderRole & ModuleMap::TextualHeader);
+ if (auto FE = FileMgr.getOptionalFileRef(Filename)) {
+ // FIXME: NameAsWritten
+ Module::Header H = {std::string(key.Filename), "", *FE};
+ ModMap.addHeader(Mod, H, HeaderRole, /*Imported=*/true);
+ }
+ HFI.isModuleHeader |= ModuleMap::isModular(HeaderRole);
}
// This HeaderFileInfo was externally loaded.
@@ -2227,7 +2391,7 @@ bool ASTReader::shouldDisableValidationForFile(
// If a PCH is loaded and validation is disabled for PCH then disable
// validation for the PCH and the modules it loads.
- ModuleKind K = CurrentDeserializingModuleKind.getValueOr(M.Kind);
+ ModuleKind K = CurrentDeserializingModuleKind.value_or(M.Kind);
switch (K) {
case MK_MainFile:
@@ -2243,12 +2407,20 @@ bool ASTReader::shouldDisableValidationForFile(
return false;
}
-ASTReader::InputFileInfo
-ASTReader::readInputFileInfo(ModuleFile &F, unsigned ID) {
+InputFileInfo ASTReader::getInputFileInfo(ModuleFile &F, unsigned ID) {
+ // If this ID is bogus, just return an empty input file.
+ if (ID == 0 || ID > F.InputFileInfosLoaded.size())
+ return InputFileInfo();
+
+ // If we've already loaded this input file, return it.
+ if (!F.InputFileInfosLoaded[ID - 1].Filename.empty())
+ return F.InputFileInfosLoaded[ID - 1];
+
// Go find this input file.
BitstreamCursor &Cursor = F.InputFilesCursor;
SavedStreamPosition SavedPosition(Cursor);
- if (llvm::Error Err = Cursor.JumpToBit(F.InputFileOffsets[ID - 1])) {
+ if (llvm::Error Err = Cursor.JumpToBit(F.InputFilesOffsetBase +
+ F.InputFileOffsets[ID - 1])) {
// FIXME this drops errors on the floor.
consumeError(std::move(Err));
}
@@ -2276,9 +2448,22 @@ ASTReader::readInputFileInfo(ModuleFile &F, unsigned ID) {
R.StoredTime = static_cast<time_t>(Record[2]);
R.Overridden = static_cast<bool>(Record[3]);
R.Transient = static_cast<bool>(Record[4]);
- R.TopLevelModuleMap = static_cast<bool>(Record[5]);
- R.Filename = std::string(Blob);
- ResolveImportedPath(F, R.Filename);
+ R.TopLevel = static_cast<bool>(Record[5]);
+ R.ModuleMap = static_cast<bool>(Record[6]);
+ std::tie(R.FilenameAsRequested, R.Filename) = [&]() {
+ uint16_t AsRequestedLength = Record[7];
+
+ std::string NameAsRequested = Blob.substr(0, AsRequestedLength).str();
+ std::string Name = Blob.substr(AsRequestedLength).str();
+
+ ResolveImportedPath(F, NameAsRequested);
+ ResolveImportedPath(F, Name);
+
+ if (Name.empty())
+ Name = NameAsRequested;
+
+ return std::make_pair(std::move(NameAsRequested), std::move(Name));
+ }();
Expected<llvm::BitstreamEntry> MaybeEntry = Cursor.advance();
if (!MaybeEntry) // FIXME this drops errors on the floor.
@@ -2297,6 +2482,9 @@ ASTReader::readInputFileInfo(ModuleFile &F, unsigned ID) {
}
R.ContentHash = (static_cast<uint64_t>(Record[1]) << 32) |
static_cast<uint64_t>(Record[0]);
+
+ // Note that we've loaded this input file info.
+ F.InputFileInfosLoaded[ID - 1] = R;
return R;
}
@@ -2316,35 +2504,38 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
// Go find this input file.
BitstreamCursor &Cursor = F.InputFilesCursor;
SavedStreamPosition SavedPosition(Cursor);
- if (llvm::Error Err = Cursor.JumpToBit(F.InputFileOffsets[ID - 1])) {
+ if (llvm::Error Err = Cursor.JumpToBit(F.InputFilesOffsetBase +
+ F.InputFileOffsets[ID - 1])) {
// FIXME this drops errors on the floor.
consumeError(std::move(Err));
}
- InputFileInfo FI = readInputFileInfo(F, ID);
+ InputFileInfo FI = getInputFileInfo(F, ID);
off_t StoredSize = FI.StoredSize;
time_t StoredTime = FI.StoredTime;
bool Overridden = FI.Overridden;
bool Transient = FI.Transient;
- StringRef Filename = FI.Filename;
+ StringRef Filename = FI.FilenameAsRequested;
uint64_t StoredContentHash = FI.ContentHash;
- OptionalFileEntryRefDegradesToFileEntryPtr File =
- expectedToOptional(FileMgr.getFileRef(Filename, /*OpenFile=*/false));
+ // For standard C++ modules, we don't need to check the inputs.
+ bool SkipChecks = F.StandardCXXModule;
+
+ const HeaderSearchOptions &HSOpts =
+ PP.getHeaderSearchInfo().getHeaderSearchOpts();
- // If we didn't find the file, resolve it relative to the
- // original directory from which this AST file was created.
- if (!File && !F.OriginalDir.empty() && !F.BaseDirectory.empty() &&
- F.OriginalDir != F.BaseDirectory) {
- std::string Resolved = resolveFileRelativeToOriginalDir(
- std::string(Filename), F.OriginalDir, F.BaseDirectory);
- if (!Resolved.empty())
- File = expectedToOptional(FileMgr.getFileRef(Resolved));
+ // The option ForceCheckCXX20ModulesInputFiles is only meaningful for C++20
+ // modules.
+ if (F.StandardCXXModule && HSOpts.ForceCheckCXX20ModulesInputFiles) {
+ SkipChecks = false;
+ Overridden = false;
}
+ auto File = FileMgr.getOptionalFileRef(Filename, /*OpenFile=*/false);
+
// For an overridden file, create a virtual file with the stored
// size/timestamp.
- if ((Overridden || Transient) && !File)
+ if ((Overridden || Transient || SkipChecks) && !File)
File = FileMgr.getVirtualFileRef(Filename, StoredSize, StoredTime);
if (!File) {
@@ -2367,7 +2558,8 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
// PCH.
SourceManager &SM = getSourceManager();
// FIXME: Reject if the overrides are different.
- if ((!Overridden && !Transient) && SM.isFileOverridden(File)) {
+ if ((!Overridden && !Transient) && !SkipChecks &&
+ SM.isFileOverridden(*File)) {
if (Complain)
Error(diag::err_fe_pch_file_overridden, Filename);
@@ -2380,46 +2572,71 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
}
}
- enum ModificationType {
- Size,
- ModTime,
- Content,
- None,
+ struct Change {
+ enum ModificationKind {
+ Size,
+ ModTime,
+ Content,
+ None,
+ } Kind;
+ std::optional<int64_t> Old = std::nullopt;
+ std::optional<int64_t> New = std::nullopt;
+ };
+ auto HasInputContentChanged = [&](Change OriginalChange) {
+ assert(ValidateASTInputFilesContent &&
+ "We should only check the content of the inputs with "
+ "ValidateASTInputFilesContent enabled.");
+
+ if (StoredContentHash == static_cast<uint64_t>(llvm::hash_code(-1)))
+ return OriginalChange;
+
+ auto MemBuffOrError = FileMgr.getBufferForFile(*File);
+ if (!MemBuffOrError) {
+ if (!Complain)
+ return OriginalChange;
+ std::string ErrorStr = "could not get buffer for file '";
+ ErrorStr += File->getName();
+ ErrorStr += "'";
+ Error(ErrorStr);
+ return OriginalChange;
+ }
+
+ // FIXME: hash_value is not guaranteed to be stable!
+ auto ContentHash = hash_value(MemBuffOrError.get()->getBuffer());
+ if (StoredContentHash == static_cast<uint64_t>(ContentHash))
+ return Change{Change::None};
+
+ return Change{Change::Content};
};
auto HasInputFileChanged = [&]() {
if (StoredSize != File->getSize())
- return ModificationType::Size;
+ return Change{Change::Size, StoredSize, File->getSize()};
if (!shouldDisableValidationForFile(F) && StoredTime &&
StoredTime != File->getModificationTime()) {
+ Change MTimeChange = {Change::ModTime, StoredTime,
+ File->getModificationTime()};
+
// In case the modification time changes but not the content,
// accept the cached file as legit.
- if (ValidateASTInputFilesContent &&
- StoredContentHash != static_cast<uint64_t>(llvm::hash_code(-1))) {
- auto MemBuffOrError = FileMgr.getBufferForFile(File);
- if (!MemBuffOrError) {
- if (!Complain)
- return ModificationType::ModTime;
- std::string ErrorStr = "could not get buffer for file '";
- ErrorStr += File->getName();
- ErrorStr += "'";
- Error(ErrorStr);
- return ModificationType::ModTime;
- }
+ if (ValidateASTInputFilesContent)
+ return HasInputContentChanged(MTimeChange);
- auto ContentHash = hash_value(MemBuffOrError.get()->getBuffer());
- if (StoredContentHash == static_cast<uint64_t>(ContentHash))
- return ModificationType::None;
- return ModificationType::Content;
- }
- return ModificationType::ModTime;
+ return MTimeChange;
}
- return ModificationType::None;
+ return Change{Change::None};
};
bool IsOutOfDate = false;
- auto FileChange = HasInputFileChanged();
+ auto FileChange = SkipChecks ? Change{Change::None} : HasInputFileChanged();
+ // When ForceCheckCXX20ModulesInputFiles and ValidateASTInputFilesContent
+ // enabled, it is better to check the contents of the inputs. Since we can't
+ // get correct modified time information for inputs from overriden inputs.
+ if (HSOpts.ForceCheckCXX20ModulesInputFiles && ValidateASTInputFilesContent &&
+ F.StandardCXXModule && FileChange.Kind == Change::None)
+ FileChange = HasInputContentChanged(FileChange);
+
// For an overridden file, there is nothing to validate.
- if (!Overridden && FileChange != ModificationType::None) {
+ if (!Overridden && FileChange.Kind != Change::None) {
if (Complain && !Diags.isDiagnosticInFlight()) {
// Build a list of the PCH imports that got us here (in reverse).
SmallVector<ModuleFile *, 4> ImportStack(1, &F);
@@ -2430,7 +2647,10 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
StringRef TopLevelPCHName(ImportStack.back()->FileName);
Diag(diag::err_fe_ast_file_modified)
<< Filename << moduleKindForDiagnostic(ImportStack.back()->Kind)
- << TopLevelPCHName << FileChange;
+ << TopLevelPCHName << FileChange.Kind
+ << (FileChange.Old && FileChange.New)
+ << llvm::itostr(FileChange.Old.value_or(0))
+ << llvm::itostr(FileChange.New.value_or(0));
// Print the import stack.
if (ImportStack.size() > 1) {
@@ -2466,7 +2686,8 @@ void ASTReader::ResolveImportedPath(ModuleFile &M, std::string &Filename) {
}
void ASTReader::ResolveImportedPath(std::string &Filename, StringRef Prefix) {
- if (Filename.empty() || llvm::sys::path::is_absolute(Filename))
+ if (Filename.empty() || llvm::sys::path::is_absolute(Filename) ||
+ Filename == "<built-in>" || Filename == "<command line>")
return;
SmallString<128> Buffer;
@@ -2645,12 +2866,11 @@ ASTReader::ReadControlBlock(ModuleFile &F,
// so we verify all input files. Otherwise, verify only user input
// files.
- unsigned N = NumUserInputs;
- if (ValidateSystemInputs ||
- (HSOpts.ModulesValidateOncePerBuildSession &&
- F.InputFilesValidationTimestamp <= HSOpts.BuildSessionTimestamp &&
- F.Kind == MK_ImplicitModule))
- N = NumInputs;
+ unsigned N = ValidateSystemInputs ? NumInputs : NumUserInputs;
+ if (HSOpts.ModulesValidateOncePerBuildSession &&
+ F.InputFilesValidationTimestamp > HSOpts.BuildSessionTimestamp &&
+ F.Kind == MK_ImplicitModule)
+ N = NumUserInputs;
for (unsigned I = 0; I < N; ++I) {
InputFile IF = getInputFile(F, I+1, Complain);
@@ -2667,10 +2887,10 @@ ASTReader::ReadControlBlock(ModuleFile &F,
: 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,
- F.Kind == MK_ExplicitModule ||
- F.Kind == MK_PrebuiltModule);
+ InputFileInfo FI = getInputFileInfo(F, I + 1);
+ Listener->visitInputFile(
+ FI.FilenameAsRequested, IsSystem, FI.Overridden,
+ F.Kind == MK_ExplicitModule || F.Kind == MK_PrebuiltModule);
}
}
@@ -2689,6 +2909,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
Error("malformed block record in AST file");
return Failure;
}
+ F.InputFilesOffsetBase = F.InputFilesCursor.GetCurrentBitNo();
continue;
case OPTIONS_BLOCK_ID:
@@ -2759,7 +2980,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
return VersionMismatch;
}
- bool hasErrors = Record[6];
+ bool hasErrors = Record[7];
if (hasErrors && !DisableValidation) {
// If requested by the caller and the module hasn't already been read
// or compiled, mark modules on error as out-of-date.
@@ -2783,7 +3004,9 @@ ASTReader::ReadControlBlock(ModuleFile &F,
if (F.RelocatablePCH)
F.BaseDirectory = isysroot.empty() ? "/" : isysroot;
- F.HasTimestamps = Record[5];
+ F.StandardCXXModule = Record[5];
+
+ F.HasTimestamps = Record[6];
const std::string &CurBranch = getClangFullRepositoryVersion();
StringRef ASTBranch = Blob;
@@ -2807,36 +3030,51 @@ ASTReader::ReadControlBlock(ModuleFile &F,
while (Idx < N) {
// Read information about the AST file.
ModuleKind ImportedKind = (ModuleKind)Record[Idx++];
+ // Whether we're importing a standard c++ module.
+ bool IsImportingStdCXXModule = Record[Idx++];
// The import location will be the local one for now; we will adjust
// all import locations of module imports after the global source
// location info are setup, in ReadAST.
SourceLocation ImportLoc =
ReadUntranslatedSourceLocation(Record[Idx++]);
- off_t StoredSize = (off_t)Record[Idx++];
- time_t StoredModTime = (time_t)Record[Idx++];
- auto FirstSignatureByte = Record.begin() + Idx;
- ASTFileSignature StoredSignature = ASTFileSignature::create(
- FirstSignatureByte, FirstSignatureByte + ASTFileSignature::size);
- Idx += ASTFileSignature::size;
+ off_t StoredSize = !IsImportingStdCXXModule ? (off_t)Record[Idx++] : 0;
+ time_t StoredModTime =
+ !IsImportingStdCXXModule ? (time_t)Record[Idx++] : 0;
+
+ ASTFileSignature StoredSignature;
+ if (!IsImportingStdCXXModule) {
+ auto FirstSignatureByte = Record.begin() + Idx;
+ StoredSignature = ASTFileSignature::create(
+ FirstSignatureByte, FirstSignatureByte + ASTFileSignature::size);
+ Idx += ASTFileSignature::size;
+ }
std::string ImportedName = ReadString(Record, Idx);
std::string ImportedFile;
// For prebuilt and explicit modules first consult the file map for
// an override. Note that here we don't search prebuilt module
- // directories, only the explicit name to file mappings. Also, we will
- // still verify the size/signature making sure it is essentially the
- // same file but perhaps in a different location.
+ // directories if we're not importing standard c++ module, only the
+ // explicit name to file mappings. Also, we will still verify the
+ // size/signature making sure it is essentially the same file but
+ // perhaps in a different location.
if (ImportedKind == MK_PrebuiltModule || ImportedKind == MK_ExplicitModule)
ImportedFile = PP.getHeaderSearchInfo().getPrebuiltModuleFileName(
- ImportedName, /*FileMapOnly*/ true);
-
- if (ImportedFile.empty())
- // Use BaseDirectoryAsWritten to ensure we use the same path in the
- // ModuleCache as when writing.
- ImportedFile = ReadPath(BaseDirectoryAsWritten, Record, Idx);
- else
- SkipPath(Record, Idx);
+ ImportedName, /*FileMapOnly*/ !IsImportingStdCXXModule);
+
+ // For C++20 Modules, we won't record the path to the imported modules
+ // in the BMI
+ if (!IsImportingStdCXXModule) {
+ if (ImportedFile.empty()) {
+ // Use BaseDirectoryAsWritten to ensure we use the same path in the
+ // ModuleCache as when writing.
+ ImportedFile = ReadPath(BaseDirectoryAsWritten, Record, Idx);
+ } else
+ SkipPath(Record, Idx);
+ } else if (ImportedFile.empty()) {
+ Diag(clang::diag::err_failed_to_find_module_file) << ImportedName;
+ return Missing;
+ }
// If our client can't cope with us being out of date, we can't cope with
// our dependency being missing.
@@ -2884,10 +3122,6 @@ ASTReader::ReadControlBlock(ModuleFile &F,
F.OriginalSourceFileID = FileID::get(Record[0]);
break;
- case ORIGINAL_PCH_DIR:
- F.OriginalDir = std::string(Blob);
- break;
-
case MODULE_NAME:
F.ModuleName = std::string(Blob);
Diag(diag::remark_module_import)
@@ -2909,10 +3143,13 @@ ASTReader::ReadControlBlock(ModuleFile &F,
BaseDirectoryAsWritten = Blob;
assert(!F.ModuleName.empty() &&
"MODULE_DIRECTORY found before MODULE_NAME");
+ F.BaseDirectory = std::string(Blob);
+ if (!PP.getPreprocessorOpts().ModulesCheckRelocated)
+ break;
// If we've already loaded a module map file covering this module, we may
// have a better path for it (relative to the current build).
Module *M = PP.getHeaderSearchInfo().lookupModule(
- F.ModuleName, /*AllowSearch*/ true,
+ F.ModuleName, SourceLocation(), /*AllowSearch*/ true,
/*AllowExtraModuleMapSearch*/ true);
if (M && M->Directory) {
// If we're implicitly loading a module, the base directory can't
@@ -2921,7 +3158,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
if (!bool(PP.getPreprocessorOpts().DisablePCHOrModuleValidation &
DisableValidationForModuleKind::Module) &&
F.Kind != MK_ExplicitModule && F.Kind != MK_PrebuiltModule) {
- auto BuildDir = PP.getFileManager().getDirectory(Blob);
+ auto BuildDir = PP.getFileManager().getOptionalDirectoryRef(Blob);
if (!BuildDir || *BuildDir != M->Directory) {
if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities))
Diag(diag::err_imported_module_relocated)
@@ -2930,8 +3167,6 @@ ASTReader::ReadControlBlock(ModuleFile &F,
}
}
F.BaseDirectory = std::string(M->Directory->getName());
- } else {
- F.BaseDirectory = std::string(Blob);
}
break;
}
@@ -2948,36 +3183,34 @@ ASTReader::ReadControlBlock(ModuleFile &F,
F.InputFileOffsets =
(const llvm::support::unaligned_uint64_t *)Blob.data();
F.InputFilesLoaded.resize(NumInputs);
+ F.InputFileInfosLoaded.resize(NumInputs);
F.NumUserInputFiles = NumUserInputs;
break;
}
}
}
-ASTReader::ASTReadResult
-ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
+llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
+ unsigned ClientLoadCapabilities) {
BitstreamCursor &Stream = F.Stream;
- if (llvm::Error Err = Stream.EnterSubBlock(AST_BLOCK_ID)) {
- Error(std::move(Err));
- return Failure;
- }
+ if (llvm::Error Err = Stream.EnterSubBlock(AST_BLOCK_ID))
+ return Err;
F.ASTBlockStartOffset = Stream.GetCurrentBitNo();
// Read all of the records and blocks for the AST file.
RecordData Record;
while (true) {
Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
- if (!MaybeEntry) {
- Error(MaybeEntry.takeError());
- return Failure;
- }
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
llvm::BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case llvm::BitstreamEntry::Error:
- Error("error at end of module block in AST file");
- return Failure;
+ return llvm::createStringError(
+ std::errc::illegal_byte_sequence,
+ "error at end of module block in AST file");
case llvm::BitstreamEntry::EndBlock:
// Outside of C++, we do not store a lookup map for the translation unit.
// Instead, mark it as needing a lookup map to be built if this module
@@ -2990,7 +3223,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
DC->setMustBuildLookupTable();
}
- return Success;
+ return llvm::Error::success();
case llvm::BitstreamEntry::SubBlock:
switch (Entry.ID) {
case DECLTYPES_BLOCK_ID:
@@ -2999,15 +3232,11 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
// cursor to it, enter the block and read the abbrevs in that block.
// With the main cursor, we just skip over it.
F.DeclsCursor = Stream;
- if (llvm::Error Err = Stream.SkipBlock()) {
- Error(std::move(Err));
- return Failure;
- }
- if (ReadBlockAbbrevs(F.DeclsCursor, DECLTYPES_BLOCK_ID,
- &F.DeclsBlockStartOffset)) {
- Error("malformed block record in AST file");
- return Failure;
- }
+ if (llvm::Error Err = Stream.SkipBlock())
+ return Err;
+ if (llvm::Error Err = ReadBlockAbbrevs(
+ F.DeclsCursor, DECLTYPES_BLOCK_ID, &F.DeclsBlockStartOffset))
+ return Err;
break;
case PREPROCESSOR_BLOCK_ID:
@@ -3015,14 +3244,11 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
if (!PP.getExternalSource())
PP.setExternalSource(this);
- if (llvm::Error Err = Stream.SkipBlock()) {
- Error(std::move(Err));
- return Failure;
- }
- if (ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID)) {
- Error("malformed block record in AST file");
- return Failure;
- }
+ if (llvm::Error Err = Stream.SkipBlock())
+ return Err;
+ if (llvm::Error Err =
+ ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID))
+ return Err;
F.MacroStartOffset = F.MacroCursor.GetCurrentBitNo();
break;
@@ -3030,14 +3256,11 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
F.PreprocessorDetailCursor = Stream;
if (llvm::Error Err = Stream.SkipBlock()) {
- Error(std::move(Err));
- return Failure;
- }
- if (ReadBlockAbbrevs(F.PreprocessorDetailCursor,
- PREPROCESSOR_DETAIL_BLOCK_ID)) {
- Error("malformed preprocessor detail record in AST file");
- return Failure;
+ return Err;
}
+ if (llvm::Error Err = ReadBlockAbbrevs(F.PreprocessorDetailCursor,
+ PREPROCESSOR_DETAIL_BLOCK_ID))
+ return Err;
F.PreprocessorDetailStartOffset
= F.PreprocessorDetailCursor.GetCurrentBitNo();
@@ -3048,36 +3271,29 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
case SOURCE_MANAGER_BLOCK_ID:
- if (ReadSourceManagerBlock(F))
- return Failure;
+ if (llvm::Error Err = ReadSourceManagerBlock(F))
+ return Err;
break;
case SUBMODULE_BLOCK_ID:
- if (ASTReadResult Result =
- ReadSubmoduleBlock(F, ClientLoadCapabilities))
- return Result;
+ if (llvm::Error Err = ReadSubmoduleBlock(F, ClientLoadCapabilities))
+ return Err;
break;
case COMMENTS_BLOCK_ID: {
BitstreamCursor C = Stream;
- if (llvm::Error Err = Stream.SkipBlock()) {
- Error(std::move(Err));
- return Failure;
- }
- if (ReadBlockAbbrevs(C, COMMENTS_BLOCK_ID)) {
- Error("malformed comments block in AST file");
- return Failure;
- }
+ if (llvm::Error Err = Stream.SkipBlock())
+ return Err;
+ if (llvm::Error Err = ReadBlockAbbrevs(C, COMMENTS_BLOCK_ID))
+ return Err;
CommentsCursors.push_back(std::make_pair(C, &F));
break;
}
default:
- if (llvm::Error Err = Stream.SkipBlock()) {
- Error(std::move(Err));
- return Failure;
- }
+ if (llvm::Error Err = Stream.SkipBlock())
+ return Err;
break;
}
continue;
@@ -3092,10 +3308,8 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
StringRef Blob;
Expected<unsigned> MaybeRecordType =
Stream.readRecord(Entry.ID, Record, &Blob);
- if (!MaybeRecordType) {
- Error(MaybeRecordType.takeError());
- return Failure;
- }
+ if (!MaybeRecordType)
+ return MaybeRecordType.takeError();
ASTRecordTypes RecordType = (ASTRecordTypes)MaybeRecordType.get();
// If we're not loading an AST context, we don't care about most records.
@@ -3105,12 +3319,12 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
case IDENTIFIER_OFFSET:
case INTERESTING_IDENTIFIERS:
case STATISTICS:
+ case PP_ASSUME_NONNULL_LOC:
case PP_CONDITIONAL_STACK:
case PP_COUNTER_VALUE:
case SOURCE_LOCATION_OFFSETS:
case MODULE_OFFSET_MAP:
case SOURCE_MANAGER_LINE_TABLE:
- case SOURCE_LOCATION_PRELOADS:
case PPD_ENTITIES_OFFSETS:
case HEADER_SEARCH_TABLE:
case IMPORTED_MODULES:
@@ -3126,10 +3340,10 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
case TYPE_OFFSET: {
- if (F.LocalNumTypes != 0) {
- Error("duplicate TYPE_OFFSET record in AST file");
- return Failure;
- }
+ if (F.LocalNumTypes != 0)
+ return llvm::createStringError(
+ std::errc::illegal_byte_sequence,
+ "duplicate TYPE_OFFSET record in AST file");
F.TypeOffsets = reinterpret_cast<const UnderalignedInt64 *>(Blob.data());
F.LocalNumTypes = Record[0];
unsigned LocalBaseTypeIndex = Record[1];
@@ -3150,10 +3364,10 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
case DECL_OFFSET: {
- if (F.LocalNumDecls != 0) {
- Error("duplicate DECL_OFFSET record in AST file");
- return Failure;
- }
+ if (F.LocalNumDecls != 0)
+ return llvm::createStringError(
+ std::errc::illegal_byte_sequence,
+ "duplicate DECL_OFFSET record in AST file");
F.DeclOffsets = (const DeclOffset *)Blob.data();
F.LocalNumDecls = Record[0];
unsigned LocalBaseDeclID = Record[1];
@@ -3218,10 +3432,10 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
case IDENTIFIER_OFFSET: {
- if (F.LocalNumIdentifiers != 0) {
- Error("duplicate IDENTIFIER_OFFSET record in AST file");
- return Failure;
- }
+ if (F.LocalNumIdentifiers != 0)
+ return llvm::createStringError(
+ std::errc::illegal_byte_sequence,
+ "duplicate IDENTIFIER_OFFSET record in AST file");
F.IdentifierOffsets = (const uint32_t *)Blob.data();
F.LocalNumIdentifiers = Record[0];
unsigned LocalBaseIdentifierID = Record[1];
@@ -3272,10 +3486,9 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
}
- if (SpecialTypes.size() != Record.size()) {
- Error("invalid special-types record");
- return Failure;
- }
+ if (SpecialTypes.size() != Record.size())
+ return llvm::createStringError(std::errc::illegal_byte_sequence,
+ "invalid special-types record");
for (unsigned I = 0, N = Record.size(); I != N; ++I) {
serialization::TypeID ID = getGlobalTypeID(F, Record[I]);
@@ -3304,10 +3517,9 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
case WEAK_UNDECLARED_IDENTIFIERS:
- if (Record.size() % 4 != 0) {
- Error("invalid weak identifiers record");
- return Failure;
- }
+ if (Record.size() % 3 != 0)
+ return llvm::createStringError(std::errc::illegal_byte_sequence,
+ "invalid weak identifiers record");
// FIXME: Ignore weak undeclared identifiers from non-original PCH
// files. This isn't the way to do it :)
@@ -3320,8 +3532,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
WeakUndeclaredIdentifiers.push_back(
getGlobalIdentifierID(F, Record[I++]));
WeakUndeclaredIdentifiers.push_back(
- ReadSourceLocation(F, Record, I).getRawEncoding());
- WeakUndeclaredIdentifiers.push_back(Record[I++]);
+ ReadSourceLocation(F, Record, I).getRawEncoding());
}
break;
@@ -3369,11 +3580,19 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
break;
+ case PP_ASSUME_NONNULL_LOC: {
+ unsigned Idx = 0;
+ if (!Record.empty())
+ PP.setPreambleRecordedPragmaAssumeNonNullLoc(
+ ReadSourceLocation(F, Record, Idx));
+ break;
+ }
+
case PP_CONDITIONAL_STACK:
if (!Record.empty()) {
unsigned Idx = 0, End = Record.size() - 1;
bool ReachedEOFWhileSkipping = Record[Idx++];
- llvm::Optional<Preprocessor::PreambleSkipInfo> SkipInfo;
+ std::optional<Preprocessor::PreambleSkipInfo> SkipInfo;
if (ReachedEOFWhileSkipping) {
SourceLocation HashToken = ReadSourceLocation(F, Record, Idx);
SourceLocation IfTokenLoc = ReadSourceLocation(F, Record, Idx);
@@ -3415,8 +3634,12 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
SourceMgr.AllocateLoadedSLocEntries(F.LocalNumSLocEntries,
SLocSpaceSize);
if (!F.SLocEntryBaseID) {
- Error("ran out of source locations");
- break;
+ if (!Diags.isDiagnosticInFlight()) {
+ Diags.Report(SourceLocation(), diag::remark_sloc_usage);
+ SourceMgr.noteSLocAddressSpaceUsage(Diags);
+ }
+ return llvm::createStringError(std::errc::invalid_argument,
+ "ran out of source locations");
}
// Make our entry in the range map. BaseID is negative and growing, so
// we invert it. Because we invert it, though, we need the other end of
@@ -3448,34 +3671,18 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
case SOURCE_MANAGER_LINE_TABLE:
- if (ParseLineTable(F, Record)) {
- Error("malformed SOURCE_MANAGER_LINE_TABLE in AST file");
- return Failure;
- }
+ ParseLineTable(F, Record);
break;
- case SOURCE_LOCATION_PRELOADS: {
- // Need to transform from the local view (1-based IDs) to the global view,
- // which is based off F.SLocEntryBaseID.
- if (!F.PreloadSLocEntries.empty()) {
- Error("Multiple SOURCE_LOCATION_PRELOADS records in AST file");
- return Failure;
- }
-
- F.PreloadSLocEntries.swap(Record);
- break;
- }
-
case EXT_VECTOR_DECLS:
for (unsigned I = 0, N = Record.size(); I != N; ++I)
ExtVectorDecls.push_back(getGlobalDeclID(F, Record[I]));
break;
case VTABLE_USES:
- if (Record.size() % 3 != 0) {
- Error("Invalid VTABLE_USES record");
- return Failure;
- }
+ if (Record.size() % 3 != 0)
+ return llvm::createStringError(std::errc::illegal_byte_sequence,
+ "Invalid VTABLE_USES record");
// Later tables overwrite earlier ones.
// FIXME: Modules will have some trouble with this. This is clearly not
@@ -3491,15 +3698,15 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
case PENDING_IMPLICIT_INSTANTIATIONS:
- if (PendingInstantiations.size() % 2 != 0) {
- Error("Invalid existing PendingInstantiations");
- return Failure;
- }
+ if (PendingInstantiations.size() % 2 != 0)
+ return llvm::createStringError(
+ std::errc::illegal_byte_sequence,
+ "Invalid existing PendingInstantiations");
- if (Record.size() % 2 != 0) {
- Error("Invalid PENDING_IMPLICIT_INSTANTIATIONS block");
- return Failure;
- }
+ if (Record.size() % 2 != 0)
+ return llvm::createStringError(
+ std::errc::illegal_byte_sequence,
+ "Invalid PENDING_IMPLICIT_INSTANTIATIONS block");
for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
PendingInstantiations.push_back(getGlobalDeclID(F, Record[I++]));
@@ -3509,10 +3716,9 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
case SEMA_DECL_REFS:
- if (Record.size() != 3) {
- Error("Invalid SEMA_DECL_REFS block");
- return Failure;
- }
+ if (Record.size() != 3)
+ return llvm::createStringError(std::errc::illegal_byte_sequence,
+ "Invalid SEMA_DECL_REFS block");
for (unsigned I = 0, N = Record.size(); I != N; ++I)
SemaDeclRefs.push_back(getGlobalDeclID(F, Record[I]));
break;
@@ -3568,10 +3774,10 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
case DECL_UPDATE_OFFSETS:
- if (Record.size() % 2 != 0) {
- Error("invalid DECL_UPDATE_OFFSETS block in AST file");
- return Failure;
- }
+ if (Record.size() % 2 != 0)
+ return llvm::createStringError(
+ std::errc::illegal_byte_sequence,
+ "invalid DECL_UPDATE_OFFSETS block in AST file");
for (unsigned I = 0, N = Record.size(); I != N; I += 2) {
GlobalDeclID ID = getGlobalDeclID(F, Record[I]);
DeclUpdateOffsets[ID].push_back(std::make_pair(&F, Record[I + 1]));
@@ -3585,10 +3791,10 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
case OBJC_CATEGORIES_MAP:
- if (F.LocalNumObjCCategoriesInMap != 0) {
- Error("duplicate OBJC_CATEGORIES_MAP record in AST file");
- return Failure;
- }
+ if (F.LocalNumObjCCategoriesInMap != 0)
+ return llvm::createStringError(
+ std::errc::illegal_byte_sequence,
+ "duplicate OBJC_CATEGORIES_MAP record in AST file");
F.LocalNumObjCCategoriesInMap = Record[0];
F.ObjCCategoriesMap = (const ObjCCategoriesInfo *)Blob.data();
@@ -3653,15 +3859,13 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
case UNDEFINED_BUT_USED:
- if (UndefinedButUsed.size() % 2 != 0) {
- Error("Invalid existing UndefinedButUsed");
- return Failure;
- }
+ if (UndefinedButUsed.size() % 2 != 0)
+ return llvm::createStringError(std::errc::illegal_byte_sequence,
+ "Invalid existing UndefinedButUsed");
- if (Record.size() % 2 != 0) {
- Error("invalid undefined-but-used record");
- return Failure;
- }
+ if (Record.size() % 2 != 0)
+ return llvm::createStringError(std::errc::illegal_byte_sequence,
+ "invalid undefined-but-used record");
for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
UndefinedButUsed.push_back(getGlobalDeclID(F, Record[I++]));
UndefinedButUsed.push_back(
@@ -3691,7 +3895,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
unsigned GlobalID = getGlobalSubmoduleID(F, Record[I++]);
SourceLocation Loc = ReadSourceLocation(F, Record, I);
if (GlobalID) {
- ImportedModules.push_back(ImportedSubmodule(GlobalID, Loc));
+ PendingImportedModules.push_back(ImportedSubmodule(GlobalID, Loc));
if (DeserializationListener)
DeserializationListener->ModuleImportRead(GlobalID, Loc);
}
@@ -3700,10 +3904,10 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
case MACRO_OFFSET: {
- if (F.LocalNumMacros != 0) {
- Error("duplicate MACRO_OFFSET record in AST file");
- return Failure;
- }
+ if (F.LocalNumMacros != 0)
+ return llvm::createStringError(
+ std::errc::illegal_byte_sequence,
+ "duplicate MACRO_OFFSET record in AST file");
F.MacroOffsets = (const uint32_t *)Blob.data();
F.LocalNumMacros = Record[0];
unsigned LocalBaseMacroID = Record[1];
@@ -3731,26 +3935,24 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
case OPTIMIZE_PRAGMA_OPTIONS:
- if (Record.size() != 1) {
- Error("invalid pragma optimize record");
- return Failure;
- }
+ if (Record.size() != 1)
+ return llvm::createStringError(std::errc::illegal_byte_sequence,
+ "invalid pragma optimize record");
OptimizeOffPragmaLocation = ReadSourceLocation(F, Record[0]);
break;
case MSSTRUCT_PRAGMA_OPTIONS:
- if (Record.size() != 1) {
- Error("invalid pragma ms_struct record");
- return Failure;
- }
+ if (Record.size() != 1)
+ return llvm::createStringError(std::errc::illegal_byte_sequence,
+ "invalid pragma ms_struct record");
PragmaMSStructState = Record[0];
break;
case POINTERS_TO_MEMBERS_PRAGMA_OPTIONS:
- if (Record.size() != 2) {
- Error("invalid pragma ms_struct record");
- return Failure;
- }
+ if (Record.size() != 2)
+ return llvm::createStringError(
+ std::errc::illegal_byte_sequence,
+ "invalid pragma pointers to members record");
PragmaMSPointersToMembersState = Record[0];
PointersToMembersPragmaLocation = ReadSourceLocation(F, Record[1]);
break;
@@ -3762,18 +3964,16 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
case CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH:
- if (Record.size() != 1) {
- Error("invalid cuda pragma options record");
- return Failure;
- }
+ if (Record.size() != 1)
+ return llvm::createStringError(std::errc::illegal_byte_sequence,
+ "invalid cuda pragma options record");
ForceCUDAHostDeviceDepth = Record[0];
break;
case ALIGN_PACK_PRAGMA_OPTIONS: {
- if (Record.size() < 3) {
- Error("invalid pragma pack record");
- return Failure;
- }
+ if (Record.size() < 3)
+ return llvm::createStringError(std::errc::illegal_byte_sequence,
+ "invalid pragma pack record");
PragmaAlignPackCurrentValue = ReadAlignPackInfo(Record[0]);
PragmaAlignPackCurrentLocation = ReadSourceLocation(F, Record[1]);
unsigned NumStackEntries = Record[2];
@@ -3793,10 +3993,9 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
case FLOAT_CONTROL_PRAGMA_OPTIONS: {
- if (Record.size() < 3) {
- Error("invalid pragma pack record");
- return Failure;
- }
+ if (Record.size() < 3)
+ return llvm::createStringError(std::errc::illegal_byte_sequence,
+ "invalid pragma float control record");
FpPragmaCurrentValue = FPOptionsOverride::getFromOpaqueInt(Record[0]);
FpPragmaCurrentLocation = ReadSourceLocation(F, Record[1]);
unsigned NumStackEntries = Record[2];
@@ -3857,8 +4056,9 @@ void ASTReader::ReadModuleOffsetMap(ModuleFile &F) const {
// how it goes...
using namespace llvm::support;
ModuleKind Kind = static_cast<ModuleKind>(
- endian::readNext<uint8_t, little, unaligned>(Data));
- uint16_t Len = endian::readNext<uint16_t, little, unaligned>(Data);
+ endian::readNext<uint8_t, llvm::endianness::little, unaligned>(Data));
+ uint16_t Len =
+ endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data);
StringRef Name = StringRef((const char*)Data, Len);
Data += Len;
ModuleFile *OM = (Kind == MK_PrebuiltModule || Kind == MK_ExplicitModule ||
@@ -3874,21 +4074,21 @@ void ASTReader::ReadModuleOffsetMap(ModuleFile &F) const {
}
SourceLocation::UIntTy SLocOffset =
- endian::readNext<uint32_t, little, unaligned>(Data);
+ endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
uint32_t IdentifierIDOffset =
- endian::readNext<uint32_t, little, unaligned>(Data);
+ endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
uint32_t MacroIDOffset =
- endian::readNext<uint32_t, little, unaligned>(Data);
+ endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
uint32_t PreprocessedEntityIDOffset =
- endian::readNext<uint32_t, little, unaligned>(Data);
+ endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
uint32_t SubmoduleIDOffset =
- endian::readNext<uint32_t, little, unaligned>(Data);
+ endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
uint32_t SelectorIDOffset =
- endian::readNext<uint32_t, little, unaligned>(Data);
+ endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
uint32_t DeclIDOffset =
- endian::readNext<uint32_t, little, unaligned>(Data);
+ endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
uint32_t TypeIndexOffset =
- endian::readNext<uint32_t, little, unaligned>(Data);
+ endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
auto mapOffset = [&](uint32_t Offset, uint32_t BaseOffset,
RemapBuilder &Remap) {
@@ -3932,18 +4132,21 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
// usable header search context.
assert(!F.ModuleName.empty() &&
"MODULE_NAME should come before MODULE_MAP_FILE");
- if (F.Kind == MK_ImplicitModule && ModuleMgr.begin()->Kind != MK_MainFile) {
+ if (PP.getPreprocessorOpts().ModulesCheckRelocated &&
+ F.Kind == MK_ImplicitModule && ModuleMgr.begin()->Kind != MK_MainFile) {
// An implicitly-loaded module file should have its module listed in some
// module map file that we've already loaded.
- Module *M = PP.getHeaderSearchInfo().lookupModule(F.ModuleName);
+ Module *M =
+ PP.getHeaderSearchInfo().lookupModule(F.ModuleName, F.ImportLoc);
auto &Map = PP.getHeaderSearchInfo().getModuleMap();
- const FileEntry *ModMap = M ? Map.getModuleMapFileForUniquing(M) : nullptr;
+ OptionalFileEntryRef ModMap =
+ M ? Map.getModuleMapFileForUniquing(M) : std::nullopt;
// Don't emit module relocation error if we have -fno-validate-pch
if (!bool(PP.getPreprocessorOpts().DisablePCHOrModuleValidation &
DisableValidationForModuleKind::Module) &&
!ModMap) {
if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities)) {
- if (auto ASTFE = M ? M->getASTFile() : None) {
+ if (auto ASTFE = M ? M->getASTFile() : std::nullopt) {
// This module was defined by an imported (explicit) module.
Diag(diag::err_module_file_conflict) << F.ModuleName << F.FileName
<< ASTFE->getName();
@@ -3980,11 +4183,11 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
return OutOfDate;
}
- llvm::SmallPtrSet<const FileEntry *, 1> AdditionalStoredMaps;
+ ModuleMap::AdditionalModMapsSet AdditionalStoredMaps;
for (unsigned I = 0, N = Record[Idx++]; I < N; ++I) {
// FIXME: we should use input files rather than storing names.
std::string Filename = ReadPath(F, Record, Idx);
- auto SF = FileMgr.getFile(Filename, false, false);
+ auto SF = FileMgr.getOptionalFileRef(Filename, false, false);
if (!SF) {
if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities))
Error("could not find file '" + Filename +"' referenced by AST file");
@@ -3996,13 +4199,13 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
// Check any additional module map files (e.g. module.private.modulemap)
// that are not in the pcm.
if (auto *AdditionalModuleMaps = Map.getAdditionalModuleMapFiles(M)) {
- for (const FileEntry *ModMap : *AdditionalModuleMaps) {
+ for (FileEntryRef ModMap : *AdditionalModuleMaps) {
// Remove files that match
// Note: SmallPtrSet::erase is really remove
if (!AdditionalStoredMaps.erase(ModMap)) {
if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities))
Diag(diag::err_module_different_modmap)
- << F.ModuleName << /*new*/0 << ModMap->getName();
+ << F.ModuleName << /*new*/0 << ModMap.getName();
return OutOfDate;
}
}
@@ -4010,10 +4213,10 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
// Check any additional module map files that are in the pcm, but not
// found in header search. Cases that match are already removed.
- for (const FileEntry *ModMap : AdditionalStoredMaps) {
+ for (FileEntryRef ModMap : AdditionalStoredMaps) {
if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities))
Diag(diag::err_module_different_modmap)
- << F.ModuleName << /*not new*/1 << ModMap->getName();
+ << F.ModuleName << /*not new*/1 << ModMap.getName();
return OutOfDate;
}
}
@@ -4096,7 +4299,7 @@ void ASTReader::makeModuleVisible(Module *Mod,
auto HiddenNames = std::move(*Hidden);
HiddenNamesMap.erase(Hidden);
makeNamesVisible(HiddenNames.second, HiddenNames.first);
- assert(HiddenNamesMap.find(Mod) == HiddenNamesMap.end() &&
+ assert(!HiddenNamesMap.contains(Mod) &&
"making names visible added hidden names");
}
@@ -4221,14 +4424,14 @@ static bool SkipCursorToBlock(BitstreamCursor &Cursor, unsigned BlockID) {
}
}
-ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
- ModuleKind Type,
+ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, ModuleKind Type,
SourceLocation ImportLoc,
unsigned ClientLoadCapabilities,
- SmallVectorImpl<ImportedSubmodule> *Imported) {
- llvm::SaveAndRestore<SourceLocation>
- SetCurImportLocRAII(CurrentImportLoc, ImportLoc);
- llvm::SaveAndRestore<Optional<ModuleKind>> SetCurModuleKindRAII(
+ ModuleFile **NewLoadedModuleFile) {
+ llvm::TimeTraceScope scope("ReadAST", FileName);
+
+ llvm::SaveAndRestore SetCurImportLocRAII(CurrentImportLoc, ImportLoc);
+ llvm::SaveAndRestore<std::optional<ModuleKind>> SetCurModuleKindRAII(
CurrentDeserializingModuleKind, Type);
// Defer any pending actions until we get to the end of reading the AST file.
@@ -4240,57 +4443,54 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
PreviousGeneration = incrementGeneration(*ContextObj);
unsigned NumModules = ModuleMgr.size();
- auto removeModulesAndReturn = [&](ASTReadResult ReadResult) {
- assert(ReadResult && "expected to return error");
- ModuleMgr.removeModules(ModuleMgr.begin() + NumModules,
- PP.getLangOpts().Modules
- ? &PP.getHeaderSearchInfo().getModuleMap()
- : nullptr);
+ SmallVector<ImportedModule, 4> Loaded;
+ if (ASTReadResult ReadResult =
+ ReadASTCore(FileName, Type, ImportLoc,
+ /*ImportedBy=*/nullptr, Loaded, 0, 0, ASTFileSignature(),
+ ClientLoadCapabilities)) {
+ ModuleMgr.removeModules(ModuleMgr.begin() + NumModules);
// If we find that any modules are unusable, the global index is going
// to be out-of-date. Just remove it.
GlobalIndex.reset();
ModuleMgr.setGlobalIndex(nullptr);
return ReadResult;
- };
-
- SmallVector<ImportedModule, 4> Loaded;
- switch (ASTReadResult ReadResult =
- ReadASTCore(FileName, Type, ImportLoc,
- /*ImportedBy=*/nullptr, Loaded, 0, 0,
- ASTFileSignature(), ClientLoadCapabilities)) {
- case Failure:
- case Missing:
- case OutOfDate:
- case VersionMismatch:
- case ConfigurationMismatch:
- case HadErrors:
- return removeModulesAndReturn(ReadResult);
- case Success:
- break;
}
- // Here comes stuff that we only do once the entire chain is loaded.
+ if (NewLoadedModuleFile && !Loaded.empty())
+ *NewLoadedModuleFile = Loaded.back().Mod;
+
+ // Here comes stuff that we only do once the entire chain is loaded. Do *not*
+ // remove modules from this point. Various fields are updated during reading
+ // the AST block and removing the modules would result in dangling pointers.
+ // They are generally only incidentally dereferenced, ie. a binary search
+ // runs over `GlobalSLocEntryMap`, which could cause an invalid module to
+ // be dereferenced but it wouldn't actually be used.
- // Load the AST blocks of all of the modules that we loaded. We can still
+ // Load the AST blocks of all of the modules that we loaded. We can still
// hit errors parsing the ASTs at this point.
for (ImportedModule &M : Loaded) {
ModuleFile &F = *M.Mod;
+ llvm::TimeTraceScope Scope2("Read Loaded AST", F.ModuleName);
// Read the AST block.
- if (ASTReadResult Result = ReadASTBlock(F, ClientLoadCapabilities))
- return removeModulesAndReturn(Result);
+ if (llvm::Error Err = ReadASTBlock(F, ClientLoadCapabilities)) {
+ Error(std::move(Err));
+ return Failure;
+ }
// The AST block should always have a definition for the main module.
if (F.isModule() && !F.DidReadTopLevelSubmodule) {
Error(diag::err_module_file_missing_top_level_submodule, F.FileName);
- return removeModulesAndReturn(Failure);
+ return Failure;
}
// Read the extension blocks.
while (!SkipCursorToBlock(F.Stream, EXTENSION_BLOCK_ID)) {
- if (ASTReadResult Result = ReadExtensionBlock(F))
- return removeModulesAndReturn(Result);
+ if (llvm::Error Err = ReadExtensionBlock(F)) {
+ Error(std::move(Err));
+ return Failure;
+ }
}
// Once read, set the ModuleFile bit base offset and update the size in
@@ -4304,44 +4504,61 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
for (ImportedModule &M : Loaded) {
ModuleFile &F = *M.Mod;
- // Preload SLocEntries.
- for (unsigned I = 0, N = F.PreloadSLocEntries.size(); I != N; ++I) {
- int Index = int(F.PreloadSLocEntries[I] - 1) + F.SLocEntryBaseID;
- // Load it through the SourceManager and don't call ReadSLocEntry()
- // directly because the entry may have already been loaded in which case
- // calling ReadSLocEntry() directly would trigger an assertion in
- // SourceManager.
- SourceMgr.getLoadedSLocEntryByID(Index);
- }
-
// Map the original source file ID into the ID space of the current
// compilation.
- if (F.OriginalSourceFileID.isValid()) {
- F.OriginalSourceFileID = FileID::get(
- F.SLocEntryBaseID + F.OriginalSourceFileID.getOpaqueValue() - 1);
- }
+ if (F.OriginalSourceFileID.isValid())
+ F.OriginalSourceFileID = TranslateFileID(F, F.OriginalSourceFileID);
- // Preload all the pending interesting identifiers by marking them out of
- // date.
for (auto Offset : F.PreloadIdentifierOffsets) {
const unsigned char *Data = F.IdentifierTableData + Offset;
ASTIdentifierLookupTrait Trait(*this, F);
auto KeyDataLen = Trait.ReadKeyDataLength(Data);
auto Key = Trait.ReadKey(Data, KeyDataLen.first);
- auto &II = PP.getIdentifierTable().getOwn(Key);
- II.setOutOfDate(true);
+
+ IdentifierInfo *II;
+ if (!PP.getLangOpts().CPlusPlus) {
+ // Identifiers present in both the module file and the importing
+ // instance are marked out-of-date so that they can be deserialized
+ // on next use via ASTReader::updateOutOfDateIdentifier().
+ // Identifiers present in the module file but not in the importing
+ // instance are ignored for now, preventing growth of the identifier
+ // table. They will be deserialized on first use via ASTReader::get().
+ auto It = PP.getIdentifierTable().find(Key);
+ if (It == PP.getIdentifierTable().end())
+ continue;
+ II = It->second;
+ } else {
+ // With C++ modules, not many identifiers are considered interesting.
+ // All identifiers in the module file can be placed into the identifier
+ // table of the importing instance and marked as out-of-date. This makes
+ // ASTReader::get() a no-op, and deserialization will take place on
+ // first/next use via ASTReader::updateOutOfDateIdentifier().
+ II = &PP.getIdentifierTable().getOwn(Key);
+ }
+
+ II->setOutOfDate(true);
// Mark this identifier as being from an AST file so that we can track
// whether we need to serialize it.
- markIdentifierFromAST(*this, II);
+ markIdentifierFromAST(*this, *II);
// Associate the ID with the identifier so that the writer can reuse it.
auto ID = Trait.ReadIdentifierID(Data + KeyDataLen.first);
- SetIdentifierInfo(ID, &II);
+ SetIdentifierInfo(ID, II);
}
}
+ // Builtins and library builtins have already been initialized. Mark all
+ // identifiers as out-of-date, so that they are deserialized on first use.
+ if (Type == MK_PCH || Type == MK_Preamble || Type == MK_MainFile)
+ for (auto &Id : PP.getIdentifierTable())
+ Id.second->setOutOfDate(true);
+
+ // Mark selectors as out of date.
+ for (const auto &Sel : SelectorGeneration)
+ SelectorOutOfDate[Sel.first] = true;
+
// Setup the import locations and notify the module manager that we've
// committed to these module files.
for (ImportedModule &M : Loaded) {
@@ -4359,25 +4576,6 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
F.ImportLoc = TranslateSourceLocation(*M.ImportedBy, M.ImportLoc);
}
- if (!PP.getLangOpts().CPlusPlus ||
- (Type != MK_ImplicitModule && Type != MK_ExplicitModule &&
- Type != MK_PrebuiltModule)) {
- // Mark all of the identifiers in the identifier table as being out of date,
- // so that various accessors know to check the loaded modules when the
- // identifier is used.
- //
- // For C++ modules, we don't need information on many identifiers (just
- // those that provide macros or are poisoned), so we mark all of
- // the interesting ones via PreloadIdentifierOffsets.
- for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(),
- IdEnd = PP.getIdentifierTable().end();
- Id != IdEnd; ++Id)
- Id->second->setOutOfDate(true);
- }
- // Mark selectors as out of date.
- for (auto Sel : SelectorGeneration)
- SelectorOutOfDate[Sel.first] = true;
-
// Resolve any unresolved module exports.
for (unsigned I = 0, N = UnresolvedModuleRefs.size(); I != N; ++I) {
UnresolvedModuleRef &Unresolved = UnresolvedModuleRefs[I];
@@ -4399,6 +4597,11 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
Unresolved.Mod->Imports.insert(ResolvedMod);
continue;
+ case UnresolvedModuleRef::Affecting:
+ if (ResolvedMod)
+ Unresolved.Mod->AffectingClangModules.insert(ResolvedMod);
+ continue;
+
case UnresolvedModuleRef::Export:
if (ResolvedMod || Unresolved.IsWildcard)
Unresolved.Mod->Exports.push_back(
@@ -4408,10 +4611,6 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
}
UnresolvedModuleRefs.clear();
- if (Imported)
- Imported->append(ImportedModules.begin(),
- ImportedModules.end());
-
// FIXME: How do we load the 'use'd modules? They may not be submodules.
// Might be unnecessary as use declarations are only used to build the
// module itself.
@@ -4447,18 +4646,16 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
}
}
- if (PP.getHeaderSearchInfo()
- .getHeaderSearchOpts()
- .ModulesValidateOncePerBuildSession) {
+ HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts();
+ if (HSOpts.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).
+ // up-to-date. For implicitly-built module files, ensure the corresponding
+ // timestamp files are up-to-date in this build session.
for (unsigned I = 0, N = Loaded.size(); I != N; ++I) {
ImportedModule &M = Loaded[I];
- if (M.Mod->Kind == MK_ImplicitModule) {
+ if (M.Mod->Kind == MK_ImplicitModule &&
+ M.Mod->InputFilesValidationTimestamp < HSOpts.BuildSessionTimestamp)
updateModuleTimestamp(*M.Mod);
- }
}
}
@@ -4638,12 +4835,6 @@ ASTReader::ReadASTCore(StringRef FileName,
ShouldFinalizePCM = true;
return Success;
- case UNHASHED_CONTROL_BLOCK_ID:
- // This block is handled using look-ahead during ReadControlBlock. We
- // shouldn't get here!
- Error("malformed block record in AST file");
- return Failure;
-
default:
if (llvm::Error Err = Stream.SkipBlock()) {
Error(std::move(Err));
@@ -4754,20 +4945,27 @@ ASTReader::ASTReadResult ASTReader::readUnhashedControlBlockImpl(
// Read and process a record.
Record.clear();
- Expected<unsigned> MaybeRecordType = Stream.readRecord(Entry.ID, Record);
+ StringRef Blob;
+ Expected<unsigned> MaybeRecordType =
+ Stream.readRecord(Entry.ID, Record, &Blob);
if (!MaybeRecordType) {
// FIXME this drops the error.
return Failure;
}
switch ((UnhashedControlBlockRecordTypes)MaybeRecordType.get()) {
case SIGNATURE:
- if (F)
- F->Signature = ASTFileSignature::create(Record.begin(), Record.end());
+ if (F) {
+ F->Signature = ASTFileSignature::create(Blob.begin(), Blob.end());
+ assert(F->Signature != ASTFileSignature::createDummy() &&
+ "Dummy AST file signature not backpatched in ASTWriter.");
+ }
break;
case AST_BLOCK_HASH:
- if (F)
- F->ASTBlockHash =
- ASTFileSignature::create(Record.begin(), Record.end());
+ if (F) {
+ F->ASTBlockHash = ASTFileSignature::create(Blob.begin(), Blob.end());
+ assert(F->ASTBlockHash != ASTFileSignature::createDummy() &&
+ "Dummy AST block hash not backpatched in ASTWriter.");
+ }
break;
case DIAGNOSTIC_OPTIONS: {
bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0;
@@ -4777,6 +4975,13 @@ ASTReader::ASTReadResult ASTReader::readUnhashedControlBlockImpl(
Result = OutOfDate; // Don't return early. Read the signature.
break;
}
+ case HEADER_SEARCH_PATHS: {
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
+ if (!AllowCompatibleConfigurationMismatch &&
+ ParseHeaderSearchPaths(Record, Complain, *Listener))
+ Result = ConfigurationMismatch;
+ break;
+ }
case DIAG_PRAGMA_MAPPINGS:
if (!F)
break;
@@ -4786,6 +4991,17 @@ ASTReader::ASTReadResult ASTReader::readUnhashedControlBlockImpl(
F->PragmaDiagMappings.insert(F->PragmaDiagMappings.end(),
Record.begin(), Record.end());
break;
+ case HEADER_SEARCH_ENTRY_USAGE:
+ if (!F)
+ break;
+ unsigned Count = Record[0];
+ const char *Byte = Blob.data();
+ F->SearchPathUsage = llvm::BitVector(Count, false);
+ for (unsigned I = 0; I < Count; ++Byte)
+ for (unsigned Bit = 0; Bit < 8 && I < Count; ++Bit, ++I)
+ if (*Byte & (1 << Bit))
+ F->SearchPathUsage[I] = true;
+ break;
}
}
}
@@ -4811,32 +5027,26 @@ static bool parseModuleFileExtensionMetadata(
return false;
}
-ASTReader::ASTReadResult ASTReader::ReadExtensionBlock(ModuleFile &F) {
+llvm::Error ASTReader::ReadExtensionBlock(ModuleFile &F) {
BitstreamCursor &Stream = F.Stream;
RecordData Record;
while (true) {
Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
- if (!MaybeEntry) {
- Error(MaybeEntry.takeError());
- return Failure;
- }
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
llvm::BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case llvm::BitstreamEntry::SubBlock:
- if (llvm::Error Err = Stream.SkipBlock()) {
- Error(std::move(Err));
- return Failure;
- }
+ if (llvm::Error Err = Stream.SkipBlock())
+ return Err;
continue;
-
case llvm::BitstreamEntry::EndBlock:
- return Success;
-
+ return llvm::Error::success();
case llvm::BitstreamEntry::Error:
- return HadErrors;
-
+ return llvm::createStringError(std::errc::illegal_byte_sequence,
+ "malformed block record in AST file");
case llvm::BitstreamEntry::Record:
break;
}
@@ -4845,17 +5055,15 @@ ASTReader::ASTReadResult ASTReader::ReadExtensionBlock(ModuleFile &F) {
StringRef Blob;
Expected<unsigned> MaybeRecCode =
Stream.readRecord(Entry.ID, Record, &Blob);
- if (!MaybeRecCode) {
- Error(MaybeRecCode.takeError());
- return Failure;
- }
+ if (!MaybeRecCode)
+ return MaybeRecCode.takeError();
switch (MaybeRecCode.get()) {
case EXTENSION_METADATA: {
ModuleFileExtensionMetadata Metadata;
- if (parseModuleFileExtensionMetadata(Record, Blob, Metadata)) {
- Error("malformed EXTENSION_METADATA in AST file");
- return Failure;
- }
+ if (parseModuleFileExtensionMetadata(Record, Blob, Metadata))
+ return llvm::createStringError(
+ std::errc::illegal_byte_sequence,
+ "malformed EXTENSION_METADATA in AST file");
// Find a module file extension with this block name.
auto Known = ModuleFileExtensions.find(Metadata.BlockName);
@@ -4872,7 +5080,7 @@ ASTReader::ASTReadResult ASTReader::ReadExtensionBlock(ModuleFile &F) {
}
}
- return Success;
+ return llvm::Error::success();
}
void ASTReader::InitializeContext() {
@@ -5002,7 +5210,7 @@ void ASTReader::InitializeContext() {
// Re-export any modules that were imported by a non-module AST file.
// FIXME: This does not make macro-only imports visible again.
- for (auto &Import : ImportedModules) {
+ for (auto &Import : PendingImportedModules) {
if (Module *Imported = getSubmodule(Import.ID)) {
makeModuleVisible(Imported, Module::AllVisible,
/*ImportLoc=*/Import.ImportLoc);
@@ -5012,6 +5220,10 @@ void ASTReader::InitializeContext() {
// nullptr here, we do the same later, in UpdateSema().
}
}
+
+ // Hand off these modules to Sema.
+ PendingImportedModulesSema.append(PendingImportedModules);
+ PendingImportedModules.clear();
}
void ASTReader::finalizeForWriting() {
@@ -5055,9 +5267,12 @@ static ASTFileSignature readASTFileSignature(StringRef PCH) {
consumeError(MaybeRecord.takeError());
return ASTFileSignature();
}
- if (SIGNATURE == MaybeRecord.get())
- return ASTFileSignature::create(Record.begin(),
- Record.begin() + ASTFileSignature::size);
+ if (SIGNATURE == MaybeRecord.get()) {
+ auto Signature = ASTFileSignature::create(Blob.begin(), Blob.end());
+ assert(Signature != ASTFileSignature::createDummy() &&
+ "Dummy AST file signature not backpatched in ASTWriter.");
+ return Signature;
+ }
}
}
@@ -5068,7 +5283,8 @@ std::string ASTReader::getOriginalSourceFile(
const std::string &ASTFileName, FileManager &FileMgr,
const PCHContainerReader &PCHContainerRdr, DiagnosticsEngine &Diags) {
// Open the AST file.
- auto Buffer = FileMgr.getBufferForFile(ASTFileName);
+ auto Buffer = FileMgr.getBufferForFile(ASTFileName, /*IsVolatile=*/false,
+ /*RequiresNullTerminator=*/false);
if (!Buffer) {
Diags.Report(diag::err_fe_unable_to_read_pch_file)
<< ASTFileName << Buffer.getError().message();
@@ -5131,16 +5347,19 @@ namespace {
const PreprocessorOptions &ExistingPPOpts;
std::string ExistingModuleCachePath;
FileManager &FileMgr;
+ bool StrictOptionMatches;
public:
SimplePCHValidator(const LangOptions &ExistingLangOpts,
const TargetOptions &ExistingTargetOpts,
const PreprocessorOptions &ExistingPPOpts,
- StringRef ExistingModuleCachePath, FileManager &FileMgr)
+ StringRef ExistingModuleCachePath, FileManager &FileMgr,
+ bool StrictOptionMatches)
: ExistingLangOpts(ExistingLangOpts),
ExistingTargetOpts(ExistingTargetOpts),
ExistingPPOpts(ExistingPPOpts),
- ExistingModuleCachePath(ExistingModuleCachePath), FileMgr(FileMgr) {}
+ ExistingModuleCachePath(ExistingModuleCachePath), FileMgr(FileMgr),
+ StrictOptionMatches(StrictOptionMatches) {}
bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
bool AllowCompatibleDifferences) override {
@@ -5163,10 +5382,13 @@ namespace {
}
bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
- bool Complain,
+ bool ReadMacros, bool Complain,
std::string &SuggestedPredefines) override {
- return checkPreprocessorOptions(ExistingPPOpts, PPOpts, nullptr, FileMgr,
- SuggestedPredefines, ExistingLangOpts);
+ return checkPreprocessorOptions(
+ PPOpts, ExistingPPOpts, ReadMacros, /*Diags=*/nullptr, FileMgr,
+ SuggestedPredefines, ExistingLangOpts,
+ StrictOptionMatches ? OptionValidateStrictMatches
+ : OptionValidateContradictions);
}
};
@@ -5174,19 +5396,28 @@ namespace {
bool ASTReader::readASTFileControlBlock(
StringRef Filename, FileManager &FileMgr,
- const PCHContainerReader &PCHContainerRdr,
- bool FindModuleFileExtensions,
+ const InMemoryModuleCache &ModuleCache,
+ const PCHContainerReader &PCHContainerRdr, bool FindModuleFileExtensions,
ASTReaderListener &Listener, bool ValidateDiagnosticOptions) {
// Open the AST file.
- // FIXME: This allows use of the VFS; we do not allow use of the
- // VFS when actually loading a module.
- auto Buffer = FileMgr.getBufferForFile(Filename);
+ std::unique_ptr<llvm::MemoryBuffer> OwnedBuffer;
+ llvm::MemoryBuffer *Buffer = ModuleCache.lookupPCM(Filename);
if (!Buffer) {
- return true;
+ // FIXME: We should add the pcm to the InMemoryModuleCache if it could be
+ // read again later, but we do not have the context here to determine if it
+ // is safe to change the result of InMemoryModuleCache::getPCMState().
+
+ // FIXME: This allows use of the VFS; we do not allow use of the
+ // VFS when actually loading a module.
+ auto BufferOrErr = FileMgr.getBufferForFile(Filename);
+ if (!BufferOrErr)
+ return true;
+ OwnedBuffer = std::move(*BufferOrErr);
+ Buffer = OwnedBuffer.get();
}
// Initialize the stream
- StringRef Bytes = PCHContainerRdr.ExtractPCH(**Buffer);
+ StringRef Bytes = PCHContainerRdr.ExtractPCH(*Buffer);
BitstreamCursor Stream(Bytes);
// Sniff for the signature.
@@ -5203,6 +5434,7 @@ bool ASTReader::readASTFileControlBlock(
bool NeedsSystemInputFiles = Listener.needsSystemInputFileVisitation();
bool NeedsImports = Listener.needsImportVisitation();
BitstreamCursor InputFilesCursor;
+ uint64_t InputFilesOffsetBase = 0;
RecordData Record;
std::string ModuleDir;
@@ -5238,6 +5470,7 @@ bool ASTReader::readASTFileControlBlock(
if (NeedsInputFiles &&
ReadBlockAbbrevs(InputFilesCursor, INPUT_FILES_BLOCK_ID))
return true;
+ InputFilesOffsetBase = InputFilesCursor.GetCurrentBitNo();
break;
default:
@@ -5310,7 +5543,8 @@ bool ASTReader::readASTFileControlBlock(
BitstreamCursor &Cursor = InputFilesCursor;
SavedStreamPosition SavedPosition(Cursor);
- if (llvm::Error Err = Cursor.JumpToBit(InputFileOffs[I])) {
+ if (llvm::Error Err =
+ Cursor.JumpToBit(InputFilesOffsetBase + InputFileOffs[I])) {
// FIXME this drops errors on the floor.
consumeError(std::move(Err));
}
@@ -5355,9 +5589,24 @@ bool ASTReader::readASTFileControlBlock(
unsigned Idx = 0, N = Record.size();
while (Idx < N) {
// Read information about the AST file.
- Idx +=
- 1 + 1 + 1 + 1 +
- ASTFileSignature::size; // Kind, ImportLoc, Size, ModTime, Signature
+
+ // Skip Kind
+ Idx++;
+ bool IsStandardCXXModule = Record[Idx++];
+
+ // Skip ImportLoc
+ Idx++;
+
+ // In C++20 Modules, we don't record the path to imported
+ // modules in the BMI files.
+ if (IsStandardCXXModule) {
+ std::string ModuleName = ReadString(Record, Idx);
+ Listener.visitImport(ModuleName, /*Filename=*/"");
+ continue;
+ }
+
+ // Skip Size, ModTime and Signature
+ Idx += 1 + 1 + ASTFileSignature::size;
std::string ModuleName = ReadString(Record, Idx);
std::string Filename = ReadString(Record, Idx);
ResolveImportedPath(Filename, ModuleDir);
@@ -5439,26 +5688,27 @@ bool ASTReader::readASTFileControlBlock(
}
bool ASTReader::isAcceptableASTFile(StringRef Filename, FileManager &FileMgr,
+ const InMemoryModuleCache &ModuleCache,
const PCHContainerReader &PCHContainerRdr,
const LangOptions &LangOpts,
const TargetOptions &TargetOpts,
const PreprocessorOptions &PPOpts,
- StringRef ExistingModuleCachePath) {
+ StringRef ExistingModuleCachePath,
+ bool RequireStrictOptionMatches) {
SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts,
- ExistingModuleCachePath, FileMgr);
- return !readASTFileControlBlock(Filename, FileMgr, PCHContainerRdr,
- /*FindModuleFileExtensions=*/false,
- validator,
+ ExistingModuleCachePath, FileMgr,
+ RequireStrictOptionMatches);
+ return !readASTFileControlBlock(Filename, FileMgr, ModuleCache,
+ PCHContainerRdr,
+ /*FindModuleFileExtensions=*/false, validator,
/*ValidateDiagnosticOptions=*/true);
}
-ASTReader::ASTReadResult
-ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
+llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F,
+ unsigned ClientLoadCapabilities) {
// Enter the submodule block.
- if (llvm::Error Err = F.Stream.EnterSubBlock(SUBMODULE_BLOCK_ID)) {
- Error(std::move(Err));
- return Failure;
- }
+ if (llvm::Error Err = F.Stream.EnterSubBlock(SUBMODULE_BLOCK_ID))
+ return Err;
ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();
bool First = true;
@@ -5467,19 +5717,17 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
while (true) {
Expected<llvm::BitstreamEntry> MaybeEntry =
F.Stream.advanceSkippingSubblocks();
- if (!MaybeEntry) {
- Error(MaybeEntry.takeError());
- return Failure;
- }
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
llvm::BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case llvm::BitstreamEntry::SubBlock: // Handled for us already.
case llvm::BitstreamEntry::Error:
- Error("malformed block record in AST file");
- return Failure;
+ return llvm::createStringError(std::errc::illegal_byte_sequence,
+ "malformed block record in AST file");
case llvm::BitstreamEntry::EndBlock:
- return Success;
+ return llvm::Error::success();
case llvm::BitstreamEntry::Record:
// The interesting case.
break;
@@ -5489,16 +5737,14 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
StringRef Blob;
Record.clear();
Expected<unsigned> MaybeKind = F.Stream.readRecord(Entry.ID, Record, &Blob);
- if (!MaybeKind) {
- Error(MaybeKind.takeError());
- return Failure;
- }
+ if (!MaybeKind)
+ return MaybeKind.takeError();
unsigned Kind = MaybeKind.get();
- if ((Kind == SUBMODULE_METADATA) != First) {
- Error("submodule metadata record should be at beginning of block");
- return Failure;
- }
+ if ((Kind == SUBMODULE_METADATA) != First)
+ return llvm::createStringError(
+ std::errc::illegal_byte_sequence,
+ "submodule metadata record should be at beginning of block");
First = false;
// Submodule information is only valid if we have a current module.
@@ -5512,16 +5758,16 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
case SUBMODULE_DEFINITION: {
- if (Record.size() < 12) {
- Error("malformed module definition");
- return Failure;
- }
+ if (Record.size() < 13)
+ return llvm::createStringError(std::errc::illegal_byte_sequence,
+ "malformed module definition");
StringRef Name = Blob;
unsigned Idx = 0;
SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[Idx++]);
SubmoduleID Parent = getGlobalSubmoduleID(F, Record[Idx++]);
Module::ModuleKind Kind = (Module::ModuleKind)Record[Idx++];
+ SourceLocation DefinitionLoc = ReadSourceLocation(F, Record[Idx++]);
bool IsFramework = Record[Idx++];
bool IsExplicit = Record[Idx++];
bool IsSystem = Record[Idx++];
@@ -5531,6 +5777,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
bool InferExportWildcard = Record[Idx++];
bool ConfigMacrosExhaustive = Record[Idx++];
bool ModuleMapIsPrivate = Record[Idx++];
+ bool NamedModuleHasInit = Record[Idx++];
Module *ParentModule = nullptr;
if (Parent)
@@ -5542,26 +5789,26 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
ModMap.findOrCreateModule(Name, ParentModule, IsFramework, IsExplicit)
.first;
- // FIXME: set the definition loc for CurrentModule, or call
- // ModMap.setInferredModuleAllowedBy()
+ // FIXME: Call ModMap.setInferredModuleAllowedBy()
SubmoduleID GlobalIndex = GlobalID - NUM_PREDEF_SUBMODULE_IDS;
if (GlobalIndex >= SubmodulesLoaded.size() ||
- SubmodulesLoaded[GlobalIndex]) {
- Error("too many submodules");
- return Failure;
- }
+ SubmodulesLoaded[GlobalIndex])
+ return llvm::createStringError(std::errc::invalid_argument,
+ "too many submodules");
if (!ParentModule) {
- if (const FileEntry *CurFile = CurrentModule->getASTFile()) {
+ if (OptionalFileEntryRef CurFile = CurrentModule->getASTFile()) {
// Don't emit module relocation error if we have -fno-validate-pch
if (!bool(PP.getPreprocessorOpts().DisablePCHOrModuleValidation &
DisableValidationForModuleKind::Module) &&
CurFile != F.File) {
- Error(diag::err_module_file_conflict,
- CurrentModule->getTopLevelModuleName(), CurFile->getName(),
- F.File->getName());
- return Failure;
+ auto ConflictError =
+ PartialDiagnostic(diag::err_module_file_conflict,
+ ContextObj->DiagAllocator)
+ << CurrentModule->getTopLevelModuleName() << CurFile->getName()
+ << F.File.getName();
+ return DiagnosticError::create(CurrentImportLoc, ConflictError);
}
}
@@ -5571,6 +5818,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
CurrentModule->Kind = Kind;
+ CurrentModule->DefinitionLoc = DefinitionLoc;
CurrentModule->Signature = F.Signature;
CurrentModule->IsFromModuleFile = true;
CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem;
@@ -5580,6 +5828,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
CurrentModule->InferExportWildcard = InferExportWildcard;
CurrentModule->ConfigMacrosExhaustive = ConfigMacrosExhaustive;
CurrentModule->ModuleMapIsPrivate = ModuleMapIsPrivate;
+ CurrentModule->NamedModuleHasInit = NamedModuleHasInit;
if (DeserializationListener)
DeserializationListener->ModuleRead(GlobalID, CurrentModule);
@@ -5605,17 +5854,20 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
case SUBMODULE_UMBRELLA_HEADER: {
+ // FIXME: This doesn't work for framework modules as `Filename` is the
+ // name as written in the module file and does not include
+ // `Headers/`, so this path will never exist.
std::string Filename = std::string(Blob);
ResolveImportedPath(F, Filename);
- if (auto Umbrella = PP.getFileManager().getFile(Filename)) {
- if (!CurrentModule->getUmbrellaHeader())
+ if (auto Umbrella = PP.getFileManager().getOptionalFileRef(Filename)) {
+ if (!CurrentModule->getUmbrellaHeaderAsWritten()) {
// FIXME: NameAsWritten
- ModMap.setUmbrellaHeader(CurrentModule, *Umbrella, Blob, "");
- else if (CurrentModule->getUmbrellaHeader().Entry != *Umbrella) {
- if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
- Error("mismatched umbrella headers in submodule");
- return OutOfDate;
+ ModMap.setUmbrellaHeaderAsWritten(CurrentModule, *Umbrella, Blob, "");
}
+ // Note that it's too late at this point to return out of date if the
+ // name from the PCM doesn't match up with the one in the module map,
+ // but also quite unlikely since we will have already checked the
+ // modification time and size of the module map file itself.
}
break;
}
@@ -5634,21 +5886,22 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
// them here.
break;
- case SUBMODULE_TOPHEADER:
- CurrentModule->addTopHeaderFilename(Blob);
+ case SUBMODULE_TOPHEADER: {
+ std::string HeaderName(Blob);
+ ResolveImportedPath(F, HeaderName);
+ CurrentModule->addTopHeaderFilename(HeaderName);
break;
+ }
case SUBMODULE_UMBRELLA_DIR: {
+ // See comments in SUBMODULE_UMBRELLA_HEADER
std::string Dirname = std::string(Blob);
ResolveImportedPath(F, Dirname);
- if (auto Umbrella = PP.getFileManager().getDirectory(Dirname)) {
- if (!CurrentModule->getUmbrellaDir())
+ if (auto Umbrella =
+ PP.getFileManager().getOptionalDirectoryRef(Dirname)) {
+ if (!CurrentModule->getUmbrellaDirAsWritten()) {
// FIXME: NameAsWritten
- ModMap.setUmbrellaDir(CurrentModule, *Umbrella, Blob, "");
- else if (CurrentModule->getUmbrellaDir().Entry != *Umbrella) {
- if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
- Error("mismatched umbrella directories in submodule");
- return OutOfDate;
+ ModMap.setUmbrellaDirAsWritten(CurrentModule, *Umbrella, Blob, "");
}
}
break;
@@ -5686,6 +5939,18 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
break;
+ case SUBMODULE_AFFECTING_MODULES:
+ for (unsigned Idx = 0; Idx != Record.size(); ++Idx) {
+ UnresolvedModuleRef Unresolved;
+ Unresolved.File = &F;
+ Unresolved.Mod = CurrentModule;
+ Unresolved.ID = Record[Idx];
+ Unresolved.Kind = UnresolvedModuleRef::Affecting;
+ Unresolved.IsWildcard = false;
+ UnresolvedModuleRefs.push_back(Unresolved);
+ }
+ break;
+
case SUBMODULE_EXPORTS:
for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) {
UnresolvedModuleRef Unresolved;
@@ -5848,6 +6113,28 @@ bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record,
unsigned Idx = 0;
HSOpts.Sysroot = ReadString(Record, Idx);
+ HSOpts.ResourceDir = ReadString(Record, Idx);
+ HSOpts.ModuleCachePath = ReadString(Record, Idx);
+ HSOpts.ModuleUserBuildPath = ReadString(Record, Idx);
+ HSOpts.DisableModuleHash = Record[Idx++];
+ HSOpts.ImplicitModuleMaps = Record[Idx++];
+ HSOpts.ModuleMapFileHomeIsCwd = Record[Idx++];
+ HSOpts.EnablePrebuiltImplicitModules = Record[Idx++];
+ HSOpts.UseBuiltinIncludes = Record[Idx++];
+ HSOpts.UseStandardSystemIncludes = Record[Idx++];
+ HSOpts.UseStandardCXXIncludes = Record[Idx++];
+ HSOpts.UseLibcxx = Record[Idx++];
+ std::string SpecificModuleCachePath = ReadString(Record, Idx);
+
+ return Listener.ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
+ Complain);
+}
+
+bool ASTReader::ParseHeaderSearchPaths(const RecordData &Record, bool Complain,
+ ASTReaderListener &Listener) {
+ HeaderSearchOptions HSOpts;
+ unsigned Idx = 0;
+
// Include entries.
for (unsigned N = Record[Idx++]; N; --N) {
std::string Path = ReadString(Record, Idx);
@@ -5866,21 +6153,13 @@ bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record,
HSOpts.SystemHeaderPrefixes.emplace_back(std::move(Prefix), IsSystemHeader);
}
- HSOpts.ResourceDir = ReadString(Record, Idx);
- HSOpts.ModuleCachePath = ReadString(Record, Idx);
- HSOpts.ModuleUserBuildPath = ReadString(Record, Idx);
- HSOpts.DisableModuleHash = Record[Idx++];
- HSOpts.ImplicitModuleMaps = Record[Idx++];
- HSOpts.ModuleMapFileHomeIsCwd = Record[Idx++];
- HSOpts.EnablePrebuiltImplicitModules = Record[Idx++];
- HSOpts.UseBuiltinIncludes = Record[Idx++];
- HSOpts.UseStandardSystemIncludes = Record[Idx++];
- HSOpts.UseStandardCXXIncludes = Record[Idx++];
- HSOpts.UseLibcxx = Record[Idx++];
- std::string SpecificModuleCachePath = ReadString(Record, Idx);
+ // VFS overlay files.
+ for (unsigned N = Record[Idx++]; N; --N) {
+ std::string VFSOverlayFile = ReadString(Record, Idx);
+ HSOpts.VFSOverlayFiles.emplace_back(std::move(VFSOverlayFile));
+ }
- return Listener.ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
- Complain);
+ return Listener.ReadHeaderSearchPaths(HSOpts, Complain);
}
bool ASTReader::ParsePreprocessorOptions(const RecordData &Record,
@@ -5891,10 +6170,13 @@ bool ASTReader::ParsePreprocessorOptions(const RecordData &Record,
unsigned Idx = 0;
// Macro definitions/undefs
- for (unsigned N = Record[Idx++]; N; --N) {
- std::string Macro = ReadString(Record, Idx);
- bool IsUndef = Record[Idx++];
- PPOpts.Macros.push_back(std::make_pair(Macro, IsUndef));
+ bool ReadMacros = Record[Idx++];
+ if (ReadMacros) {
+ for (unsigned N = Record[Idx++]; N; --N) {
+ std::string Macro = ReadString(Record, Idx);
+ bool IsUndef = Record[Idx++];
+ PPOpts.Macros.push_back(std::make_pair(Macro, IsUndef));
+ }
}
// Includes
@@ -5913,7 +6195,7 @@ bool ASTReader::ParsePreprocessorOptions(const RecordData &Record,
PPOpts.ObjCXXARCStandardLibrary =
static_cast<ObjCXXARCStandardLibraryKind>(Record[Idx++]);
SuggestedPredefines.clear();
- return Listener.ReadPreprocessorOptions(PPOpts, Complain,
+ return Listener.ReadPreprocessorOptions(PPOpts, ReadMacros, Complain,
SuggestedPredefines);
}
@@ -6046,10 +6328,9 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
case PPD_INCLUSION_DIRECTIVE: {
const char *FullFileNameStart = Blob.data() + Record[0];
StringRef FullFileName(FullFileNameStart, Blob.size() - Record[0]);
- const FileEntry *File = nullptr;
+ OptionalFileEntryRef File;
if (!FullFileName.empty())
- if (auto FE = PP.getFileManager().getFile(FullFileName))
- File = *FE;
+ File = PP.getFileManager().getOptionalFileRef(FullFileName);
// FIXME: Stable encoding
InclusionDirective::InclusionKind Kind
@@ -6186,8 +6467,8 @@ std::pair<unsigned, unsigned>
/// Optionally returns true or false if the preallocated preprocessed
/// entity with index \arg Index came from file \arg FID.
-Optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index,
- FileID FID) {
+std::optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index,
+ FileID FID) {
if (FID.isInvalid())
return false;
@@ -6210,11 +6491,11 @@ namespace {
/// Visitor used to search for information about a header file.
class HeaderFileInfoVisitor {
- const FileEntry *FE;
- Optional<HeaderFileInfo> HFI;
+ FileEntryRef FE;
+ std::optional<HeaderFileInfo> HFI;
public:
- explicit HeaderFileInfoVisitor(const FileEntry *FE) : FE(FE) {}
+ explicit HeaderFileInfoVisitor(FileEntryRef FE) : FE(FE) {}
bool operator()(ModuleFile &M) {
HeaderFileInfoLookupTable *Table
@@ -6231,16 +6512,16 @@ namespace {
return true;
}
- Optional<HeaderFileInfo> getHeaderFileInfo() const { return HFI; }
+ std::optional<HeaderFileInfo> getHeaderFileInfo() const { return HFI; }
};
} // namespace
-HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) {
+HeaderFileInfo ASTReader::GetHeaderFileInfo(FileEntryRef FE) {
HeaderFileInfoVisitor Visitor(FE);
ModuleMgr.visit(Visitor);
- if (Optional<HeaderFileInfo> HFI = Visitor.getHeaderFileInfo())
- return *HFI;
+ if (std::optional<HeaderFileInfo> HFI = Visitor.getHeaderFileInfo())
+ return *HFI;
return HeaderFileInfo();
}
@@ -6257,9 +6538,8 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
DiagStates.clear();
- auto ReadDiagState =
- [&](const DiagState &BasedOn, SourceLocation Loc,
- bool IncludeNonPragmaStates) -> DiagnosticsEngine::DiagState * {
+ auto ReadDiagState = [&](const DiagState &BasedOn,
+ bool IncludeNonPragmaStates) {
unsigned BackrefID = Record[Idx++];
if (BackrefID != 0)
return DiagStates[BackrefID - 1];
@@ -6320,7 +6600,7 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
Initial.EnableAllWarnings = Flags & 1; Flags >>= 1;
Initial.IgnoreAllWarnings = Flags & 1; Flags >>= 1;
Initial.ExtBehavior = (diag::Severity)Flags;
- FirstState = ReadDiagState(Initial, SourceLocation(), true);
+ FirstState = ReadDiagState(Initial, true);
assert(F.OriginalSourceFileID.isValid());
@@ -6333,8 +6613,7 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
// For prefix ASTs, start with whatever the user configured on the
// command line.
Idx++; // Skip flags.
- FirstState = ReadDiagState(*Diag.DiagStatesByLoc.CurDiagState,
- SourceLocation(), false);
+ FirstState = ReadDiagState(*Diag.DiagStatesByLoc.CurDiagState, false);
}
// Read the state transitions.
@@ -6356,8 +6635,7 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
F.StateTransitions.reserve(F.StateTransitions.size() + Transitions);
for (unsigned I = 0; I != Transitions; ++I) {
unsigned Offset = Record[Idx++];
- auto *State =
- ReadDiagState(*FirstState, Loc.getLocWithOffset(Offset), false);
+ auto *State = ReadDiagState(*FirstState, false);
F.StateTransitions.push_back({State, Offset});
}
}
@@ -6365,9 +6643,8 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
// Read the final state.
assert(Idx < Record.size() &&
"Invalid data, missing final pragma diagnostic state");
- SourceLocation CurStateLoc =
- ReadSourceLocation(F, F.PragmaDiagMappings[Idx++]);
- auto *CurState = ReadDiagState(*FirstState, CurStateLoc, false);
+ SourceLocation CurStateLoc = ReadSourceLocation(F, Record[Idx++]);
+ auto *CurState = ReadDiagState(*FirstState, false);
if (!F.isModule()) {
Diag.DiagStatesByLoc.CurDiagState = CurState;
@@ -6398,12 +6675,13 @@ ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) {
M->DeclsBlockStartOffset);
}
-static llvm::Optional<Type::TypeClass> getTypeClassForCode(TypeCode code) {
+static std::optional<Type::TypeClass> getTypeClassForCode(TypeCode code) {
switch (code) {
#define TYPE_BIT_CODE(CLASS_ID, CODE_ID, CODE_VALUE) \
case TYPE_##CODE_ID: return Type::CLASS_ID;
#include "clang/Serialization/TypeBitCodes.def"
- default: return llvm::None;
+ default:
+ return std::nullopt;
}
}
@@ -6463,11 +6741,13 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
namespace clang {
class TypeLocReader : public TypeLocVisitor<TypeLocReader> {
+ using LocSeq = SourceLocationSequence;
+
ASTRecordReader &Reader;
+ LocSeq *Seq;
- SourceLocation readSourceLocation() {
- return Reader.readSourceLocation();
- }
+ SourceLocation readSourceLocation() { return Reader.readSourceLocation(Seq); }
+ SourceRange readSourceRange() { return Reader.readSourceRange(Seq); }
TypeSourceInfo *GetTypeSourceInfo() {
return Reader.readTypeSourceInfo();
@@ -6482,7 +6762,8 @@ class TypeLocReader : public TypeLocVisitor<TypeLocReader> {
}
public:
- TypeLocReader(ASTRecordReader &Reader) : Reader(Reader) {}
+ TypeLocReader(ASTRecordReader &Reader, LocSeq *Seq)
+ : Reader(Reader), Seq(Seq) {}
// We want compile-time assurance that we've enumerated all of
// these, so unfortunately we have to declare them first, then
@@ -6579,7 +6860,7 @@ void TypeLocReader::VisitDependentAddressSpaceTypeLoc(
DependentAddressSpaceTypeLoc TL) {
TL.setAttrNameLoc(readSourceLocation());
- TL.setAttrOperandParensRange(Reader.readSourceRange());
+ TL.setAttrOperandParensRange(readSourceRange());
TL.setAttrExprOperand(Reader.readExpr());
}
@@ -6603,7 +6884,7 @@ void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
void TypeLocReader::VisitConstantMatrixTypeLoc(ConstantMatrixTypeLoc TL) {
TL.setAttrNameLoc(readSourceLocation());
- TL.setAttrOperandParensRange(Reader.readSourceRange());
+ TL.setAttrOperandParensRange(readSourceRange());
TL.setAttrRowOperand(Reader.readExpr());
TL.setAttrColumnOperand(Reader.readExpr());
}
@@ -6611,7 +6892,7 @@ void TypeLocReader::VisitConstantMatrixTypeLoc(ConstantMatrixTypeLoc TL) {
void TypeLocReader::VisitDependentSizedMatrixTypeLoc(
DependentSizedMatrixTypeLoc TL) {
TL.setAttrNameLoc(readSourceLocation());
- TL.setAttrOperandParensRange(Reader.readSourceRange());
+ TL.setAttrOperandParensRange(readSourceRange());
TL.setAttrRowOperand(Reader.readExpr());
TL.setAttrColumnOperand(Reader.readExpr());
}
@@ -6620,7 +6901,7 @@ void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
TL.setLocalRangeBegin(readSourceLocation());
TL.setLParenLoc(readSourceLocation());
TL.setRParenLoc(readSourceLocation());
- TL.setExceptionSpecRange(Reader.readSourceRange());
+ TL.setExceptionSpecRange(readSourceRange());
TL.setLocalRangeEnd(readSourceLocation());
for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i) {
TL.setParam(i, Reader.readDeclAs<ParmVarDecl>());
@@ -6639,6 +6920,10 @@ void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
TL.setNameLoc(readSourceLocation());
}
+void TypeLocReader::VisitUsingTypeLoc(UsingTypeLoc TL) {
+ TL.setNameLoc(readSourceLocation());
+}
+
void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
TL.setNameLoc(readSourceLocation());
}
@@ -6653,11 +6938,12 @@ void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
TL.setTypeofLoc(readSourceLocation());
TL.setLParenLoc(readSourceLocation());
TL.setRParenLoc(readSourceLocation());
- TL.setUnderlyingTInfo(GetTypeSourceInfo());
+ TL.setUnmodifiedTInfo(GetTypeSourceInfo());
}
void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
- TL.setNameLoc(readSourceLocation());
+ TL.setDecltypeLoc(readSourceLocation());
+ TL.setRParenLoc(readSourceLocation());
}
void TypeLocReader::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
@@ -6667,19 +6953,24 @@ void TypeLocReader::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
TL.setUnderlyingTInfo(GetTypeSourceInfo());
}
+ConceptReference *ASTRecordReader::readConceptReference() {
+ auto NNS = readNestedNameSpecifierLoc();
+ auto TemplateKWLoc = readSourceLocation();
+ auto ConceptNameLoc = readDeclarationNameInfo();
+ auto FoundDecl = readDeclAs<NamedDecl>();
+ auto NamedConcept = readDeclAs<ConceptDecl>();
+ auto *CR = ConceptReference::Create(
+ getContext(), NNS, TemplateKWLoc, ConceptNameLoc, FoundDecl, NamedConcept,
+ (readBool() ? readASTTemplateArgumentListInfo() : nullptr));
+ return CR;
+}
+
void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) {
TL.setNameLoc(readSourceLocation());
- if (Reader.readBool()) {
- TL.setNestedNameSpecifierLoc(ReadNestedNameSpecifierLoc());
- TL.setTemplateKWLoc(readSourceLocation());
- TL.setConceptNameLoc(readSourceLocation());
- TL.setFoundDecl(Reader.readDeclAs<NamedDecl>());
- TL.setLAngleLoc(readSourceLocation());
- TL.setRAngleLoc(readSourceLocation());
- for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
- TL.setArgLocInfo(i, Reader.readTemplateArgumentLocInfo(
- TL.getTypePtr()->getArg(i).getKind()));
- }
+ if (Reader.readBool())
+ TL.setConceptReference(Reader.readConceptReference());
+ if (Reader.readBool())
+ TL.setRParenLoc(readSourceLocation());
}
void TypeLocReader::VisitDeducedTemplateSpecializationTypeLoc(
@@ -6699,6 +6990,10 @@ void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
TL.setAttr(ReadAttr());
}
+void TypeLocReader::VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) {
+ // Nothing to do.
+}
+
void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
TL.setNameLoc(readSourceLocation());
}
@@ -6720,10 +7015,9 @@ void TypeLocReader::VisitTemplateSpecializationTypeLoc(
TL.setLAngleLoc(readSourceLocation());
TL.setRAngleLoc(readSourceLocation());
for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
- TL.setArgLocInfo(
- i,
- Reader.readTemplateArgumentLocInfo(
- TL.getTypePtr()->getArg(i).getKind()));
+ TL.setArgLocInfo(i,
+ Reader.readTemplateArgumentLocInfo(
+ TL.getTypePtr()->template_arguments()[i].getKind()));
}
void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) {
@@ -6755,10 +7049,9 @@ void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc(
TL.setLAngleLoc(readSourceLocation());
TL.setRAngleLoc(readSourceLocation());
for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I)
- TL.setArgLocInfo(
- I,
- Reader.readTemplateArgumentLocInfo(
- TL.getTypePtr()->getArg(I).getKind()));
+ TL.setArgLocInfo(I,
+ Reader.readTemplateArgumentLocInfo(
+ TL.getTypePtr()->template_arguments()[I].getKind()));
}
void TypeLocReader::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
@@ -6767,6 +7060,7 @@ void TypeLocReader::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
TL.setNameLoc(readSourceLocation());
+ TL.setNameEndLoc(readSourceLocation());
}
void TypeLocReader::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) {
@@ -6804,17 +7098,17 @@ void TypeLocReader::VisitPipeTypeLoc(PipeTypeLoc TL) {
TL.setKWLoc(readSourceLocation());
}
-void TypeLocReader::VisitExtIntTypeLoc(clang::ExtIntTypeLoc TL) {
+void TypeLocReader::VisitBitIntTypeLoc(clang::BitIntTypeLoc TL) {
TL.setNameLoc(readSourceLocation());
}
-void TypeLocReader::VisitDependentExtIntTypeLoc(
- clang::DependentExtIntTypeLoc TL) {
+void TypeLocReader::VisitDependentBitIntTypeLoc(
+ clang::DependentBitIntTypeLoc TL) {
TL.setNameLoc(readSourceLocation());
}
-
-void ASTRecordReader::readTypeLoc(TypeLoc TL) {
- TypeLocReader TLR(*this);
+void ASTRecordReader::readTypeLoc(TypeLoc TL, LocSeq *ParentSeq) {
+ LocSeq::State Seq(ParentSeq);
+ TypeLocReader TLR(*this, Seq);
for (; !TL.isNull(); TL = TL.getNextTypeLoc())
TLR.Visit(TL);
}
@@ -6839,6 +7133,10 @@ QualType ASTReader::GetType(TypeID ID) {
if (Index < NUM_PREDEF_TYPE_IDS) {
QualType T;
switch ((PredefinedTypeIDs)Index) {
+ case PREDEF_TYPE_LAST_ID:
+ // We should never use this one.
+ llvm_unreachable("Invalid predefined type");
+ break;
case PREDEF_TYPE_NULL_ID:
return QualType();
case PREDEF_TYPE_VOID_ID:
@@ -6984,6 +7282,9 @@ QualType ASTReader::GetType(TypeID ID) {
case PREDEF_TYPE_FLOAT128_ID:
T = Context.Float128Ty;
break;
+ case PREDEF_TYPE_IBM128_ID:
+ T = Context.Ibm128Ty;
+ break;
case PREDEF_TYPE_OVERLOAD_ID:
T = Context.OverloadTy;
break;
@@ -7084,6 +7385,11 @@ QualType ASTReader::GetType(TypeID ID) {
T = Context.SingletonId; \
break;
#include "clang/Basic/RISCVVTypes.def"
+#define WASM_TYPE(Name, Id, SingletonId) \
+ case PREDEF_TYPE_##Id##_ID: \
+ T = Context.SingletonId; \
+ break;
+#include "clang/Basic/WebAssemblyReferenceTypes.def"
}
assert(!T.isNull() && "Unknown predefined type");
@@ -7154,6 +7460,7 @@ ASTRecordReader::readTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind) {
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
case TemplateArgument::NullPtr:
+ case TemplateArgument::StructuralValue:
case TemplateArgument::Pack:
// FIXME: Is this right?
return TemplateArgumentLocInfo();
@@ -7171,15 +7478,20 @@ TemplateArgumentLoc ASTRecordReader::readTemplateArgumentLoc() {
return TemplateArgumentLoc(Arg, readTemplateArgumentLocInfo(Arg.getKind()));
}
-const ASTTemplateArgumentListInfo *
-ASTRecordReader::readASTTemplateArgumentListInfo() {
- SourceLocation LAngleLoc = readSourceLocation();
- SourceLocation RAngleLoc = readSourceLocation();
+void ASTRecordReader::readTemplateArgumentListInfo(
+ TemplateArgumentListInfo &Result) {
+ Result.setLAngleLoc(readSourceLocation());
+ Result.setRAngleLoc(readSourceLocation());
unsigned NumArgsAsWritten = readInt();
- TemplateArgumentListInfo TemplArgsInfo(LAngleLoc, RAngleLoc);
for (unsigned i = 0; i != NumArgsAsWritten; ++i)
- TemplArgsInfo.addArgument(readTemplateArgumentLoc());
- return ASTTemplateArgumentListInfo::Create(getContext(), TemplArgsInfo);
+ Result.addArgument(readTemplateArgumentLoc());
+}
+
+const ASTTemplateArgumentListInfo *
+ASTRecordReader::readASTTemplateArgumentListInfo() {
+ TemplateArgumentListInfo Result;
+ readTemplateArgumentListInfo(Result);
+ return ASTTemplateArgumentListInfo::Create(getContext(), Result);
}
Decl *ASTReader::GetExternalDecl(uint32_t ID) {
@@ -7208,8 +7520,7 @@ void ASTReader::CompleteRedeclChain(const Decl *D) {
//
// FIXME: Merging a function definition should merge
// all mergeable entities within it.
- if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC) ||
- isa<CXXRecordDecl>(DC) || isa<EnumDecl>(DC)) {
+ if (isa<TranslationUnitDecl, NamespaceDecl, RecordDecl, EnumDecl>(DC)) {
if (DeclarationName Name = cast<NamedDecl>(D)->getDeclName()) {
if (!getContext().getLangOpts().CPlusPlus &&
isa<TranslationUnitDecl>(DC)) {
@@ -7253,6 +7564,7 @@ ASTReader::GetExternalCXXCtorInitializers(uint64_t Offset) {
return nullptr;
}
ReadingKindTracker ReadingKind(Read_Decl, *this);
+ Deserializing D(this);
Expected<unsigned> MaybeCode = Cursor.ReadCode();
if (!MaybeCode) {
@@ -7287,6 +7599,7 @@ CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
return nullptr;
}
ReadingKindTracker ReadingKind(Read_Decl, *this);
+ Deserializing D(this);
Expected<unsigned> MaybeCode = Cursor.ReadCode();
if (!MaybeCode) {
@@ -7554,7 +7867,7 @@ void ASTReader::FindExternalLexicalDecls(
};
if (isa<TranslationUnitDecl>(DC)) {
- for (auto Lexical : TULexicalDecls)
+ for (const auto &Lexical : TULexicalDecls)
Visit(Lexical.first, Lexical.second);
} else {
auto I = LexicalDecls.find(DC);
@@ -7730,24 +8043,18 @@ void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) {
void ASTReader::PrintStats() {
std::fprintf(stderr, "*** AST File Statistics:\n");
- unsigned NumTypesLoaded
- = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
- QualType());
- unsigned NumDeclsLoaded
- = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
- (Decl *)nullptr);
- unsigned NumIdentifiersLoaded
- = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),
- IdentifiersLoaded.end(),
- (IdentifierInfo *)nullptr);
- unsigned NumMacrosLoaded
- = MacrosLoaded.size() - std::count(MacrosLoaded.begin(),
- MacrosLoaded.end(),
- (MacroInfo *)nullptr);
- unsigned NumSelectorsLoaded
- = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
- SelectorsLoaded.end(),
- Selector());
+ unsigned NumTypesLoaded =
+ TypesLoaded.size() - llvm::count(TypesLoaded.materialized(), QualType());
+ unsigned NumDeclsLoaded =
+ DeclsLoaded.size() -
+ llvm::count(DeclsLoaded.materialized(), (Decl *)nullptr);
+ unsigned NumIdentifiersLoaded =
+ IdentifiersLoaded.size() -
+ llvm::count(IdentifiersLoaded, (IdentifierInfo *)nullptr);
+ unsigned NumMacrosLoaded =
+ MacrosLoaded.size() - llvm::count(MacrosLoaded, (MacroInfo *)nullptr);
+ unsigned NumSelectorsLoaded =
+ SelectorsLoaded.size() - llvm::count(SelectorsLoaded, Selector());
if (unsigned TotalNumSLocEntries = getTotalNumSLocs())
std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n",
@@ -7950,8 +8257,8 @@ void ASTReader::UpdateSema() {
PragmaAlignPackStack.front().PushLocation);
DropFirst = true;
}
- for (const auto &Entry : llvm::makeArrayRef(PragmaAlignPackStack)
- .drop_front(DropFirst ? 1 : 0)) {
+ for (const auto &Entry :
+ llvm::ArrayRef(PragmaAlignPackStack).drop_front(DropFirst ? 1 : 0)) {
SemaObj->AlignPackStack.Stack.emplace_back(
Entry.SlotLabel, Entry.Value, Entry.Location, Entry.PushLocation);
}
@@ -7982,7 +8289,7 @@ void ASTReader::UpdateSema() {
DropFirst = true;
}
for (const auto &Entry :
- llvm::makeArrayRef(FpPragmaStack).drop_front(DropFirst ? 1 : 0))
+ llvm::ArrayRef(FpPragmaStack).drop_front(DropFirst ? 1 : 0))
SemaObj->FpPragmaStack.Stack.emplace_back(
Entry.SlotLabel, Entry.Value, Entry.Location, Entry.PushLocation);
if (FpPragmaCurrentLocation.isInvalid()) {
@@ -7996,13 +8303,14 @@ void ASTReader::UpdateSema() {
}
// For non-modular AST files, restore visiblity of modules.
- for (auto &Import : ImportedModules) {
+ for (auto &Import : PendingImportedModulesSema) {
if (Import.ImportLoc.isInvalid())
continue;
if (Module *Imported = getSubmodule(Import.ID)) {
SemaObj->makeModuleVisible(Imported, Import.ImportLoc);
}
}
+ PendingImportedModulesSema.clear();
}
IdentifierInfo *ASTReader::get(StringRef Name) {
@@ -8018,7 +8326,7 @@ IdentifierInfo *ASTReader::get(StringRef Name) {
// lookups). Perform the lookup in PCH files, though, since we don't build
// a complete initial identifier table if we're carrying on from a PCH.
if (PP.getLangOpts().CPlusPlus) {
- for (auto F : ModuleMgr.pch_modules())
+ for (auto *F : ModuleMgr.pch_modules())
if (Visitor(*F))
break;
} else {
@@ -8187,13 +8495,16 @@ namespace serialization {
if (Reader.DeserializationListener)
Reader.DeserializationListener->SelectorRead(Data.ID, Sel);
- InstanceMethods.append(Data.Instance.begin(), Data.Instance.end());
- FactoryMethods.append(Data.Factory.begin(), Data.Factory.end());
+ // Append methods in the reverse order, so that later we can process them
+ // in the order they appear in the source code by iterating through
+ // the vector in the reverse order.
+ InstanceMethods.append(Data.Instance.rbegin(), Data.Instance.rend());
+ FactoryMethods.append(Data.Factory.rbegin(), Data.Factory.rend());
InstanceBits = Data.InstanceBits;
FactoryBits = Data.FactoryBits;
InstanceHasMoreThanOneDecl = Data.InstanceHasMoreThanOneDecl;
FactoryHasMoreThanOneDecl = Data.FactoryHasMoreThanOneDecl;
- return true;
+ return false;
}
/// Retrieve the instance methods found by this visitor.
@@ -8222,9 +8533,8 @@ namespace serialization {
/// Add the given set of methods to the method list.
static void addMethodsToPool(Sema &S, ArrayRef<ObjCMethodDecl *> Methods,
ObjCMethodList &List) {
- for (unsigned I = 0, N = Methods.size(); I != N; ++I) {
- S.addMethodToGlobalList(&List, Methods[I]);
- }
+ for (ObjCMethodDecl *M : llvm::reverse(Methods))
+ S.addMethodToGlobalList(&List, M);
}
void ASTReader::ReadMethodPool(Selector Sel) {
@@ -8249,8 +8559,9 @@ void ASTReader::ReadMethodPool(Selector Sel) {
return;
Sema &S = *getSema();
- Sema::GlobalMethodPool::iterator Pos
- = S.MethodPool.insert(std::make_pair(Sel, Sema::GlobalMethods())).first;
+ Sema::GlobalMethodPool::iterator Pos =
+ S.MethodPool.insert(std::make_pair(Sel, Sema::GlobalMethodPool::Lists()))
+ .first;
Pos->second.first.setBits(Visitor.getInstanceBits());
Pos->second.first.setHasMoreThanOneDecl(Visitor.instanceHasMoreThanOneDecl());
@@ -8397,11 +8708,9 @@ void ASTReader::ReadWeakUndeclaredIdentifiers(
= DecodeIdentifierInfo(WeakUndeclaredIdentifiers[I++]);
IdentifierInfo *AliasId
= DecodeIdentifierInfo(WeakUndeclaredIdentifiers[I++]);
- SourceLocation Loc
- = SourceLocation::getFromRawEncoding(WeakUndeclaredIdentifiers[I++]);
- bool Used = WeakUndeclaredIdentifiers[I++];
+ SourceLocation Loc =
+ SourceLocation::getFromRawEncoding(WeakUndeclaredIdentifiers[I++]);
WeakInfo WI(AliasId, Loc);
- WI.setUsed(Used);
WeakIDs.push_back(std::make_pair(WeakId, WI));
}
WeakUndeclaredIdentifiers.clear();
@@ -8444,6 +8753,7 @@ void ASTReader::ReadLateParsedTemplates(
auto LT = std::make_unique<LateParsedTemplate>();
LT->D = GetLocalDecl(*FMod, LateParsed[Idx++]);
+ LT->FPO = FPOptions::getFromOpaqueInt(LateParsed[Idx++]);
ModuleFile *F = getOwningModuleFile(LT->D);
assert(F && "No module");
@@ -8460,6 +8770,17 @@ void ASTReader::ReadLateParsedTemplates(
LateParsedTemplates.clear();
}
+void ASTReader::AssignedLambdaNumbering(const CXXRecordDecl *Lambda) {
+ if (Lambda->getLambdaContextDecl()) {
+ // Keep track of this lambda so it can be merged with another lambda that
+ // is loaded later.
+ LambdaDeclarationsForMerging.insert(
+ {{Lambda->getLambdaContextDecl()->getCanonicalDecl(),
+ Lambda->getLambdaIndexInContext()},
+ const_cast<CXXRecordDecl *>(Lambda)});
+ }
+}
+
void ASTReader::LoadSelector(Selector Sel) {
// It would be complicated to avoid reading the methods anyway. So don't.
ReadMethodPool(Sel);
@@ -8647,10 +8968,10 @@ Module *ASTReader::getModule(unsigned ID) {
return getSubmodule(ID);
}
-ModuleFile *ASTReader::getLocalModuleFile(ModuleFile &F, unsigned ID) {
+ModuleFile *ASTReader::getLocalModuleFile(ModuleFile &M, unsigned ID) {
if (ID & 1) {
// It's a module, look it up by submodule ID.
- auto I = GlobalSubmoduleMap.find(getGlobalSubmoduleID(F, ID >> 1));
+ auto I = GlobalSubmoduleMap.find(getGlobalSubmoduleID(M, ID >> 1));
return I == GlobalSubmoduleMap.end() ? nullptr : I->second;
} else {
// It's a prefix (preamble, PCH, ...). Look it up by index.
@@ -8660,25 +8981,24 @@ ModuleFile *ASTReader::getLocalModuleFile(ModuleFile &F, unsigned ID) {
}
}
-unsigned ASTReader::getModuleFileID(ModuleFile *F) {
- if (!F)
+unsigned ASTReader::getModuleFileID(ModuleFile *M) {
+ if (!M)
return 1;
// For a file representing a module, use the submodule ID of the top-level
// module as the file ID. For any other kind of file, the number of such
// files loaded beforehand will be the same on reload.
// FIXME: Is this true even if we have an explicit module file and a PCH?
- if (F->isModule())
- return ((F->BaseSubmoduleID + NUM_PREDEF_SUBMODULE_IDS) << 1) | 1;
+ if (M->isModule())
+ return ((M->BaseSubmoduleID + NUM_PREDEF_SUBMODULE_IDS) << 1) | 1;
auto PCHModules = getModuleManager().pch_modules();
- auto I = llvm::find(PCHModules, F);
+ auto I = llvm::find(PCHModules, M);
assert(I != PCHModules.end() && "emitting reference to unknown file");
return (I - PCHModules.end()) << 1;
}
-llvm::Optional<ASTSourceDescriptor>
-ASTReader::getSourceDescriptor(unsigned ID) {
+std::optional<ASTSourceDescriptor> ASTReader::getSourceDescriptor(unsigned ID) {
if (Module *M = getSubmodule(ID))
return ASTSourceDescriptor(*M);
@@ -8689,10 +9009,11 @@ ASTReader::getSourceDescriptor(unsigned ID) {
ModuleFile &MF = ModuleMgr.getPrimaryModule();
StringRef ModuleName = llvm::sys::path::filename(MF.OriginalSourceFileName);
StringRef FileName = llvm::sys::path::filename(MF.FileName);
- return ASTSourceDescriptor(ModuleName, MF.OriginalDir, FileName,
- MF.Signature);
+ return ASTSourceDescriptor(ModuleName,
+ llvm::sys::path::parent_path(MF.FileName),
+ FileName, MF.Signature);
}
- return None;
+ return std::nullopt;
}
ExternalASTSource::ExtKind ASTReader::hasExternalDefinitions(const Decl *FD) {
@@ -8984,11 +9305,10 @@ ASTRecordReader::readNestedNameSpecifierLoc() {
return Builder.getWithLocInContext(Context);
}
-SourceRange
-ASTReader::ReadSourceRange(ModuleFile &F, const RecordData &Record,
- unsigned &Idx) {
- SourceLocation beg = ReadSourceLocation(F, Record, Idx);
- SourceLocation end = ReadSourceLocation(F, Record, Idx);
+SourceRange ASTReader::ReadSourceRange(ModuleFile &F, const RecordData &Record,
+ unsigned &Idx, LocSeq *Seq) {
+ SourceLocation beg = ReadSourceLocation(F, Record, Idx, Seq);
+ SourceLocation end = ReadSourceLocation(F, Record, Idx, Seq);
return SourceRange(beg, end);
}
@@ -8998,7 +9318,7 @@ llvm::APFloat ASTRecordReader::readAPFloat(const llvm::fltSemantics &Sem) {
}
// Read a string
-std::string ASTReader::ReadString(const RecordData &Record, unsigned &Idx) {
+std::string ASTReader::ReadString(const RecordDataImpl &Record, unsigned &Idx) {
unsigned Len = Record[Idx++];
std::string Result(Record.data() + Idx, Record.data() + Idx + Len);
Idx += Len;
@@ -9143,6 +9463,22 @@ void ASTReader::ReadComments() {
}
}
+void ASTReader::visitInputFileInfos(
+ serialization::ModuleFile &MF, bool IncludeSystem,
+ llvm::function_ref<void(const serialization::InputFileInfo &IFI,
+ bool IsSystem)>
+ Visitor) {
+ unsigned NumUserInputs = MF.NumUserInputFiles;
+ unsigned NumInputs = MF.InputFilesLoaded.size();
+ assert(NumUserInputs <= NumInputs);
+ unsigned N = IncludeSystem ? NumInputs : NumUserInputs;
+ for (unsigned I = 0; I < N; ++I) {
+ bool IsSystem = I >= NumUserInputs;
+ InputFileInfo IFI = getInputFileInfo(MF, I+1);
+ Visitor(IFI, IsSystem);
+ }
+}
+
void ASTReader::visitInputFiles(serialization::ModuleFile &MF,
bool IncludeSystem, bool Complain,
llvm::function_ref<void(const serialization::InputFile &IF,
@@ -9160,35 +9496,23 @@ void ASTReader::visitInputFiles(serialization::ModuleFile &MF,
void ASTReader::visitTopLevelModuleMaps(
serialization::ModuleFile &MF,
- llvm::function_ref<void(const FileEntry *FE)> Visitor) {
+ llvm::function_ref<void(FileEntryRef FE)> Visitor) {
unsigned NumInputs = MF.InputFilesLoaded.size();
for (unsigned I = 0; I < NumInputs; ++I) {
- InputFileInfo IFI = readInputFileInfo(MF, I + 1);
- if (IFI.TopLevelModuleMap)
- // FIXME: This unnecessarily re-reads the InputFileInfo.
+ InputFileInfo IFI = getInputFileInfo(MF, I + 1);
+ if (IFI.TopLevel && IFI.ModuleMap)
if (auto FE = getInputFile(MF, I + 1).getFile())
- Visitor(FE);
+ Visitor(*FE);
}
}
-std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) {
- // If we know the owning module, use it.
- if (Module *M = D->getImportedOwningModule())
- return M->getFullModuleName();
-
- // Otherwise, use the name of the top-level module the decl is within.
- if (ModuleFile *M = getOwningModuleFile(D))
- return M->ModuleName;
-
- // Not from a module.
- return {};
-}
-
void ASTReader::finishPendingActions() {
- while (!PendingIdentifierInfos.empty() || !PendingFunctionTypes.empty() ||
- !PendingIncompleteDeclChains.empty() || !PendingDeclChains.empty() ||
- !PendingMacroIDs.empty() || !PendingDeclContextInfos.empty() ||
- !PendingUpdateRecords.empty()) {
+ while (
+ !PendingIdentifierInfos.empty() || !PendingDeducedFunctionTypes.empty() ||
+ !PendingDeducedVarTypes.empty() || !PendingIncompleteDeclChains.empty() ||
+ !PendingDeclChains.empty() || !PendingMacroIDs.empty() ||
+ !PendingDeclContextInfos.empty() || !PendingUpdateRecords.empty() ||
+ !PendingObjCExtensionIvarRedeclarations.empty()) {
// If any identifiers with corresponding top-level declarations have
// been loaded, load those declarations now.
using TopLevelDeclsMap =
@@ -9206,18 +9530,35 @@ void ASTReader::finishPendingActions() {
// Load each function type that we deferred loading because it was a
// deduced type that might refer to a local type declared within itself.
- for (unsigned I = 0; I != PendingFunctionTypes.size(); ++I) {
- auto *FD = PendingFunctionTypes[I].first;
- FD->setType(GetType(PendingFunctionTypes[I].second));
+ for (unsigned I = 0; I != PendingDeducedFunctionTypes.size(); ++I) {
+ auto *FD = PendingDeducedFunctionTypes[I].first;
+ FD->setType(GetType(PendingDeducedFunctionTypes[I].second));
+
+ if (auto *DT = FD->getReturnType()->getContainedDeducedType()) {
+ // If we gave a function a deduced return type, remember that we need to
+ // propagate that along the redeclaration chain.
+ if (DT->isDeduced()) {
+ PendingDeducedTypeUpdates.insert(
+ {FD->getCanonicalDecl(), FD->getReturnType()});
+ continue;
+ }
- // If we gave a function a deduced return type, remember that we need to
- // propagate that along the redeclaration chain.
- auto *DT = FD->getReturnType()->getContainedDeducedType();
- if (DT && DT->isDeduced())
- PendingDeducedTypeUpdates.insert(
- {FD->getCanonicalDecl(), FD->getReturnType()});
+ // The function has undeduced DeduceType return type. We hope we can
+ // find the deduced type by iterating the redecls in other modules
+ // later.
+ PendingUndeducedFunctionDecls.push_back(FD);
+ continue;
+ }
}
- PendingFunctionTypes.clear();
+ PendingDeducedFunctionTypes.clear();
+
+ // Load each variable type that we deferred loading because it was a
+ // deduced type that might refer to a local type declared within itself.
+ for (unsigned I = 0; I != PendingDeducedVarTypes.size(); ++I) {
+ auto *VD = PendingDeducedVarTypes[I].first;
+ VD->setType(GetType(PendingDeducedVarTypes[I].second));
+ }
+ PendingDeducedVarTypes.clear();
// For each decl chain that we wanted to complete while deserializing, mark
// it as "still needs to be completed".
@@ -9279,6 +9620,43 @@ void ASTReader::finishPendingActions() {
ReadingKindTracker ReadingKind(Read_Decl, *this);
loadDeclUpdateRecords(Update);
}
+
+ while (!PendingObjCExtensionIvarRedeclarations.empty()) {
+ auto ExtensionsPair = PendingObjCExtensionIvarRedeclarations.back().first;
+ auto DuplicateIvars =
+ PendingObjCExtensionIvarRedeclarations.back().second;
+ llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls;
+ StructuralEquivalenceContext Ctx(
+ ExtensionsPair.first->getASTContext(),
+ ExtensionsPair.second->getASTContext(), NonEquivalentDecls,
+ StructuralEquivalenceKind::Default, /*StrictTypeSpelling =*/false,
+ /*Complain =*/false,
+ /*ErrorOnTagTypeMismatch =*/true);
+ if (Ctx.IsEquivalent(ExtensionsPair.first, ExtensionsPair.second)) {
+ // Merge redeclared ivars with their predecessors.
+ for (auto IvarPair : DuplicateIvars) {
+ ObjCIvarDecl *Ivar = IvarPair.first, *PrevIvar = IvarPair.second;
+ // Change semantic DeclContext but keep the lexical one.
+ Ivar->setDeclContextsImpl(PrevIvar->getDeclContext(),
+ Ivar->getLexicalDeclContext(),
+ getContext());
+ getContext().setPrimaryMergedDecl(Ivar, PrevIvar->getCanonicalDecl());
+ }
+ // Invalidate duplicate extension and the cached ivar list.
+ ExtensionsPair.first->setInvalidDecl();
+ ExtensionsPair.second->getClassInterface()
+ ->getDefinition()
+ ->setIvarList(nullptr);
+ } else {
+ for (auto IvarPair : DuplicateIvars) {
+ Diag(IvarPair.first->getLocation(),
+ diag::err_duplicate_ivar_declaration)
+ << IvarPair.first->getIdentifier();
+ Diag(IvarPair.second->getLocation(), diag::note_previous_definition);
+ }
+ }
+ PendingObjCExtensionIvarRedeclarations.pop_back();
+ }
}
// At this point, all update records for loaded decls are in place, so any
@@ -9356,7 +9734,6 @@ void ASTReader::finishPendingActions() {
continue;
// FIXME: Check for =delete/=default?
- // FIXME: Complain about ODR violations here?
const FunctionDecl *Defn = nullptr;
if (!getContext().getLangOpts().Modules || !FD->hasBody(Defn)) {
FD->setLazyBody(PB->second);
@@ -9366,6 +9743,9 @@ void ASTReader::finishPendingActions() {
if (!FD->isLateTemplateParsed() &&
!NonConstDefn->isLateTemplateParsed() &&
+ // We only perform ODR checks for decls not in the explicit
+ // global module fragment.
+ !FD->shouldSkipCheckingODR() &&
FD->getODRHash() != NonConstDefn->getODRHash()) {
if (!isa<CXXMethodDecl>(FD)) {
PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn);
@@ -9387,6 +9767,12 @@ void ASTReader::finishPendingActions() {
}
PendingBodies.clear();
+ // Inform any classes that had members added that they now have more members.
+ for (auto [RD, MD] : PendingAddedClassMembers) {
+ RD->addedMember(MD);
+ }
+ PendingAddedClassMembers.clear();
+
// Do some cleanup.
for (auto *ND : PendingMergedDefinitionsToDeduplicate)
getContext().deduplicateMergedDefinitonsFor(ND);
@@ -9395,8 +9781,11 @@ void ASTReader::finishPendingActions() {
void ASTReader::diagnoseOdrViolations() {
if (PendingOdrMergeFailures.empty() && PendingOdrMergeChecks.empty() &&
+ PendingRecordOdrMergeFailures.empty() &&
PendingFunctionOdrMergeFailures.empty() &&
- PendingEnumOdrMergeFailures.empty())
+ PendingEnumOdrMergeFailures.empty() &&
+ PendingObjCInterfaceOdrMergeFailures.empty() &&
+ PendingObjCProtocolOdrMergeFailures.empty())
return;
// Trigger the import of the full definition of each class that had any
@@ -9418,6 +9807,25 @@ void ASTReader::diagnoseOdrViolations() {
}
}
+ // Trigger the import of the full definition of each record in C/ObjC.
+ auto RecordOdrMergeFailures = std::move(PendingRecordOdrMergeFailures);
+ PendingRecordOdrMergeFailures.clear();
+ for (auto &Merge : RecordOdrMergeFailures) {
+ Merge.first->decls_begin();
+ for (auto &D : Merge.second)
+ D->decls_begin();
+ }
+
+ // Trigger the import of the full interface definition.
+ auto ObjCInterfaceOdrMergeFailures =
+ std::move(PendingObjCInterfaceOdrMergeFailures);
+ PendingObjCInterfaceOdrMergeFailures.clear();
+ for (auto &Merge : ObjCInterfaceOdrMergeFailures) {
+ Merge.first->decls_begin();
+ for (auto &InterfacePair : Merge.second)
+ InterfacePair.first->decls_begin();
+ }
+
// Trigger the import of functions.
auto FunctionOdrMergeFailures = std::move(PendingFunctionOdrMergeFailures);
PendingFunctionOdrMergeFailures.clear();
@@ -9442,6 +9850,16 @@ void ASTReader::diagnoseOdrViolations() {
}
}
+ // Trigger the import of the full protocol definition.
+ auto ObjCProtocolOdrMergeFailures =
+ std::move(PendingObjCProtocolOdrMergeFailures);
+ PendingObjCProtocolOdrMergeFailures.clear();
+ for (auto &Merge : ObjCProtocolOdrMergeFailures) {
+ Merge.first->decls_begin();
+ for (auto &ProtocolPair : Merge.second)
+ ProtocolPair.first->decls_begin();
+ }
+
// For each declaration from a merged context, check that the canonical
// definition of that context also contains a declaration of the same
// entity.
@@ -9463,7 +9881,7 @@ void ASTReader::diagnoseOdrViolations() {
bool Found = false;
const Decl *DCanon = D->getCanonicalDecl();
- for (auto RI : D->redecls()) {
+ for (auto *RI : D->redecls()) {
if (RI->getLexicalDeclContext() == CanonDef) {
Found = true;
break;
@@ -9505,9 +9923,10 @@ void ASTReader::diagnoseOdrViolations() {
Deserializing RecursionGuard(this);
std::string CanonDefModule =
- getOwningModuleNameForDiagnostic(cast<Decl>(CanonDef));
+ ODRDiagsEmitter::getOwningModuleNameForDiagnostic(
+ cast<Decl>(CanonDef));
Diag(D->getLocation(), diag::err_module_odr_violation_missing_decl)
- << D << getOwningModuleNameForDiagnostic(D)
+ << D << ODRDiagsEmitter::getOwningModuleNameForDiagnostic(D)
<< CanonDef << CanonDefModule.empty() << CanonDefModule;
if (Candidates.empty())
@@ -9524,489 +9943,14 @@ void ASTReader::diagnoseOdrViolations() {
}
}
- if (OdrMergeFailures.empty() && FunctionOdrMergeFailures.empty() &&
- EnumOdrMergeFailures.empty())
+ if (OdrMergeFailures.empty() && RecordOdrMergeFailures.empty() &&
+ FunctionOdrMergeFailures.empty() && EnumOdrMergeFailures.empty() &&
+ ObjCInterfaceOdrMergeFailures.empty() &&
+ ObjCProtocolOdrMergeFailures.empty())
return;
- // Ensure we don't accidentally recursively enter deserialization while
- // we're producing our diagnostics.
- Deserializing RecursionGuard(this);
-
- // Common code for hashing helpers.
- ODRHash Hash;
- auto ComputeQualTypeODRHash = [&Hash](QualType Ty) {
- Hash.clear();
- Hash.AddQualType(Ty);
- return Hash.CalculateHash();
- };
-
- auto ComputeODRHash = [&Hash](const Stmt *S) {
- assert(S);
- Hash.clear();
- Hash.AddStmt(S);
- return Hash.CalculateHash();
- };
-
- auto ComputeSubDeclODRHash = [&Hash](const Decl *D) {
- assert(D);
- Hash.clear();
- Hash.AddSubDecl(D);
- return Hash.CalculateHash();
- };
-
- auto ComputeTemplateArgumentODRHash = [&Hash](const TemplateArgument &TA) {
- Hash.clear();
- Hash.AddTemplateArgument(TA);
- return Hash.CalculateHash();
- };
-
- auto ComputeTemplateParameterListODRHash =
- [&Hash](const TemplateParameterList *TPL) {
- assert(TPL);
- Hash.clear();
- Hash.AddTemplateParameterList(TPL);
- return Hash.CalculateHash();
- };
-
- // Used with err_module_odr_violation_mismatch_decl and
- // note_module_odr_violation_mismatch_decl
- // This list should be the same Decl's as in ODRHash::isDeclToBeProcessed
- enum ODRMismatchDecl {
- EndOfClass,
- PublicSpecifer,
- PrivateSpecifer,
- ProtectedSpecifer,
- StaticAssert,
- Field,
- CXXMethod,
- TypeAlias,
- TypeDef,
- Var,
- Friend,
- FunctionTemplate,
- Other
- };
-
- // Used with err_module_odr_violation_mismatch_decl_diff and
- // note_module_odr_violation_mismatch_decl_diff
- enum ODRMismatchDeclDifference {
- StaticAssertCondition,
- StaticAssertMessage,
- StaticAssertOnlyMessage,
- FieldName,
- FieldTypeName,
- FieldSingleBitField,
- FieldDifferentWidthBitField,
- FieldSingleMutable,
- FieldSingleInitializer,
- FieldDifferentInitializers,
- MethodName,
- MethodDeleted,
- MethodDefaulted,
- MethodVirtual,
- MethodStatic,
- MethodVolatile,
- MethodConst,
- MethodInline,
- MethodNumberParameters,
- MethodParameterType,
- MethodParameterName,
- MethodParameterSingleDefaultArgument,
- MethodParameterDifferentDefaultArgument,
- MethodNoTemplateArguments,
- MethodDifferentNumberTemplateArguments,
- MethodDifferentTemplateArgument,
- MethodSingleBody,
- MethodDifferentBody,
- TypedefName,
- TypedefType,
- VarName,
- VarType,
- VarSingleInitializer,
- VarDifferentInitializer,
- VarConstexpr,
- FriendTypeFunction,
- FriendType,
- FriendFunction,
- FunctionTemplateDifferentNumberParameters,
- FunctionTemplateParameterDifferentKind,
- FunctionTemplateParameterName,
- FunctionTemplateParameterSingleDefaultArgument,
- FunctionTemplateParameterDifferentDefaultArgument,
- FunctionTemplateParameterDifferentType,
- FunctionTemplatePackParameter,
- };
-
- // These lambdas have the common portions of the ODR diagnostics. This
- // has the same return as Diag(), so addition parameters can be passed
- // in with operator<<
- auto ODRDiagDeclError = [this](NamedDecl *FirstRecord, StringRef FirstModule,
- SourceLocation Loc, SourceRange Range,
- ODRMismatchDeclDifference DiffType) {
- return Diag(Loc, diag::err_module_odr_violation_mismatch_decl_diff)
- << FirstRecord << FirstModule.empty() << FirstModule << Range
- << DiffType;
- };
- auto ODRDiagDeclNote = [this](StringRef SecondModule, SourceLocation Loc,
- SourceRange Range, ODRMismatchDeclDifference DiffType) {
- return Diag(Loc, diag::note_module_odr_violation_mismatch_decl_diff)
- << SecondModule << Range << DiffType;
- };
-
- auto ODRDiagField = [this, &ODRDiagDeclError, &ODRDiagDeclNote,
- &ComputeQualTypeODRHash, &ComputeODRHash](
- NamedDecl *FirstRecord, StringRef FirstModule,
- StringRef SecondModule, FieldDecl *FirstField,
- FieldDecl *SecondField) {
- IdentifierInfo *FirstII = FirstField->getIdentifier();
- IdentifierInfo *SecondII = SecondField->getIdentifier();
- if (FirstII->getName() != SecondII->getName()) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstField->getLocation(),
- FirstField->getSourceRange(), FieldName)
- << FirstII;
- ODRDiagDeclNote(SecondModule, SecondField->getLocation(),
- SecondField->getSourceRange(), FieldName)
- << SecondII;
-
- return true;
- }
-
- assert(getContext().hasSameType(FirstField->getType(),
- SecondField->getType()));
-
- QualType FirstType = FirstField->getType();
- QualType SecondType = SecondField->getType();
- if (ComputeQualTypeODRHash(FirstType) !=
- ComputeQualTypeODRHash(SecondType)) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstField->getLocation(),
- FirstField->getSourceRange(), FieldTypeName)
- << FirstII << FirstType;
- ODRDiagDeclNote(SecondModule, SecondField->getLocation(),
- SecondField->getSourceRange(), FieldTypeName)
- << SecondII << SecondType;
-
- return true;
- }
-
- const bool IsFirstBitField = FirstField->isBitField();
- const bool IsSecondBitField = SecondField->isBitField();
- if (IsFirstBitField != IsSecondBitField) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstField->getLocation(),
- FirstField->getSourceRange(), FieldSingleBitField)
- << FirstII << IsFirstBitField;
- ODRDiagDeclNote(SecondModule, SecondField->getLocation(),
- SecondField->getSourceRange(), FieldSingleBitField)
- << SecondII << IsSecondBitField;
- return true;
- }
-
- if (IsFirstBitField && IsSecondBitField) {
- unsigned FirstBitWidthHash =
- ComputeODRHash(FirstField->getBitWidth());
- unsigned SecondBitWidthHash =
- ComputeODRHash(SecondField->getBitWidth());
- if (FirstBitWidthHash != SecondBitWidthHash) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstField->getLocation(),
- FirstField->getSourceRange(),
- FieldDifferentWidthBitField)
- << FirstII << FirstField->getBitWidth()->getSourceRange();
- ODRDiagDeclNote(SecondModule, SecondField->getLocation(),
- SecondField->getSourceRange(),
- FieldDifferentWidthBitField)
- << SecondII << SecondField->getBitWidth()->getSourceRange();
- return true;
- }
- }
-
- if (!PP.getLangOpts().CPlusPlus)
- return false;
-
- const bool IsFirstMutable = FirstField->isMutable();
- const bool IsSecondMutable = SecondField->isMutable();
- if (IsFirstMutable != IsSecondMutable) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstField->getLocation(),
- FirstField->getSourceRange(), FieldSingleMutable)
- << FirstII << IsFirstMutable;
- ODRDiagDeclNote(SecondModule, SecondField->getLocation(),
- SecondField->getSourceRange(), FieldSingleMutable)
- << SecondII << IsSecondMutable;
- return true;
- }
-
- const Expr *FirstInitializer = FirstField->getInClassInitializer();
- const Expr *SecondInitializer = SecondField->getInClassInitializer();
- if ((!FirstInitializer && SecondInitializer) ||
- (FirstInitializer && !SecondInitializer)) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstField->getLocation(),
- FirstField->getSourceRange(), FieldSingleInitializer)
- << FirstII << (FirstInitializer != nullptr);
- ODRDiagDeclNote(SecondModule, SecondField->getLocation(),
- SecondField->getSourceRange(), FieldSingleInitializer)
- << SecondII << (SecondInitializer != nullptr);
- return true;
- }
-
- if (FirstInitializer && SecondInitializer) {
- unsigned FirstInitHash = ComputeODRHash(FirstInitializer);
- unsigned SecondInitHash = ComputeODRHash(SecondInitializer);
- if (FirstInitHash != SecondInitHash) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstField->getLocation(),
- FirstField->getSourceRange(),
- FieldDifferentInitializers)
- << FirstII << FirstInitializer->getSourceRange();
- ODRDiagDeclNote(SecondModule, SecondField->getLocation(),
- SecondField->getSourceRange(),
- FieldDifferentInitializers)
- << SecondII << SecondInitializer->getSourceRange();
- return true;
- }
- }
-
- return false;
- };
-
- auto ODRDiagTypeDefOrAlias =
- [&ODRDiagDeclError, &ODRDiagDeclNote, &ComputeQualTypeODRHash](
- NamedDecl *FirstRecord, StringRef FirstModule, StringRef SecondModule,
- TypedefNameDecl *FirstTD, TypedefNameDecl *SecondTD,
- bool IsTypeAlias) {
- auto FirstName = FirstTD->getDeclName();
- auto SecondName = SecondTD->getDeclName();
- if (FirstName != SecondName) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstTD->getLocation(),
- FirstTD->getSourceRange(), TypedefName)
- << IsTypeAlias << FirstName;
- ODRDiagDeclNote(SecondModule, SecondTD->getLocation(),
- SecondTD->getSourceRange(), TypedefName)
- << IsTypeAlias << SecondName;
- return true;
- }
-
- QualType FirstType = FirstTD->getUnderlyingType();
- QualType SecondType = SecondTD->getUnderlyingType();
- if (ComputeQualTypeODRHash(FirstType) !=
- ComputeQualTypeODRHash(SecondType)) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstTD->getLocation(),
- FirstTD->getSourceRange(), TypedefType)
- << IsTypeAlias << FirstName << FirstType;
- ODRDiagDeclNote(SecondModule, SecondTD->getLocation(),
- SecondTD->getSourceRange(), TypedefType)
- << IsTypeAlias << SecondName << SecondType;
- return true;
- }
-
- return false;
- };
-
- auto ODRDiagVar = [&ODRDiagDeclError, &ODRDiagDeclNote,
- &ComputeQualTypeODRHash, &ComputeODRHash,
- this](NamedDecl *FirstRecord, StringRef FirstModule,
- StringRef SecondModule, VarDecl *FirstVD,
- VarDecl *SecondVD) {
- auto FirstName = FirstVD->getDeclName();
- auto SecondName = SecondVD->getDeclName();
- if (FirstName != SecondName) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstVD->getLocation(),
- FirstVD->getSourceRange(), VarName)
- << FirstName;
- ODRDiagDeclNote(SecondModule, SecondVD->getLocation(),
- SecondVD->getSourceRange(), VarName)
- << SecondName;
- return true;
- }
-
- QualType FirstType = FirstVD->getType();
- QualType SecondType = SecondVD->getType();
- if (ComputeQualTypeODRHash(FirstType) !=
- ComputeQualTypeODRHash(SecondType)) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstVD->getLocation(),
- FirstVD->getSourceRange(), VarType)
- << FirstName << FirstType;
- ODRDiagDeclNote(SecondModule, SecondVD->getLocation(),
- SecondVD->getSourceRange(), VarType)
- << SecondName << SecondType;
- return true;
- }
-
- if (!PP.getLangOpts().CPlusPlus)
- return false;
-
- const Expr *FirstInit = FirstVD->getInit();
- const Expr *SecondInit = SecondVD->getInit();
- if ((FirstInit == nullptr) != (SecondInit == nullptr)) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstVD->getLocation(),
- FirstVD->getSourceRange(), VarSingleInitializer)
- << FirstName << (FirstInit == nullptr)
- << (FirstInit ? FirstInit->getSourceRange() : SourceRange());
- ODRDiagDeclNote(SecondModule, SecondVD->getLocation(),
- SecondVD->getSourceRange(), VarSingleInitializer)
- << SecondName << (SecondInit == nullptr)
- << (SecondInit ? SecondInit->getSourceRange() : SourceRange());
- return true;
- }
-
- if (FirstInit && SecondInit &&
- ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstVD->getLocation(),
- FirstVD->getSourceRange(), VarDifferentInitializer)
- << FirstName << FirstInit->getSourceRange();
- ODRDiagDeclNote(SecondModule, SecondVD->getLocation(),
- SecondVD->getSourceRange(), VarDifferentInitializer)
- << SecondName << SecondInit->getSourceRange();
- return true;
- }
-
- const bool FirstIsConstexpr = FirstVD->isConstexpr();
- const bool SecondIsConstexpr = SecondVD->isConstexpr();
- if (FirstIsConstexpr != SecondIsConstexpr) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstVD->getLocation(),
- FirstVD->getSourceRange(), VarConstexpr)
- << FirstName << FirstIsConstexpr;
- ODRDiagDeclNote(SecondModule, SecondVD->getLocation(),
- SecondVD->getSourceRange(), VarConstexpr)
- << SecondName << SecondIsConstexpr;
- return true;
- }
- return false;
- };
-
- auto DifferenceSelector = [](Decl *D) {
- assert(D && "valid Decl required");
- switch (D->getKind()) {
- default:
- return Other;
- case Decl::AccessSpec:
- switch (D->getAccess()) {
- case AS_public:
- return PublicSpecifer;
- case AS_private:
- return PrivateSpecifer;
- case AS_protected:
- return ProtectedSpecifer;
- case AS_none:
- break;
- }
- llvm_unreachable("Invalid access specifier");
- case Decl::StaticAssert:
- return StaticAssert;
- case Decl::Field:
- return Field;
- case Decl::CXXMethod:
- case Decl::CXXConstructor:
- case Decl::CXXDestructor:
- return CXXMethod;
- case Decl::TypeAlias:
- return TypeAlias;
- case Decl::Typedef:
- return TypeDef;
- case Decl::Var:
- return Var;
- case Decl::Friend:
- return Friend;
- case Decl::FunctionTemplate:
- return FunctionTemplate;
- }
- };
-
- using DeclHashes = llvm::SmallVector<std::pair<Decl *, unsigned>, 4>;
- auto PopulateHashes = [&ComputeSubDeclODRHash](DeclHashes &Hashes,
- RecordDecl *Record,
- const DeclContext *DC) {
- for (auto *D : Record->decls()) {
- if (!ODRHash::isDeclToBeProcessed(D, DC))
- continue;
- Hashes.emplace_back(D, ComputeSubDeclODRHash(D));
- }
- };
-
- struct DiffResult {
- Decl *FirstDecl = nullptr, *SecondDecl = nullptr;
- ODRMismatchDecl FirstDiffType = Other, SecondDiffType = Other;
- };
-
- // If there is a diagnoseable difference, FirstDiffType and
- // SecondDiffType will not be Other and FirstDecl and SecondDecl will be
- // filled in if not EndOfClass.
- auto FindTypeDiffs = [&DifferenceSelector](DeclHashes &FirstHashes,
- DeclHashes &SecondHashes) {
- DiffResult DR;
- auto FirstIt = FirstHashes.begin();
- auto SecondIt = SecondHashes.begin();
- while (FirstIt != FirstHashes.end() || SecondIt != SecondHashes.end()) {
- if (FirstIt != FirstHashes.end() && SecondIt != SecondHashes.end() &&
- FirstIt->second == SecondIt->second) {
- ++FirstIt;
- ++SecondIt;
- continue;
- }
-
- DR.FirstDecl = FirstIt == FirstHashes.end() ? nullptr : FirstIt->first;
- DR.SecondDecl =
- SecondIt == SecondHashes.end() ? nullptr : SecondIt->first;
-
- DR.FirstDiffType =
- DR.FirstDecl ? DifferenceSelector(DR.FirstDecl) : EndOfClass;
- DR.SecondDiffType =
- DR.SecondDecl ? DifferenceSelector(DR.SecondDecl) : EndOfClass;
- return DR;
- }
- return DR;
- };
-
- // Use this to diagnose that an unexpected Decl was encountered
- // or no difference was detected. This causes a generic error
- // message to be emitted.
- auto DiagnoseODRUnexpected = [this](DiffResult &DR, NamedDecl *FirstRecord,
- StringRef FirstModule,
- NamedDecl *SecondRecord,
- StringRef SecondModule) {
- Diag(FirstRecord->getLocation(),
- diag::err_module_odr_violation_different_definitions)
- << FirstRecord << FirstModule.empty() << FirstModule;
-
- if (DR.FirstDecl) {
- Diag(DR.FirstDecl->getLocation(), diag::note_first_module_difference)
- << FirstRecord << DR.FirstDecl->getSourceRange();
- }
-
- Diag(SecondRecord->getLocation(),
- diag::note_module_odr_violation_different_definitions)
- << SecondModule;
-
- if (DR.SecondDecl) {
- Diag(DR.SecondDecl->getLocation(), diag::note_second_module_difference)
- << DR.SecondDecl->getSourceRange();
- }
- };
-
- auto DiagnoseODRMismatch =
- [this](DiffResult &DR, NamedDecl *FirstRecord, StringRef FirstModule,
- NamedDecl *SecondRecord, StringRef SecondModule) {
- SourceLocation FirstLoc;
- SourceRange FirstRange;
- auto *FirstTag = dyn_cast<TagDecl>(FirstRecord);
- if (DR.FirstDiffType == EndOfClass && FirstTag) {
- FirstLoc = FirstTag->getBraceRange().getEnd();
- } else {
- FirstLoc = DR.FirstDecl->getLocation();
- FirstRange = DR.FirstDecl->getSourceRange();
- }
- Diag(FirstLoc, diag::err_module_odr_violation_mismatch_decl)
- << FirstRecord << FirstModule.empty() << FirstModule << FirstRange
- << DR.FirstDiffType;
-
- SourceLocation SecondLoc;
- SourceRange SecondRange;
- auto *SecondTag = dyn_cast<TagDecl>(SecondRecord);
- if (DR.SecondDiffType == EndOfClass && SecondTag) {
- SecondLoc = SecondTag->getBraceRange().getEnd();
- } else {
- SecondLoc = DR.SecondDecl->getLocation();
- SecondRange = DR.SecondDecl->getSourceRange();
- }
- Diag(SecondLoc, diag::note_module_odr_violation_mismatch_decl)
- << SecondModule << SecondRange << DR.SecondDiffType;
- };
+ ODRDiagsEmitter DiagsEmitter(Diags, getContext(),
+ getPreprocessor().getLangOpts());
// Issue any pending ODR-failure diagnostics.
for (auto &Merge : OdrMergeFailures) {
@@ -10017,1190 +9961,12 @@ void ASTReader::diagnoseOdrViolations() {
bool Diagnosed = false;
CXXRecordDecl *FirstRecord = Merge.first;
- std::string FirstModule = getOwningModuleNameForDiagnostic(FirstRecord);
for (auto &RecordPair : Merge.second) {
- CXXRecordDecl *SecondRecord = RecordPair.first;
- // Multiple different declarations got merged together; tell the user
- // where they came from.
- if (FirstRecord == SecondRecord)
- continue;
-
- std::string SecondModule = getOwningModuleNameForDiagnostic(SecondRecord);
-
- auto *FirstDD = FirstRecord->DefinitionData;
- auto *SecondDD = RecordPair.second;
-
- assert(FirstDD && SecondDD && "Definitions without DefinitionData");
-
- // Diagnostics from DefinitionData are emitted here.
- if (FirstDD != SecondDD) {
- enum ODRDefinitionDataDifference {
- NumBases,
- NumVBases,
- BaseType,
- BaseVirtual,
- BaseAccess,
- };
- auto ODRDiagBaseError = [FirstRecord, &FirstModule,
- this](SourceLocation Loc, SourceRange Range,
- ODRDefinitionDataDifference DiffType) {
- return Diag(Loc, diag::err_module_odr_violation_definition_data)
- << FirstRecord << FirstModule.empty() << FirstModule << Range
- << DiffType;
- };
- auto ODRDiagBaseNote = [&SecondModule,
- this](SourceLocation Loc, SourceRange Range,
- ODRDefinitionDataDifference DiffType) {
- return Diag(Loc, diag::note_module_odr_violation_definition_data)
- << SecondModule << Range << DiffType;
- };
-
- unsigned FirstNumBases = FirstDD->NumBases;
- unsigned FirstNumVBases = FirstDD->NumVBases;
- unsigned SecondNumBases = SecondDD->NumBases;
- unsigned SecondNumVBases = SecondDD->NumVBases;
-
- auto GetSourceRange = [](struct CXXRecordDecl::DefinitionData *DD) {
- unsigned NumBases = DD->NumBases;
- if (NumBases == 0) return SourceRange();
- auto bases = DD->bases();
- return SourceRange(bases[0].getBeginLoc(),
- bases[NumBases - 1].getEndLoc());
- };
-
- if (FirstNumBases != SecondNumBases) {
- ODRDiagBaseError(FirstRecord->getLocation(), GetSourceRange(FirstDD),
- NumBases)
- << FirstNumBases;
- ODRDiagBaseNote(SecondRecord->getLocation(), GetSourceRange(SecondDD),
- NumBases)
- << SecondNumBases;
- Diagnosed = true;
- break;
- }
-
- if (FirstNumVBases != SecondNumVBases) {
- ODRDiagBaseError(FirstRecord->getLocation(), GetSourceRange(FirstDD),
- NumVBases)
- << FirstNumVBases;
- ODRDiagBaseNote(SecondRecord->getLocation(), GetSourceRange(SecondDD),
- NumVBases)
- << SecondNumVBases;
- Diagnosed = true;
- break;
- }
-
- auto FirstBases = FirstDD->bases();
- auto SecondBases = SecondDD->bases();
- unsigned i = 0;
- for (i = 0; i < FirstNumBases; ++i) {
- auto FirstBase = FirstBases[i];
- auto SecondBase = SecondBases[i];
- if (ComputeQualTypeODRHash(FirstBase.getType()) !=
- ComputeQualTypeODRHash(SecondBase.getType())) {
- ODRDiagBaseError(FirstRecord->getLocation(),
- FirstBase.getSourceRange(), BaseType)
- << (i + 1) << FirstBase.getType();
- ODRDiagBaseNote(SecondRecord->getLocation(),
- SecondBase.getSourceRange(), BaseType)
- << (i + 1) << SecondBase.getType();
- break;
- }
-
- if (FirstBase.isVirtual() != SecondBase.isVirtual()) {
- ODRDiagBaseError(FirstRecord->getLocation(),
- FirstBase.getSourceRange(), BaseVirtual)
- << (i + 1) << FirstBase.isVirtual() << FirstBase.getType();
- ODRDiagBaseNote(SecondRecord->getLocation(),
- SecondBase.getSourceRange(), BaseVirtual)
- << (i + 1) << SecondBase.isVirtual() << SecondBase.getType();
- break;
- }
-
- if (FirstBase.getAccessSpecifierAsWritten() !=
- SecondBase.getAccessSpecifierAsWritten()) {
- ODRDiagBaseError(FirstRecord->getLocation(),
- FirstBase.getSourceRange(), BaseAccess)
- << (i + 1) << FirstBase.getType()
- << (int)FirstBase.getAccessSpecifierAsWritten();
- ODRDiagBaseNote(SecondRecord->getLocation(),
- SecondBase.getSourceRange(), BaseAccess)
- << (i + 1) << SecondBase.getType()
- << (int)SecondBase.getAccessSpecifierAsWritten();
- break;
- }
- }
-
- if (i != FirstNumBases) {
- Diagnosed = true;
- break;
- }
- }
-
- const ClassTemplateDecl *FirstTemplate =
- FirstRecord->getDescribedClassTemplate();
- const ClassTemplateDecl *SecondTemplate =
- SecondRecord->getDescribedClassTemplate();
-
- assert(!FirstTemplate == !SecondTemplate &&
- "Both pointers should be null or non-null");
-
- enum ODRTemplateDifference {
- ParamEmptyName,
- ParamName,
- ParamSingleDefaultArgument,
- ParamDifferentDefaultArgument,
- };
-
- if (FirstTemplate && SecondTemplate) {
- DeclHashes FirstTemplateHashes;
- DeclHashes SecondTemplateHashes;
-
- auto PopulateTemplateParameterHashs =
- [&ComputeSubDeclODRHash](DeclHashes &Hashes,
- const ClassTemplateDecl *TD) {
- for (auto *D : TD->getTemplateParameters()->asArray()) {
- Hashes.emplace_back(D, ComputeSubDeclODRHash(D));
- }
- };
-
- PopulateTemplateParameterHashs(FirstTemplateHashes, FirstTemplate);
- PopulateTemplateParameterHashs(SecondTemplateHashes, SecondTemplate);
-
- assert(FirstTemplateHashes.size() == SecondTemplateHashes.size() &&
- "Number of template parameters should be equal.");
-
- auto FirstIt = FirstTemplateHashes.begin();
- auto FirstEnd = FirstTemplateHashes.end();
- auto SecondIt = SecondTemplateHashes.begin();
- for (; FirstIt != FirstEnd; ++FirstIt, ++SecondIt) {
- if (FirstIt->second == SecondIt->second)
- continue;
-
- auto ODRDiagTemplateError = [FirstRecord, &FirstModule, this](
- SourceLocation Loc, SourceRange Range,
- ODRTemplateDifference DiffType) {
- return Diag(Loc, diag::err_module_odr_violation_template_parameter)
- << FirstRecord << FirstModule.empty() << FirstModule << Range
- << DiffType;
- };
- auto ODRDiagTemplateNote = [&SecondModule, this](
- SourceLocation Loc, SourceRange Range,
- ODRTemplateDifference DiffType) {
- return Diag(Loc, diag::note_module_odr_violation_template_parameter)
- << SecondModule << Range << DiffType;
- };
-
- const NamedDecl* FirstDecl = cast<NamedDecl>(FirstIt->first);
- const NamedDecl* SecondDecl = cast<NamedDecl>(SecondIt->first);
-
- assert(FirstDecl->getKind() == SecondDecl->getKind() &&
- "Parameter Decl's should be the same kind.");
-
- DeclarationName FirstName = FirstDecl->getDeclName();
- DeclarationName SecondName = SecondDecl->getDeclName();
-
- if (FirstName != SecondName) {
- const bool FirstNameEmpty =
- FirstName.isIdentifier() && !FirstName.getAsIdentifierInfo();
- const bool SecondNameEmpty =
- SecondName.isIdentifier() && !SecondName.getAsIdentifierInfo();
- assert((!FirstNameEmpty || !SecondNameEmpty) &&
- "Both template parameters cannot be unnamed.");
- ODRDiagTemplateError(FirstDecl->getLocation(),
- FirstDecl->getSourceRange(),
- FirstNameEmpty ? ParamEmptyName : ParamName)
- << FirstName;
- ODRDiagTemplateNote(SecondDecl->getLocation(),
- SecondDecl->getSourceRange(),
- SecondNameEmpty ? ParamEmptyName : ParamName)
- << SecondName;
- break;
- }
-
- switch (FirstDecl->getKind()) {
- default:
- llvm_unreachable("Invalid template parameter type.");
- case Decl::TemplateTypeParm: {
- const auto *FirstParam = cast<TemplateTypeParmDecl>(FirstDecl);
- const auto *SecondParam = cast<TemplateTypeParmDecl>(SecondDecl);
- const bool HasFirstDefaultArgument =
- FirstParam->hasDefaultArgument() &&
- !FirstParam->defaultArgumentWasInherited();
- const bool HasSecondDefaultArgument =
- SecondParam->hasDefaultArgument() &&
- !SecondParam->defaultArgumentWasInherited();
-
- if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
- ODRDiagTemplateError(FirstDecl->getLocation(),
- FirstDecl->getSourceRange(),
- ParamSingleDefaultArgument)
- << HasFirstDefaultArgument;
- ODRDiagTemplateNote(SecondDecl->getLocation(),
- SecondDecl->getSourceRange(),
- ParamSingleDefaultArgument)
- << HasSecondDefaultArgument;
- break;
- }
-
- assert(HasFirstDefaultArgument && HasSecondDefaultArgument &&
- "Expecting default arguments.");
-
- ODRDiagTemplateError(FirstDecl->getLocation(),
- FirstDecl->getSourceRange(),
- ParamDifferentDefaultArgument);
- ODRDiagTemplateNote(SecondDecl->getLocation(),
- SecondDecl->getSourceRange(),
- ParamDifferentDefaultArgument);
-
- break;
- }
- case Decl::NonTypeTemplateParm: {
- const auto *FirstParam = cast<NonTypeTemplateParmDecl>(FirstDecl);
- const auto *SecondParam = cast<NonTypeTemplateParmDecl>(SecondDecl);
- const bool HasFirstDefaultArgument =
- FirstParam->hasDefaultArgument() &&
- !FirstParam->defaultArgumentWasInherited();
- const bool HasSecondDefaultArgument =
- SecondParam->hasDefaultArgument() &&
- !SecondParam->defaultArgumentWasInherited();
-
- if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
- ODRDiagTemplateError(FirstDecl->getLocation(),
- FirstDecl->getSourceRange(),
- ParamSingleDefaultArgument)
- << HasFirstDefaultArgument;
- ODRDiagTemplateNote(SecondDecl->getLocation(),
- SecondDecl->getSourceRange(),
- ParamSingleDefaultArgument)
- << HasSecondDefaultArgument;
- break;
- }
-
- assert(HasFirstDefaultArgument && HasSecondDefaultArgument &&
- "Expecting default arguments.");
-
- ODRDiagTemplateError(FirstDecl->getLocation(),
- FirstDecl->getSourceRange(),
- ParamDifferentDefaultArgument);
- ODRDiagTemplateNote(SecondDecl->getLocation(),
- SecondDecl->getSourceRange(),
- ParamDifferentDefaultArgument);
-
- break;
- }
- case Decl::TemplateTemplateParm: {
- const auto *FirstParam = cast<TemplateTemplateParmDecl>(FirstDecl);
- const auto *SecondParam =
- cast<TemplateTemplateParmDecl>(SecondDecl);
- const bool HasFirstDefaultArgument =
- FirstParam->hasDefaultArgument() &&
- !FirstParam->defaultArgumentWasInherited();
- const bool HasSecondDefaultArgument =
- SecondParam->hasDefaultArgument() &&
- !SecondParam->defaultArgumentWasInherited();
-
- if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
- ODRDiagTemplateError(FirstDecl->getLocation(),
- FirstDecl->getSourceRange(),
- ParamSingleDefaultArgument)
- << HasFirstDefaultArgument;
- ODRDiagTemplateNote(SecondDecl->getLocation(),
- SecondDecl->getSourceRange(),
- ParamSingleDefaultArgument)
- << HasSecondDefaultArgument;
- break;
- }
-
- assert(HasFirstDefaultArgument && HasSecondDefaultArgument &&
- "Expecting default arguments.");
-
- ODRDiagTemplateError(FirstDecl->getLocation(),
- FirstDecl->getSourceRange(),
- ParamDifferentDefaultArgument);
- ODRDiagTemplateNote(SecondDecl->getLocation(),
- SecondDecl->getSourceRange(),
- ParamDifferentDefaultArgument);
-
- break;
- }
- }
-
- break;
- }
-
- if (FirstIt != FirstEnd) {
- Diagnosed = true;
- break;
- }
- }
-
- DeclHashes FirstHashes;
- DeclHashes SecondHashes;
- const DeclContext *DC = FirstRecord;
- PopulateHashes(FirstHashes, FirstRecord, DC);
- PopulateHashes(SecondHashes, SecondRecord, DC);
-
- auto DR = FindTypeDiffs(FirstHashes, SecondHashes);
- ODRMismatchDecl FirstDiffType = DR.FirstDiffType;
- ODRMismatchDecl SecondDiffType = DR.SecondDiffType;
- Decl *FirstDecl = DR.FirstDecl;
- Decl *SecondDecl = DR.SecondDecl;
-
- if (FirstDiffType == Other || SecondDiffType == Other) {
- DiagnoseODRUnexpected(DR, FirstRecord, FirstModule, SecondRecord,
- SecondModule);
- Diagnosed = true;
- break;
- }
-
- if (FirstDiffType != SecondDiffType) {
- DiagnoseODRMismatch(DR, FirstRecord, FirstModule, SecondRecord,
- SecondModule);
- Diagnosed = true;
- break;
- }
-
- assert(FirstDiffType == SecondDiffType);
-
- switch (FirstDiffType) {
- case Other:
- case EndOfClass:
- case PublicSpecifer:
- case PrivateSpecifer:
- case ProtectedSpecifer:
- llvm_unreachable("Invalid diff type");
-
- case StaticAssert: {
- StaticAssertDecl *FirstSA = cast<StaticAssertDecl>(FirstDecl);
- StaticAssertDecl *SecondSA = cast<StaticAssertDecl>(SecondDecl);
-
- Expr *FirstExpr = FirstSA->getAssertExpr();
- Expr *SecondExpr = SecondSA->getAssertExpr();
- unsigned FirstODRHash = ComputeODRHash(FirstExpr);
- unsigned SecondODRHash = ComputeODRHash(SecondExpr);
- if (FirstODRHash != SecondODRHash) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstExpr->getBeginLoc(),
- FirstExpr->getSourceRange(), StaticAssertCondition);
- ODRDiagDeclNote(SecondModule, SecondExpr->getBeginLoc(),
- SecondExpr->getSourceRange(), StaticAssertCondition);
- Diagnosed = true;
- break;
- }
-
- StringLiteral *FirstStr = FirstSA->getMessage();
- StringLiteral *SecondStr = SecondSA->getMessage();
- assert((FirstStr || SecondStr) && "Both messages cannot be empty");
- if ((FirstStr && !SecondStr) || (!FirstStr && SecondStr)) {
- SourceLocation FirstLoc, SecondLoc;
- SourceRange FirstRange, SecondRange;
- if (FirstStr) {
- FirstLoc = FirstStr->getBeginLoc();
- FirstRange = FirstStr->getSourceRange();
- } else {
- FirstLoc = FirstSA->getBeginLoc();
- FirstRange = FirstSA->getSourceRange();
- }
- if (SecondStr) {
- SecondLoc = SecondStr->getBeginLoc();
- SecondRange = SecondStr->getSourceRange();
- } else {
- SecondLoc = SecondSA->getBeginLoc();
- SecondRange = SecondSA->getSourceRange();
- }
- ODRDiagDeclError(FirstRecord, FirstModule, FirstLoc, FirstRange,
- StaticAssertOnlyMessage)
- << (FirstStr == nullptr);
- ODRDiagDeclNote(SecondModule, SecondLoc, SecondRange,
- StaticAssertOnlyMessage)
- << (SecondStr == nullptr);
- Diagnosed = true;
- break;
- }
-
- if (FirstStr && SecondStr &&
- FirstStr->getString() != SecondStr->getString()) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstStr->getBeginLoc(),
- FirstStr->getSourceRange(), StaticAssertMessage);
- ODRDiagDeclNote(SecondModule, SecondStr->getBeginLoc(),
- SecondStr->getSourceRange(), StaticAssertMessage);
- Diagnosed = true;
- break;
- }
- break;
- }
- case Field: {
- Diagnosed = ODRDiagField(FirstRecord, FirstModule, SecondModule,
- cast<FieldDecl>(FirstDecl),
- cast<FieldDecl>(SecondDecl));
- break;
- }
- case CXXMethod: {
- enum {
- DiagMethod,
- DiagConstructor,
- DiagDestructor,
- } FirstMethodType,
- SecondMethodType;
- auto GetMethodTypeForDiagnostics = [](const CXXMethodDecl* D) {
- if (isa<CXXConstructorDecl>(D)) return DiagConstructor;
- if (isa<CXXDestructorDecl>(D)) return DiagDestructor;
- return DiagMethod;
- };
- const CXXMethodDecl *FirstMethod = cast<CXXMethodDecl>(FirstDecl);
- const CXXMethodDecl *SecondMethod = cast<CXXMethodDecl>(SecondDecl);
- FirstMethodType = GetMethodTypeForDiagnostics(FirstMethod);
- SecondMethodType = GetMethodTypeForDiagnostics(SecondMethod);
- auto FirstName = FirstMethod->getDeclName();
- auto SecondName = SecondMethod->getDeclName();
- if (FirstMethodType != SecondMethodType || FirstName != SecondName) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstMethod->getLocation(),
- FirstMethod->getSourceRange(), MethodName)
- << FirstMethodType << FirstName;
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(), MethodName)
- << SecondMethodType << SecondName;
-
- Diagnosed = true;
- break;
- }
-
- const bool FirstDeleted = FirstMethod->isDeletedAsWritten();
- const bool SecondDeleted = SecondMethod->isDeletedAsWritten();
- if (FirstDeleted != SecondDeleted) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstMethod->getLocation(),
- FirstMethod->getSourceRange(), MethodDeleted)
- << FirstMethodType << FirstName << FirstDeleted;
-
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(), MethodDeleted)
- << SecondMethodType << SecondName << SecondDeleted;
- Diagnosed = true;
- break;
- }
-
- const bool FirstDefaulted = FirstMethod->isExplicitlyDefaulted();
- const bool SecondDefaulted = SecondMethod->isExplicitlyDefaulted();
- if (FirstDefaulted != SecondDefaulted) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstMethod->getLocation(),
- FirstMethod->getSourceRange(), MethodDefaulted)
- << FirstMethodType << FirstName << FirstDefaulted;
-
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(), MethodDefaulted)
- << SecondMethodType << SecondName << SecondDefaulted;
- Diagnosed = true;
- break;
- }
-
- const bool FirstVirtual = FirstMethod->isVirtualAsWritten();
- const bool SecondVirtual = SecondMethod->isVirtualAsWritten();
- const bool FirstPure = FirstMethod->isPure();
- const bool SecondPure = SecondMethod->isPure();
- if ((FirstVirtual || SecondVirtual) &&
- (FirstVirtual != SecondVirtual || FirstPure != SecondPure)) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstMethod->getLocation(),
- FirstMethod->getSourceRange(), MethodVirtual)
- << FirstMethodType << FirstName << FirstPure << FirstVirtual;
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(), MethodVirtual)
- << SecondMethodType << SecondName << SecondPure << SecondVirtual;
- Diagnosed = true;
- break;
- }
-
- // CXXMethodDecl::isStatic uses the canonical Decl. With Decl merging,
- // FirstDecl is the canonical Decl of SecondDecl, so the storage
- // class needs to be checked instead.
- const auto FirstStorage = FirstMethod->getStorageClass();
- const auto SecondStorage = SecondMethod->getStorageClass();
- const bool FirstStatic = FirstStorage == SC_Static;
- const bool SecondStatic = SecondStorage == SC_Static;
- if (FirstStatic != SecondStatic) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstMethod->getLocation(),
- FirstMethod->getSourceRange(), MethodStatic)
- << FirstMethodType << FirstName << FirstStatic;
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(), MethodStatic)
- << SecondMethodType << SecondName << SecondStatic;
- Diagnosed = true;
- break;
- }
-
- const bool FirstVolatile = FirstMethod->isVolatile();
- const bool SecondVolatile = SecondMethod->isVolatile();
- if (FirstVolatile != SecondVolatile) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstMethod->getLocation(),
- FirstMethod->getSourceRange(), MethodVolatile)
- << FirstMethodType << FirstName << FirstVolatile;
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(), MethodVolatile)
- << SecondMethodType << SecondName << SecondVolatile;
- Diagnosed = true;
- break;
- }
-
- const bool FirstConst = FirstMethod->isConst();
- const bool SecondConst = SecondMethod->isConst();
- if (FirstConst != SecondConst) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstMethod->getLocation(),
- FirstMethod->getSourceRange(), MethodConst)
- << FirstMethodType << FirstName << FirstConst;
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(), MethodConst)
- << SecondMethodType << SecondName << SecondConst;
- Diagnosed = true;
- break;
- }
-
- const bool FirstInline = FirstMethod->isInlineSpecified();
- const bool SecondInline = SecondMethod->isInlineSpecified();
- if (FirstInline != SecondInline) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstMethod->getLocation(),
- FirstMethod->getSourceRange(), MethodInline)
- << FirstMethodType << FirstName << FirstInline;
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(), MethodInline)
- << SecondMethodType << SecondName << SecondInline;
- Diagnosed = true;
- break;
- }
-
- const unsigned FirstNumParameters = FirstMethod->param_size();
- const unsigned SecondNumParameters = SecondMethod->param_size();
- if (FirstNumParameters != SecondNumParameters) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstMethod->getLocation(),
- FirstMethod->getSourceRange(),
- MethodNumberParameters)
- << FirstMethodType << FirstName << FirstNumParameters;
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(),
- MethodNumberParameters)
- << SecondMethodType << SecondName << SecondNumParameters;
- Diagnosed = true;
- break;
- }
-
- // Need this status boolean to know when break out of the switch.
- bool ParameterMismatch = false;
- for (unsigned I = 0; I < FirstNumParameters; ++I) {
- const ParmVarDecl *FirstParam = FirstMethod->getParamDecl(I);
- const ParmVarDecl *SecondParam = SecondMethod->getParamDecl(I);
-
- QualType FirstParamType = FirstParam->getType();
- QualType SecondParamType = SecondParam->getType();
- if (FirstParamType != SecondParamType &&
- ComputeQualTypeODRHash(FirstParamType) !=
- ComputeQualTypeODRHash(SecondParamType)) {
- if (const DecayedType *ParamDecayedType =
- FirstParamType->getAs<DecayedType>()) {
- ODRDiagDeclError(
- FirstRecord, FirstModule, FirstMethod->getLocation(),
- FirstMethod->getSourceRange(), MethodParameterType)
- << FirstMethodType << FirstName << (I + 1) << FirstParamType
- << true << ParamDecayedType->getOriginalType();
- } else {
- ODRDiagDeclError(
- FirstRecord, FirstModule, FirstMethod->getLocation(),
- FirstMethod->getSourceRange(), MethodParameterType)
- << FirstMethodType << FirstName << (I + 1) << FirstParamType
- << false;
- }
-
- if (const DecayedType *ParamDecayedType =
- SecondParamType->getAs<DecayedType>()) {
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(),
- MethodParameterType)
- << SecondMethodType << SecondName << (I + 1)
- << SecondParamType << true
- << ParamDecayedType->getOriginalType();
- } else {
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(),
- MethodParameterType)
- << SecondMethodType << SecondName << (I + 1)
- << SecondParamType << false;
- }
- ParameterMismatch = true;
- break;
- }
-
- DeclarationName FirstParamName = FirstParam->getDeclName();
- DeclarationName SecondParamName = SecondParam->getDeclName();
- if (FirstParamName != SecondParamName) {
- ODRDiagDeclError(FirstRecord, FirstModule,
- FirstMethod->getLocation(),
- FirstMethod->getSourceRange(), MethodParameterName)
- << FirstMethodType << FirstName << (I + 1) << FirstParamName;
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(), MethodParameterName)
- << SecondMethodType << SecondName << (I + 1) << SecondParamName;
- ParameterMismatch = true;
- break;
- }
-
- const Expr *FirstInit = FirstParam->getInit();
- const Expr *SecondInit = SecondParam->getInit();
- if ((FirstInit == nullptr) != (SecondInit == nullptr)) {
- ODRDiagDeclError(FirstRecord, FirstModule,
- FirstMethod->getLocation(),
- FirstMethod->getSourceRange(),
- MethodParameterSingleDefaultArgument)
- << FirstMethodType << FirstName << (I + 1)
- << (FirstInit == nullptr)
- << (FirstInit ? FirstInit->getSourceRange() : SourceRange());
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(),
- MethodParameterSingleDefaultArgument)
- << SecondMethodType << SecondName << (I + 1)
- << (SecondInit == nullptr)
- << (SecondInit ? SecondInit->getSourceRange() : SourceRange());
- ParameterMismatch = true;
- break;
- }
-
- if (FirstInit && SecondInit &&
- ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) {
- ODRDiagDeclError(FirstRecord, FirstModule,
- FirstMethod->getLocation(),
- FirstMethod->getSourceRange(),
- MethodParameterDifferentDefaultArgument)
- << FirstMethodType << FirstName << (I + 1)
- << FirstInit->getSourceRange();
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(),
- MethodParameterDifferentDefaultArgument)
- << SecondMethodType << SecondName << (I + 1)
- << SecondInit->getSourceRange();
- ParameterMismatch = true;
- break;
-
- }
- }
-
- if (ParameterMismatch) {
- Diagnosed = true;
- break;
- }
-
- const auto *FirstTemplateArgs =
- FirstMethod->getTemplateSpecializationArgs();
- const auto *SecondTemplateArgs =
- SecondMethod->getTemplateSpecializationArgs();
-
- if ((FirstTemplateArgs && !SecondTemplateArgs) ||
- (!FirstTemplateArgs && SecondTemplateArgs)) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstMethod->getLocation(),
- FirstMethod->getSourceRange(),
- MethodNoTemplateArguments)
- << FirstMethodType << FirstName << (FirstTemplateArgs != nullptr);
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(),
- MethodNoTemplateArguments)
- << SecondMethodType << SecondName
- << (SecondTemplateArgs != nullptr);
-
- Diagnosed = true;
- break;
- }
-
- if (FirstTemplateArgs && SecondTemplateArgs) {
- // Remove pack expansions from argument list.
- auto ExpandTemplateArgumentList =
- [](const TemplateArgumentList *TAL) {
- llvm::SmallVector<const TemplateArgument *, 8> ExpandedList;
- for (const TemplateArgument &TA : TAL->asArray()) {
- if (TA.getKind() != TemplateArgument::Pack) {
- ExpandedList.push_back(&TA);
- continue;
- }
- for (const TemplateArgument &PackTA : TA.getPackAsArray()) {
- ExpandedList.push_back(&PackTA);
- }
- }
- return ExpandedList;
- };
- llvm::SmallVector<const TemplateArgument *, 8> FirstExpandedList =
- ExpandTemplateArgumentList(FirstTemplateArgs);
- llvm::SmallVector<const TemplateArgument *, 8> SecondExpandedList =
- ExpandTemplateArgumentList(SecondTemplateArgs);
-
- if (FirstExpandedList.size() != SecondExpandedList.size()) {
- ODRDiagDeclError(FirstRecord, FirstModule,
- FirstMethod->getLocation(),
- FirstMethod->getSourceRange(),
- MethodDifferentNumberTemplateArguments)
- << FirstMethodType << FirstName
- << (unsigned)FirstExpandedList.size();
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(),
- MethodDifferentNumberTemplateArguments)
- << SecondMethodType << SecondName
- << (unsigned)SecondExpandedList.size();
-
- Diagnosed = true;
- break;
- }
-
- bool TemplateArgumentMismatch = false;
- for (unsigned i = 0, e = FirstExpandedList.size(); i != e; ++i) {
- const TemplateArgument &FirstTA = *FirstExpandedList[i],
- &SecondTA = *SecondExpandedList[i];
- if (ComputeTemplateArgumentODRHash(FirstTA) ==
- ComputeTemplateArgumentODRHash(SecondTA)) {
- continue;
- }
-
- ODRDiagDeclError(
- FirstRecord, FirstModule, FirstMethod->getLocation(),
- FirstMethod->getSourceRange(), MethodDifferentTemplateArgument)
- << FirstMethodType << FirstName << FirstTA << i + 1;
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(),
- MethodDifferentTemplateArgument)
- << SecondMethodType << SecondName << SecondTA << i + 1;
-
- TemplateArgumentMismatch = true;
- break;
- }
-
- if (TemplateArgumentMismatch) {
- Diagnosed = true;
- break;
- }
- }
-
- // Compute the hash of the method as if it has no body.
- auto ComputeCXXMethodODRHash = [&Hash](const CXXMethodDecl *D) {
- Hash.clear();
- Hash.AddFunctionDecl(D, true /*SkipBody*/);
- return Hash.CalculateHash();
- };
-
- // Compare the hash generated to the hash stored. A difference means
- // that a body was present in the original source. Due to merging,
- // the stardard way of detecting a body will not work.
- const bool HasFirstBody =
- ComputeCXXMethodODRHash(FirstMethod) != FirstMethod->getODRHash();
- const bool HasSecondBody =
- ComputeCXXMethodODRHash(SecondMethod) != SecondMethod->getODRHash();
-
- if (HasFirstBody != HasSecondBody) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstMethod->getLocation(),
- FirstMethod->getSourceRange(), MethodSingleBody)
- << FirstMethodType << FirstName << HasFirstBody;
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(), MethodSingleBody)
- << SecondMethodType << SecondName << HasSecondBody;
- Diagnosed = true;
- break;
- }
-
- if (HasFirstBody && HasSecondBody) {
- ODRDiagDeclError(FirstRecord, FirstModule, FirstMethod->getLocation(),
- FirstMethod->getSourceRange(), MethodDifferentBody)
- << FirstMethodType << FirstName;
- ODRDiagDeclNote(SecondModule, SecondMethod->getLocation(),
- SecondMethod->getSourceRange(), MethodDifferentBody)
- << SecondMethodType << SecondName;
- Diagnosed = true;
- break;
- }
-
- break;
- }
- case TypeAlias:
- case TypeDef: {
- Diagnosed = ODRDiagTypeDefOrAlias(
- FirstRecord, FirstModule, SecondModule,
- cast<TypedefNameDecl>(FirstDecl), cast<TypedefNameDecl>(SecondDecl),
- FirstDiffType == TypeAlias);
- break;
- }
- case Var: {
- Diagnosed =
- ODRDiagVar(FirstRecord, FirstModule, SecondModule,
- cast<VarDecl>(FirstDecl), cast<VarDecl>(SecondDecl));
- break;
- }
- case Friend: {
- FriendDecl *FirstFriend = cast<FriendDecl>(FirstDecl);
- FriendDecl *SecondFriend = cast<FriendDecl>(SecondDecl);
-
- NamedDecl *FirstND = FirstFriend->getFriendDecl();
- NamedDecl *SecondND = SecondFriend->getFriendDecl();
-
- TypeSourceInfo *FirstTSI = FirstFriend->getFriendType();
- TypeSourceInfo *SecondTSI = SecondFriend->getFriendType();
-
- if (FirstND && SecondND) {
- ODRDiagDeclError(FirstRecord, FirstModule,
- FirstFriend->getFriendLoc(),
- FirstFriend->getSourceRange(), FriendFunction)
- << FirstND;
- ODRDiagDeclNote(SecondModule, SecondFriend->getFriendLoc(),
- SecondFriend->getSourceRange(), FriendFunction)
- << SecondND;
-
- Diagnosed = true;
- break;
- }
-
- if (FirstTSI && SecondTSI) {
- QualType FirstFriendType = FirstTSI->getType();
- QualType SecondFriendType = SecondTSI->getType();
- assert(ComputeQualTypeODRHash(FirstFriendType) !=
- ComputeQualTypeODRHash(SecondFriendType));
- ODRDiagDeclError(FirstRecord, FirstModule,
- FirstFriend->getFriendLoc(),
- FirstFriend->getSourceRange(), FriendType)
- << FirstFriendType;
- ODRDiagDeclNote(SecondModule, SecondFriend->getFriendLoc(),
- SecondFriend->getSourceRange(), FriendType)
- << SecondFriendType;
- Diagnosed = true;
- break;
- }
-
- ODRDiagDeclError(FirstRecord, FirstModule, FirstFriend->getFriendLoc(),
- FirstFriend->getSourceRange(), FriendTypeFunction)
- << (FirstTSI == nullptr);
- ODRDiagDeclNote(SecondModule, SecondFriend->getFriendLoc(),
- SecondFriend->getSourceRange(), FriendTypeFunction)
- << (SecondTSI == nullptr);
-
+ if (DiagsEmitter.diagnoseMismatch(FirstRecord, RecordPair.first,
+ RecordPair.second)) {
Diagnosed = true;
break;
}
- case FunctionTemplate: {
- FunctionTemplateDecl *FirstTemplate =
- cast<FunctionTemplateDecl>(FirstDecl);
- FunctionTemplateDecl *SecondTemplate =
- cast<FunctionTemplateDecl>(SecondDecl);
-
- TemplateParameterList *FirstTPL =
- FirstTemplate->getTemplateParameters();
- TemplateParameterList *SecondTPL =
- SecondTemplate->getTemplateParameters();
-
- if (FirstTPL->size() != SecondTPL->size()) {
- ODRDiagDeclError(FirstRecord, FirstModule,
- FirstTemplate->getLocation(),
- FirstTemplate->getSourceRange(),
- FunctionTemplateDifferentNumberParameters)
- << FirstTemplate << FirstTPL->size();
- ODRDiagDeclNote(SecondModule, SecondTemplate->getLocation(),
- SecondTemplate->getSourceRange(),
- FunctionTemplateDifferentNumberParameters)
- << SecondTemplate << SecondTPL->size();
-
- Diagnosed = true;
- break;
- }
-
- bool ParameterMismatch = false;
- for (unsigned i = 0, e = FirstTPL->size(); i != e; ++i) {
- NamedDecl *FirstParam = FirstTPL->getParam(i);
- NamedDecl *SecondParam = SecondTPL->getParam(i);
-
- if (FirstParam->getKind() != SecondParam->getKind()) {
- enum {
- TemplateTypeParameter,
- NonTypeTemplateParameter,
- TemplateTemplateParameter,
- };
- auto GetParamType = [](NamedDecl *D) {
- switch (D->getKind()) {
- default:
- llvm_unreachable("Unexpected template parameter type");
- case Decl::TemplateTypeParm:
- return TemplateTypeParameter;
- case Decl::NonTypeTemplateParm:
- return NonTypeTemplateParameter;
- case Decl::TemplateTemplateParm:
- return TemplateTemplateParameter;
- }
- };
-
- ODRDiagDeclError(FirstRecord, FirstModule,
- FirstTemplate->getLocation(),
- FirstTemplate->getSourceRange(),
- FunctionTemplateParameterDifferentKind)
- << FirstTemplate << (i + 1) << GetParamType(FirstParam);
- ODRDiagDeclNote(SecondModule, SecondTemplate->getLocation(),
- SecondTemplate->getSourceRange(),
- FunctionTemplateParameterDifferentKind)
- << SecondTemplate << (i + 1) << GetParamType(SecondParam);
-
- ParameterMismatch = true;
- break;
- }
-
- if (FirstParam->getName() != SecondParam->getName()) {
- ODRDiagDeclError(
- FirstRecord, FirstModule, FirstTemplate->getLocation(),
- FirstTemplate->getSourceRange(), FunctionTemplateParameterName)
- << FirstTemplate << (i + 1) << (bool)FirstParam->getIdentifier()
- << FirstParam;
- ODRDiagDeclNote(SecondModule, SecondTemplate->getLocation(),
- SecondTemplate->getSourceRange(),
- FunctionTemplateParameterName)
- << SecondTemplate << (i + 1)
- << (bool)SecondParam->getIdentifier() << SecondParam;
- ParameterMismatch = true;
- break;
- }
-
- if (isa<TemplateTypeParmDecl>(FirstParam) &&
- isa<TemplateTypeParmDecl>(SecondParam)) {
- TemplateTypeParmDecl *FirstTTPD =
- cast<TemplateTypeParmDecl>(FirstParam);
- TemplateTypeParmDecl *SecondTTPD =
- cast<TemplateTypeParmDecl>(SecondParam);
- bool HasFirstDefaultArgument =
- FirstTTPD->hasDefaultArgument() &&
- !FirstTTPD->defaultArgumentWasInherited();
- bool HasSecondDefaultArgument =
- SecondTTPD->hasDefaultArgument() &&
- !SecondTTPD->defaultArgumentWasInherited();
- if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
- ODRDiagDeclError(FirstRecord, FirstModule,
- FirstTemplate->getLocation(),
- FirstTemplate->getSourceRange(),
- FunctionTemplateParameterSingleDefaultArgument)
- << FirstTemplate << (i + 1) << HasFirstDefaultArgument;
- ODRDiagDeclNote(SecondModule, SecondTemplate->getLocation(),
- SecondTemplate->getSourceRange(),
- FunctionTemplateParameterSingleDefaultArgument)
- << SecondTemplate << (i + 1) << HasSecondDefaultArgument;
- ParameterMismatch = true;
- break;
- }
-
- if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
- QualType FirstType = FirstTTPD->getDefaultArgument();
- QualType SecondType = SecondTTPD->getDefaultArgument();
- if (ComputeQualTypeODRHash(FirstType) !=
- ComputeQualTypeODRHash(SecondType)) {
- ODRDiagDeclError(
- FirstRecord, FirstModule, FirstTemplate->getLocation(),
- FirstTemplate->getSourceRange(),
- FunctionTemplateParameterDifferentDefaultArgument)
- << FirstTemplate << (i + 1) << FirstType;
- ODRDiagDeclNote(
- SecondModule, SecondTemplate->getLocation(),
- SecondTemplate->getSourceRange(),
- FunctionTemplateParameterDifferentDefaultArgument)
- << SecondTemplate << (i + 1) << SecondType;
- ParameterMismatch = true;
- break;
- }
- }
-
- if (FirstTTPD->isParameterPack() !=
- SecondTTPD->isParameterPack()) {
- ODRDiagDeclError(FirstRecord, FirstModule,
- FirstTemplate->getLocation(),
- FirstTemplate->getSourceRange(),
- FunctionTemplatePackParameter)
- << FirstTemplate << (i + 1) << FirstTTPD->isParameterPack();
- ODRDiagDeclNote(SecondModule, SecondTemplate->getLocation(),
- SecondTemplate->getSourceRange(),
- FunctionTemplatePackParameter)
- << SecondTemplate << (i + 1) << SecondTTPD->isParameterPack();
- ParameterMismatch = true;
- break;
- }
- }
-
- if (isa<TemplateTemplateParmDecl>(FirstParam) &&
- isa<TemplateTemplateParmDecl>(SecondParam)) {
- TemplateTemplateParmDecl *FirstTTPD =
- cast<TemplateTemplateParmDecl>(FirstParam);
- TemplateTemplateParmDecl *SecondTTPD =
- cast<TemplateTemplateParmDecl>(SecondParam);
-
- TemplateParameterList *FirstTPL =
- FirstTTPD->getTemplateParameters();
- TemplateParameterList *SecondTPL =
- SecondTTPD->getTemplateParameters();
-
- if (ComputeTemplateParameterListODRHash(FirstTPL) !=
- ComputeTemplateParameterListODRHash(SecondTPL)) {
- ODRDiagDeclError(FirstRecord, FirstModule,
- FirstTemplate->getLocation(),
- FirstTemplate->getSourceRange(),
- FunctionTemplateParameterDifferentType)
- << FirstTemplate << (i + 1);
- ODRDiagDeclNote(SecondModule, SecondTemplate->getLocation(),
- SecondTemplate->getSourceRange(),
- FunctionTemplateParameterDifferentType)
- << SecondTemplate << (i + 1);
- ParameterMismatch = true;
- break;
- }
-
- bool HasFirstDefaultArgument =
- FirstTTPD->hasDefaultArgument() &&
- !FirstTTPD->defaultArgumentWasInherited();
- bool HasSecondDefaultArgument =
- SecondTTPD->hasDefaultArgument() &&
- !SecondTTPD->defaultArgumentWasInherited();
- if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
- ODRDiagDeclError(FirstRecord, FirstModule,
- FirstTemplate->getLocation(),
- FirstTemplate->getSourceRange(),
- FunctionTemplateParameterSingleDefaultArgument)
- << FirstTemplate << (i + 1) << HasFirstDefaultArgument;
- ODRDiagDeclNote(SecondModule, SecondTemplate->getLocation(),
- SecondTemplate->getSourceRange(),
- FunctionTemplateParameterSingleDefaultArgument)
- << SecondTemplate << (i + 1) << HasSecondDefaultArgument;
- ParameterMismatch = true;
- break;
- }
-
- if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
- TemplateArgument FirstTA =
- FirstTTPD->getDefaultArgument().getArgument();
- TemplateArgument SecondTA =
- SecondTTPD->getDefaultArgument().getArgument();
- if (ComputeTemplateArgumentODRHash(FirstTA) !=
- ComputeTemplateArgumentODRHash(SecondTA)) {
- ODRDiagDeclError(
- FirstRecord, FirstModule, FirstTemplate->getLocation(),
- FirstTemplate->getSourceRange(),
- FunctionTemplateParameterDifferentDefaultArgument)
- << FirstTemplate << (i + 1) << FirstTA;
- ODRDiagDeclNote(
- SecondModule, SecondTemplate->getLocation(),
- SecondTemplate->getSourceRange(),
- FunctionTemplateParameterDifferentDefaultArgument)
- << SecondTemplate << (i + 1) << SecondTA;
- ParameterMismatch = true;
- break;
- }
- }
-
- if (FirstTTPD->isParameterPack() !=
- SecondTTPD->isParameterPack()) {
- ODRDiagDeclError(FirstRecord, FirstModule,
- FirstTemplate->getLocation(),
- FirstTemplate->getSourceRange(),
- FunctionTemplatePackParameter)
- << FirstTemplate << (i + 1) << FirstTTPD->isParameterPack();
- ODRDiagDeclNote(SecondModule, SecondTemplate->getLocation(),
- SecondTemplate->getSourceRange(),
- FunctionTemplatePackParameter)
- << SecondTemplate << (i + 1) << SecondTTPD->isParameterPack();
- ParameterMismatch = true;
- break;
- }
- }
-
- if (isa<NonTypeTemplateParmDecl>(FirstParam) &&
- isa<NonTypeTemplateParmDecl>(SecondParam)) {
- NonTypeTemplateParmDecl *FirstNTTPD =
- cast<NonTypeTemplateParmDecl>(FirstParam);
- NonTypeTemplateParmDecl *SecondNTTPD =
- cast<NonTypeTemplateParmDecl>(SecondParam);
-
- QualType FirstType = FirstNTTPD->getType();
- QualType SecondType = SecondNTTPD->getType();
- if (ComputeQualTypeODRHash(FirstType) !=
- ComputeQualTypeODRHash(SecondType)) {
- ODRDiagDeclError(FirstRecord, FirstModule,
- FirstTemplate->getLocation(),
- FirstTemplate->getSourceRange(),
- FunctionTemplateParameterDifferentType)
- << FirstTemplate << (i + 1);
- ODRDiagDeclNote(SecondModule, SecondTemplate->getLocation(),
- SecondTemplate->getSourceRange(),
- FunctionTemplateParameterDifferentType)
- << SecondTemplate << (i + 1);
- ParameterMismatch = true;
- break;
- }
-
- bool HasFirstDefaultArgument =
- FirstNTTPD->hasDefaultArgument() &&
- !FirstNTTPD->defaultArgumentWasInherited();
- bool HasSecondDefaultArgument =
- SecondNTTPD->hasDefaultArgument() &&
- !SecondNTTPD->defaultArgumentWasInherited();
- if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
- ODRDiagDeclError(FirstRecord, FirstModule,
- FirstTemplate->getLocation(),
- FirstTemplate->getSourceRange(),
- FunctionTemplateParameterSingleDefaultArgument)
- << FirstTemplate << (i + 1) << HasFirstDefaultArgument;
- ODRDiagDeclNote(SecondModule, SecondTemplate->getLocation(),
- SecondTemplate->getSourceRange(),
- FunctionTemplateParameterSingleDefaultArgument)
- << SecondTemplate << (i + 1) << HasSecondDefaultArgument;
- ParameterMismatch = true;
- break;
- }
-
- if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
- Expr *FirstDefaultArgument = FirstNTTPD->getDefaultArgument();
- Expr *SecondDefaultArgument = SecondNTTPD->getDefaultArgument();
- if (ComputeODRHash(FirstDefaultArgument) !=
- ComputeODRHash(SecondDefaultArgument)) {
- ODRDiagDeclError(
- FirstRecord, FirstModule, FirstTemplate->getLocation(),
- FirstTemplate->getSourceRange(),
- FunctionTemplateParameterDifferentDefaultArgument)
- << FirstTemplate << (i + 1) << FirstDefaultArgument;
- ODRDiagDeclNote(
- SecondModule, SecondTemplate->getLocation(),
- SecondTemplate->getSourceRange(),
- FunctionTemplateParameterDifferentDefaultArgument)
- << SecondTemplate << (i + 1) << SecondDefaultArgument;
- ParameterMismatch = true;
- break;
- }
- }
-
- if (FirstNTTPD->isParameterPack() !=
- SecondNTTPD->isParameterPack()) {
- ODRDiagDeclError(FirstRecord, FirstModule,
- FirstTemplate->getLocation(),
- FirstTemplate->getSourceRange(),
- FunctionTemplatePackParameter)
- << FirstTemplate << (i + 1) << FirstNTTPD->isParameterPack();
- ODRDiagDeclNote(SecondModule, SecondTemplate->getLocation(),
- SecondTemplate->getSourceRange(),
- FunctionTemplatePackParameter)
- << SecondTemplate << (i + 1)
- << SecondNTTPD->isParameterPack();
- ParameterMismatch = true;
- break;
- }
- }
- }
-
- if (ParameterMismatch) {
- Diagnosed = true;
- break;
- }
-
- break;
- }
- }
-
- if (Diagnosed)
- continue;
-
- Diag(FirstDecl->getLocation(),
- diag::err_module_odr_violation_mismatch_decl_unknown)
- << FirstRecord << FirstModule.empty() << FirstModule << FirstDiffType
- << FirstDecl->getSourceRange();
- Diag(SecondDecl->getLocation(),
- diag::note_module_odr_violation_mismatch_decl_unknown)
- << SecondModule << FirstDiffType << SecondDecl->getSourceRange();
- Diagnosed = true;
}
if (!Diagnosed) {
@@ -11212,160 +9978,39 @@ void ASTReader::diagnoseOdrViolations() {
// FIXME: How can this even happen?
Diag(Merge.first->getLocation(),
diag::err_module_odr_violation_different_instantiations)
- << Merge.first;
+ << Merge.first;
}
}
- // Issue ODR failures diagnostics for functions.
- for (auto &Merge : FunctionOdrMergeFailures) {
- enum ODRFunctionDifference {
- ReturnType,
- ParameterName,
- ParameterType,
- ParameterSingleDefaultArgument,
- ParameterDifferentDefaultArgument,
- FunctionBody,
- };
-
- FunctionDecl *FirstFunction = Merge.first;
- std::string FirstModule = getOwningModuleNameForDiagnostic(FirstFunction);
+ // Issue any pending ODR-failure diagnostics for RecordDecl in C/ObjC. Note
+ // that in C++ this is done as a part of CXXRecordDecl ODR checking.
+ for (auto &Merge : RecordOdrMergeFailures) {
+ // If we've already pointed out a specific problem with this class, don't
+ // bother issuing a general "something's different" diagnostic.
+ if (!DiagnosedOdrMergeFailures.insert(Merge.first).second)
+ continue;
+ RecordDecl *FirstRecord = Merge.first;
bool Diagnosed = false;
- for (auto &SecondFunction : Merge.second) {
-
- if (FirstFunction == SecondFunction)
- continue;
-
- std::string SecondModule =
- getOwningModuleNameForDiagnostic(SecondFunction);
-
- auto ODRDiagError = [FirstFunction, &FirstModule,
- this](SourceLocation Loc, SourceRange Range,
- ODRFunctionDifference DiffType) {
- return Diag(Loc, diag::err_module_odr_violation_function)
- << FirstFunction << FirstModule.empty() << FirstModule << Range
- << DiffType;
- };
- auto ODRDiagNote = [&SecondModule, this](SourceLocation Loc,
- SourceRange Range,
- ODRFunctionDifference DiffType) {
- return Diag(Loc, diag::note_module_odr_violation_function)
- << SecondModule << Range << DiffType;
- };
-
- if (ComputeQualTypeODRHash(FirstFunction->getReturnType()) !=
- ComputeQualTypeODRHash(SecondFunction->getReturnType())) {
- ODRDiagError(FirstFunction->getReturnTypeSourceRange().getBegin(),
- FirstFunction->getReturnTypeSourceRange(), ReturnType)
- << FirstFunction->getReturnType();
- ODRDiagNote(SecondFunction->getReturnTypeSourceRange().getBegin(),
- SecondFunction->getReturnTypeSourceRange(), ReturnType)
- << SecondFunction->getReturnType();
+ for (auto *SecondRecord : Merge.second) {
+ if (DiagsEmitter.diagnoseMismatch(FirstRecord, SecondRecord)) {
Diagnosed = true;
break;
}
+ }
+ (void)Diagnosed;
+ assert(Diagnosed && "Unable to emit ODR diagnostic.");
+ }
- assert(FirstFunction->param_size() == SecondFunction->param_size() &&
- "Merged functions with different number of parameters");
-
- auto ParamSize = FirstFunction->param_size();
- bool ParameterMismatch = false;
- for (unsigned I = 0; I < ParamSize; ++I) {
- auto *FirstParam = FirstFunction->getParamDecl(I);
- auto *SecondParam = SecondFunction->getParamDecl(I);
-
- assert(getContext().hasSameType(FirstParam->getType(),
- SecondParam->getType()) &&
- "Merged function has different parameter types.");
-
- if (FirstParam->getDeclName() != SecondParam->getDeclName()) {
- ODRDiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
- ParameterName)
- << I + 1 << FirstParam->getDeclName();
- ODRDiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
- ParameterName)
- << I + 1 << SecondParam->getDeclName();
- ParameterMismatch = true;
- break;
- };
-
- QualType FirstParamType = FirstParam->getType();
- QualType SecondParamType = SecondParam->getType();
- if (FirstParamType != SecondParamType &&
- ComputeQualTypeODRHash(FirstParamType) !=
- ComputeQualTypeODRHash(SecondParamType)) {
- if (const DecayedType *ParamDecayedType =
- FirstParamType->getAs<DecayedType>()) {
- ODRDiagError(FirstParam->getLocation(),
- FirstParam->getSourceRange(), ParameterType)
- << (I + 1) << FirstParamType << true
- << ParamDecayedType->getOriginalType();
- } else {
- ODRDiagError(FirstParam->getLocation(),
- FirstParam->getSourceRange(), ParameterType)
- << (I + 1) << FirstParamType << false;
- }
-
- if (const DecayedType *ParamDecayedType =
- SecondParamType->getAs<DecayedType>()) {
- ODRDiagNote(SecondParam->getLocation(),
- SecondParam->getSourceRange(), ParameterType)
- << (I + 1) << SecondParamType << true
- << ParamDecayedType->getOriginalType();
- } else {
- ODRDiagNote(SecondParam->getLocation(),
- SecondParam->getSourceRange(), ParameterType)
- << (I + 1) << SecondParamType << false;
- }
- ParameterMismatch = true;
- break;
- }
-
- const Expr *FirstInit = FirstParam->getInit();
- const Expr *SecondInit = SecondParam->getInit();
- if ((FirstInit == nullptr) != (SecondInit == nullptr)) {
- ODRDiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
- ParameterSingleDefaultArgument)
- << (I + 1) << (FirstInit == nullptr)
- << (FirstInit ? FirstInit->getSourceRange() : SourceRange());
- ODRDiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
- ParameterSingleDefaultArgument)
- << (I + 1) << (SecondInit == nullptr)
- << (SecondInit ? SecondInit->getSourceRange() : SourceRange());
- ParameterMismatch = true;
- break;
- }
-
- if (FirstInit && SecondInit &&
- ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) {
- ODRDiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
- ParameterDifferentDefaultArgument)
- << (I + 1) << FirstInit->getSourceRange();
- ODRDiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
- ParameterDifferentDefaultArgument)
- << (I + 1) << SecondInit->getSourceRange();
- ParameterMismatch = true;
- break;
- }
-
- assert(ComputeSubDeclODRHash(FirstParam) ==
- ComputeSubDeclODRHash(SecondParam) &&
- "Undiagnosed parameter difference.");
- }
-
- if (ParameterMismatch) {
+ // Issue ODR failures diagnostics for functions.
+ for (auto &Merge : FunctionOdrMergeFailures) {
+ FunctionDecl *FirstFunction = Merge.first;
+ bool Diagnosed = false;
+ for (auto &SecondFunction : Merge.second) {
+ if (DiagsEmitter.diagnoseMismatch(FirstFunction, SecondFunction)) {
Diagnosed = true;
break;
}
-
- // If no error has been generated before now, assume the problem is in
- // the body and generate a message.
- ODRDiagError(FirstFunction->getLocation(),
- FirstFunction->getSourceRange(), FunctionBody);
- ODRDiagNote(SecondFunction->getLocation(),
- SecondFunction->getSourceRange(), FunctionBody);
- Diagnosed = true;
- break;
}
(void)Diagnosed;
assert(Diagnosed && "Unable to emit ODR diagnostic.");
@@ -11373,188 +10018,57 @@ void ASTReader::diagnoseOdrViolations() {
// Issue ODR failures diagnostics for enums.
for (auto &Merge : EnumOdrMergeFailures) {
- enum ODREnumDifference {
- SingleScopedEnum,
- EnumTagKeywordMismatch,
- SingleSpecifiedType,
- DifferentSpecifiedTypes,
- DifferentNumberEnumConstants,
- EnumConstantName,
- EnumConstantSingleInitilizer,
- EnumConstantDifferentInitilizer,
- };
-
// If we've already pointed out a specific problem with this enum, don't
// bother issuing a general "something's different" diagnostic.
if (!DiagnosedOdrMergeFailures.insert(Merge.first).second)
continue;
EnumDecl *FirstEnum = Merge.first;
- std::string FirstModule = getOwningModuleNameForDiagnostic(FirstEnum);
-
- using DeclHashes =
- llvm::SmallVector<std::pair<EnumConstantDecl *, unsigned>, 4>;
- auto PopulateHashes = [&ComputeSubDeclODRHash, FirstEnum](
- DeclHashes &Hashes, EnumDecl *Enum) {
- for (auto *D : Enum->decls()) {
- // Due to decl merging, the first EnumDecl is the parent of
- // Decls in both records.
- if (!ODRHash::isDeclToBeProcessed(D, FirstEnum))
- continue;
- assert(isa<EnumConstantDecl>(D) && "Unexpected Decl kind");
- Hashes.emplace_back(cast<EnumConstantDecl>(D),
- ComputeSubDeclODRHash(D));
- }
- };
- DeclHashes FirstHashes;
- PopulateHashes(FirstHashes, FirstEnum);
bool Diagnosed = false;
for (auto &SecondEnum : Merge.second) {
-
- if (FirstEnum == SecondEnum)
- continue;
-
- std::string SecondModule =
- getOwningModuleNameForDiagnostic(SecondEnum);
-
- auto ODRDiagError = [FirstEnum, &FirstModule,
- this](SourceLocation Loc, SourceRange Range,
- ODREnumDifference DiffType) {
- return Diag(Loc, diag::err_module_odr_violation_enum)
- << FirstEnum << FirstModule.empty() << FirstModule << Range
- << DiffType;
- };
- auto ODRDiagNote = [&SecondModule, this](SourceLocation Loc,
- SourceRange Range,
- ODREnumDifference DiffType) {
- return Diag(Loc, diag::note_module_odr_violation_enum)
- << SecondModule << Range << DiffType;
- };
-
- if (FirstEnum->isScoped() != SecondEnum->isScoped()) {
- ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(),
- SingleScopedEnum)
- << FirstEnum->isScoped();
- ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(),
- SingleScopedEnum)
- << SecondEnum->isScoped();
+ if (DiagsEmitter.diagnoseMismatch(FirstEnum, SecondEnum)) {
Diagnosed = true;
- continue;
- }
-
- if (FirstEnum->isScoped() && SecondEnum->isScoped()) {
- if (FirstEnum->isScopedUsingClassTag() !=
- SecondEnum->isScopedUsingClassTag()) {
- ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(),
- EnumTagKeywordMismatch)
- << FirstEnum->isScopedUsingClassTag();
- ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(),
- EnumTagKeywordMismatch)
- << SecondEnum->isScopedUsingClassTag();
- Diagnosed = true;
- continue;
- }
- }
-
- QualType FirstUnderlyingType =
- FirstEnum->getIntegerTypeSourceInfo()
- ? FirstEnum->getIntegerTypeSourceInfo()->getType()
- : QualType();
- QualType SecondUnderlyingType =
- SecondEnum->getIntegerTypeSourceInfo()
- ? SecondEnum->getIntegerTypeSourceInfo()->getType()
- : QualType();
- if (FirstUnderlyingType.isNull() != SecondUnderlyingType.isNull()) {
- ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(),
- SingleSpecifiedType)
- << !FirstUnderlyingType.isNull();
- ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(),
- SingleSpecifiedType)
- << !SecondUnderlyingType.isNull();
- Diagnosed = true;
- continue;
- }
-
- if (!FirstUnderlyingType.isNull() && !SecondUnderlyingType.isNull()) {
- if (ComputeQualTypeODRHash(FirstUnderlyingType) !=
- ComputeQualTypeODRHash(SecondUnderlyingType)) {
- ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(),
- DifferentSpecifiedTypes)
- << FirstUnderlyingType;
- ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(),
- DifferentSpecifiedTypes)
- << SecondUnderlyingType;
- Diagnosed = true;
- continue;
- }
+ break;
}
+ }
+ (void)Diagnosed;
+ assert(Diagnosed && "Unable to emit ODR diagnostic.");
+ }
- DeclHashes SecondHashes;
- PopulateHashes(SecondHashes, SecondEnum);
+ for (auto &Merge : ObjCInterfaceOdrMergeFailures) {
+ // If we've already pointed out a specific problem with this interface,
+ // don't bother issuing a general "something's different" diagnostic.
+ if (!DiagnosedOdrMergeFailures.insert(Merge.first).second)
+ continue;
- if (FirstHashes.size() != SecondHashes.size()) {
- ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(),
- DifferentNumberEnumConstants)
- << (int)FirstHashes.size();
- ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(),
- DifferentNumberEnumConstants)
- << (int)SecondHashes.size();
+ bool Diagnosed = false;
+ ObjCInterfaceDecl *FirstID = Merge.first;
+ for (auto &InterfacePair : Merge.second) {
+ if (DiagsEmitter.diagnoseMismatch(FirstID, InterfacePair.first,
+ InterfacePair.second)) {
Diagnosed = true;
- continue;
+ break;
}
+ }
+ (void)Diagnosed;
+ assert(Diagnosed && "Unable to emit ODR diagnostic.");
+ }
- for (unsigned I = 0; I < FirstHashes.size(); ++I) {
- if (FirstHashes[I].second == SecondHashes[I].second)
- continue;
- const EnumConstantDecl *FirstEnumConstant = FirstHashes[I].first;
- const EnumConstantDecl *SecondEnumConstant = SecondHashes[I].first;
-
- if (FirstEnumConstant->getDeclName() !=
- SecondEnumConstant->getDeclName()) {
-
- ODRDiagError(FirstEnumConstant->getLocation(),
- FirstEnumConstant->getSourceRange(), EnumConstantName)
- << I + 1 << FirstEnumConstant;
- ODRDiagNote(SecondEnumConstant->getLocation(),
- SecondEnumConstant->getSourceRange(), EnumConstantName)
- << I + 1 << SecondEnumConstant;
- Diagnosed = true;
- break;
- }
-
- const Expr *FirstInit = FirstEnumConstant->getInitExpr();
- const Expr *SecondInit = SecondEnumConstant->getInitExpr();
- if (!FirstInit && !SecondInit)
- continue;
-
- if (!FirstInit || !SecondInit) {
- ODRDiagError(FirstEnumConstant->getLocation(),
- FirstEnumConstant->getSourceRange(),
- EnumConstantSingleInitilizer)
- << I + 1 << FirstEnumConstant << (FirstInit != nullptr);
- ODRDiagNote(SecondEnumConstant->getLocation(),
- SecondEnumConstant->getSourceRange(),
- EnumConstantSingleInitilizer)
- << I + 1 << SecondEnumConstant << (SecondInit != nullptr);
- Diagnosed = true;
- break;
- }
+ for (auto &Merge : ObjCProtocolOdrMergeFailures) {
+ // If we've already pointed out a specific problem with this protocol,
+ // don't bother issuing a general "something's different" diagnostic.
+ if (!DiagnosedOdrMergeFailures.insert(Merge.first).second)
+ continue;
- if (ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) {
- ODRDiagError(FirstEnumConstant->getLocation(),
- FirstEnumConstant->getSourceRange(),
- EnumConstantDifferentInitilizer)
- << I + 1 << FirstEnumConstant;
- ODRDiagNote(SecondEnumConstant->getLocation(),
- SecondEnumConstant->getSourceRange(),
- EnumConstantDifferentInitilizer)
- << I + 1 << SecondEnumConstant;
- Diagnosed = true;
- break;
- }
+ ObjCProtocolDecl *FirstProtocol = Merge.first;
+ bool Diagnosed = false;
+ for (auto &ProtocolPair : Merge.second) {
+ if (DiagsEmitter.diagnoseMismatch(FirstProtocol, ProtocolPair.first,
+ ProtocolPair.second)) {
+ Diagnosed = true;
+ break;
}
}
-
(void)Diagnosed;
assert(Diagnosed && "Unable to emit ODR diagnostic.");
}
@@ -11603,6 +10117,13 @@ void ASTReader::FinishedDeserializing() {
getContext().adjustDeducedFunctionResultType(Update.first,
Update.second);
}
+
+ auto UDTUpdates = std::move(PendingUndeducedFunctionDecls);
+ PendingUndeducedFunctionDecls.clear();
+ // We hope we can find the deduced type for the functions by iterating
+ // redeclarations in other modules.
+ for (FunctionDecl *UndeducedFD : UDTUpdates)
+ (void)UndeducedFD->getMostRecentDecl();
}
if (ReadTimer)
@@ -11637,8 +10158,7 @@ void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) {
// Adding the decl to IdResolver may have failed because it was already in
// (even though it was not added in scope). If it is already in, make sure
// it gets in the scope as well.
- if (std::find(SemaObj->IdResolver.begin(Name),
- SemaObj->IdResolver.end(), D) != SemaObj->IdResolver.end())
+ if (llvm::is_contained(SemaObj->IdResolver.decls(Name), D))
SemaObj->TUScope->AddDecl(D);
}
}
@@ -11794,6 +10314,12 @@ OMPClause *OMPClauseReader::readClause() {
case llvm::omp::OMPC_capture:
C = new (Context) OMPCaptureClause();
break;
+ case llvm::omp::OMPC_compare:
+ C = new (Context) OMPCompareClause();
+ break;
+ case llvm::omp::OMPC_fail:
+ C = new (Context) OMPFailClause();
+ break;
case llvm::omp::OMPC_seq_cst:
C = new (Context) OMPSeqCstClause();
break;
@@ -11833,7 +10359,16 @@ OMPClause *OMPClauseReader::readClause() {
case llvm::omp::OMPC_atomic_default_mem_order:
C = new (Context) OMPAtomicDefaultMemOrderClause();
break;
- case llvm::omp::OMPC_private:
+ case llvm::omp::OMPC_at:
+ C = new (Context) OMPAtClause();
+ break;
+ case llvm::omp::OMPC_severity:
+ C = new (Context) OMPSeverityClause();
+ break;
+ case llvm::omp::OMPC_message:
+ C = new (Context) OMPMessageClause();
+ break;
+ case llvm::omp::OMPC_private:
C = OMPPrivateClause::CreateEmpty(Context, Record.readInt());
break;
case llvm::omp::OMPC_firstprivate:
@@ -11962,6 +10497,15 @@ OMPClause *OMPClauseReader::readClause() {
C = OMPIsDevicePtrClause::CreateEmpty(Context, Sizes);
break;
}
+ case llvm::omp::OMPC_has_device_addr: {
+ OMPMappableExprListSizeTy Sizes;
+ Sizes.NumVars = Record.readInt();
+ Sizes.NumUniqueDeclarations = Record.readInt();
+ Sizes.NumComponentLists = Record.readInt();
+ Sizes.NumComponents = Record.readInt();
+ C = OMPHasDeviceAddrClause::CreateEmpty(Context, Sizes);
+ break;
+ }
case llvm::omp::OMPC_allocate:
C = OMPAllocateClause::CreateEmpty(Context, Record.readInt());
break;
@@ -12004,6 +10548,27 @@ OMPClause *OMPClauseReader::readClause() {
case llvm::omp::OMPC_filter:
C = new (Context) OMPFilterClause();
break;
+ case llvm::omp::OMPC_bind:
+ C = OMPBindClause::CreateEmpty(Context);
+ break;
+ case llvm::omp::OMPC_align:
+ C = new (Context) OMPAlignClause();
+ break;
+ case llvm::omp::OMPC_ompx_dyn_cgroup_mem:
+ C = new (Context) OMPXDynCGroupMemClause();
+ break;
+ case llvm::omp::OMPC_doacross: {
+ unsigned NumVars = Record.readInt();
+ unsigned NumLoops = Record.readInt();
+ C = OMPDoacrossClause::CreateEmpty(Context, NumVars, NumLoops);
+ break;
+ }
+ case llvm::omp::OMPC_ompx_attribute:
+ C = new (Context) OMPXAttributeClause();
+ break;
+ case llvm::omp::OMPC_ompx_bare:
+ C = new (Context) OMPXBareClause();
+ break;
#define OMP_CLAUSE_NO_CLASS(Enum, Str) \
case llvm::omp::Enum: \
break;
@@ -12146,6 +10711,18 @@ void OMPClauseReader::VisitOMPUpdateClause(OMPUpdateClause *C) {
void OMPClauseReader::VisitOMPCaptureClause(OMPCaptureClause *) {}
+void OMPClauseReader::VisitOMPCompareClause(OMPCompareClause *) {}
+
+// Read the parameter of fail clause. This will have been saved when
+// OMPClauseWriter is called.
+void OMPClauseReader::VisitOMPFailClause(OMPFailClause *C) {
+ C->setLParenLoc(Record.readSourceLocation());
+ SourceLocation FailParameterLoc = Record.readSourceLocation();
+ C->setFailParameterLoc(FailParameterLoc);
+ OpenMPClauseKind CKind = Record.readEnum<OpenMPClauseKind>();
+ C->setFailParameter(CKind);
+}
+
void OMPClauseReader::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
void OMPClauseReader::VisitOMPAcqRelClause(OMPAcqRelClause *) {}
@@ -12218,6 +10795,23 @@ void OMPClauseReader::VisitOMPAtomicDefaultMemOrderClause(
C->setAtomicDefaultMemOrderKindKwLoc(Record.readSourceLocation());
}
+void OMPClauseReader::VisitOMPAtClause(OMPAtClause *C) {
+ C->setAtKind(static_cast<OpenMPAtClauseKind>(Record.readInt()));
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setAtKindKwLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPSeverityClause(OMPSeverityClause *C) {
+ C->setSeverityKind(static_cast<OpenMPSeverityClauseKind>(Record.readInt()));
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setSeverityKindKwLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPMessageClause(OMPMessageClause *C) {
+ C->setMessageString(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) {
C->setLParenLoc(Record.readSourceLocation());
unsigned NumVars = C->varlist_size();
@@ -12523,6 +11117,7 @@ void OMPClauseReader::VisitOMPDependClause(OMPDependClause *C) {
static_cast<OpenMPDependClauseKind>(Record.readInt()));
C->setDependencyLoc(Record.readSourceLocation());
C->setColonLoc(Record.readSourceLocation());
+ C->setOmpAllMemoryLoc(Record.readSourceLocation());
unsigned NumVars = C->varlist_size();
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
@@ -12543,10 +11138,13 @@ void OMPClauseReader::VisitOMPDeviceClause(OMPDeviceClause *C) {
void OMPClauseReader::VisitOMPMapClause(OMPMapClause *C) {
C->setLParenLoc(Record.readSourceLocation());
+ bool HasIteratorModifier = false;
for (unsigned I = 0; I < NumberOfOMPMapClauseModifiers; ++I) {
C->setMapTypeModifier(
I, static_cast<OpenMPMapModifierKind>(Record.readInt()));
C->setMapTypeModifierLoc(I, Record.readSourceLocation());
+ if (C->getMapTypeModifier(I) == OMPC_MAP_MODIFIER_iterator)
+ HasIteratorModifier = true;
}
C->setMapperQualifierLoc(Record.readNestedNameSpecifierLoc());
C->setMapperIdInfo(Record.readDeclarationNameInfo());
@@ -12571,6 +11169,9 @@ void OMPClauseReader::VisitOMPMapClause(OMPMapClause *C) {
UDMappers.push_back(Record.readExpr());
C->setUDMapperRefs(UDMappers);
+ if (HasIteratorModifier)
+ C->setIteratorModifier(Record.readExpr());
+
SmallVector<ValueDecl *, 16> Decls;
Decls.reserve(UniqueDecls);
for (unsigned i = 0; i < UniqueDecls; ++i)
@@ -12632,13 +11233,17 @@ void OMPClauseReader::VisitOMPPriorityClause(OMPPriorityClause *C) {
void OMPClauseReader::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) {
VisitOMPClauseWithPreInit(C);
+ C->setModifier(Record.readEnum<OpenMPGrainsizeClauseModifier>());
C->setGrainsize(Record.readSubExpr());
+ C->setModifierLoc(Record.readSourceLocation());
C->setLParenLoc(Record.readSourceLocation());
}
void OMPClauseReader::VisitOMPNumTasksClause(OMPNumTasksClause *C) {
VisitOMPClauseWithPreInit(C);
+ C->setModifier(Record.readEnum<OpenMPNumTasksClauseModifier>());
C->setNumTasks(Record.readSubExpr());
+ C->setModifierLoc(Record.readSourceLocation());
C->setLParenLoc(Record.readSourceLocation());
}
@@ -12914,6 +11519,49 @@ void OMPClauseReader::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) {
C->setComponents(Components, ListSizes);
}
+void OMPClauseReader::VisitOMPHasDeviceAddrClause(OMPHasDeviceAddrClause *C) {
+ C->setLParenLoc(Record.readSourceLocation());
+ auto NumVars = C->varlist_size();
+ auto UniqueDecls = C->getUniqueDeclarationsNum();
+ auto TotalLists = C->getTotalComponentListNum();
+ auto TotalComponents = C->getTotalComponentsNum();
+
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+ Vars.clear();
+
+ SmallVector<ValueDecl *, 16> Decls;
+ Decls.reserve(UniqueDecls);
+ for (unsigned I = 0; I < UniqueDecls; ++I)
+ Decls.push_back(Record.readDeclAs<ValueDecl>());
+ C->setUniqueDecls(Decls);
+
+ SmallVector<unsigned, 16> ListsPerDecl;
+ ListsPerDecl.reserve(UniqueDecls);
+ for (unsigned I = 0; I < UniqueDecls; ++I)
+ ListsPerDecl.push_back(Record.readInt());
+ C->setDeclNumLists(ListsPerDecl);
+
+ SmallVector<unsigned, 32> ListSizes;
+ ListSizes.reserve(TotalLists);
+ for (unsigned i = 0; i < TotalLists; ++i)
+ ListSizes.push_back(Record.readInt());
+ C->setComponentListSizes(ListSizes);
+
+ SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components;
+ Components.reserve(TotalComponents);
+ for (unsigned I = 0; I < TotalComponents; ++I) {
+ Expr *AssociatedExpr = Record.readSubExpr();
+ auto *AssociatedDecl = Record.readDeclAs<ValueDecl>();
+ Components.emplace_back(AssociatedExpr, AssociatedDecl,
+ /*IsNonContiguous=*/false);
+ }
+ C->setComponents(Components, ListSizes);
+}
+
void OMPClauseReader::VisitOMPNontemporalClause(OMPNontemporalClause *C) {
C->setLParenLoc(Record.readSourceLocation());
unsigned NumVars = C->varlist_size();
@@ -12978,8 +11626,10 @@ void OMPClauseReader::VisitOMPAffinityClause(OMPAffinityClause *C) {
void OMPClauseReader::VisitOMPOrderClause(OMPOrderClause *C) {
C->setKind(Record.readEnum<OpenMPOrderClauseKind>());
+ C->setModifier(Record.readEnum<OpenMPOrderClauseModifier>());
C->setLParenLoc(Record.readSourceLocation());
C->setKindKwLoc(Record.readSourceLocation());
+ C->setModifierKwLoc(Record.readSourceLocation());
}
void OMPClauseReader::VisitOMPFilterClause(OMPFilterClause *C) {
@@ -12988,6 +11638,50 @@ void OMPClauseReader::VisitOMPFilterClause(OMPFilterClause *C) {
C->setLParenLoc(Record.readSourceLocation());
}
+void OMPClauseReader::VisitOMPBindClause(OMPBindClause *C) {
+ C->setBindKind(Record.readEnum<OpenMPBindClauseKind>());
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setBindKindLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPAlignClause(OMPAlignClause *C) {
+ C->setAlignment(Record.readExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPXDynCGroupMemClause(OMPXDynCGroupMemClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ C->setSize(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPDoacrossClause(OMPDoacrossClause *C) {
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setDependenceType(
+ static_cast<OpenMPDoacrossClauseModifier>(Record.readInt()));
+ C->setDependenceLoc(Record.readSourceLocation());
+ C->setColonLoc(Record.readSourceLocation());
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+ for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I)
+ C->setLoopData(I, Record.readSubExpr());
+}
+
+void OMPClauseReader::VisitOMPXAttributeClause(OMPXAttributeClause *C) {
+ AttrVec Attrs;
+ Record.readAttributes(Attrs);
+ C->setAttrs(Attrs);
+ C->setLocStart(Record.readSourceLocation());
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setLocEnd(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPXBareClause(OMPXBareClause *C) {}
+
OMPTraitInfo *ASTRecordReader::readOMPTraitInfo() {
OMPTraitInfo &TI = getContext().getNewOMPTraitInfo();
TI.Sets.resize(readUInt32());