aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp1920
1 files changed, 1010 insertions, 910 deletions
diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp
index 18ab4666a7d8..154acdfbe032 100644
--- a/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -13,7 +13,9 @@
#include "ASTCommon.h"
#include "ASTReaderInternals.h"
+#include "clang/AST/ASTConcept.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTStructuralEquivalence.h"
#include "clang/AST/Attr.h"
#include "clang/AST/AttrIterator.h"
#include "clang/AST/Decl.h"
@@ -36,6 +38,7 @@
#include "clang/AST/Type.h"
#include "clang/AST/UnresolvedSet.h"
#include "clang/Basic/AttrKinds.h"
+#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
@@ -46,6 +49,7 @@
#include "clang/Basic/PragmaKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/Stack.h"
#include "clang/Sema/IdentifierResolver.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ASTRecordReader.h"
@@ -81,18 +85,16 @@ namespace clang {
ASTReader &Reader;
ASTRecordReader &Record;
ASTReader::RecordLocation Loc;
- const DeclID ThisDeclID;
+ const GlobalDeclID ThisDeclID;
const SourceLocation ThisDeclLoc;
using RecordData = ASTReader::RecordData;
TypeID DeferredTypeID = 0;
- unsigned AnonymousDeclNumber;
- GlobalDeclID NamedDeclForTagDecl = 0;
+ unsigned AnonymousDeclNumber = 0;
+ GlobalDeclID NamedDeclForTagDecl = GlobalDeclID();
IdentifierInfo *TypedefNameForLinkage = nullptr;
- bool HasPendingBody = false;
-
///A flag to carry the information for a decl from the entity is
/// used. We use it to delay the marking of the canonical decl as used until
/// the entire declaration is deserialized and merged.
@@ -123,15 +125,13 @@ namespace clang {
return Record.readTypeSourceInfo();
}
- serialization::DeclID readDeclID() {
- return Record.readDeclID();
- }
+ GlobalDeclID readDeclID() { return Record.readDeclID(); }
std::string readString() {
return Record.readString();
}
- void readDeclIDList(SmallVectorImpl<DeclID> &IDs) {
+ void readDeclIDList(SmallVectorImpl<GlobalDeclID> &IDs) {
for (unsigned I = 0, Size = Record.readInt(); I != Size; ++I)
IDs.push_back(readDeclID());
}
@@ -156,9 +156,12 @@ namespace clang {
return Record.getSubmodule(readSubmoduleID());
}
- void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update);
+ void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update,
+ Decl *LambdaContext = nullptr,
+ unsigned IndexInLambdaContext = 0);
void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data,
- const CXXRecordDecl *D);
+ const CXXRecordDecl *D, Decl *LambdaContext,
+ unsigned IndexInLambdaContext);
void MergeDefinitionData(CXXRecordDecl *D,
struct CXXRecordDecl::DefinitionData &&NewDD);
void ReadObjCDefinitionData(struct ObjCInterfaceDecl::DefinitionData &Data);
@@ -176,6 +179,13 @@ namespace clang {
static void setAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC,
unsigned Index, NamedDecl *D);
+ /// Commit to a primary definition of the class RD, which is known to be
+ /// a definition of the class. We might not have read the definition data
+ /// for it yet. If we haven't then allocate placeholder definition data
+ /// now too.
+ static CXXRecordDecl *getOrFakePrimaryClassDefinition(ASTReader &Reader,
+ CXXRecordDecl *RD);
+
/// Results from loading a RedeclarableDecl.
class RedeclarableResult {
Decl *MergeWith;
@@ -247,14 +257,14 @@ namespace clang {
public:
ASTDeclReader(ASTReader &Reader, ASTRecordReader &Record,
- ASTReader::RecordLocation Loc,
- DeclID thisDeclID, SourceLocation ThisDeclLoc)
+ ASTReader::RecordLocation Loc, GlobalDeclID thisDeclID,
+ SourceLocation ThisDeclLoc)
: Reader(Reader), Record(Record), Loc(Loc), ThisDeclID(thisDeclID),
ThisDeclLoc(ThisDeclLoc) {}
- template <typename T> static
- void AddLazySpecializations(T *D,
- SmallVectorImpl<serialization::DeclID>& IDs) {
+ template <typename T>
+ static void AddLazySpecializations(T *D,
+ SmallVectorImpl<GlobalDeclID> &IDs) {
if (IDs.empty())
return;
@@ -264,13 +274,14 @@ namespace clang {
auto *&LazySpecializations = D->getCommonPtr()->LazySpecializations;
if (auto &Old = LazySpecializations) {
- IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]);
+ IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0].getRawValue());
llvm::sort(IDs);
IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end());
}
- auto *Result = new (C) serialization::DeclID[1 + IDs.size()];
- *Result = IDs.size();
+ auto *Result = new (C) GlobalDeclID[1 + IDs.size()];
+ *Result = GlobalDeclID(IDs.size());
+
std::copy(IDs.begin(), IDs.end(), Result + 1);
LazySpecializations = Result;
@@ -301,13 +312,10 @@ namespace clang {
static void markIncompleteDeclChainImpl(Redeclarable<DeclT> *D);
static void markIncompleteDeclChainImpl(...);
- /// Determine whether this declaration has a pending body.
- bool hasPendingBody() const { return HasPendingBody; }
-
void ReadFunctionDefinition(FunctionDecl *FD);
void Visit(Decl *D);
- void UpdateDecl(Decl *D, SmallVectorImpl<serialization::DeclID> &);
+ void UpdateDecl(Decl *D, SmallVectorImpl<GlobalDeclID> &);
static void setNextObjCCategory(ObjCCategoryDecl *Cat,
ObjCCategoryDecl *Next) {
@@ -321,6 +329,7 @@ namespace clang {
void VisitNamedDecl(NamedDecl *ND);
void VisitLabelDecl(LabelDecl *LD);
void VisitNamespaceDecl(NamespaceDecl *D);
+ void VisitHLSLBufferDecl(HLSLBufferDecl *D);
void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
void VisitTypeDecl(TypeDecl *TD);
@@ -328,10 +337,11 @@ namespace clang {
void VisitTypedefDecl(TypedefDecl *TD);
void VisitTypeAliasDecl(TypeAliasDecl *TD);
void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+ void VisitUnresolvedUsingIfExistsDecl(UnresolvedUsingIfExistsDecl *D);
RedeclarableResult VisitTagDecl(TagDecl *TD);
void VisitEnumDecl(EnumDecl *ED);
RedeclarableResult VisitRecordDeclImpl(RecordDecl *RD);
- void VisitRecordDecl(RecordDecl *RD) { VisitRecordDeclImpl(RD); }
+ void VisitRecordDecl(RecordDecl *RD);
RedeclarableResult VisitCXXRecordDeclImpl(CXXRecordDecl *D);
void VisitCXXRecordDecl(CXXRecordDecl *D) { VisitCXXRecordDeclImpl(D); }
RedeclarableResult VisitClassTemplateSpecializationDeclImpl(
@@ -343,9 +353,7 @@ namespace clang {
}
void VisitClassTemplatePartialSpecializationDecl(
- ClassTemplatePartialSpecializationDecl *D);
- void VisitClassScopeFunctionSpecializationDecl(
- ClassScopeFunctionSpecializationDecl *D);
+ ClassTemplatePartialSpecializationDecl *D);
RedeclarableResult
VisitVarTemplateSpecializationDeclImpl(VarTemplateSpecializationDecl *D);
@@ -369,17 +377,21 @@ namespace clang {
void VisitFieldDecl(FieldDecl *FD);
void VisitMSPropertyDecl(MSPropertyDecl *FD);
void VisitMSGuidDecl(MSGuidDecl *D);
+ void VisitUnnamedGlobalConstantDecl(UnnamedGlobalConstantDecl *D);
void VisitTemplateParamObjectDecl(TemplateParamObjectDecl *D);
void VisitIndirectFieldDecl(IndirectFieldDecl *FD);
RedeclarableResult VisitVarDeclImpl(VarDecl *D);
+ void ReadVarDeclInit(VarDecl *VD);
void VisitVarDecl(VarDecl *VD) { VisitVarDeclImpl(VD); }
void VisitImplicitParamDecl(ImplicitParamDecl *PD);
void VisitParmVarDecl(ParmVarDecl *PD);
void VisitDecompositionDecl(DecompositionDecl *DD);
void VisitBindingDecl(BindingDecl *BD);
void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
- DeclID VisitTemplateDecl(TemplateDecl *D);
+ void VisitTemplateDecl(TemplateDecl *D);
void VisitConceptDecl(ConceptDecl *D);
+ void VisitImplicitConceptSpecializationDecl(
+ ImplicitConceptSpecializationDecl *D);
void VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D);
RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
void VisitClassTemplateDecl(ClassTemplateDecl *D);
@@ -389,12 +401,14 @@ namespace clang {
void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
void VisitUsingDecl(UsingDecl *D);
+ void VisitUsingEnumDecl(UsingEnumDecl *D);
void VisitUsingPackDecl(UsingPackDecl *D);
void VisitUsingShadowDecl(UsingShadowDecl *D);
void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D);
void VisitLinkageSpecDecl(LinkageSpecDecl *D);
void VisitExportDecl(ExportDecl *D);
void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD);
+ void VisitTopLevelStmtDecl(TopLevelStmtDecl *D);
void VisitImportDecl(ImportDecl *D);
void VisitAccessSpecDecl(AccessSpecDecl *D);
void VisitFriendDecl(FriendDecl *D);
@@ -410,14 +424,18 @@ namespace clang {
template<typename T>
RedeclarableResult VisitRedeclarable(Redeclarable<T> *D);
- template<typename T>
- void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl,
- DeclID TemplatePatternID = 0);
+ template <typename T>
+ void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl);
- template<typename T>
+ void mergeLambda(CXXRecordDecl *D, RedeclarableResult &Redecl,
+ Decl *Context, unsigned Number);
+
+ void mergeRedeclarableTemplate(RedeclarableTemplateDecl *D,
+ RedeclarableResult &Redecl);
+
+ template <typename T>
void mergeRedeclarable(Redeclarable<T> *D, T *Existing,
- RedeclarableResult &Redecl,
- DeclID TemplatePatternID = 0);
+ RedeclarableResult &Redecl);
template<typename T>
void mergeMergeable(Mergeable<T> *D);
@@ -426,7 +444,7 @@ namespace clang {
void mergeTemplatePattern(RedeclarableTemplateDecl *D,
RedeclarableTemplateDecl *Existing,
- DeclID DsID, bool IsKeyDecl);
+ bool IsKeyDecl);
ObjCTypeParamList *ReadObjCTypeParamList();
@@ -459,9 +477,8 @@ namespace {
/// Iterator over the redeclarations of a declaration that have already
/// been merged into the same redeclaration chain.
-template<typename DeclT>
-class MergedRedeclIterator {
- DeclT *Start;
+template <typename DeclT> class MergedRedeclIterator {
+ DeclT *Start = nullptr;
DeclT *Canonical = nullptr;
DeclT *Current = nullptr;
@@ -519,7 +536,6 @@ void ASTDeclReader::ReadFunctionDefinition(FunctionDecl *FD) {
}
// Store the offset of the body so we can lazily load it later.
Reader.PendingBodies[FD] = GetCurrentCursorOffset();
- HasPendingBody = true;
}
void ASTDeclReader::Visit(Decl *D) {
@@ -541,7 +557,7 @@ void ASTDeclReader::Visit(Decl *D) {
// If this is a tag declaration with a typedef name for linkage, it's safe
// to load that typedef now.
- if (NamedDeclForTagDecl)
+ if (NamedDeclForTagDecl.isValid())
cast<TagDecl>(D)->TypedefNameDeclOrQualifier =
cast<TypedefNameDecl>(Reader.GetDecl(NamedDeclForTagDecl));
} else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
@@ -549,17 +565,34 @@ void ASTDeclReader::Visit(Decl *D) {
ID->TypeForDecl = Reader.GetType(DeferredTypeID).getTypePtrOrNull();
} else if (auto *FD = dyn_cast<FunctionDecl>(D)) {
// FunctionDecl's body was written last after all other Stmts/Exprs.
- // We only read it if FD doesn't already have a body (e.g., from another
- // module).
- // FIXME: Can we diagnose ODR violations somehow?
if (Record.readInt())
ReadFunctionDefinition(FD);
+ } else if (auto *VD = dyn_cast<VarDecl>(D)) {
+ ReadVarDeclInit(VD);
+ } else if (auto *FD = dyn_cast<FieldDecl>(D)) {
+ if (FD->hasInClassInitializer() && Record.readInt()) {
+ FD->setLazyInClassInitializer(LazyDeclStmtPtr(GetCurrentCursorOffset()));
+ }
}
}
void ASTDeclReader::VisitDecl(Decl *D) {
+ BitsUnpacker DeclBits(Record.readInt());
+ auto ModuleOwnership =
+ (Decl::ModuleOwnershipKind)DeclBits.getNextBits(/*Width=*/3);
+ D->setReferenced(DeclBits.getNextBit());
+ D->Used = DeclBits.getNextBit();
+ IsDeclMarkedUsed |= D->Used;
+ D->setAccess((AccessSpecifier)DeclBits.getNextBits(/*Width=*/2));
+ D->setImplicit(DeclBits.getNextBit());
+ bool HasStandaloneLexicalDC = DeclBits.getNextBit();
+ bool HasAttrs = DeclBits.getNextBit();
+ D->setTopLevelDeclInObjCContainer(DeclBits.getNextBit());
+ D->InvalidDecl = DeclBits.getNextBit();
+ D->FromASTFile = true;
+
if (D->isTemplateParameter() || D->isTemplateParameterPack() ||
- isa<ParmVarDecl>(D) || isa<ObjCTypeParamDecl>(D)) {
+ isa<ParmVarDecl, ObjCTypeParamDecl>(D)) {
// We don't want to deserialize the DeclContext of a template
// parameter or of a parameter of a function template immediately. These
// entities might be used in the formulation of its DeclContext (for
@@ -567,8 +600,9 @@ void ASTDeclReader::VisitDecl(Decl *D) {
// return type of the function). Use the translation unit DeclContext as a
// placeholder.
GlobalDeclID SemaDCIDForTemplateParmDecl = readDeclID();
- GlobalDeclID LexicalDCIDForTemplateParmDecl = readDeclID();
- if (!LexicalDCIDForTemplateParmDecl)
+ GlobalDeclID LexicalDCIDForTemplateParmDecl =
+ HasStandaloneLexicalDC ? readDeclID() : GlobalDeclID();
+ if (LexicalDCIDForTemplateParmDecl.isInvalid())
LexicalDCIDForTemplateParmDecl = SemaDCIDForTemplateParmDecl;
Reader.addPendingDeclContextInfo(D,
SemaDCIDForTemplateParmDecl,
@@ -576,40 +610,50 @@ void ASTDeclReader::VisitDecl(Decl *D) {
D->setDeclContext(Reader.getContext().getTranslationUnitDecl());
} else {
auto *SemaDC = readDeclAs<DeclContext>();
- auto *LexicalDC = readDeclAs<DeclContext>();
+ auto *LexicalDC =
+ HasStandaloneLexicalDC ? readDeclAs<DeclContext>() : nullptr;
if (!LexicalDC)
LexicalDC = SemaDC;
- DeclContext *MergedSemaDC = Reader.MergedDeclContexts.lookup(SemaDC);
+ // If the context is a class, we might not have actually merged it yet, in
+ // the case where the definition comes from an update record.
+ DeclContext *MergedSemaDC;
+ if (auto *RD = dyn_cast<CXXRecordDecl>(SemaDC))
+ MergedSemaDC = getOrFakePrimaryClassDefinition(Reader, RD);
+ else
+ MergedSemaDC = Reader.MergedDeclContexts.lookup(SemaDC);
// Avoid calling setLexicalDeclContext() directly because it uses
// Decl::getASTContext() internally which is unsafe during derialization.
D->setDeclContextsImpl(MergedSemaDC ? MergedSemaDC : SemaDC, LexicalDC,
Reader.getContext());
}
D->setLocation(ThisDeclLoc);
- D->InvalidDecl = Record.readInt();
- if (Record.readInt()) { // hasAttrs
+
+ if (HasAttrs) {
AttrVec Attrs;
Record.readAttributes(Attrs);
// Avoid calling setAttrs() directly because it uses Decl::getASTContext()
// internally which is unsafe during derialization.
D->setAttrsImpl(Attrs, Reader.getContext());
}
- D->setImplicit(Record.readInt());
- D->Used = Record.readInt();
- IsDeclMarkedUsed |= D->Used;
- D->setReferenced(Record.readInt());
- D->setTopLevelDeclInObjCContainer(Record.readInt());
- D->setAccess((AccessSpecifier)Record.readInt());
- D->FromASTFile = true;
- bool ModulePrivate = Record.readInt();
// Determine whether this declaration is part of a (sub)module. If so, it
// may not yet be visible.
+ bool ModulePrivate =
+ (ModuleOwnership == Decl::ModuleOwnershipKind::ModulePrivate);
if (unsigned SubmoduleID = readSubmoduleID()) {
+ switch (ModuleOwnership) {
+ case Decl::ModuleOwnershipKind::Visible:
+ ModuleOwnership = Decl::ModuleOwnershipKind::VisibleWhenImported;
+ break;
+ case Decl::ModuleOwnershipKind::Unowned:
+ case Decl::ModuleOwnershipKind::VisibleWhenImported:
+ case Decl::ModuleOwnershipKind::ReachableWhenImported:
+ case Decl::ModuleOwnershipKind::ModulePrivate:
+ break;
+ }
+
+ D->setModuleOwnershipKind(ModuleOwnership);
// Store the owning submodule ID in the declaration.
- D->setModuleOwnershipKind(
- ModulePrivate ? Decl::ModuleOwnershipKind::ModulePrivate
- : Decl::ModuleOwnershipKind::VisibleWhenImported);
D->setOwningModuleID(SubmoduleID);
if (ModulePrivate) {
@@ -707,15 +751,17 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) {
VisitTypeDecl(TD);
TD->IdentifierNamespace = Record.readInt();
- TD->setTagKind((TagDecl::TagKind)Record.readInt());
- if (!isa<CXXRecordDecl>(TD))
- TD->setCompleteDefinition(Record.readInt());
- TD->setEmbeddedInDeclarator(Record.readInt());
- TD->setFreeStanding(Record.readInt());
- TD->setCompleteDefinitionRequired(Record.readInt());
+
+ BitsUnpacker TagDeclBits(Record.readInt());
+ TD->setTagKind(
+ static_cast<TagTypeKind>(TagDeclBits.getNextBits(/*Width=*/3)));
+ TD->setCompleteDefinition(TagDeclBits.getNextBit());
+ TD->setEmbeddedInDeclarator(TagDeclBits.getNextBit());
+ TD->setFreeStanding(TagDeclBits.getNextBit());
+ TD->setCompleteDefinitionRequired(TagDeclBits.getNextBit());
TD->setBraceRange(readSourceRange());
- switch (Record.readInt()) {
+ switch (TagDeclBits.getNextBits(/*Width=*/2)) {
case 0:
break;
case 1: { // ExtInfo
@@ -744,20 +790,20 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
else
ED->setIntegerType(Record.readType());
ED->setPromotionType(Record.readType());
- ED->setNumPositiveBits(Record.readInt());
- ED->setNumNegativeBits(Record.readInt());
- ED->setScoped(Record.readInt());
- ED->setScopedUsingClassTag(Record.readInt());
- ED->setFixed(Record.readInt());
+
+ BitsUnpacker EnumDeclBits(Record.readInt());
+ ED->setNumPositiveBits(EnumDeclBits.getNextBits(/*Width=*/8));
+ ED->setNumNegativeBits(EnumDeclBits.getNextBits(/*Width=*/8));
+ ED->setScoped(EnumDeclBits.getNextBit());
+ ED->setScopedUsingClassTag(EnumDeclBits.getNextBit());
+ ED->setFixed(EnumDeclBits.getNextBit());
ED->setHasODRHash(true);
ED->ODRHash = Record.readInt();
// If this is a definition subject to the ODR, and we already have a
// definition, merge this one into it.
- if (ED->isCompleteDefinition() &&
- Reader.getContext().getLangOpts().Modules &&
- Reader.getContext().getLangOpts().CPlusPlus) {
+ if (ED->isCompleteDefinition() && Reader.getContext().getLangOpts().Modules) {
EnumDecl *&OldDef = Reader.EnumDefinitions[ED->getCanonicalDecl()];
if (!OldDef) {
// This is the first time we've seen an imported definition. Look for a
@@ -771,9 +817,12 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
}
if (OldDef) {
Reader.MergedDeclContexts.insert(std::make_pair(ED, OldDef));
- ED->setCompleteDefinition(false);
+ ED->demoteThisDefinitionToDeclaration();
Reader.mergeDefinitionVisibility(OldDef, ED);
- if (OldDef->getODRHash() != ED->getODRHash())
+ // We don't want to check the ODR hash value for declarations from global
+ // module fragment.
+ if (!shouldSkipCheckingODR(ED) && !shouldSkipCheckingODR(OldDef) &&
+ OldDef->getODRHash() != ED->getODRHash())
Reader.PendingEnumOdrMergeFailures[OldDef].push_back(ED);
} else {
OldDef = ED;
@@ -791,27 +840,62 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) {
RedeclarableResult Redecl = VisitTagDecl(RD);
- RD->setHasFlexibleArrayMember(Record.readInt());
- RD->setAnonymousStructOrUnion(Record.readInt());
- RD->setHasObjectMember(Record.readInt());
- RD->setHasVolatileMember(Record.readInt());
- RD->setNonTrivialToPrimitiveDefaultInitialize(Record.readInt());
- RD->setNonTrivialToPrimitiveCopy(Record.readInt());
- RD->setNonTrivialToPrimitiveDestroy(Record.readInt());
- RD->setHasNonTrivialToPrimitiveDefaultInitializeCUnion(Record.readInt());
- RD->setHasNonTrivialToPrimitiveDestructCUnion(Record.readInt());
- RD->setHasNonTrivialToPrimitiveCopyCUnion(Record.readInt());
- RD->setParamDestroyedInCallee(Record.readInt());
- RD->setArgPassingRestrictions((RecordDecl::ArgPassingKind)Record.readInt());
+
+ BitsUnpacker RecordDeclBits(Record.readInt());
+ RD->setHasFlexibleArrayMember(RecordDeclBits.getNextBit());
+ RD->setAnonymousStructOrUnion(RecordDeclBits.getNextBit());
+ RD->setHasObjectMember(RecordDeclBits.getNextBit());
+ RD->setHasVolatileMember(RecordDeclBits.getNextBit());
+ RD->setNonTrivialToPrimitiveDefaultInitialize(RecordDeclBits.getNextBit());
+ RD->setNonTrivialToPrimitiveCopy(RecordDeclBits.getNextBit());
+ RD->setNonTrivialToPrimitiveDestroy(RecordDeclBits.getNextBit());
+ RD->setHasNonTrivialToPrimitiveDefaultInitializeCUnion(
+ RecordDeclBits.getNextBit());
+ RD->setHasNonTrivialToPrimitiveDestructCUnion(RecordDeclBits.getNextBit());
+ RD->setHasNonTrivialToPrimitiveCopyCUnion(RecordDeclBits.getNextBit());
+ RD->setParamDestroyedInCallee(RecordDeclBits.getNextBit());
+ RD->setArgPassingRestrictions(
+ (RecordArgPassingKind)RecordDeclBits.getNextBits(/*Width=*/2));
return Redecl;
}
+void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) {
+ VisitRecordDeclImpl(RD);
+ RD->setODRHash(Record.readInt());
+
+ // Maintain the invariant of a redeclaration chain containing only
+ // a single definition.
+ if (RD->isCompleteDefinition()) {
+ RecordDecl *Canon = static_cast<RecordDecl *>(RD->getCanonicalDecl());
+ RecordDecl *&OldDef = Reader.RecordDefinitions[Canon];
+ if (!OldDef) {
+ // This is the first time we've seen an imported definition. Look for a
+ // local definition before deciding that we are the first definition.
+ for (auto *D : merged_redecls(Canon)) {
+ if (!D->isFromASTFile() && D->isCompleteDefinition()) {
+ OldDef = D;
+ break;
+ }
+ }
+ }
+ if (OldDef) {
+ Reader.MergedDeclContexts.insert(std::make_pair(RD, OldDef));
+ RD->demoteThisDefinitionToDeclaration();
+ Reader.mergeDefinitionVisibility(OldDef, RD);
+ if (OldDef->getODRHash() != RD->getODRHash())
+ Reader.PendingRecordOdrMergeFailures[OldDef].push_back(RD);
+ } else {
+ OldDef = RD;
+ }
+ }
+}
+
void ASTDeclReader::VisitValueDecl(ValueDecl *VD) {
VisitNamedDecl(VD);
- // For function declarations, defer reading the type in case the function has
- // a deduced return type that references an entity declared within the
- // function.
- if (isa<FunctionDecl>(VD))
+ // For function or variable declarations, defer reading the type in case the
+ // declaration has a deduced type that references an entity declared within
+ // the function definition or variable initializer.
+ if (isa<FunctionDecl, VarDecl>(VD))
DeferredTypeID = Record.getGlobalTypeID(Record.readInt());
else
VD->setType(Record.readType());
@@ -821,7 +905,7 @@ void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
VisitValueDecl(ECD);
if (Record.readInt())
ECD->setInitExpr(Record.readExpr());
- ECD->setInitVal(Record.readAPSInt());
+ ECD->setInitVal(Reader.getContext(), Record.readAPSInt());
mergeMergeable(ECD);
}
@@ -842,84 +926,27 @@ void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
RedeclarableResult Redecl = VisitRedeclarable(FD);
- VisitDeclaratorDecl(FD);
-
- // Attach a type to this function. Use the real type if possible, but fall
- // back to the type as written if it involves a deduced return type.
- if (FD->getTypeSourceInfo() &&
- FD->getTypeSourceInfo()->getType()->castAs<FunctionType>()
- ->getReturnType()->getContainedAutoType()) {
- // We'll set up the real type in Visit, once we've finished loading the
- // function.
- FD->setType(FD->getTypeSourceInfo()->getType());
- Reader.PendingFunctionTypes.push_back({FD, DeferredTypeID});
- } else {
- FD->setType(Reader.GetType(DeferredTypeID));
- }
- DeferredTypeID = 0;
-
- FD->DNLoc = Record.readDeclarationNameLoc(FD->getDeclName());
- FD->IdentifierNamespace = Record.readInt();
-
- // FunctionDecl's body is handled last at ASTDeclReader::Visit,
- // after everything else is read.
-
- FD->setStorageClass(static_cast<StorageClass>(Record.readInt()));
- FD->setInlineSpecified(Record.readInt());
- FD->setImplicitlyInline(Record.readInt());
- FD->setVirtualAsWritten(Record.readInt());
- // We defer calling `FunctionDecl::setPure()` here as for methods of
- // `CXXTemplateSpecializationDecl`s, we may not have connected up the
- // definition (which is required for `setPure`).
- const bool Pure = Record.readInt();
- FD->setHasInheritedPrototype(Record.readInt());
- FD->setHasWrittenPrototype(Record.readInt());
- FD->setDeletedAsWritten(Record.readInt());
- FD->setTrivial(Record.readInt());
- FD->setTrivialForCall(Record.readInt());
- FD->setDefaulted(Record.readInt());
- FD->setExplicitlyDefaulted(Record.readInt());
- FD->setHasImplicitReturnZero(Record.readInt());
- FD->setConstexprKind(static_cast<ConstexprSpecKind>(Record.readInt()));
- FD->setUsesSEHTry(Record.readInt());
- FD->setHasSkippedBody(Record.readInt());
- FD->setIsMultiVersion(Record.readInt());
- FD->setLateTemplateParsed(Record.readInt());
-
- FD->setCachedLinkage(static_cast<Linkage>(Record.readInt()));
- FD->EndRangeLoc = readSourceLocation();
-
- FD->ODRHash = Record.readInt();
- FD->setHasODRHash(true);
- if (FD->isDefaulted()) {
- if (unsigned NumLookups = Record.readInt()) {
- SmallVector<DeclAccessPair, 8> Lookups;
- for (unsigned I = 0; I != NumLookups; ++I) {
- NamedDecl *ND = Record.readDeclAs<NamedDecl>();
- AccessSpecifier AS = (AccessSpecifier)Record.readInt();
- Lookups.push_back(DeclAccessPair::make(ND, AS));
- }
- FD->setDefaultedFunctionInfo(FunctionDecl::DefaultedFunctionInfo::Create(
- Reader.getContext(), Lookups));
- }
- }
+ FunctionDecl *Existing = nullptr;
switch ((FunctionDecl::TemplatedKind)Record.readInt()) {
case FunctionDecl::TK_NonTemplate:
- mergeRedeclarable(FD, Redecl);
break;
- case FunctionDecl::TK_FunctionTemplate:
- // Merged when we merge the template.
- FD->setDescribedFunctionTemplate(readDeclAs<FunctionTemplateDecl>());
+ case FunctionDecl::TK_DependentNonTemplate:
+ FD->setInstantiatedFromDecl(readDeclAs<FunctionDecl>());
+ break;
+ case FunctionDecl::TK_FunctionTemplate: {
+ auto *Template = readDeclAs<FunctionTemplateDecl>();
+ Template->init(FD);
+ FD->setDescribedFunctionTemplate(Template);
break;
+ }
case FunctionDecl::TK_MemberSpecialization: {
auto *InstFD = readDeclAs<FunctionDecl>();
auto TSK = (TemplateSpecializationKind)Record.readInt();
SourceLocation POI = readSourceLocation();
FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK);
FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
- mergeRedeclarable(FD, Redecl);
break;
}
case FunctionDecl::TK_FunctionTemplateSpecialization: {
@@ -931,27 +958,16 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true);
// Template args as written.
- SmallVector<TemplateArgumentLoc, 8> TemplArgLocs;
- SourceLocation LAngleLoc, RAngleLoc;
- bool HasTemplateArgumentsAsWritten = Record.readInt();
- if (HasTemplateArgumentsAsWritten) {
- unsigned NumTemplateArgLocs = Record.readInt();
- TemplArgLocs.reserve(NumTemplateArgLocs);
- for (unsigned i = 0; i != NumTemplateArgLocs; ++i)
- TemplArgLocs.push_back(Record.readTemplateArgumentLoc());
-
- LAngleLoc = readSourceLocation();
- RAngleLoc = readSourceLocation();
- }
+ TemplateArgumentListInfo TemplArgsWritten;
+ bool HasTemplateArgumentsAsWritten = Record.readBool();
+ if (HasTemplateArgumentsAsWritten)
+ Record.readTemplateArgumentListInfo(TemplArgsWritten);
SourceLocation POI = readSourceLocation();
ASTContext &C = Reader.getContext();
- TemplateArgumentList *TemplArgList
- = TemplateArgumentList::CreateCopy(C, TemplArgs);
- TemplateArgumentListInfo TemplArgsInfo(LAngleLoc, RAngleLoc);
- for (unsigned i = 0, e = TemplArgLocs.size(); i != e; ++i)
- TemplArgsInfo.addArgument(TemplArgLocs[i]);
+ TemplateArgumentList *TemplArgList =
+ TemplateArgumentList::CreateCopy(C, TemplArgs);
MemberSpecializationInfo *MSInfo = nullptr;
if (Record.readInt()) {
@@ -966,7 +982,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FunctionTemplateSpecializationInfo *FTInfo =
FunctionTemplateSpecializationInfo::Create(
C, FD, Template, TSK, TemplArgList,
- HasTemplateArgumentsAsWritten ? &TemplArgsInfo : nullptr, POI,
+ HasTemplateArgumentsAsWritten ? &TemplArgsWritten : nullptr, POI,
MSInfo);
FD->TemplateOrSpecialization = FTInfo;
@@ -990,37 +1006,141 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
else {
assert(Reader.getContext().getLangOpts().Modules &&
"already deserialized this template specialization");
- mergeRedeclarable(FD, ExistingInfo->getFunction(), Redecl);
+ Existing = ExistingInfo->getFunction();
}
}
break;
}
case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
// Templates.
- UnresolvedSet<8> TemplDecls;
- unsigned NumTemplates = Record.readInt();
- while (NumTemplates--)
- TemplDecls.addDecl(readDeclAs<NamedDecl>());
+ UnresolvedSet<8> Candidates;
+ unsigned NumCandidates = Record.readInt();
+ while (NumCandidates--)
+ Candidates.addDecl(readDeclAs<NamedDecl>());
// Templates args.
- TemplateArgumentListInfo TemplArgs;
- unsigned NumArgs = Record.readInt();
- while (NumArgs--)
- TemplArgs.addArgument(Record.readTemplateArgumentLoc());
- TemplArgs.setLAngleLoc(readSourceLocation());
- TemplArgs.setRAngleLoc(readSourceLocation());
-
- FD->setDependentTemplateSpecialization(Reader.getContext(),
- TemplDecls, TemplArgs);
+ TemplateArgumentListInfo TemplArgsWritten;
+ bool HasTemplateArgumentsAsWritten = Record.readBool();
+ if (HasTemplateArgumentsAsWritten)
+ Record.readTemplateArgumentListInfo(TemplArgsWritten);
+
+ FD->setDependentTemplateSpecialization(
+ Reader.getContext(), Candidates,
+ HasTemplateArgumentsAsWritten ? &TemplArgsWritten : nullptr);
// These are not merged; we don't need to merge redeclarations of dependent
// template friends.
break;
}
}
+ VisitDeclaratorDecl(FD);
+
+ // Attach a type to this function. Use the real type if possible, but fall
+ // back to the type as written if it involves a deduced return type.
+ if (FD->getTypeSourceInfo() && FD->getTypeSourceInfo()
+ ->getType()
+ ->castAs<FunctionType>()
+ ->getReturnType()
+ ->getContainedAutoType()) {
+ // We'll set up the real type in Visit, once we've finished loading the
+ // function.
+ FD->setType(FD->getTypeSourceInfo()->getType());
+ Reader.PendingDeducedFunctionTypes.push_back({FD, DeferredTypeID});
+ } else {
+ FD->setType(Reader.GetType(DeferredTypeID));
+ }
+ DeferredTypeID = 0;
+
+ FD->DNLoc = Record.readDeclarationNameLoc(FD->getDeclName());
+ FD->IdentifierNamespace = Record.readInt();
+
+ // FunctionDecl's body is handled last at ASTDeclReader::Visit,
+ // after everything else is read.
+ BitsUnpacker FunctionDeclBits(Record.readInt());
+
+ FD->setCachedLinkage((Linkage)FunctionDeclBits.getNextBits(/*Width=*/3));
+ FD->setStorageClass((StorageClass)FunctionDeclBits.getNextBits(/*Width=*/3));
+ FD->setInlineSpecified(FunctionDeclBits.getNextBit());
+ FD->setImplicitlyInline(FunctionDeclBits.getNextBit());
+ FD->setHasSkippedBody(FunctionDeclBits.getNextBit());
+ FD->setVirtualAsWritten(FunctionDeclBits.getNextBit());
+ // We defer calling `FunctionDecl::setPure()` here as for methods of
+ // `CXXTemplateSpecializationDecl`s, we may not have connected up the
+ // definition (which is required for `setPure`).
+ const bool Pure = FunctionDeclBits.getNextBit();
+ FD->setHasInheritedPrototype(FunctionDeclBits.getNextBit());
+ FD->setHasWrittenPrototype(FunctionDeclBits.getNextBit());
+ FD->setDeletedAsWritten(FunctionDeclBits.getNextBit());
+ FD->setTrivial(FunctionDeclBits.getNextBit());
+ FD->setTrivialForCall(FunctionDeclBits.getNextBit());
+ FD->setDefaulted(FunctionDeclBits.getNextBit());
+ FD->setExplicitlyDefaulted(FunctionDeclBits.getNextBit());
+ FD->setIneligibleOrNotSelected(FunctionDeclBits.getNextBit());
+ FD->setConstexprKind(
+ (ConstexprSpecKind)FunctionDeclBits.getNextBits(/*Width=*/2));
+ FD->setHasImplicitReturnZero(FunctionDeclBits.getNextBit());
+ FD->setIsMultiVersion(FunctionDeclBits.getNextBit());
+ FD->setLateTemplateParsed(FunctionDeclBits.getNextBit());
+ FD->setFriendConstraintRefersToEnclosingTemplate(
+ FunctionDeclBits.getNextBit());
+ FD->setUsesSEHTry(FunctionDeclBits.getNextBit());
+
+ FD->EndRangeLoc = readSourceLocation();
+ if (FD->isExplicitlyDefaulted())
+ FD->setDefaultLoc(readSourceLocation());
+
+ FD->ODRHash = Record.readInt();
+ FD->setHasODRHash(true);
+
+ if (FD->isDefaulted() || FD->isDeletedAsWritten()) {
+ // If 'Info' is nonzero, we need to read an DefaultedOrDeletedInfo; if,
+ // additionally, the second bit is also set, we also need to read
+ // a DeletedMessage for the DefaultedOrDeletedInfo.
+ if (auto Info = Record.readInt()) {
+ bool HasMessage = Info & 2;
+ StringLiteral *DeletedMessage =
+ HasMessage ? cast<StringLiteral>(Record.readExpr()) : nullptr;
+
+ unsigned NumLookups = Record.readInt();
+ SmallVector<DeclAccessPair, 8> Lookups;
+ for (unsigned I = 0; I != NumLookups; ++I) {
+ NamedDecl *ND = Record.readDeclAs<NamedDecl>();
+ AccessSpecifier AS = (AccessSpecifier)Record.readInt();
+ Lookups.push_back(DeclAccessPair::make(ND, AS));
+ }
+
+ FD->setDefaultedOrDeletedInfo(
+ FunctionDecl::DefaultedOrDeletedFunctionInfo::Create(
+ Reader.getContext(), Lookups, DeletedMessage));
+ }
+ }
+
+ if (Existing)
+ mergeRedeclarable(FD, Existing, Redecl);
+ else if (auto Kind = FD->getTemplatedKind();
+ Kind == FunctionDecl::TK_FunctionTemplate ||
+ Kind == FunctionDecl::TK_FunctionTemplateSpecialization) {
+ // Function Templates have their FunctionTemplateDecls merged instead of
+ // their FunctionDecls.
+ auto merge = [this, &Redecl, FD](auto &&F) {
+ auto *Existing = cast_or_null<FunctionDecl>(Redecl.getKnownMergeTarget());
+ RedeclarableResult NewRedecl(Existing ? F(Existing) : nullptr,
+ Redecl.getFirstID(), Redecl.isKeyDecl());
+ mergeRedeclarableTemplate(F(FD), NewRedecl);
+ };
+ if (Kind == FunctionDecl::TK_FunctionTemplate)
+ merge(
+ [](FunctionDecl *FD) { return FD->getDescribedFunctionTemplate(); });
+ else
+ merge([](FunctionDecl *FD) {
+ return FD->getTemplateSpecializationInfo()->getTemplate();
+ });
+ } else
+ mergeRedeclarable(FD, Redecl);
+
// Defer calling `setPure` until merging above has guaranteed we've set
// `DefinitionData` (as this will need to access it).
- FD->setPure(Pure);
+ FD->setIsPureVirtual(Pure);
// Read in the parameters.
unsigned NumParams = Record.readInt();
@@ -1037,7 +1157,6 @@ void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
// Load the body on-demand. Most clients won't care, because method
// definitions rarely show up in headers.
Reader.PendingBodies[MD] = GetCurrentCursorOffset();
- HasPendingBody = true;
}
MD->setSelfDecl(readDeclAs<ImplicitParamDecl>());
MD->setCmdDecl(readDeclAs<ImplicitParamDecl>());
@@ -1055,7 +1174,8 @@ void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
Reader.getContext().setObjCMethodRedeclaration(MD,
readDeclAs<ObjCMethodDecl>());
- MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record.readInt());
+ MD->setDeclImplementation(
+ static_cast<ObjCImplementationControl>(Record.readInt()));
MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record.readInt());
MD->setRelatedResultType(Record.readInt());
MD->setReturnType(Record.readType());
@@ -1121,6 +1241,8 @@ void ASTDeclReader::ReadObjCDefinitionData(
Data.EndLoc = readSourceLocation();
Data.HasDesignatedInitializers = Record.readInt();
+ Data.ODRHash = Record.readInt();
+ Data.HasODRHash = true;
// Read the directly referenced protocols and their SourceLocations.
unsigned NumProtocols = Record.readInt();
@@ -1147,7 +1269,17 @@ void ASTDeclReader::ReadObjCDefinitionData(
void ASTDeclReader::MergeDefinitionData(ObjCInterfaceDecl *D,
struct ObjCInterfaceDecl::DefinitionData &&NewDD) {
- // FIXME: odr checking?
+ struct ObjCInterfaceDecl::DefinitionData &DD = D->data();
+ if (DD.Definition == NewDD.Definition)
+ return;
+
+ Reader.MergedDeclContexts.insert(
+ std::make_pair(NewDD.Definition, DD.Definition));
+ Reader.mergeDefinitionVisibility(DD.Definition, NewDD.Definition);
+
+ if (D->getODRHash() != NewDD.ODRHash)
+ Reader.PendingObjCInterfaceOdrMergeFailures[DD.Definition].push_back(
+ {NewDD.Definition, &NewDD});
}
void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
@@ -1194,6 +1326,39 @@ void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) {
IVD->setNextIvar(nullptr);
bool synth = Record.readInt();
IVD->setSynthesize(synth);
+
+ // Check ivar redeclaration.
+ if (IVD->isInvalidDecl())
+ return;
+ // Don't check ObjCInterfaceDecl as interfaces are named and mismatches can be
+ // detected in VisitObjCInterfaceDecl. Here we are looking for redeclarations
+ // in extensions.
+ if (isa<ObjCInterfaceDecl>(IVD->getDeclContext()))
+ return;
+ ObjCInterfaceDecl *CanonIntf =
+ IVD->getContainingInterface()->getCanonicalDecl();
+ IdentifierInfo *II = IVD->getIdentifier();
+ ObjCIvarDecl *PrevIvar = CanonIntf->lookupInstanceVariable(II);
+ if (PrevIvar && PrevIvar != IVD) {
+ auto *ParentExt = dyn_cast<ObjCCategoryDecl>(IVD->getDeclContext());
+ auto *PrevParentExt =
+ dyn_cast<ObjCCategoryDecl>(PrevIvar->getDeclContext());
+ if (ParentExt && PrevParentExt) {
+ // Postpone diagnostic as we should merge identical extensions from
+ // different modules.
+ Reader
+ .PendingObjCExtensionIvarRedeclarations[std::make_pair(ParentExt,
+ PrevParentExt)]
+ .push_back(std::make_pair(IVD, PrevIvar));
+ } else if (ParentExt || PrevParentExt) {
+ // Duplicate ivars in extension + implementation are never compatible.
+ // Compatibility of implementation + implementation should be handled in
+ // VisitObjCImplementationDecl.
+ Reader.Diag(IVD->getLocation(), diag::err_duplicate_ivar_declaration)
+ << II;
+ Reader.Diag(PrevIvar->getLocation(), diag::note_previous_definition);
+ }
+ }
}
void ASTDeclReader::ReadObjCDefinitionData(
@@ -1209,11 +1374,23 @@ void ASTDeclReader::ReadObjCDefinitionData(
ProtoLocs.push_back(readSourceLocation());
Data.ReferencedProtocols.set(ProtoRefs.data(), NumProtoRefs,
ProtoLocs.data(), Reader.getContext());
+ Data.ODRHash = Record.readInt();
+ Data.HasODRHash = true;
}
-void ASTDeclReader::MergeDefinitionData(ObjCProtocolDecl *D,
- struct ObjCProtocolDecl::DefinitionData &&NewDD) {
- // FIXME: odr checking?
+void ASTDeclReader::MergeDefinitionData(
+ ObjCProtocolDecl *D, struct ObjCProtocolDecl::DefinitionData &&NewDD) {
+ struct ObjCProtocolDecl::DefinitionData &DD = D->data();
+ if (DD.Definition == NewDD.Definition)
+ return;
+
+ Reader.MergedDeclContexts.insert(
+ std::make_pair(NewDD.Definition, DD.Definition));
+ Reader.mergeDefinitionVisibility(DD.Definition, NewDD.Definition);
+
+ if (D->getODRHash() != NewDD.ODRHash)
+ Reader.PendingObjCProtocolOdrMergeFailures[DD.Definition].push_back(
+ {NewDD.Definition, &NewDD});
}
void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
@@ -1348,15 +1525,13 @@ void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) {
VisitDeclaratorDecl(FD);
FD->Mutable = Record.readInt();
- if (auto ISK = static_cast<FieldDecl::InitStorageKind>(Record.readInt())) {
- FD->InitStorage.setInt(ISK);
- FD->InitStorage.setPointer(ISK == FieldDecl::ISK_CapturedVLAType
- ? Record.readType().getAsOpaquePtr()
- : Record.readExpr());
- }
-
- if (auto *BW = Record.readExpr())
- FD->setBitWidth(BW);
+ unsigned Bits = Record.readInt();
+ FD->StorageKind = Bits >> 1;
+ if (FD->StorageKind == FieldDecl::ISK_CapturedVLAType)
+ FD->CapturedVLAType =
+ cast<VariableArrayType>(Record.readType().getTypePtr());
+ else if (Bits & 1)
+ FD->setBitWidth(Record.readExpr());
if (!FD->getDeclName()) {
if (auto *Tmpl = readDeclAs<FieldDecl>())
@@ -1384,6 +1559,17 @@ void ASTDeclReader::VisitMSGuidDecl(MSGuidDecl *D) {
Reader.getContext().setPrimaryMergedDecl(D, Existing->getCanonicalDecl());
}
+void ASTDeclReader::VisitUnnamedGlobalConstantDecl(
+ UnnamedGlobalConstantDecl *D) {
+ VisitValueDecl(D);
+ D->Value = Record.readAPValue();
+
+ // Add this to the AST context's lookup structure, and merge if needed.
+ if (UnnamedGlobalConstantDecl *Existing =
+ Reader.getContext().UnnamedGlobalConstantDecls.GetOrInsertNode(D))
+ Reader.getContext().setPrimaryMergedDecl(D, Existing->getCanonicalDecl());
+}
+
void ASTDeclReader::VisitTemplateParamObjectDecl(TemplateParamObjectDecl *D) {
VisitValueDecl(D);
D->Value = Record.readAPValue();
@@ -1412,54 +1598,64 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
RedeclarableResult Redecl = VisitRedeclarable(VD);
VisitDeclaratorDecl(VD);
- VD->VarDeclBits.SClass = (StorageClass)Record.readInt();
- VD->VarDeclBits.TSCSpec = Record.readInt();
- VD->VarDeclBits.InitStyle = Record.readInt();
- VD->VarDeclBits.ARCPseudoStrong = Record.readInt();
+ BitsUnpacker VarDeclBits(Record.readInt());
+ auto VarLinkage = Linkage(VarDeclBits.getNextBits(/*Width=*/3));
+ bool DefGeneratedInModule = VarDeclBits.getNextBit();
+ VD->VarDeclBits.SClass = (StorageClass)VarDeclBits.getNextBits(/*Width=*/3);
+ VD->VarDeclBits.TSCSpec = VarDeclBits.getNextBits(/*Width=*/2);
+ VD->VarDeclBits.InitStyle = VarDeclBits.getNextBits(/*Width=*/2);
+ VD->VarDeclBits.ARCPseudoStrong = VarDeclBits.getNextBit();
+ bool HasDeducedType = false;
if (!isa<ParmVarDecl>(VD)) {
VD->NonParmVarDeclBits.IsThisDeclarationADemotedDefinition =
- Record.readInt();
- VD->NonParmVarDeclBits.ExceptionVar = Record.readInt();
- VD->NonParmVarDeclBits.NRVOVariable = Record.readInt();
- VD->NonParmVarDeclBits.CXXForRangeDecl = Record.readInt();
- VD->NonParmVarDeclBits.ObjCForDecl = Record.readInt();
- VD->NonParmVarDeclBits.IsInline = Record.readInt();
- VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt();
- VD->NonParmVarDeclBits.IsConstexpr = Record.readInt();
- VD->NonParmVarDeclBits.IsInitCapture = Record.readInt();
- VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = Record.readInt();
- VD->NonParmVarDeclBits.ImplicitParamKind = Record.readInt();
- VD->NonParmVarDeclBits.EscapingByref = Record.readInt();
- }
- auto VarLinkage = Linkage(Record.readInt());
+ VarDeclBits.getNextBit();
+ VD->NonParmVarDeclBits.ExceptionVar = VarDeclBits.getNextBit();
+ VD->NonParmVarDeclBits.NRVOVariable = VarDeclBits.getNextBit();
+ VD->NonParmVarDeclBits.CXXForRangeDecl = VarDeclBits.getNextBit();
+
+ VD->NonParmVarDeclBits.IsInline = VarDeclBits.getNextBit();
+ VD->NonParmVarDeclBits.IsInlineSpecified = VarDeclBits.getNextBit();
+ VD->NonParmVarDeclBits.IsConstexpr = VarDeclBits.getNextBit();
+ VD->NonParmVarDeclBits.IsInitCapture = VarDeclBits.getNextBit();
+ VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope =
+ VarDeclBits.getNextBit();
+
+ VD->NonParmVarDeclBits.EscapingByref = VarDeclBits.getNextBit();
+ HasDeducedType = VarDeclBits.getNextBit();
+ VD->NonParmVarDeclBits.ImplicitParamKind =
+ VarDeclBits.getNextBits(/*Width*/ 3);
+
+ VD->NonParmVarDeclBits.ObjCForDecl = VarDeclBits.getNextBit();
+ }
+
+ // If this variable has a deduced type, defer reading that type until we are
+ // done deserializing this variable, because the type might refer back to the
+ // variable.
+ if (HasDeducedType)
+ Reader.PendingDeducedVarTypes.push_back({VD, DeferredTypeID});
+ else
+ VD->setType(Reader.GetType(DeferredTypeID));
+ DeferredTypeID = 0;
+
VD->setCachedLinkage(VarLinkage);
// Reconstruct the one piece of the IdentifierNamespace that we need.
- if (VD->getStorageClass() == SC_Extern && VarLinkage != NoLinkage &&
+ if (VD->getStorageClass() == SC_Extern && VarLinkage != Linkage::None &&
VD->getLexicalDeclContext()->isFunctionOrMethod())
VD->setLocalExternDecl();
- if (uint64_t Val = Record.readInt()) {
- VD->setInit(Record.readExpr());
- if (Val != 1) {
- EvaluatedStmt *Eval = VD->ensureEvaluatedStmt();
- Eval->HasConstantInitialization = (Val & 2) != 0;
- Eval->HasConstantDestruction = (Val & 4) != 0;
- }
+ if (DefGeneratedInModule) {
+ Reader.DefinitionSource[VD] =
+ Loc.F->Kind == ModuleKind::MK_MainFile ||
+ Reader.getContext().getLangOpts().BuildingPCHWithObjectFile;
}
- if (VD->hasAttr<BlocksAttr>() && VD->getType()->getAsCXXRecordDecl()) {
+ if (VD->hasAttr<BlocksAttr>()) {
Expr *CopyExpr = Record.readExpr();
if (CopyExpr)
Reader.getContext().setBlockVarCopyInit(VD, CopyExpr, Record.readInt());
}
- if (VD->getStorageDuration() == SD_Static && Record.readInt()) {
- Reader.DefinitionSource[VD] =
- Loc.F->Kind == ModuleKind::MK_MainFile ||
- Reader.getContext().getLangOpts().BuildingPCHWithObjectFile;
- }
-
enum VarKind {
VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization
};
@@ -1488,16 +1684,37 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
return Redecl;
}
+void ASTDeclReader::ReadVarDeclInit(VarDecl *VD) {
+ if (uint64_t Val = Record.readInt()) {
+ EvaluatedStmt *Eval = VD->ensureEvaluatedStmt();
+ Eval->HasConstantInitialization = (Val & 2) != 0;
+ Eval->HasConstantDestruction = (Val & 4) != 0;
+ Eval->WasEvaluated = (Val & 8) != 0;
+ if (Eval->WasEvaluated) {
+ Eval->Evaluated = Record.readAPValue();
+ if (Eval->Evaluated.needsCleanup())
+ Reader.getContext().addDestruction(&Eval->Evaluated);
+ }
+
+ // Store the offset of the initializer. Don't deserialize it yet: it might
+ // not be needed, and might refer back to the variable, for example if it
+ // contains a lambda.
+ Eval->Value = GetCurrentCursorOffset();
+ }
+}
+
void ASTDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) {
VisitVarDecl(PD);
}
void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
VisitVarDecl(PD);
- unsigned isObjCMethodParam = Record.readInt();
- unsigned scopeDepth = Record.readInt();
+
unsigned scopeIndex = Record.readInt();
- unsigned declQualifier = Record.readInt();
+ BitsUnpacker ParmVarDeclBits(Record.readInt());
+ unsigned isObjCMethodParam = ParmVarDeclBits.getNextBit();
+ unsigned scopeDepth = ParmVarDeclBits.getNextBits(/*Width=*/7);
+ unsigned declQualifier = ParmVarDeclBits.getNextBits(/*Width=*/7);
if (isObjCMethodParam) {
assert(scopeDepth == 0);
PD->setObjCMethodScopeInfo(scopeIndex);
@@ -1505,11 +1722,15 @@ void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
} else {
PD->setScopeInfo(scopeDepth, scopeIndex);
}
- PD->ParmVarDeclBits.IsKNRPromoted = Record.readInt();
- PD->ParmVarDeclBits.HasInheritedDefaultArg = Record.readInt();
- if (Record.readInt()) // hasUninstantiatedDefaultArg.
+ PD->ParmVarDeclBits.IsKNRPromoted = ParmVarDeclBits.getNextBit();
+
+ PD->ParmVarDeclBits.HasInheritedDefaultArg = ParmVarDeclBits.getNextBit();
+ if (ParmVarDeclBits.getNextBit()) // hasUninstantiatedDefaultArg.
PD->setUninstantiatedDefaultArg(Record.readExpr());
+ if (ParmVarDeclBits.getNextBit()) // Valid explicit object parameter
+ PD->ExplicitObjectParameterIntroducerLoc = Record.readSourceLocation();
+
// FIXME: If this is a redeclaration of a function from another module, handle
// inheritance of default arguments.
}
@@ -1534,6 +1755,11 @@ void ASTDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {
AD->setRParenLoc(readSourceLocation());
}
+void ASTDeclReader::VisitTopLevelStmtDecl(TopLevelStmtDecl *D) {
+ VisitDecl(D);
+ D->Statement = Record.readStmt();
+}
+
void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) {
VisitDecl(BD);
BD->setBody(cast_or_null<CompoundStmt>(Record.readStmt()));
@@ -1582,7 +1808,7 @@ void ASTDeclReader::VisitCapturedDecl(CapturedDecl *CD) {
void ASTDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
VisitDecl(D);
- D->setLanguage((LinkageSpecDecl::LanguageIDs)Record.readInt());
+ D->setLanguage(static_cast<LinkageSpecLanguageIDs>(Record.readInt()));
D->setExternLoc(readSourceLocation());
D->setRBraceLoc(readSourceLocation());
}
@@ -1600,7 +1826,10 @@ void ASTDeclReader::VisitLabelDecl(LabelDecl *D) {
void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
RedeclarableResult Redecl = VisitRedeclarable(D);
VisitNamedDecl(D);
- D->setInline(Record.readInt());
+
+ BitsUnpacker NamespaceDeclBits(Record.readInt());
+ D->setInline(NamespaceDeclBits.getNextBit());
+ D->setNested(NamespaceDeclBits.getNextBit());
D->LocStart = readSourceLocation();
D->RBraceLoc = readSourceLocation();
@@ -1608,18 +1837,13 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
// this namespace; loading it might load a later declaration of the
// same namespace, and we have an invariant that older declarations
// get merged before newer ones try to merge.
- GlobalDeclID AnonNamespace = 0;
- if (Redecl.getFirstID() == ThisDeclID) {
+ GlobalDeclID AnonNamespace;
+ if (Redecl.getFirstID() == ThisDeclID)
AnonNamespace = readDeclID();
- } else {
- // Link this namespace back to the first declaration, which has already
- // been deserialized.
- D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDecl());
- }
mergeRedeclarable(D, Redecl);
- if (AnonNamespace) {
+ if (AnonNamespace.isValid()) {
// Each module has its own anonymous namespace, which is disjoint from
// any other module's anonymous namespaces, so don't attach the anonymous
// namespace at all.
@@ -1629,6 +1853,15 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
}
}
+void ASTDeclReader::VisitHLSLBufferDecl(HLSLBufferDecl *D) {
+ VisitNamedDecl(D);
+ VisitDeclContext(D);
+ D->IsCBuffer = Record.readBool();
+ D->KwLoc = readSourceLocation();
+ D->LBraceLoc = readSourceLocation();
+ D->RBraceLoc = readSourceLocation();
+}
+
void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
RedeclarableResult Redecl = VisitRedeclarable(D);
VisitNamedDecl(D);
@@ -1651,6 +1884,17 @@ void ASTDeclReader::VisitUsingDecl(UsingDecl *D) {
mergeMergeable(D);
}
+void ASTDeclReader::VisitUsingEnumDecl(UsingEnumDecl *D) {
+ VisitNamedDecl(D);
+ D->setUsingLoc(readSourceLocation());
+ D->setEnumLoc(readSourceLocation());
+ D->setEnumType(Record.readTypeSourceInfo());
+ D->FirstUsingShadow.setPointer(readDeclAs<UsingShadowDecl>());
+ if (auto *Pattern = readDeclAs<UsingEnumDecl>())
+ Reader.getContext().setInstantiatedFromUsingEnumDecl(D, Pattern);
+ mergeMergeable(D);
+}
+
void ASTDeclReader::VisitUsingPackDecl(UsingPackDecl *D) {
VisitNamedDecl(D);
D->InstantiatedFrom = readDeclAs<NamedDecl>();
@@ -1707,68 +1951,99 @@ void ASTDeclReader::VisitUnresolvedUsingTypenameDecl(
mergeMergeable(D);
}
+void ASTDeclReader::VisitUnresolvedUsingIfExistsDecl(
+ UnresolvedUsingIfExistsDecl *D) {
+ VisitNamedDecl(D);
+}
+
void ASTDeclReader::ReadCXXDefinitionData(
- struct CXXRecordDecl::DefinitionData &Data, const CXXRecordDecl *D) {
- #define FIELD(Name, Width, Merge) \
- Data.Name = Record.readInt();
- #include "clang/AST/CXXRecordDeclDefinitionBits.def"
+ struct CXXRecordDecl::DefinitionData &Data, const CXXRecordDecl *D,
+ Decl *LambdaContext, unsigned IndexInLambdaContext) {
+
+ BitsUnpacker CXXRecordDeclBits = Record.readInt();
+
+#define FIELD(Name, Width, Merge) \
+ if (!CXXRecordDeclBits.canGetNextNBits(Width)) \
+ CXXRecordDeclBits.updateValue(Record.readInt()); \
+ Data.Name = CXXRecordDeclBits.getNextBits(Width);
+
+#include "clang/AST/CXXRecordDeclDefinitionBits.def"
+#undef FIELD
// Note: the caller has deserialized the IsLambda bit already.
Data.ODRHash = Record.readInt();
Data.HasODRHash = true;
if (Record.readInt()) {
- Reader.DefinitionSource[D] =
+ Reader.DefinitionSource[D] =
Loc.F->Kind == ModuleKind::MK_MainFile ||
Reader.getContext().getLangOpts().BuildingPCHWithObjectFile;
}
- Data.NumBases = Record.readInt();
- if (Data.NumBases)
- Data.Bases = ReadGlobalOffset();
- Data.NumVBases = Record.readInt();
- if (Data.NumVBases)
- Data.VBases = ReadGlobalOffset();
-
Record.readUnresolvedSet(Data.Conversions);
Data.ComputedVisibleConversions = Record.readInt();
if (Data.ComputedVisibleConversions)
Record.readUnresolvedSet(Data.VisibleConversions);
assert(Data.Definition && "Data.Definition should be already set!");
- Data.FirstFriend = readDeclID();
- if (Data.IsLambda) {
+ if (!Data.IsLambda) {
+ assert(!LambdaContext && !IndexInLambdaContext &&
+ "given lambda context for non-lambda");
+
+ Data.NumBases = Record.readInt();
+ if (Data.NumBases)
+ Data.Bases = ReadGlobalOffset();
+
+ Data.NumVBases = Record.readInt();
+ if (Data.NumVBases)
+ Data.VBases = ReadGlobalOffset();
+
+ Data.FirstFriend = readDeclID().getRawValue();
+ } else {
using Capture = LambdaCapture;
auto &Lambda = static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data);
- Lambda.Dependent = Record.readInt();
- Lambda.IsGenericLambda = Record.readInt();
- Lambda.CaptureDefault = Record.readInt();
- Lambda.NumCaptures = Record.readInt();
+
+ BitsUnpacker LambdaBits(Record.readInt());
+ Lambda.DependencyKind = LambdaBits.getNextBits(/*Width=*/2);
+ Lambda.IsGenericLambda = LambdaBits.getNextBit();
+ Lambda.CaptureDefault = LambdaBits.getNextBits(/*Width=*/2);
+ Lambda.NumCaptures = LambdaBits.getNextBits(/*Width=*/15);
+ Lambda.HasKnownInternalLinkage = LambdaBits.getNextBit();
+
Lambda.NumExplicitCaptures = Record.readInt();
- Lambda.HasKnownInternalLinkage = Record.readInt();
Lambda.ManglingNumber = Record.readInt();
- D->setDeviceLambdaManglingNumber(Record.readInt());
- Lambda.ContextDecl = readDeclID();
- Lambda.Captures = (Capture *)Reader.getContext().Allocate(
- sizeof(Capture) * Lambda.NumCaptures);
- Capture *ToCapture = Lambda.Captures;
+ if (unsigned DeviceManglingNumber = Record.readInt())
+ Reader.getContext().DeviceLambdaManglingNumbers[D] = DeviceManglingNumber;
+ Lambda.IndexInContext = IndexInLambdaContext;
+ Lambda.ContextDecl = LambdaContext;
+ Capture *ToCapture = nullptr;
+ if (Lambda.NumCaptures) {
+ ToCapture = (Capture *)Reader.getContext().Allocate(sizeof(Capture) *
+ Lambda.NumCaptures);
+ Lambda.AddCaptureList(Reader.getContext(), ToCapture);
+ }
Lambda.MethodTyInfo = readTypeSourceInfo();
for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
SourceLocation Loc = readSourceLocation();
- bool IsImplicit = Record.readInt();
- auto Kind = static_cast<LambdaCaptureKind>(Record.readInt());
+ BitsUnpacker CaptureBits(Record.readInt());
+ bool IsImplicit = CaptureBits.getNextBit();
+ auto Kind =
+ static_cast<LambdaCaptureKind>(CaptureBits.getNextBits(/*Width=*/3));
switch (Kind) {
case LCK_StarThis:
case LCK_This:
case LCK_VLAType:
- *ToCapture++ = Capture(Loc, IsImplicit, Kind, nullptr,SourceLocation());
+ new (ToCapture)
+ Capture(Loc, IsImplicit, Kind, nullptr, SourceLocation());
+ ToCapture++;
break;
case LCK_ByCopy:
case LCK_ByRef:
- auto *Var = readDeclAs<VarDecl>();
+ auto *Var = readDeclAs<ValueDecl>();
SourceLocation EllipsisLoc = readSourceLocation();
- *ToCapture++ = Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc);
+ new (ToCapture) Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc);
+ ToCapture++;
break;
}
}
@@ -1788,7 +2063,7 @@ void ASTDeclReader::MergeDefinitionData(
Reader.PendingDefinitions.erase(MergeDD.Definition);
MergeDD.Definition->setCompleteDefinition(false);
Reader.mergeDefinitionVisibility(DD.Definition, MergeDD.Definition);
- assert(Reader.Lookups.find(MergeDD.Definition) == Reader.Lookups.end() &&
+ assert(!Reader.Lookups.contains(MergeDD.Definition) &&
"already loaded pending lookups for merged definition");
}
@@ -1836,10 +2111,32 @@ void ASTDeclReader::MergeDefinitionData(
// lazily load it.
if (DD.IsLambda) {
- // FIXME: ODR-checking for merging lambdas (this happens, for instance,
- // when they occur within the body of a function template specialization).
+ auto &Lambda1 = static_cast<CXXRecordDecl::LambdaDefinitionData &>(DD);
+ auto &Lambda2 = static_cast<CXXRecordDecl::LambdaDefinitionData &>(MergeDD);
+ DetectedOdrViolation |= Lambda1.DependencyKind != Lambda2.DependencyKind;
+ DetectedOdrViolation |= Lambda1.IsGenericLambda != Lambda2.IsGenericLambda;
+ DetectedOdrViolation |= Lambda1.CaptureDefault != Lambda2.CaptureDefault;
+ DetectedOdrViolation |= Lambda1.NumCaptures != Lambda2.NumCaptures;
+ DetectedOdrViolation |=
+ Lambda1.NumExplicitCaptures != Lambda2.NumExplicitCaptures;
+ DetectedOdrViolation |=
+ Lambda1.HasKnownInternalLinkage != Lambda2.HasKnownInternalLinkage;
+ DetectedOdrViolation |= Lambda1.ManglingNumber != Lambda2.ManglingNumber;
+
+ if (Lambda1.NumCaptures && Lambda1.NumCaptures == Lambda2.NumCaptures) {
+ for (unsigned I = 0, N = Lambda1.NumCaptures; I != N; ++I) {
+ LambdaCapture &Cap1 = Lambda1.Captures.front()[I];
+ LambdaCapture &Cap2 = Lambda2.Captures.front()[I];
+ DetectedOdrViolation |= Cap1.getCaptureKind() != Cap2.getCaptureKind();
+ }
+ Lambda1.AddCaptureList(Reader.getContext(), Lambda2.Captures.front());
+ }
}
+ // We don't want to check ODR for decls in the global module fragment.
+ if (shouldSkipCheckingODR(MergeDD.Definition) || shouldSkipCheckingODR(D))
+ return;
+
if (D->getODRHash() != MergeDD.ODRHash) {
DetectedOdrViolation = true;
}
@@ -1849,16 +2146,20 @@ void ASTDeclReader::MergeDefinitionData(
{MergeDD.Definition, &MergeDD});
}
-void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) {
+void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update,
+ Decl *LambdaContext,
+ unsigned IndexInLambdaContext) {
struct CXXRecordDecl::DefinitionData *DD;
ASTContext &C = Reader.getContext();
// Determine whether this is a lambda closure type, so that we can
// allocate the appropriate DefinitionData structure.
bool IsLambda = Record.readInt();
+ assert(!(IsLambda && Update) &&
+ "lambda definition should not be added by update record");
if (IsLambda)
- DD = new (C) CXXRecordDecl::LambdaDefinitionData(D, nullptr, false, false,
- LCD_None);
+ DD = new (C) CXXRecordDecl::LambdaDefinitionData(
+ D, nullptr, CXXRecordDecl::LDK_Unknown, false, LCD_None);
else
DD = new (C) struct CXXRecordDecl::DefinitionData(D);
@@ -1869,7 +2170,7 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) {
if (!Canon->DefinitionData)
Canon->DefinitionData = DD;
D->DefinitionData = Canon->DefinitionData;
- ReadCXXDefinitionData(*DD, D);
+ ReadCXXDefinitionData(*DD, D, LambdaContext, IndexInLambdaContext);
// We might already have a different definition for this record. This can
// happen either because we're reading an update record, or because we've
@@ -1896,8 +2197,15 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
ASTContext &C = Reader.getContext();
enum CXXRecKind {
- CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization
+ CXXRecNotTemplate = 0,
+ CXXRecTemplate,
+ CXXRecMemberSpecialization,
+ CXXLambda
};
+
+ Decl *LambdaContext = nullptr;
+ unsigned IndexInLambdaContext = 0;
+
switch ((CXXRecKind)Record.readInt()) {
case CXXRecNotTemplate:
// Merged when we merge the folding set entry in the primary template.
@@ -1929,11 +2237,19 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
mergeRedeclarable(D, Redecl);
break;
}
+ case CXXLambda: {
+ LambdaContext = readDecl();
+ if (LambdaContext)
+ IndexInLambdaContext = Record.readInt();
+ mergeLambda(D, Redecl, LambdaContext, IndexInLambdaContext);
+ break;
+ }
}
bool WasDefinition = Record.readInt();
if (WasDefinition)
- ReadCXXRecordDefinition(D, /*Update*/false);
+ ReadCXXRecordDefinition(D, /*Update=*/false, LambdaContext,
+ IndexInLambdaContext);
else
// Propagate DefinitionData pointer from the canonical declaration.
D->DefinitionData = D->getCanonicalDecl()->DefinitionData;
@@ -1941,12 +2257,12 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
// Lazily load the key function to avoid deserializing every method so we can
// compute it.
if (WasDefinition) {
- DeclID KeyFn = readDeclID();
- if (KeyFn && D->isCompleteDefinition())
+ GlobalDeclID KeyFn = readDeclID();
+ if (KeyFn.isValid() && D->isCompleteDefinition())
// FIXME: This is wrong for the ARM ABI, where some other module may have
// made this function no longer be a key function. We need an update
// record or similar for that case.
- C.KeyFunctions[D] = KeyFn;
+ C.KeyFunctions[D] = KeyFn.getRawValue();
}
return Redecl;
@@ -1954,8 +2270,10 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
void ASTDeclReader::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
D->setExplicitSpecifier(Record.readExplicitSpec());
+ D->Ctor = readDeclAs<CXXConstructorDecl>();
VisitFunctionDecl(D);
- D->setIsCopyDeductionCandidate(Record.readInt());
+ D->setDeductionCandidateKind(
+ static_cast<DeductionCandidate>(Record.readInt()));
}
void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
@@ -2033,7 +2351,7 @@ void ASTDeclReader::VisitFriendDecl(FriendDecl *D) {
for (unsigned i = 0; i != D->NumTPLists; ++i)
D->getTrailingObjects<TemplateParameterList *>()[i] =
Record.readTemplateParameterList();
- D->NextFriend = readDeclID();
+ D->NextFriend = readDeclID().getRawValue();
D->UnsupportedFriend = (Record.readInt() != 0);
D->FriendLoc = readSourceLocation();
}
@@ -2042,7 +2360,7 @@ void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
VisitDecl(D);
unsigned NumParams = Record.readInt();
D->NumParams = NumParams;
- D->Params = new TemplateParameterList*[NumParams];
+ D->Params = new (Reader.getContext()) TemplateParameterList *[NumParams];
for (unsigned i = 0; i != NumParams; ++i)
D->Params[i] = Record.readTemplateParameterList();
if (Record.readInt()) // HasFriendDecl
@@ -2052,15 +2370,12 @@ void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
D->FriendLoc = readSourceLocation();
}
-DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
+void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
VisitNamedDecl(D);
- DeclID PatternID = readDeclID();
- auto *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID));
- TemplateParameterList *TemplateParams = Record.readTemplateParameterList();
- D->init(TemplatedDecl, TemplateParams);
-
- return PatternID;
+ assert(!D->TemplateParams && "TemplateParams already set!");
+ D->TemplateParams = Record.readTemplateParameterList();
+ D->init(readDeclAs<NamedDecl>());
}
void ASTDeclReader::VisitConceptDecl(ConceptDecl *D) {
@@ -2069,6 +2384,17 @@ void ASTDeclReader::VisitConceptDecl(ConceptDecl *D) {
mergeMergeable(D);
}
+void ASTDeclReader::VisitImplicitConceptSpecializationDecl(
+ ImplicitConceptSpecializationDecl *D) {
+ // The size of the template list was read during creation of the Decl, so we
+ // don't have to re-read it here.
+ VisitDecl(D);
+ llvm::SmallVector<TemplateArgument, 4> Args;
+ for (unsigned I = 0; I < D->NumTemplateArgs; ++I)
+ Args.push_back(Record.readTemplateArgument(/*Canonicalize=*/true));
+ D->setTemplateArguments(Args);
+}
+
void ASTDeclReader::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) {
}
@@ -2097,26 +2423,20 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
}
}
- DeclID PatternID = VisitTemplateDecl(D);
+ VisitTemplateDecl(D);
D->IdentifierNamespace = Record.readInt();
- mergeRedeclarable(D, Redecl, PatternID);
-
- // If we merged the template with a prior declaration chain, merge the common
- // pointer.
- // FIXME: Actually merge here, don't just overwrite.
- D->Common = D->getCanonicalDecl()->Common;
-
return Redecl;
}
void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
+ mergeRedeclarableTemplate(D, Redecl);
if (ThisDeclID == Redecl.getFirstID()) {
// This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
// the specializations.
- SmallVector<serialization::DeclID, 32> SpecIDs;
+ SmallVector<GlobalDeclID, 32> SpecIDs;
readDeclIDList(SpecIDs);
ASTDeclReader::AddLazySpecializations(D, SpecIDs);
}
@@ -2139,11 +2459,12 @@ void ASTDeclReader::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) {
/// VarTemplateDecl beyond TemplateDecl...
void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) {
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
+ mergeRedeclarableTemplate(D, Redecl);
if (ThisDeclID == Redecl.getFirstID()) {
// This VarTemplateDecl owns a CommonPtr; read it to keep track of all of
// the specializations.
- SmallVector<serialization::DeclID, 32> SpecIDs;
+ SmallVector<GlobalDeclID, 32> SpecIDs;
readDeclIDList(SpecIDs);
ASTDeclReader::AddLazySpecializations(D, SpecIDs);
}
@@ -2209,16 +2530,17 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
}
}
- // Explicit info.
- if (TypeSourceInfo *TyInfo = readTypeSourceInfo()) {
- auto *ExplicitInfo =
- new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo;
- ExplicitInfo->TypeAsWritten = TyInfo;
- ExplicitInfo->ExternLoc = readSourceLocation();
+ // extern/template keyword locations for explicit instantiations
+ if (Record.readBool()) {
+ auto *ExplicitInfo = new (C) ExplicitInstantiationInfo;
+ ExplicitInfo->ExternKeywordLoc = readSourceLocation();
ExplicitInfo->TemplateKeywordLoc = readSourceLocation();
D->ExplicitInfo = ExplicitInfo;
}
+ if (Record.readBool())
+ D->setTemplateArgsAsWritten(Record.readASTTemplateArgumentListInfo());
+
return Redecl;
}
@@ -2228,7 +2550,6 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
// need them for profiling
TemplateParameterList *Params = Record.readTemplateParameterList();
D->TemplateParams = Params;
- D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D);
@@ -2240,20 +2561,12 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
}
}
-void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl(
- ClassScopeFunctionSpecializationDecl *D) {
- VisitDecl(D);
- D->Specialization = readDeclAs<CXXMethodDecl>();
- if (Record.readInt())
- D->TemplateArgs = Record.readASTTemplateArgumentListInfo();
-}
-
void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
if (ThisDeclID == Redecl.getFirstID()) {
// This FunctionTemplateDecl owns a CommonPtr; read it.
- SmallVector<serialization::DeclID, 32> SpecIDs;
+ SmallVector<GlobalDeclID, 32> SpecIDs;
readDeclIDList(SpecIDs);
ASTDeclReader::AddLazySpecializations(D, SpecIDs);
}
@@ -2267,8 +2580,6 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
VarTemplateSpecializationDecl *D) {
- RedeclarableResult Redecl = VisitVarDeclImpl(D);
-
ASTContext &C = Reader.getContext();
if (Decl *InstD = readDecl()) {
if (auto *VTD = dyn_cast<VarTemplateDecl>(InstD)) {
@@ -2288,16 +2599,17 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
}
}
- // Explicit info.
- if (TypeSourceInfo *TyInfo = readTypeSourceInfo()) {
- auto *ExplicitInfo =
- new (C) VarTemplateSpecializationDecl::ExplicitSpecializationInfo;
- ExplicitInfo->TypeAsWritten = TyInfo;
- ExplicitInfo->ExternLoc = readSourceLocation();
+ // extern/template keyword locations for explicit instantiations
+ if (Record.readBool()) {
+ auto *ExplicitInfo = new (C) ExplicitInstantiationInfo;
+ ExplicitInfo->ExternKeywordLoc = readSourceLocation();
ExplicitInfo->TemplateKeywordLoc = readSourceLocation();
D->ExplicitInfo = ExplicitInfo;
}
+ if (Record.readBool())
+ D->setTemplateArgsAsWritten(Record.readASTTemplateArgumentListInfo());
+
SmallVector<TemplateArgument, 8> TemplArgs;
Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true);
D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs);
@@ -2305,17 +2617,23 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
D->SpecializationKind = (TemplateSpecializationKind)Record.readInt();
D->IsCompleteDefinition = Record.readInt();
+ RedeclarableResult Redecl = VisitVarDeclImpl(D);
+
bool writtenAsCanonicalDecl = Record.readInt();
if (writtenAsCanonicalDecl) {
auto *CanonPattern = readDeclAs<VarTemplateDecl>();
if (D->isCanonicalDecl()) { // It's kept in the folding set.
- // FIXME: If it's already present, merge it.
+ VarTemplateSpecializationDecl *CanonSpec;
if (auto *Partial = dyn_cast<VarTemplatePartialSpecializationDecl>(D)) {
- CanonPattern->getCommonPtr()->PartialSpecializations
- .GetOrInsertNode(Partial);
+ CanonSpec = CanonPattern->getCommonPtr()
+ ->PartialSpecializations.GetOrInsertNode(Partial);
} else {
- CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D);
+ CanonSpec =
+ CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D);
}
+ // If we already have a matching specialization, merge it.
+ if (CanonSpec != D)
+ mergeRedeclarable<VarDecl>(D, CanonSpec, Redecl);
}
}
@@ -2331,7 +2649,6 @@ void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl(
VarTemplatePartialSpecializationDecl *D) {
TemplateParameterList *Params = Record.readTemplateParameterList();
D->TemplateParams = Params;
- D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D);
@@ -2348,22 +2665,21 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
D->setDeclaredWithTypename(Record.readInt());
- if (Record.readBool()) {
- NestedNameSpecifierLoc NNS = Record.readNestedNameSpecifierLoc();
- DeclarationNameInfo DN = Record.readDeclarationNameInfo();
- ConceptDecl *NamedConcept = Record.readDeclAs<ConceptDecl>();
- const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
+ const bool TypeConstraintInitialized = Record.readBool();
+ if (TypeConstraintInitialized && D->hasTypeConstraint()) {
+ ConceptReference *CR = nullptr;
if (Record.readBool())
- ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
+ CR = Record.readConceptReference();
Expr *ImmediatelyDeclaredConstraint = Record.readExpr();
- D->setTypeConstraint(NNS, DN, /*FoundDecl=*/nullptr, NamedConcept,
- ArgsAsWritten, ImmediatelyDeclaredConstraint);
+
+ D->setTypeConstraint(CR, ImmediatelyDeclaredConstraint);
if ((D->ExpandedParameterPack = Record.readInt()))
D->NumExpanded = Record.readInt();
}
if (Record.readInt())
- D->setDefaultArgument(readTypeSourceInfo());
+ D->setDefaultArgument(Reader.getContext(),
+ Record.readTemplateArgumentLoc());
}
void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
@@ -2384,12 +2700,14 @@ void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
// Rest of NonTypeTemplateParmDecl.
D->ParameterPack = Record.readInt();
if (Record.readInt())
- D->setDefaultArgument(Record.readExpr());
+ D->setDefaultArgument(Reader.getContext(),
+ Record.readTemplateArgumentLoc());
}
}
void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
VisitTemplateDecl(D);
+ D->setDeclaredWithTypename(Record.readBool());
// TemplateParmPosition.
D->setDepth(Record.readInt());
D->setPosition(Record.readInt());
@@ -2408,7 +2726,8 @@ void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
}
void ASTDeclReader::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
- VisitRedeclarableTemplateDecl(D);
+ RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
+ mergeRedeclarableTemplate(D, Redecl);
}
void ASTDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) {
@@ -2446,7 +2765,7 @@ ASTDeclReader::VisitDeclContext(DeclContext *DC) {
template <typename T>
ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
- DeclID FirstDeclID = readDeclID();
+ GlobalDeclID FirstDeclID = readDeclID();
Decl *MergeWith = nullptr;
bool IsKeyDecl = ThisDeclID == FirstDeclID;
@@ -2454,9 +2773,9 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
uint64_t RedeclOffset = 0;
- // 0 indicates that this declaration was the only declaration of its entity,
- // and is used for space optimization.
- if (FirstDeclID == 0) {
+ // invalid FirstDeclID indicates that this declaration was the only
+ // declaration of its entity, and is used for space optimization.
+ if (FirstDeclID.isInvalid()) {
FirstDeclID = ThisDeclID;
IsKeyDecl = true;
IsFirstLocalDecl = true;
@@ -2505,10 +2824,9 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
/// Attempts to merge the given declaration (D) with another declaration
/// of the same entity.
-template<typename T>
+template <typename T>
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase,
- RedeclarableResult &Redecl,
- DeclID TemplatePatternID) {
+ RedeclarableResult &Redecl) {
// If modules are not available, there is no reason to perform this merge.
if (!Reader.getContext().getLangOpts().Modules)
return;
@@ -2521,10 +2839,54 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase,
if (auto *Existing = Redecl.getKnownMergeTarget())
// We already know of an existing declaration we should merge with.
- mergeRedeclarable(D, cast<T>(Existing), Redecl, TemplatePatternID);
+ mergeRedeclarable(D, cast<T>(Existing), Redecl);
else if (FindExistingResult ExistingRes = findExisting(D))
if (T *Existing = ExistingRes)
- mergeRedeclarable(D, Existing, Redecl, TemplatePatternID);
+ mergeRedeclarable(D, Existing, Redecl);
+}
+
+/// Attempt to merge D with a previous declaration of the same lambda, which is
+/// found by its index within its context declaration, if it has one.
+///
+/// We can't look up lambdas in their enclosing lexical or semantic context in
+/// general, because for lambdas in variables, both of those might be a
+/// namespace or the translation unit.
+void ASTDeclReader::mergeLambda(CXXRecordDecl *D, RedeclarableResult &Redecl,
+ Decl *Context, unsigned IndexInContext) {
+ // If we don't have a mangling context, treat this like any other
+ // declaration.
+ if (!Context)
+ return mergeRedeclarable(D, Redecl);
+
+ // If modules are not available, there is no reason to perform this merge.
+ if (!Reader.getContext().getLangOpts().Modules)
+ return;
+
+ // If we're not the canonical declaration, we don't need to merge.
+ if (!D->isFirstDecl())
+ return;
+
+ if (auto *Existing = Redecl.getKnownMergeTarget())
+ // We already know of an existing declaration we should merge with.
+ mergeRedeclarable(D, cast<TagDecl>(Existing), Redecl);
+
+ // Look up this lambda to see if we've seen it before. If so, merge with the
+ // one we already loaded.
+ NamedDecl *&Slot = Reader.LambdaDeclarationsForMerging[{
+ Context->getCanonicalDecl(), IndexInContext}];
+ if (Slot)
+ mergeRedeclarable(D, cast<TagDecl>(Slot), Redecl);
+ else
+ Slot = D;
+}
+
+void ASTDeclReader::mergeRedeclarableTemplate(RedeclarableTemplateDecl *D,
+ RedeclarableResult &Redecl) {
+ mergeRedeclarable(D, Redecl);
+ // If we merged the template with a prior declaration chain, merge the
+ // common pointer.
+ // FIXME: Actually merge here, don't just overwrite.
+ D->Common = D->getCanonicalDecl()->Common;
}
/// "Cast" to type T, asserting if we don't have an implicit conversion.
@@ -2539,12 +2901,12 @@ template<typename T> static T assert_cast(...) {
/// declarations.
void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D,
RedeclarableTemplateDecl *Existing,
- DeclID DsID, bool IsKeyDecl) {
+ bool IsKeyDecl) {
auto *DPattern = D->getTemplatedDecl();
auto *ExistingPattern = Existing->getTemplatedDecl();
- RedeclarableResult Result(/*MergeWith*/ ExistingPattern,
- DPattern->getCanonicalDecl()->getGlobalID(),
- IsKeyDecl);
+ RedeclarableResult Result(
+ /*MergeWith*/ ExistingPattern,
+ DPattern->getCanonicalDecl()->getGlobalID(), IsKeyDecl);
if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern)) {
// Merge with any existing definition.
@@ -2579,17 +2941,13 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D,
/// Attempts to merge the given declaration (D) with another declaration
/// of the same entity.
-template<typename T>
+template <typename T>
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
- RedeclarableResult &Redecl,
- DeclID TemplatePatternID) {
+ RedeclarableResult &Redecl) {
auto *D = static_cast<T *>(DBase);
T *ExistingCanon = Existing->getCanonicalDecl();
T *DCanon = D->getCanonicalDecl();
if (ExistingCanon != DCanon) {
- assert(DCanon->getGlobalID() == Redecl.getFirstID() &&
- "already merged this declaration");
-
// Have our redeclaration link point back at the canonical declaration
// of the existing declaration, so that this declaration has the
// appropriate canonical declaration.
@@ -2598,18 +2956,11 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
ExistingCanon->Used |= D->Used;
D->Used = false;
- // When we merge a namespace, update its pointer to the first namespace.
- // We cannot have loaded any redeclarations of this declaration yet, so
- // there's nothing else that needs to be updated.
- if (auto *Namespace = dyn_cast<NamespaceDecl>(D))
- Namespace->AnonOrFirstNamespaceAndInline.setPointer(
- assert_cast<NamespaceDecl*>(ExistingCanon));
-
// When we merge a template, merge its pattern.
if (auto *DTemplate = dyn_cast<RedeclarableTemplateDecl>(D))
mergeTemplatePattern(
- DTemplate, assert_cast<RedeclarableTemplateDecl*>(ExistingCanon),
- TemplatePatternID, Redecl.isKeyDecl());
+ DTemplate, assert_cast<RedeclarableTemplateDecl *>(ExistingCanon),
+ Redecl.isKeyDecl());
// If this declaration is a key declaration, make a note of that.
if (Redecl.isKeyDecl())
@@ -2626,7 +2977,7 @@ static bool allowODRLikeMergeInC(NamedDecl *ND) {
if (!ND)
return false;
// TODO: implement merge for other necessary decls.
- if (isa<EnumConstantDecl>(ND))
+ if (isa<EnumConstantDecl, FieldDecl, IndirectFieldDecl>(ND))
return true;
return false;
}
@@ -2701,16 +3052,16 @@ void ASTDeclReader::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
Expr *Priv = Record.readExpr();
D->setInitializerData(Orig, Priv);
Expr *Init = Record.readExpr();
- auto IK = static_cast<OMPDeclareReductionDecl::InitKind>(Record.readInt());
+ auto IK = static_cast<OMPDeclareReductionInitKind>(Record.readInt());
D->setInitializer(Init, IK);
- D->PrevDeclInScope = readDeclID();
+ D->PrevDeclInScope = readDeclID().getRawValue();
}
void ASTDeclReader::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) {
Record.readOMPChildren(D->Data);
VisitValueDecl(D);
D->VarName = Record.readDeclarationName();
- D->PrevDeclInScope = readDeclID();
+ D->PrevDeclInScope = readDeclID().getRawValue();
}
void ASTDeclReader::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) {
@@ -2732,6 +3083,8 @@ public:
return Reader.readInt();
}
+ bool readBool() { return Reader.readBool(); }
+
SourceRange readSourceRange() {
return Reader.readSourceRange();
}
@@ -2742,6 +3095,8 @@ public:
Expr *readExpr() { return Reader.readExpr(); }
+ Attr *readAttr() { return Reader.readAttr(); }
+
std::string readString() {
return Reader.readString();
}
@@ -2760,9 +3115,7 @@ public:
OMPTraitInfo *readOMPTraitInfo() { return Reader.readOMPTraitInfo(); }
- template <typename T> T *GetLocalDeclAs(uint32_t LocalID) {
- return Reader.GetLocalDeclAs<T>(LocalID);
- }
+ template <typename T> T *readDeclAs() { return Reader.readDeclAs<T>(); }
};
}
@@ -2785,10 +3138,15 @@ Attr *ASTRecordReader::readAttr() {
unsigned ParsedKind = Record.readInt();
unsigned Syntax = Record.readInt();
unsigned SpellingIndex = Record.readInt();
+ bool IsAlignas = (ParsedKind == AttributeCommonInfo::AT_Aligned &&
+ Syntax == AttributeCommonInfo::AS_Keyword &&
+ SpellingIndex == AlignedAttr::Keyword_alignas);
+ bool IsRegularKeywordAttribute = Record.readBool();
AttributeCommonInfo Info(AttrName, ScopeName, AttrRange, ScopeLoc,
AttributeCommonInfo::Kind(ParsedKind),
- AttributeCommonInfo::Syntax(Syntax), SpellingIndex);
+ {AttributeCommonInfo::Syntax(Syntax), SpellingIndex,
+ IsAlignas, IsRegularKeywordAttribute});
#include "clang/Serialization/AttrPCHRead.inc"
@@ -2799,7 +3157,8 @@ Attr *ASTRecordReader::readAttr() {
/// Reads attributes from the current stream position.
void ASTRecordReader::readAttributes(AttrVec &Attrs) {
for (unsigned I = 0, E = readInt(); I != E; ++I)
- Attrs.push_back(readAttr());
+ if (auto *A = readAttr())
+ Attrs.push_back(A);
}
//===----------------------------------------------------------------------===//
@@ -2823,7 +3182,7 @@ inline void ASTReader::LoadedDecl(unsigned Index, Decl *D) {
/// This routine should return true for anything that might affect
/// code generation, e.g., inline function definitions, Objective-C
/// declarations with metadata, etc.
-static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) {
+bool ASTReader::isConsumerInterestedIn(Decl *D) {
// An ObjCMethodDecl is never considered as "interesting" because its
// implementation container always is.
@@ -2832,27 +3191,22 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) {
if (isPartOfPerModuleInitializer(D)) {
auto *M = D->getImportedOwningModule();
if (M && M->Kind == Module::ModuleMapModule &&
- Ctx.DeclMustBeEmitted(D))
+ getContext().DeclMustBeEmitted(D))
return false;
}
- if (isa<FileScopeAsmDecl>(D) ||
- isa<ObjCProtocolDecl>(D) ||
- isa<ObjCImplDecl>(D) ||
- isa<ImportDecl>(D) ||
- isa<PragmaCommentDecl>(D) ||
- isa<PragmaDetectMismatchDecl>(D))
+ if (isa<FileScopeAsmDecl, TopLevelStmtDecl, ObjCProtocolDecl, ObjCImplDecl,
+ ImportDecl, PragmaCommentDecl, PragmaDetectMismatchDecl>(D))
return true;
- if (isa<OMPThreadPrivateDecl>(D) || isa<OMPDeclareReductionDecl>(D) ||
- isa<OMPDeclareMapperDecl>(D) || isa<OMPAllocateDecl>(D) ||
- isa<OMPRequiresDecl>(D))
+ if (isa<OMPThreadPrivateDecl, OMPDeclareReductionDecl, OMPDeclareMapperDecl,
+ OMPAllocateDecl, OMPRequiresDecl>(D))
return !D->getDeclContext()->isFunctionOrMethod();
if (const auto *Var = dyn_cast<VarDecl>(D))
return Var->isFileVarDecl() &&
(Var->isThisDeclarationADefinition() == VarDecl::Definition ||
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Var));
if (const auto *Func = dyn_cast<FunctionDecl>(D))
- return Func->doesThisDeclarationHaveABody() || HasBody;
+ return Func->doesThisDeclarationHaveABody() || PendingBodies.count(D);
if (auto *ES = D->getASTContext().getExternalSource())
if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never)
@@ -2862,14 +3216,13 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) {
}
/// Get the correct cursor and offset for loading a declaration.
-ASTReader::RecordLocation
-ASTReader::DeclCursorForID(DeclID ID, SourceLocation &Loc) {
- GlobalDeclMapType::iterator I = GlobalDeclMap.find(ID);
- assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
- ModuleFile *M = I->second;
- const DeclOffset &DOffs =
- M->DeclOffsets[ID - M->BaseDeclID - NUM_PREDEF_DECL_IDS];
- Loc = TranslateSourceLocation(*M, DOffs.getLocation());
+ASTReader::RecordLocation ASTReader::DeclCursorForID(GlobalDeclID ID,
+ SourceLocation &Loc) {
+ ModuleFile *M = getOwningModuleFile(ID);
+ assert(M);
+ unsigned LocalDeclIndex = ID.getLocalDeclIndex();
+ const DeclOffset &DOffs = M->DeclOffsets[LocalDeclIndex];
+ Loc = ReadSourceLocation(*M, DOffs.getRawLoc());
return RecordLocation(M, DOffs.getBitOffset(M->DeclsBlockStartOffset));
}
@@ -2884,376 +3237,30 @@ uint64_t ASTReader::getGlobalBitOffset(ModuleFile &M, uint64_t LocalOffset) {
return LocalOffset + M.GlobalBitOffset;
}
-static bool isSameTemplateParameterList(const ASTContext &C,
- const TemplateParameterList *X,
- const TemplateParameterList *Y);
-
-/// Determine whether two template parameters are similar enough
-/// that they may be used in declarations of the same template.
-static bool isSameTemplateParameter(const NamedDecl *X,
- const NamedDecl *Y) {
- if (X->getKind() != Y->getKind())
- return false;
-
- if (const auto *TX = dyn_cast<TemplateTypeParmDecl>(X)) {
- const auto *TY = cast<TemplateTypeParmDecl>(Y);
- if (TX->isParameterPack() != TY->isParameterPack())
- return false;
- if (TX->hasTypeConstraint() != TY->hasTypeConstraint())
- return false;
- const TypeConstraint *TXTC = TX->getTypeConstraint();
- const TypeConstraint *TYTC = TY->getTypeConstraint();
- if (!TXTC != !TYTC)
- return false;
- if (TXTC && TYTC) {
- if (TXTC->getNamedConcept() != TYTC->getNamedConcept())
- return false;
- if (TXTC->hasExplicitTemplateArgs() != TYTC->hasExplicitTemplateArgs())
- return false;
- if (TXTC->hasExplicitTemplateArgs()) {
- const auto *TXTCArgs = TXTC->getTemplateArgsAsWritten();
- const auto *TYTCArgs = TYTC->getTemplateArgsAsWritten();
- if (TXTCArgs->NumTemplateArgs != TYTCArgs->NumTemplateArgs)
- return false;
- llvm::FoldingSetNodeID XID, YID;
- for (const auto &ArgLoc : TXTCArgs->arguments())
- ArgLoc.getArgument().Profile(XID, X->getASTContext());
- for (const auto &ArgLoc : TYTCArgs->arguments())
- ArgLoc.getArgument().Profile(YID, Y->getASTContext());
- if (XID != YID)
- return false;
- }
- }
- return true;
- }
-
- if (const auto *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) {
- const auto *TY = cast<NonTypeTemplateParmDecl>(Y);
- return TX->isParameterPack() == TY->isParameterPack() &&
- TX->getASTContext().hasSameType(TX->getType(), TY->getType());
- }
-
- const auto *TX = cast<TemplateTemplateParmDecl>(X);
- const auto *TY = cast<TemplateTemplateParmDecl>(Y);
- return TX->isParameterPack() == TY->isParameterPack() &&
- isSameTemplateParameterList(TX->getASTContext(),
- TX->getTemplateParameters(),
- TY->getTemplateParameters());
-}
-
-static NamespaceDecl *getNamespace(const NestedNameSpecifier *X) {
- if (auto *NS = X->getAsNamespace())
- return NS;
- if (auto *NAS = X->getAsNamespaceAlias())
- return NAS->getNamespace();
- return nullptr;
-}
-
-static bool isSameQualifier(const NestedNameSpecifier *X,
- const NestedNameSpecifier *Y) {
- if (auto *NSX = getNamespace(X)) {
- auto *NSY = getNamespace(Y);
- if (!NSY || NSX->getCanonicalDecl() != NSY->getCanonicalDecl())
- return false;
- } else if (X->getKind() != Y->getKind())
- return false;
-
- // FIXME: For namespaces and types, we're permitted to check that the entity
- // is named via the same tokens. We should probably do so.
- switch (X->getKind()) {
- case NestedNameSpecifier::Identifier:
- if (X->getAsIdentifier() != Y->getAsIdentifier())
- return false;
- break;
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::NamespaceAlias:
- // We've already checked that we named the same namespace.
- break;
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::TypeSpecWithTemplate:
- if (X->getAsType()->getCanonicalTypeInternal() !=
- Y->getAsType()->getCanonicalTypeInternal())
- return false;
- break;
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
- return true;
- }
-
- // Recurse into earlier portion of NNS, if any.
- auto *PX = X->getPrefix();
- auto *PY = Y->getPrefix();
- if (PX && PY)
- return isSameQualifier(PX, PY);
- return !PX && !PY;
-}
-
-/// Determine whether two template parameter lists are similar enough
-/// that they may be used in declarations of the same template.
-static bool isSameTemplateParameterList(const ASTContext &C,
- const TemplateParameterList *X,
- const TemplateParameterList *Y) {
- if (X->size() != Y->size())
- return false;
-
- for (unsigned I = 0, N = X->size(); I != N; ++I)
- if (!isSameTemplateParameter(X->getParam(I), Y->getParam(I)))
- return false;
-
- const Expr *XRC = X->getRequiresClause();
- const Expr *YRC = Y->getRequiresClause();
- if (!XRC != !YRC)
- return false;
- if (XRC) {
- llvm::FoldingSetNodeID XRCID, YRCID;
- XRC->Profile(XRCID, C, /*Canonical=*/true);
- YRC->Profile(YRCID, C, /*Canonical=*/true);
- if (XRCID != YRCID)
- return false;
- }
-
- return true;
-}
-
-/// Determine whether the attributes we can overload on are identical for A and
-/// B. Will ignore any overloadable attrs represented in the type of A and B.
-static bool hasSameOverloadableAttrs(const FunctionDecl *A,
- const FunctionDecl *B) {
- // Note that pass_object_size attributes are represented in the function's
- // ExtParameterInfo, so we don't need to check them here.
-
- llvm::FoldingSetNodeID Cand1ID, Cand2ID;
- auto AEnableIfAttrs = A->specific_attrs<EnableIfAttr>();
- auto BEnableIfAttrs = B->specific_attrs<EnableIfAttr>();
-
- for (auto Pair : zip_longest(AEnableIfAttrs, BEnableIfAttrs)) {
- Optional<EnableIfAttr *> Cand1A = std::get<0>(Pair);
- Optional<EnableIfAttr *> Cand2A = std::get<1>(Pair);
-
- // Return false if the number of enable_if attributes is different.
- if (!Cand1A || !Cand2A)
- return false;
-
- Cand1ID.clear();
- Cand2ID.clear();
-
- (*Cand1A)->getCond()->Profile(Cand1ID, A->getASTContext(), true);
- (*Cand2A)->getCond()->Profile(Cand2ID, B->getASTContext(), true);
-
- // Return false if any of the enable_if expressions of A and B are
- // different.
- if (Cand1ID != Cand2ID)
- return false;
- }
- return true;
-}
-
-/// Determine whether the two declarations refer to the same entity.pr
-static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
- assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!");
-
- if (X == Y)
- return true;
-
- // Must be in the same context.
- //
- // Note that we can't use DeclContext::Equals here, because the DeclContexts
- // could be two different declarations of the same function. (We will fix the
- // semantic DC to refer to the primary definition after merging.)
- if (!declaresSameEntity(cast<Decl>(X->getDeclContext()->getRedeclContext()),
- cast<Decl>(Y->getDeclContext()->getRedeclContext())))
- return false;
-
- // Two typedefs refer to the same entity if they have the same underlying
- // type.
- if (const auto *TypedefX = dyn_cast<TypedefNameDecl>(X))
- if (const auto *TypedefY = dyn_cast<TypedefNameDecl>(Y))
- return X->getASTContext().hasSameType(TypedefX->getUnderlyingType(),
- TypedefY->getUnderlyingType());
-
- // Must have the same kind.
- if (X->getKind() != Y->getKind())
- return false;
-
- // Objective-C classes and protocols with the same name always match.
- if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X))
- return true;
-
- if (isa<ClassTemplateSpecializationDecl>(X)) {
- // No need to handle these here: we merge them when adding them to the
- // template.
- return false;
- }
-
- // Compatible tags match.
- if (const auto *TagX = dyn_cast<TagDecl>(X)) {
- const auto *TagY = cast<TagDecl>(Y);
- return (TagX->getTagKind() == TagY->getTagKind()) ||
- ((TagX->getTagKind() == TTK_Struct || TagX->getTagKind() == TTK_Class ||
- TagX->getTagKind() == TTK_Interface) &&
- (TagY->getTagKind() == TTK_Struct || TagY->getTagKind() == TTK_Class ||
- TagY->getTagKind() == TTK_Interface));
- }
-
- // Functions with the same type and linkage match.
- // FIXME: This needs to cope with merging of prototyped/non-prototyped
- // functions, etc.
- if (const auto *FuncX = dyn_cast<FunctionDecl>(X)) {
- const auto *FuncY = cast<FunctionDecl>(Y);
- if (const auto *CtorX = dyn_cast<CXXConstructorDecl>(X)) {
- const auto *CtorY = cast<CXXConstructorDecl>(Y);
- if (CtorX->getInheritedConstructor() &&
- !isSameEntity(CtorX->getInheritedConstructor().getConstructor(),
- CtorY->getInheritedConstructor().getConstructor()))
- return false;
- }
-
- if (FuncX->isMultiVersion() != FuncY->isMultiVersion())
- return false;
-
- // Multiversioned functions with different feature strings are represented
- // as separate declarations.
- if (FuncX->isMultiVersion()) {
- const auto *TAX = FuncX->getAttr<TargetAttr>();
- const auto *TAY = FuncY->getAttr<TargetAttr>();
- assert(TAX && TAY && "Multiversion Function without target attribute");
-
- if (TAX->getFeaturesStr() != TAY->getFeaturesStr())
- return false;
- }
-
- ASTContext &C = FuncX->getASTContext();
-
- const Expr *XRC = FuncX->getTrailingRequiresClause();
- const Expr *YRC = FuncY->getTrailingRequiresClause();
- if (!XRC != !YRC)
- return false;
- if (XRC) {
- llvm::FoldingSetNodeID XRCID, YRCID;
- XRC->Profile(XRCID, C, /*Canonical=*/true);
- YRC->Profile(YRCID, C, /*Canonical=*/true);
- if (XRCID != YRCID)
- return false;
- }
-
- auto GetTypeAsWritten = [](const FunctionDecl *FD) {
- // Map to the first declaration that we've already merged into this one.
- // The TSI of redeclarations might not match (due to calling conventions
- // being inherited onto the type but not the TSI), but the TSI type of
- // the first declaration of the function should match across modules.
- FD = FD->getCanonicalDecl();
- return FD->getTypeSourceInfo() ? FD->getTypeSourceInfo()->getType()
- : FD->getType();
- };
- QualType XT = GetTypeAsWritten(FuncX), YT = GetTypeAsWritten(FuncY);
- if (!C.hasSameType(XT, YT)) {
- // We can get functions with different types on the redecl chain in C++17
- // if they have differing exception specifications and at least one of
- // the excpetion specs is unresolved.
- auto *XFPT = XT->getAs<FunctionProtoType>();
- auto *YFPT = YT->getAs<FunctionProtoType>();
- if (C.getLangOpts().CPlusPlus17 && XFPT && YFPT &&
- (isUnresolvedExceptionSpec(XFPT->getExceptionSpecType()) ||
- isUnresolvedExceptionSpec(YFPT->getExceptionSpecType())) &&
- C.hasSameFunctionTypeIgnoringExceptionSpec(XT, YT))
- return true;
- return false;
- }
-
- return FuncX->getLinkageInternal() == FuncY->getLinkageInternal() &&
- hasSameOverloadableAttrs(FuncX, FuncY);
- }
-
- // Variables with the same type and linkage match.
- if (const auto *VarX = dyn_cast<VarDecl>(X)) {
- const auto *VarY = cast<VarDecl>(Y);
- if (VarX->getLinkageInternal() == VarY->getLinkageInternal()) {
- ASTContext &C = VarX->getASTContext();
- if (C.hasSameType(VarX->getType(), VarY->getType()))
- return true;
-
- // We can get decls with different types on the redecl chain. Eg.
- // template <typename T> struct S { static T Var[]; }; // #1
- // template <typename T> T S<T>::Var[sizeof(T)]; // #2
- // Only? happens when completing an incomplete array type. In this case
- // when comparing #1 and #2 we should go through their element type.
- const ArrayType *VarXTy = C.getAsArrayType(VarX->getType());
- const ArrayType *VarYTy = C.getAsArrayType(VarY->getType());
- if (!VarXTy || !VarYTy)
- return false;
- if (VarXTy->isIncompleteArrayType() || VarYTy->isIncompleteArrayType())
- return C.hasSameType(VarXTy->getElementType(), VarYTy->getElementType());
- }
- return false;
- }
-
- // Namespaces with the same name and inlinedness match.
- if (const auto *NamespaceX = dyn_cast<NamespaceDecl>(X)) {
- const auto *NamespaceY = cast<NamespaceDecl>(Y);
- return NamespaceX->isInline() == NamespaceY->isInline();
- }
-
- // Identical template names and kinds match if their template parameter lists
- // and patterns match.
- if (const auto *TemplateX = dyn_cast<TemplateDecl>(X)) {
- const auto *TemplateY = cast<TemplateDecl>(Y);
- return isSameEntity(TemplateX->getTemplatedDecl(),
- TemplateY->getTemplatedDecl()) &&
- isSameTemplateParameterList(TemplateX->getASTContext(),
- TemplateX->getTemplateParameters(),
- TemplateY->getTemplateParameters());
- }
-
- // Fields with the same name and the same type match.
- if (const auto *FDX = dyn_cast<FieldDecl>(X)) {
- const auto *FDY = cast<FieldDecl>(Y);
- // FIXME: Also check the bitwidth is odr-equivalent, if any.
- return X->getASTContext().hasSameType(FDX->getType(), FDY->getType());
- }
-
- // Indirect fields with the same target field match.
- if (const auto *IFDX = dyn_cast<IndirectFieldDecl>(X)) {
- const auto *IFDY = cast<IndirectFieldDecl>(Y);
- return IFDX->getAnonField()->getCanonicalDecl() ==
- IFDY->getAnonField()->getCanonicalDecl();
- }
+CXXRecordDecl *
+ASTDeclReader::getOrFakePrimaryClassDefinition(ASTReader &Reader,
+ CXXRecordDecl *RD) {
+ // Try to dig out the definition.
+ auto *DD = RD->DefinitionData;
+ if (!DD)
+ DD = RD->getCanonicalDecl()->DefinitionData;
- // Enumerators with the same name match.
- if (isa<EnumConstantDecl>(X))
- // FIXME: Also check the value is odr-equivalent.
- return true;
+ // If there's no definition yet, then DC's definition is added by an update
+ // record, but we've not yet loaded that update record. In this case, we
+ // commit to DC being the canonical definition now, and will fix this when
+ // we load the update record.
+ if (!DD) {
+ DD = new (Reader.getContext()) struct CXXRecordDecl::DefinitionData(RD);
+ RD->setCompleteDefinition(true);
+ RD->DefinitionData = DD;
+ RD->getCanonicalDecl()->DefinitionData = DD;
- // Using shadow declarations with the same target match.
- if (const auto *USX = dyn_cast<UsingShadowDecl>(X)) {
- const auto *USY = cast<UsingShadowDecl>(Y);
- return USX->getTargetDecl() == USY->getTargetDecl();
- }
-
- // Using declarations with the same qualifier match. (We already know that
- // the name matches.)
- if (const auto *UX = dyn_cast<UsingDecl>(X)) {
- const auto *UY = cast<UsingDecl>(Y);
- return isSameQualifier(UX->getQualifier(), UY->getQualifier()) &&
- UX->hasTypename() == UY->hasTypename() &&
- UX->isAccessDeclaration() == UY->isAccessDeclaration();
- }
- if (const auto *UX = dyn_cast<UnresolvedUsingValueDecl>(X)) {
- const auto *UY = cast<UnresolvedUsingValueDecl>(Y);
- return isSameQualifier(UX->getQualifier(), UY->getQualifier()) &&
- UX->isAccessDeclaration() == UY->isAccessDeclaration();
- }
- if (const auto *UX = dyn_cast<UnresolvedUsingTypenameDecl>(X))
- return isSameQualifier(
- UX->getQualifier(),
- cast<UnresolvedUsingTypenameDecl>(Y)->getQualifier());
-
- // Namespace alias definitions with the same target match.
- if (const auto *NAX = dyn_cast<NamespaceAliasDecl>(X)) {
- const auto *NAY = cast<NamespaceAliasDecl>(Y);
- return NAX->getNamespace()->Equals(NAY->getNamespace());
+ // Track that we did this horrible thing so that we can fix it later.
+ Reader.PendingFakeDefinitionData.insert(
+ std::make_pair(DD, ASTReader::PendingFakeDefinitionKind::Fake));
}
- return false;
+ return DD->Definition;
}
/// Find the context in which we should search for previous declarations when
@@ -3261,40 +3268,24 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader,
DeclContext *DC) {
if (auto *ND = dyn_cast<NamespaceDecl>(DC))
- return ND->getOriginalNamespace();
-
- if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
- // Try to dig out the definition.
- auto *DD = RD->DefinitionData;
- if (!DD)
- DD = RD->getCanonicalDecl()->DefinitionData;
-
- // If there's no definition yet, then DC's definition is added by an update
- // record, but we've not yet loaded that update record. In this case, we
- // commit to DC being the canonical definition now, and will fix this when
- // we load the update record.
- if (!DD) {
- DD = new (Reader.getContext()) struct CXXRecordDecl::DefinitionData(RD);
- RD->setCompleteDefinition(true);
- RD->DefinitionData = DD;
- RD->getCanonicalDecl()->DefinitionData = DD;
-
- // Track that we did this horrible thing so that we can fix it later.
- Reader.PendingFakeDefinitionData.insert(
- std::make_pair(DD, ASTReader::PendingFakeDefinitionKind::Fake));
- }
+ return ND->getFirstDecl();
- return DD->Definition;
- }
+ if (auto *RD = dyn_cast<CXXRecordDecl>(DC))
+ return getOrFakePrimaryClassDefinition(Reader, RD);
+
+ if (auto *RD = dyn_cast<RecordDecl>(DC))
+ return RD->getDefinition();
if (auto *ED = dyn_cast<EnumDecl>(DC))
- return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition()
- : nullptr;
+ return ED->getDefinition();
+
+ if (auto *OID = dyn_cast<ObjCInterfaceDecl>(DC))
+ return OID->getDefinition();
- // We can see the TU here only if we have no Sema object. In that case,
- // there's no TU scope to look in, so using the DC alone is sufficient.
+ // We can see the TU here only if we have no Sema object. It is possible
+ // we're in clang-repl so we still need to get the primary context.
if (auto *TU = dyn_cast<TranslationUnitDecl>(DC))
- return TU;
+ return TU->getPrimaryContext();
return nullptr;
}
@@ -3358,6 +3349,8 @@ ASTDeclReader::getPrimaryDCForAnonymousDecl(DeclContext *LexicalDC) {
if (auto *RD = dyn_cast<CXXRecordDecl>(LexicalDC)) {
auto *DD = RD->getCanonicalDecl()->DefinitionData;
return DD ? DD->Definition : nullptr;
+ } else if (auto *OID = dyn_cast<ObjCInterfaceDecl>(LexicalDC)) {
+ return OID->getCanonicalDecl()->getDefinition();
}
// For anything else, walk its merged redeclarations looking for a definition.
@@ -3370,6 +3363,9 @@ ASTDeclReader::getPrimaryDCForAnonymousDecl(DeclContext *LexicalDC) {
if (auto *MD = dyn_cast<ObjCMethodDecl>(D))
if (MD->isThisDeclarationADefinition())
return MD;
+ if (auto *RD = dyn_cast<RecordDecl>(D))
+ if (RD->isThisDeclarationADefinition())
+ return RD;
}
// No merged definition yet.
@@ -3428,12 +3424,13 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
return Result;
}
+ ASTContext &C = Reader.getContext();
DeclContext *DC = D->getDeclContext()->getRedeclContext();
if (TypedefNameForLinkage) {
auto It = Reader.ImportedTypedefNamesForLinkage.find(
std::make_pair(DC, TypedefNameForLinkage));
if (It != Reader.ImportedTypedefNamesForLinkage.end())
- if (isSameEntity(It->second, D))
+ if (C.isSameEntity(It->second, D))
return FindExistingResult(Reader, D, It->second, AnonymousDeclNumber,
TypedefNameForLinkage);
// Go on to check in other places in case an existing typedef name
@@ -3445,7 +3442,7 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
// in its context by number.
if (auto *Existing = getAnonymousDeclForMerging(
Reader, D->getLexicalDeclContext(), AnonymousDeclNumber))
- if (isSameEntity(Existing, D))
+ if (C.isSameEntity(Existing, D))
return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber,
TypedefNameForLinkage);
} else if (DC->isTranslationUnit() &&
@@ -3477,7 +3474,7 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
IEnd = IdResolver.end();
I != IEnd; ++I) {
if (NamedDecl *Existing = getDeclForMerging(*I, TypedefNameForLinkage))
- if (isSameEntity(Existing, D))
+ if (C.isSameEntity(Existing, D))
return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber,
TypedefNameForLinkage);
}
@@ -3485,7 +3482,7 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
DeclContext::lookup_result R = MergeDC->noload_lookup(Name);
for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) {
if (NamedDecl *Existing = getDeclForMerging(*I, TypedefNameForLinkage))
- if (isSameEntity(Existing, D))
+ if (C.isSameEntity(Existing, D))
return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber,
TypedefNameForLinkage);
}
@@ -3497,11 +3494,14 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
// If this declaration is from a merged context, make a note that we need to
// check that the canonical definition of that context contains the decl.
//
+ // Note that we don't perform ODR checks for decls from the global module
+ // fragment.
+ //
// FIXME: We should do something similar if we merge two definitions of the
// same template specialization into the same CXXRecordDecl.
auto MergedDCIt = Reader.MergedDeclContexts.find(D->getLexicalDeclContext());
if (MergedDCIt != Reader.MergedDeclContexts.end() &&
- MergedDCIt->second == D->getDeclContext())
+ !shouldSkipCheckingODR(D) && MergedDCIt->second == D->getDeclContext())
Reader.PendingOdrMergeChecks.push_back(D);
return FindExistingResult(Reader, D, /*Existing=*/nullptr,
@@ -3545,6 +3545,13 @@ void ASTDeclReader::mergeInheritableAttributes(ASTReader &Reader, Decl *D,
NewAttr->setInherited(true);
D->addAttr(NewAttr);
}
+
+ const auto *AA = Previous->getAttr<AvailabilityAttr>();
+ if (AA && !D->hasAttr<AvailabilityAttr>()) {
+ NewAttr = AA->clone(Context);
+ NewAttr->setInherited(true);
+ D->addAttr(NewAttr);
+ }
}
template<typename DeclT>
@@ -3678,6 +3685,54 @@ static void inheritDefaultTemplateArguments(ASTContext &Context,
}
}
+// [basic.link]/p10:
+// If two declarations of an entity are attached to different modules,
+// the program is ill-formed;
+static void checkMultipleDefinitionInNamedModules(ASTReader &Reader, Decl *D,
+ Decl *Previous) {
+ Module *M = Previous->getOwningModule();
+
+ // We only care about the case in named modules.
+ if (!M || !M->isNamedModule())
+ return;
+
+ // If it is previous implcitly introduced, it is not meaningful to
+ // diagnose it.
+ if (Previous->isImplicit())
+ return;
+
+ // FIXME: Get rid of the enumeration of decl types once we have an appropriate
+ // abstract for decls of an entity. e.g., the namespace decl and using decl
+ // doesn't introduce an entity.
+ if (!isa<VarDecl, FunctionDecl, TagDecl, RedeclarableTemplateDecl>(Previous))
+ return;
+
+ // Skip implicit instantiations since it may give false positive diagnostic
+ // messages.
+ // FIXME: Maybe this shows the implicit instantiations may have incorrect
+ // module owner ships. But given we've finished the compilation of a module,
+ // how can we add new entities to that module?
+ if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(Previous);
+ VTSD && !VTSD->isExplicitSpecialization())
+ return;
+ if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Previous);
+ CTSD && !CTSD->isExplicitSpecialization())
+ return;
+ if (auto *Func = dyn_cast<FunctionDecl>(Previous))
+ if (auto *FTSI = Func->getTemplateSpecializationInfo();
+ FTSI && !FTSI->isExplicitSpecialization())
+ return;
+
+ // It is fine if they are in the same module.
+ if (Reader.getContext().isInSameModule(M, D->getOwningModule()))
+ return;
+
+ Reader.Diag(Previous->getLocation(),
+ diag::err_multiple_decl_in_different_modules)
+ << cast<NamedDecl>(Previous) << M->Name;
+ Reader.Diag(D->getLocation(), diag::note_also_found);
+}
+
void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D,
Decl *Previous, Decl *Canon) {
assert(D && Previous);
@@ -3691,6 +3746,8 @@ void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D,
#include "clang/AST/DeclNodes.inc"
}
+ checkMultipleDefinitionInNamedModules(Reader, D, Previous);
+
// If the declaration was visible in one module, a redeclaration of it in
// another module remains visible even if it wouldn't be visible by itself.
//
@@ -3756,8 +3813,7 @@ void ASTReader::markIncompleteDeclChain(Decl *D) {
}
/// Read the declaration at the given offset from the AST file.
-Decl *ASTReader::ReadDeclRecord(DeclID ID) {
- unsigned Index = ID - NUM_PREDEF_DECL_IDS;
+Decl *ASTReader::ReadDeclRecord(GlobalDeclID ID) {
SourceLocation DeclLoc;
RecordLocation Loc = DeclCursorForID(ID, DeclLoc);
llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor;
@@ -3789,8 +3845,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
Expected<unsigned> MaybeDeclCode = Record.readRecord(DeclsCursor, Code);
if (!MaybeDeclCode)
llvm::report_fatal_error(
- "ASTReader::readDeclRecord failed reading decl code: " +
+ Twine("ASTReader::readDeclRecord failed reading decl code: ") +
toString(MaybeDeclCode.takeError()));
+
switch ((DeclCode)MaybeDeclCode.get()) {
case DECL_CONTEXT_LEXICAL:
case DECL_CONTEXT_VISIBLE:
@@ -3837,6 +3894,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
case DECL_USING_SHADOW:
D = UsingShadowDecl::CreateDeserialized(Context, ID);
break;
+ case DECL_USING_ENUM:
+ D = UsingEnumDecl::CreateDeserialized(Context, ID);
+ break;
case DECL_CONSTRUCTOR_USING_SHADOW:
D = ConstructorUsingShadowDecl::CreateDeserialized(Context, ID);
break;
@@ -3849,6 +3909,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
case DECL_UNRESOLVED_USING_TYPENAME:
D = UnresolvedUsingTypenameDecl::CreateDeserialized(Context, ID);
break;
+ case DECL_UNRESOLVED_USING_IF_EXISTS:
+ D = UnresolvedUsingIfExistsDecl::CreateDeserialized(Context, ID);
+ break;
case DECL_CXX_RECORD:
D = CXXRecordDecl::CreateDeserialized(Context, ID);
break;
@@ -3894,9 +3957,6 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
case DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION:
D = VarTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID);
break;
- case DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION:
- D = ClassScopeFunctionSpecializationDecl::CreateDeserialized(Context, ID);
- break;
case DECL_FUNCTION_TEMPLATE:
D = FunctionTemplateDecl::CreateDeserialized(Context, ID);
break;
@@ -3914,9 +3974,8 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
}
case DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK: {
bool HasTypeConstraint = Record.readInt();
- D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID,
- Record.readInt(),
- HasTypeConstraint);
+ D = NonTypeTemplateParmDecl::CreateDeserialized(
+ Context, ID, Record.readInt(), HasTypeConstraint);
break;
}
case DECL_TEMPLATE_TEMPLATE_PARM:
@@ -3995,6 +4054,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
case DECL_FILE_SCOPE_ASM:
D = FileScopeAsmDecl::CreateDeserialized(Context, ID);
break;
+ case DECL_TOP_LEVEL_STMT_DECL:
+ D = TopLevelStmtDecl::CreateDeserialized(Context, ID);
+ break;
case DECL_BLOCK:
D = BlockDecl::CreateDeserialized(Context, ID);
break;
@@ -4004,6 +4066,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
case DECL_MS_GUID:
D = MSGuidDecl::CreateDeserialized(Context, ID);
break;
+ case DECL_UNNAMED_GLOBAL_CONSTANT:
+ D = UnnamedGlobalConstantDecl::CreateDeserialized(Context, ID);
+ break;
case DECL_TEMPLATE_PARAM_OBJECT:
D = TemplateParamObjectDecl::CreateDeserialized(Context, ID);
break;
@@ -4069,20 +4134,39 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
case DECL_OBJC_TYPE_PARAM:
D = ObjCTypeParamDecl::CreateDeserialized(Context, ID);
break;
+ case DECL_HLSL_BUFFER:
+ D = HLSLBufferDecl::CreateDeserialized(Context, ID);
+ break;
+ case DECL_IMPLICIT_CONCEPT_SPECIALIZATION:
+ D = ImplicitConceptSpecializationDecl::CreateDeserialized(Context, ID,
+ Record.readInt());
+ break;
}
assert(D && "Unknown declaration reading AST file");
- LoadedDecl(Index, D);
+ LoadedDecl(translateGlobalDeclIDToIndex(ID), D);
// Set the DeclContext before doing any deserialization, to make sure internal
// calls to Decl::getASTContext() by Decl's methods will find the
// TranslationUnitDecl without crashing.
D->setDeclContext(Context.getTranslationUnitDecl());
- Reader.Visit(D);
+
+ // Reading some declarations can result in deep recursion.
+ clang::runWithSufficientStackSpace([&] { warnStackExhausted(DeclLoc); },
+ [&] { Reader.Visit(D); });
// If this declaration is also a declaration context, get the
// offsets for its tables of lexical and visible declarations.
if (auto *DC = dyn_cast<DeclContext>(D)) {
std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC);
+
+ // Get the lexical and visible block for the delayed namespace.
+ // It is sufficient to judge if ID is in DelayedNamespaceOffsetMap.
+ // But it may be more efficient to filter the other cases.
+ if (!Offsets.first && !Offsets.second && isa<NamespaceDecl>(D))
+ if (auto Iter = DelayedNamespaceOffsetMap.find(ID);
+ Iter != DelayedNamespaceOffsetMap.end())
+ Offsets = Iter->second;
+
if (Offsets.first &&
ReadLexicalDeclContextStorage(*Loc.F, DeclsCursor, Offsets.first, DC))
return nullptr;
@@ -4108,8 +4192,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
// AST consumer might need to know about, queue it.
// We don't pass it to the consumer immediately because we may be in recursive
// loading, and some declarations may still be initializing.
- PotentiallyInterestingDecls.push_back(
- InterestingDecl(D, Reader.hasPendingBody()));
+ PotentiallyInterestingDecls.push_back(D);
return D;
}
@@ -4122,8 +4205,7 @@ void ASTReader::PassInterestingDeclsToConsumer() {
// Guard variable to avoid recursively redoing the process of passing
// decls to consumer.
- SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer,
- true);
+ SaveAndRestore GuardPassingDeclsToConsumer(PassingDeclsToConsumer, true);
// Ensure that we've loaded all potentially-interesting declarations
// that need to be eagerly loaded.
@@ -4131,24 +4213,55 @@ void ASTReader::PassInterestingDeclsToConsumer() {
GetDecl(ID);
EagerlyDeserializedDecls.clear();
- while (!PotentiallyInterestingDecls.empty()) {
- InterestingDecl D = PotentiallyInterestingDecls.front();
- PotentiallyInterestingDecls.pop_front();
- if (isConsumerInterestedIn(getContext(), D.getDecl(), D.hasPendingBody()))
- PassInterestingDeclToConsumer(D.getDecl());
- }
+ auto ConsumingPotentialInterestingDecls = [this]() {
+ while (!PotentiallyInterestingDecls.empty()) {
+ Decl *D = PotentiallyInterestingDecls.front();
+ PotentiallyInterestingDecls.pop_front();
+ if (isConsumerInterestedIn(D))
+ PassInterestingDeclToConsumer(D);
+ }
+ };
+ std::deque<Decl *> MaybeInterestingDecls =
+ std::move(PotentiallyInterestingDecls);
+ PotentiallyInterestingDecls.clear();
+ assert(PotentiallyInterestingDecls.empty());
+ while (!MaybeInterestingDecls.empty()) {
+ Decl *D = MaybeInterestingDecls.front();
+ MaybeInterestingDecls.pop_front();
+ // Since we load the variable's initializers lazily, it'd be problematic
+ // if the initializers dependent on each other. So here we try to load the
+ // initializers of static variables to make sure they are passed to code
+ // generator by order. If we read anything interesting, we would consume
+ // that before emitting the current declaration.
+ if (auto *VD = dyn_cast<VarDecl>(D);
+ VD && VD->isFileVarDecl() && !VD->isExternallyVisible())
+ VD->getInit();
+ ConsumingPotentialInterestingDecls();
+ if (isConsumerInterestedIn(D))
+ PassInterestingDeclToConsumer(D);
+ }
+
+ // If we add any new potential interesting decl in the last call, consume it.
+ ConsumingPotentialInterestingDecls();
+
+ for (GlobalDeclID ID : VTablesToEmit) {
+ auto *RD = cast<CXXRecordDecl>(GetDecl(ID));
+ assert(!RD->shouldEmitInExternalSource());
+ PassVTableToConsumer(RD);
+ }
+ VTablesToEmit.clear();
}
void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
// The declaration may have been modified by files later in the chain.
// If this is the case, read the record containing the updates from each file
// and pass it to ASTDeclReader to make the modifications.
- serialization::GlobalDeclID ID = Record.ID;
+ GlobalDeclID ID = Record.ID;
Decl *D = Record.D;
ProcessingUpdatesRAIIObj ProcessingUpdates(*this);
DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID);
- SmallVector<serialization::DeclID, 8> PendingLazySpecializationIDs;
+ SmallVector<GlobalDeclID, 8> PendingLazySpecializationIDs;
if (UpdI != DeclUpdateOffsets.end()) {
auto UpdateOffsets = std::move(UpdI->second);
@@ -4158,8 +4271,7 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
// the declaration, then we know it was interesting and we skip the call
// to isConsumerInterestedIn because it is unsafe to call in the
// current ASTReader state.
- bool WasInteresting =
- Record.JustLoaded || isConsumerInterestedIn(getContext(), D, false);
+ bool WasInteresting = Record.JustLoaded || isConsumerInterestedIn(D);
for (auto &FileAndOffset : UpdateOffsets) {
ModuleFile *F = FileAndOffset.first;
uint64_t Offset = FileAndOffset.second;
@@ -4168,12 +4280,12 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
if (llvm::Error JumpFailed = Cursor.JumpToBit(Offset))
// FIXME don't do a fatal error.
llvm::report_fatal_error(
- "ASTReader::loadDeclUpdateRecords failed jumping: " +
+ Twine("ASTReader::loadDeclUpdateRecords failed jumping: ") +
toString(std::move(JumpFailed)));
Expected<unsigned> MaybeCode = Cursor.ReadCode();
if (!MaybeCode)
llvm::report_fatal_error(
- "ASTReader::loadDeclUpdateRecords failed reading code: " +
+ Twine("ASTReader::loadDeclUpdateRecords failed reading code: ") +
toString(MaybeCode.takeError()));
unsigned Code = MaybeCode.get();
ASTRecordReader Record(*this, *F);
@@ -4182,7 +4294,7 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
"Expected DECL_UPDATES record!");
else
llvm::report_fatal_error(
- "ASTReader::loadDeclUpdateRecords failed reading rec code: " +
+ Twine("ASTReader::loadDeclUpdateRecords failed reading rec code: ") +
toString(MaybeCode.takeError()));
ASTDeclReader Reader(*this, Record, RecordLocation(F, Offset), ID,
@@ -4191,17 +4303,15 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
// We might have made this declaration interesting. If so, remember that
// we need to hand it off to the consumer.
- if (!WasInteresting &&
- isConsumerInterestedIn(getContext(), D, Reader.hasPendingBody())) {
- PotentiallyInterestingDecls.push_back(
- InterestingDecl(D, Reader.hasPendingBody()));
+ if (!WasInteresting && isConsumerInterestedIn(D)) {
+ PotentiallyInterestingDecls.push_back(D);
WasInteresting = true;
}
}
}
// Add the lazy specializations to the template.
assert((PendingLazySpecializationIDs.empty() || isa<ClassTemplateDecl>(D) ||
- isa<FunctionTemplateDecl>(D) || isa<VarTemplateDecl>(D)) &&
+ isa<FunctionTemplateDecl, VarTemplateDecl>(D)) &&
"Must not have pending specializations");
if (auto *CTD = dyn_cast<ClassTemplateDecl>(D))
ASTDeclReader::AddLazySpecializations(CTD, PendingLazySpecializationIDs);
@@ -4249,14 +4359,14 @@ void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) {
SavedStreamPosition SavedPosition(Cursor);
if (llvm::Error JumpFailed = Cursor.JumpToBit(LocalOffset))
llvm::report_fatal_error(
- "ASTReader::loadPendingDeclChain failed jumping: " +
+ Twine("ASTReader::loadPendingDeclChain failed jumping: ") +
toString(std::move(JumpFailed)));
RecordData Record;
Expected<unsigned> MaybeCode = Cursor.ReadCode();
if (!MaybeCode)
llvm::report_fatal_error(
- "ASTReader::loadPendingDeclChain failed reading code: " +
+ Twine("ASTReader::loadPendingDeclChain failed reading code: ") +
toString(MaybeCode.takeError()));
unsigned Code = MaybeCode.get();
if (Expected<unsigned> MaybeRecCode = Cursor.readRecord(Code, Record))
@@ -4264,14 +4374,15 @@ void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) {
"expected LOCAL_REDECLARATIONS record!");
else
llvm::report_fatal_error(
- "ASTReader::loadPendingDeclChain failed reading rec code: " +
+ Twine("ASTReader::loadPendingDeclChain failed reading rec code: ") +
toString(MaybeCode.takeError()));
// FIXME: We have several different dispatches on decl kind here; maybe
// we should instead generate one loop per kind and dispatch up-front?
Decl *MostRecent = FirstLocal;
for (unsigned I = 0, N = Record.size(); I != N; ++I) {
- auto *D = GetLocalDecl(*M, Record[N - I - 1]);
+ unsigned Idx = N - I - 1;
+ auto *D = ReadDecl(*M, Record, Idx);
ASTDeclReader::attachPreviousDecl(*this, D, MostRecent, CanonDecl);
MostRecent = D;
}
@@ -4288,7 +4399,7 @@ namespace {
llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized;
ObjCCategoryDecl *Tail = nullptr;
llvm::DenseMap<DeclarationName, ObjCCategoryDecl *> NameCategoryMap;
- serialization::GlobalDeclID InterfaceID;
+ GlobalDeclID InterfaceID;
unsigned PreviousGeneration;
void add(ObjCCategoryDecl *Cat) {
@@ -4299,23 +4410,22 @@ namespace {
// Check for duplicate categories.
if (Cat->getDeclName()) {
ObjCCategoryDecl *&Existing = NameCategoryMap[Cat->getDeclName()];
- if (Existing &&
- Reader.getOwningModuleFile(Existing)
- != Reader.getOwningModuleFile(Cat)) {
- // FIXME: We should not warn for duplicates in diamond:
- //
- // MT //
- // / \ //
- // ML MR //
- // \ / //
- // MB //
- //
- // If there are duplicates in ML/MR, there will be warning when
- // creating MB *and* when importing MB. We should not warn when
- // importing.
- Reader.Diag(Cat->getLocation(), diag::warn_dup_category_def)
- << Interface->getDeclName() << Cat->getDeclName();
- Reader.Diag(Existing->getLocation(), diag::note_previous_definition);
+ if (Existing && Reader.getOwningModuleFile(Existing) !=
+ Reader.getOwningModuleFile(Cat)) {
+ llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls;
+ StructuralEquivalenceContext Ctx(
+ Cat->getASTContext(), Existing->getASTContext(),
+ NonEquivalentDecls, StructuralEquivalenceKind::Default,
+ /*StrictTypeSpelling =*/false,
+ /*Complain =*/false,
+ /*ErrorOnTagTypeMismatch =*/true);
+ if (!Ctx.IsEquivalent(Cat, Existing)) {
+ // Warn only if the categories with the same name are different.
+ Reader.Diag(Cat->getLocation(), diag::warn_dup_category_def)
+ << Interface->getDeclName() << Cat->getDeclName();
+ Reader.Diag(Existing->getLocation(),
+ diag::note_previous_definition);
+ }
} else if (!Existing) {
// Record this category.
Existing = Cat;
@@ -4331,11 +4441,10 @@ namespace {
}
public:
- ObjCCategoriesVisitor(ASTReader &Reader,
- ObjCInterfaceDecl *Interface,
- llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized,
- serialization::GlobalDeclID InterfaceID,
- unsigned PreviousGeneration)
+ ObjCCategoriesVisitor(
+ ASTReader &Reader, ObjCInterfaceDecl *Interface,
+ llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized,
+ GlobalDeclID InterfaceID, unsigned PreviousGeneration)
: Reader(Reader), Interface(Interface), Deserialized(Deserialized),
InterfaceID(InterfaceID), PreviousGeneration(PreviousGeneration) {
// Populate the name -> category map with the set of known categories.
@@ -4357,8 +4466,9 @@ namespace {
// Map global ID of the definition down to the local ID used in this
// module file. If there is no such mapping, we'll find nothing here
// (or in any module it imports).
- DeclID LocalID = Reader.mapGlobalIDToModuleFileGlobalID(M, InterfaceID);
- if (!LocalID)
+ LocalDeclID LocalID =
+ Reader.mapGlobalIDToModuleFileGlobalID(M, InterfaceID);
+ if (LocalID.isInvalid())
return true;
// Perform a binary search to find the local redeclarations for this
@@ -4369,7 +4479,7 @@ namespace {
M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap,
Compare);
if (Result == M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap ||
- Result->DefinitionID != LocalID) {
+ LocalID != Result->getDefinitionID()) {
// We didn't find anything. If the class definition is in this module
// file, then the module files it depends on cannot have any categories,
// so suppress further lookup.
@@ -4381,16 +4491,14 @@ namespace {
unsigned N = M.ObjCCategories[Offset];
M.ObjCCategories[Offset++] = 0; // Don't try to deserialize again
for (unsigned I = 0; I != N; ++I)
- add(cast_or_null<ObjCCategoryDecl>(
- Reader.GetLocalDecl(M, M.ObjCCategories[Offset++])));
+ add(Reader.ReadDeclAs<ObjCCategoryDecl>(M, M.ObjCCategories, Offset));
return true;
}
};
} // namespace
-void ASTReader::loadObjCCategories(serialization::GlobalDeclID ID,
- ObjCInterfaceDecl *D,
+void ASTReader::loadObjCCategories(GlobalDeclID ID, ObjCInterfaceDecl *D,
unsigned PreviousGeneration) {
ObjCCategoriesVisitor Visitor(*this, D, CategoriesDeserialized, ID,
PreviousGeneration);
@@ -4418,19 +4526,16 @@ static void forAllLaterRedecls(DeclT *D, Fn F) {
}
}
-void ASTDeclReader::UpdateDecl(Decl *D,
- llvm::SmallVectorImpl<serialization::DeclID> &PendingLazySpecializationIDs) {
+void ASTDeclReader::UpdateDecl(
+ Decl *D,
+ llvm::SmallVectorImpl<GlobalDeclID> &PendingLazySpecializationIDs) {
while (Record.getIdx() < Record.size()) {
switch ((DeclUpdateKind)Record.readInt()) {
case UPD_CXX_ADDED_IMPLICIT_MEMBER: {
auto *RD = cast<CXXRecordDecl>(D);
- // FIXME: If we also have an update record for instantiating the
- // definition of D, we need that to happen before we get here.
Decl *MD = Record.readDecl();
assert(MD && "couldn't read decl from update record");
- // FIXME: We should call addHiddenDecl instead, to add the member
- // to its DeclContext.
- RD->addedMember(MD);
+ Reader.PendingAddedClassMembers.push_back({RD, MD});
break;
}
@@ -4458,15 +4563,7 @@ void ASTDeclReader::UpdateDecl(Decl *D,
auto *VD = cast<VarDecl>(D);
VD->NonParmVarDeclBits.IsInline = Record.readInt();
VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt();
- uint64_t Val = Record.readInt();
- if (Val && !VD->getInit()) {
- VD->setInit(Record.readExpr());
- if (Val != 1) {
- EvaluatedStmt *Eval = VD->ensureEvaluatedStmt();
- Eval->HasConstantInitialization = (Val & 2) != 0;
- Eval->HasConstantDestruction = (Val & 4) != 0;
- }
- }
+ ReadVarDeclInit(VD);
break;
}
@@ -4475,7 +4572,9 @@ void ASTDeclReader::UpdateDecl(Decl *D,
if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(D)) {
VTSD->setPointOfInstantiation(POI);
} else if (auto *VD = dyn_cast<VarDecl>(D)) {
- VD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
+ MemberSpecializationInfo *MSInfo = VD->getMemberSpecializationInfo();
+ assert(MSInfo && "No member specialization information");
+ MSInfo->setPointOfInstantiation(POI);
} else {
auto *FD = cast<FunctionDecl>(D);
if (auto *FTSInfo = FD->TemplateOrSpecialization
@@ -4509,7 +4608,7 @@ void ASTDeclReader::UpdateDecl(Decl *D,
// Only apply the update if the field still has an uninstantiated
// default member initializer.
- if (FD->hasInClassInitializer() && !FD->getInClassInitializer()) {
+ if (FD->hasInClassInitializer() && !FD->hasNonNullInClassInitializer()) {
if (DefaultInit)
FD->setInClassInitializer(DefaultInit);
else
@@ -4550,7 +4649,7 @@ void ASTDeclReader::UpdateDecl(Decl *D,
!Reader.PendingFakeDefinitionData.count(OldDD));
RD->setParamDestroyedInCallee(Record.readInt());
RD->setArgPassingRestrictions(
- (RecordDecl::ArgPassingKind)Record.readInt());
+ static_cast<RecordArgPassingKind>(Record.readInt()));
ReadCXXRecordDefinition(RD, /*Update*/true);
// Visible update is handled separately.
@@ -4587,7 +4686,7 @@ void ASTDeclReader::UpdateDecl(Decl *D,
}
}
- RD->setTagKind((TagTypeKind)Record.readInt());
+ RD->setTagKind(static_cast<TagTypeKind>(Record.readInt()));
RD->setLocation(readSourceLocation());
RD->setLocStart(readSourceLocation());
RD->setBraceRange(readSourceRange());
@@ -4663,19 +4762,18 @@ void ASTDeclReader::UpdateDecl(Decl *D,
break;
case UPD_DECL_MARKED_OPENMP_THREADPRIVATE:
- D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
- Reader.getContext(), readSourceRange(),
- AttributeCommonInfo::AS_Pragma));
+ D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(Reader.getContext(),
+ readSourceRange()));
break;
case UPD_DECL_MARKED_OPENMP_ALLOCATE: {
auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(Record.readInt());
Expr *Allocator = Record.readExpr();
+ Expr *Alignment = Record.readExpr();
SourceRange SR = readSourceRange();
D->addAttr(OMPAllocateDeclAttr::CreateImplicit(
- Reader.getContext(), AllocatorKind, Allocator, SR,
- AttributeCommonInfo::AS_Pragma));
+ Reader.getContext(), AllocatorKind, Allocator, Alignment, SR));
break;
}
@@ -4691,10 +4789,12 @@ void ASTDeclReader::UpdateDecl(Decl *D,
case UPD_DECL_MARKED_OPENMP_DECLARETARGET: {
auto MapType = Record.readEnum<OMPDeclareTargetDeclAttr::MapTypeTy>();
auto DevType = Record.readEnum<OMPDeclareTargetDeclAttr::DevTypeTy>();
+ Expr *IndirectE = Record.readExpr();
+ bool Indirect = Record.readBool();
unsigned Level = Record.readInt();
D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(
- Reader.getContext(), MapType, DevType, Level, readSourceRange(),
- AttributeCommonInfo::AS_Pragma));
+ Reader.getContext(), MapType, DevType, IndirectE, Indirect, Level,
+ readSourceRange()));
break;
}