summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp851
1 files changed, 593 insertions, 258 deletions
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
index b8102d8..9ed1bf9 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -99,16 +99,19 @@ namespace clang {
Module *readModule(const RecordData &R, unsigned &I) {
return Reader.getSubmodule(readSubmoduleID(R, I));
}
-
+
+ void ReadCXXRecordDefinition(CXXRecordDecl *D);
void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data,
const RecordData &R, unsigned &I);
+ void MergeDefinitionData(CXXRecordDecl *D,
+ struct CXXRecordDecl::DefinitionData &NewDD);
/// \brief RAII class used to capture the first ID within a redeclaration
/// chain and to introduce it into the list of pending redeclaration chains
/// on destruction.
///
- /// The caller can choose not to introduce this ID into the redeclaration
- /// chain by calling \c suppress().
+ /// The caller can choose not to introduce this ID into the list of pending
+ /// redeclaration chains by calling \c suppress().
class RedeclarableResult {
ASTReader &Reader;
GlobalDeclID FirstID;
@@ -160,8 +163,8 @@ namespace clang {
public:
FindExistingResult(ASTReader &Reader)
- : Reader(Reader), New(0), Existing(0), AddResult(false) { }
-
+ : Reader(Reader), New(nullptr), Existing(nullptr), AddResult(false) {}
+
FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing)
: Reader(Reader), New(New), Existing(Existing), AddResult(true) { }
@@ -195,9 +198,20 @@ namespace clang {
RawLocation(RawLocation), Record(Record), Idx(Idx),
TypeIDForTypeDecl(0), HasPendingBody(false) { }
+ template <typename DeclT>
+ static void attachPreviousDeclImpl(Redeclarable<DeclT> *D, Decl *Previous);
+ static void attachPreviousDeclImpl(...);
static void attachPreviousDecl(Decl *D, Decl *previous);
+
+ template <typename DeclT>
+ static void attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest);
+ static void attachLatestDeclImpl(...);
static void attachLatestDecl(Decl *D, Decl *latest);
+ template <typename DeclT>
+ static void markIncompleteDeclChainImpl(Redeclarable<DeclT> *D);
+ static void markIncompleteDeclChainImpl(...);
+
/// \brief Determine whether this declaration has a pending body.
bool hasPendingBody() const { return HasPendingBody; }
@@ -264,7 +278,7 @@ namespace clang {
void VisitImplicitParamDecl(ImplicitParamDecl *PD);
void VisitParmVarDecl(ParmVarDecl *PD);
void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
- void VisitTemplateDecl(TemplateDecl *D);
+ DeclID VisitTemplateDecl(TemplateDecl *D);
RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
void VisitClassTemplateDecl(ClassTemplateDecl *D);
void VisitVarTemplateDecl(VarTemplateDecl *D);
@@ -285,20 +299,26 @@ namespace clang {
void VisitEmptyDecl(EmptyDecl *D);
std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
-
- template<typename T>
+
+ template<typename T>
RedeclarableResult VisitRedeclarable(Redeclarable<T> *D);
template<typename T>
- void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl);
+ void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl,
+ DeclID TemplatePatternID = 0);
template<typename T>
void mergeRedeclarable(Redeclarable<T> *D, T *Existing,
- RedeclarableResult &Redecl);
+ RedeclarableResult &Redecl,
+ DeclID TemplatePatternID = 0);
template<typename T>
void mergeMergeable(Mergeable<T> *D);
+ void mergeTemplatePattern(RedeclarableTemplateDecl *D,
+ RedeclarableTemplateDecl *Existing,
+ DeclID DsID);
+
// FIXME: Reorder according to DeclNodes.td?
void VisitObjCMethodDecl(ObjCMethodDecl *D);
void VisitObjCContainerDecl(ObjCContainerDecl *D);
@@ -337,7 +357,7 @@ void ASTDeclReader::Visit(Decl *D) {
}
if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
- // if we have a fully initialized TypeDecl, we can safely read its type now.
+ // We have a fully initialized TypeDecl. Read its type now.
TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull());
} else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
// if we have a fully initialized TypeDecl, we can safely read its type now.
@@ -356,11 +376,14 @@ void ASTDeclReader::Visit(Decl *D) {
}
void ASTDeclReader::VisitDecl(Decl *D) {
- if (D->isTemplateParameter()) {
+ if (D->isTemplateParameter() || D->isTemplateParameterPack() ||
+ isa<ParmVarDecl>(D)) {
// We don't want to deserialize the DeclContext of a template
- // parameter immediately, because the template parameter might be
- // used in the formulation of its DeclContext. Use the translation
- // unit DeclContext as a placeholder.
+ // parameter or of a parameter of a function template immediately. These
+ // entities might be used in the formulation of its DeclContext (for
+ // example, a function parameter can be used in decltype() in trailing
+ // return type of the function). Use the translation unit DeclContext as a
+ // placeholder.
GlobalDeclID SemaDCIDForTemplateParmDecl = ReadDeclID(Record, Idx);
GlobalDeclID LexicalDCIDForTemplateParmDecl = ReadDeclID(Record, Idx);
Reader.addPendingDeclContextInfo(D,
@@ -409,7 +432,7 @@ void ASTDeclReader::VisitDecl(Decl *D) {
// Note that this declaration was hidden because its owning module is
// not yet visible.
- Reader.HiddenNamesMap[Owner].push_back(D);
+ Reader.HiddenNamesMap[Owner].HiddenDecls.push_back(D);
}
}
}
@@ -471,7 +494,8 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) {
} else
TD->NamedDeclOrQualifier = ReadDeclAs<NamedDecl>(Record, Idx);
- mergeRedeclarable(TD, Redecl);
+ if (!isa<CXXRecordDecl>(TD))
+ mergeRedeclarable(TD, Redecl);
return Redecl;
}
@@ -573,9 +597,10 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
switch ((FunctionDecl::TemplatedKind)Record[Idx++]) {
case FunctionDecl::TK_NonTemplate:
- mergeRedeclarable(FD, Redecl);
+ mergeRedeclarable(FD, Redecl);
break;
case FunctionDecl::TK_FunctionTemplate:
+ // Merged when we merge the template.
FD->setDescribedFunctionTemplate(ReadDeclAs<FunctionTemplateDecl>(Record,
Idx));
break;
@@ -585,6 +610,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
SourceLocation POI = ReadSourceLocation(Record, Idx);
FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK);
FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
+ mergeRedeclarable(FD, Redecl);
break;
}
case FunctionDecl::TK_FunctionTemplateSpecialization: {
@@ -622,7 +648,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FunctionTemplateSpecializationInfo *FTInfo
= FunctionTemplateSpecializationInfo::Create(C, FD, Template, TSK,
TemplArgList,
- HasTemplateArgumentsAsWritten ? &TemplArgsInfo : 0,
+ HasTemplateArgumentsAsWritten ? &TemplArgsInfo
+ : nullptr,
POI);
FD->TemplateOrSpecialization = FTInfo;
@@ -637,9 +664,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
// We avoid getASTContext because a decl in the parent hierarchy may
// be initializing.
llvm::FoldingSetNodeID ID;
- FunctionTemplateSpecializationInfo::Profile(ID, TemplArgs.data(),
- TemplArgs.size(), C);
- void *InsertPos = 0;
+ FunctionTemplateSpecializationInfo::Profile(ID, TemplArgs, C);
+ void *InsertPos = nullptr;
FunctionTemplateDecl::Common *CommonPtr = CanonTemplate->getCommonPtr();
CommonPtr->Specializations.FindNodeOrInsertPos(ID, InsertPos);
if (InsertPos)
@@ -670,6 +696,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FD->setDependentTemplateSpecialization(Reader.getContext(),
TemplDecls, TemplArgs);
+
+ // FIXME: Merging.
break;
}
}
@@ -709,8 +737,8 @@ void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]);
MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
MD->SetRelatedResultType(Record[Idx++]);
- MD->setResultType(Reader.readType(F, Record, Idx));
- MD->setResultTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
+ MD->setReturnType(Reader.readType(F, Record, Idx));
+ MD->setReturnTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
MD->DeclEndLoc = ReadSourceLocation(Record, Idx);
unsigned NumParams = Record[Idx++];
SmallVector<ParmVarDecl *, 16> Params;
@@ -755,6 +783,7 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
Data.SuperClassLoc = ReadSourceLocation(Record, Idx);
Data.EndLoc = ReadSourceLocation(Record, Idx);
+ Data.HasDesignatedInitializers = Record[Idx++];
// Read the directly referenced protocols and their SourceLocations.
unsigned NumProtocols = Record[Idx++];
@@ -779,8 +808,8 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
Reader.getContext());
// We will rebuild this list lazily.
- ID->setIvarList(0);
-
+ ID->setIvarList(nullptr);
+
// Note that we have deserialized a definition.
Reader.PendingDefinitions.insert(ID);
@@ -795,11 +824,9 @@ void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) {
VisitFieldDecl(IVD);
IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record[Idx++]);
// This field will be built lazily.
- IVD->setNextIvar(0);
+ IVD->setNextIvar(nullptr);
bool synth = Record[Idx++];
IVD->setSynthesize(synth);
- bool backingIvarReferencedInAccessor = Record[Idx++];
- IVD->setBackingIvarReferencedInAccessor(backingIvarReferencedInAccessor);
}
void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
@@ -907,8 +934,8 @@ void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
D->setIvarRBraceLoc(ReadSourceLocation(Record, Idx));
D->setHasNonZeroConstructors(Record[Idx++]);
D->setHasDestructors(Record[Idx++]);
- llvm::tie(D->IvarInitializers, D->NumIvarInitializers)
- = Reader.ReadCXXCtorInitializers(F, Record, Idx);
+ std::tie(D->IvarInitializers, D->NumIvarInitializers) =
+ Reader.ReadCXXCtorInitializers(F, Record, Idx);
}
@@ -971,14 +998,10 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
VD->setCachedLinkage(VarLinkage);
// Reconstruct the one piece of the IdentifierNamespace that we need.
- if (VarLinkage != NoLinkage &&
+ if (VD->getStorageClass() == SC_Extern && VarLinkage != NoLinkage &&
VD->getLexicalDeclContext()->isFunctionOrMethod())
VD->setLocalExternDecl();
- // Only true variables (not parameters or implicit parameters) can be merged.
- if (VD->getKind() != Decl::ParmVar && VD->getKind() != Decl::ImplicitParam)
- mergeRedeclarable(VD, Redecl);
-
if (uint64_t Val = Record[Idx++]) {
VD->setInit(Reader.ReadExpr(F));
if (Val > 1) {
@@ -993,8 +1016,13 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
};
switch ((VarKind)Record[Idx++]) {
case VarNotTemplate:
+ // Only true variables (not parameters or implicit parameters) can be merged
+ if (VD->getKind() != Decl::ParmVar && VD->getKind() != Decl::ImplicitParam &&
+ !isa<VarTemplateSpecializationDecl>(VD))
+ mergeRedeclarable(VD, Redecl);
break;
case VarTemplate:
+ // Merged when we merge the template.
VD->setDescribedVarTemplate(ReadDeclAs<VarTemplateDecl>(Record, Idx));
break;
case StaticDataMemberSpecialization: { // HasMemberSpecializationInfo.
@@ -1002,6 +1030,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
SourceLocation POI = ReadSourceLocation(Record, Idx);
Reader.getContext().setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI);
+ mergeRedeclarable(VD, Redecl);
break;
}
}
@@ -1065,7 +1094,7 @@ void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) {
unsigned flags = Record[Idx++];
bool byRef = (flags & 1);
bool nested = (flags & 2);
- Expr *copyExpr = ((flags & 4) ? Reader.ReadExpr(F) : 0);
+ Expr *copyExpr = ((flags & 4) ? Reader.ReadExpr(F) : nullptr);
captures.push_back(BlockDecl::Capture(decl, byRef, nested, copyExpr));
}
@@ -1075,9 +1104,15 @@ void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) {
void ASTDeclReader::VisitCapturedDecl(CapturedDecl *CD) {
VisitDecl(CD);
+ unsigned ContextParamPos = Record[Idx++];
+ CD->setNothrow(Record[Idx++] != 0);
// Body is set by VisitCapturedStmt.
- for (unsigned i = 0; i < CD->NumParams; ++i)
- CD->setParam(i, ReadDeclAs<ImplicitParamDecl>(Record, Idx));
+ for (unsigned I = 0; I < CD->NumParams; ++I) {
+ if (I != ContextParamPos)
+ CD->setParam(I, ReadDeclAs<ImplicitParamDecl>(Record, Idx));
+ else
+ CD->setContextParam(I, ReadDeclAs<ImplicitParamDecl>(Record, Idx));
+ }
}
void ASTDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
@@ -1099,8 +1134,6 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
D->setInline(Record[Idx++]);
D->LocStart = ReadSourceLocation(Record, Idx);
D->RBraceLoc = ReadSourceLocation(Record, Idx);
- // FIXME: At the point of this call, D->getCanonicalDecl() returns 0.
- mergeRedeclarable(D, Redecl);
if (Redecl.getFirstID() == ThisDeclID) {
// Each module has its own anonymous namespace, which is disjoint from
@@ -1114,6 +1147,8 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
// been deserialized.
D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDecl());
}
+
+ mergeRedeclarable(D, Redecl);
}
void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
@@ -1186,6 +1221,7 @@ void ASTDeclReader::ReadCXXDefinitionData(
Data.HasProtectedFields = Record[Idx++];
Data.HasPublicFields = Record[Idx++];
Data.HasMutableFields = Record[Idx++];
+ Data.HasVariantMembers = Record[Idx++];
Data.HasOnlyCMembers = Record[Idx++];
Data.HasInClassInitializer = Record[Idx++];
Data.HasUninitializedReferenceMember = Record[Idx++];
@@ -1196,6 +1232,7 @@ void ASTDeclReader::ReadCXXDefinitionData(
Data.DefaultedMoveAssignmentIsDeleted = Record[Idx++];
Data.DefaultedDestructorIsDeleted = Record[Idx++];
Data.HasTrivialSpecialMembers = Record[Idx++];
+ Data.DeclaredNonTrivialSpecialMembers = Record[Idx++];
Data.HasIrrelevantDestructor = Record[Idx++];
Data.HasConstexprNonCopyMoveConstructor = Record[Idx++];
Data.DefaultedDefaultConstructorIsConstexpr = Record[Idx++];
@@ -1222,7 +1259,7 @@ void ASTDeclReader::ReadCXXDefinitionData(
Data.FirstFriend = ReadDeclID(Record, Idx);
if (Data.IsLambda) {
- typedef LambdaExpr::Capture Capture;
+ typedef LambdaCapture Capture;
CXXRecordDecl::LambdaDefinitionData &Lambda
= static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data);
Lambda.Dependent = Record[Idx++];
@@ -1242,7 +1279,7 @@ void ASTDeclReader::ReadCXXDefinitionData(
LambdaCaptureKind Kind = static_cast<LambdaCaptureKind>(Record[Idx++]);
switch (Kind) {
case LCK_This:
- *ToCapture++ = Capture(Loc, IsImplicit, Kind, 0, SourceLocation());
+ *ToCapture++ = Capture(Loc, IsImplicit, Kind, nullptr,SourceLocation());
break;
case LCK_ByCopy:
case LCK_ByRef:
@@ -1255,61 +1292,172 @@ void ASTDeclReader::ReadCXXDefinitionData(
}
}
+void ASTDeclReader::MergeDefinitionData(
+ CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &MergeDD) {
+ assert(D->DefinitionData.getNotUpdated() &&
+ "merging class definition into non-definition");
+ auto &DD = *D->DefinitionData.getNotUpdated();
+
+ // If the new definition has new special members, let the name lookup
+ // code know that it needs to look in the new definition too.
+ if ((MergeDD.DeclaredSpecialMembers & ~DD.DeclaredSpecialMembers) &&
+ DD.Definition != MergeDD.Definition) {
+ Reader.MergedLookups[DD.Definition].push_back(MergeDD.Definition);
+ DD.Definition->setHasExternalVisibleStorage();
+ }
+
+ // FIXME: Move this out into a .def file?
+ // FIXME: Issue a diagnostic on a mismatched MATCH_FIELD, rather than
+ // asserting; this can happen in the case of an ODR violation.
+ bool DetectedOdrViolation = false;
+#define OR_FIELD(Field) DD.Field |= MergeDD.Field;
+#define MATCH_FIELD(Field) \
+ DetectedOdrViolation |= DD.Field != MergeDD.Field; \
+ OR_FIELD(Field)
+ MATCH_FIELD(UserDeclaredConstructor)
+ MATCH_FIELD(UserDeclaredSpecialMembers)
+ MATCH_FIELD(Aggregate)
+ MATCH_FIELD(PlainOldData)
+ MATCH_FIELD(Empty)
+ MATCH_FIELD(Polymorphic)
+ MATCH_FIELD(Abstract)
+ MATCH_FIELD(IsStandardLayout)
+ MATCH_FIELD(HasNoNonEmptyBases)
+ MATCH_FIELD(HasPrivateFields)
+ MATCH_FIELD(HasProtectedFields)
+ MATCH_FIELD(HasPublicFields)
+ MATCH_FIELD(HasMutableFields)
+ MATCH_FIELD(HasVariantMembers)
+ MATCH_FIELD(HasOnlyCMembers)
+ MATCH_FIELD(HasInClassInitializer)
+ MATCH_FIELD(HasUninitializedReferenceMember)
+ MATCH_FIELD(NeedOverloadResolutionForMoveConstructor)
+ MATCH_FIELD(NeedOverloadResolutionForMoveAssignment)
+ MATCH_FIELD(NeedOverloadResolutionForDestructor)
+ MATCH_FIELD(DefaultedMoveConstructorIsDeleted)
+ MATCH_FIELD(DefaultedMoveAssignmentIsDeleted)
+ MATCH_FIELD(DefaultedDestructorIsDeleted)
+ OR_FIELD(HasTrivialSpecialMembers)
+ OR_FIELD(DeclaredNonTrivialSpecialMembers)
+ MATCH_FIELD(HasIrrelevantDestructor)
+ OR_FIELD(HasConstexprNonCopyMoveConstructor)
+ MATCH_FIELD(DefaultedDefaultConstructorIsConstexpr)
+ OR_FIELD(HasConstexprDefaultConstructor)
+ MATCH_FIELD(HasNonLiteralTypeFieldsOrBases)
+ // ComputedVisibleConversions is handled below.
+ MATCH_FIELD(UserProvidedDefaultConstructor)
+ OR_FIELD(DeclaredSpecialMembers)
+ MATCH_FIELD(ImplicitCopyConstructorHasConstParam)
+ MATCH_FIELD(ImplicitCopyAssignmentHasConstParam)
+ OR_FIELD(HasDeclaredCopyConstructorWithConstParam)
+ OR_FIELD(HasDeclaredCopyAssignmentWithConstParam)
+ MATCH_FIELD(IsLambda)
+#undef OR_FIELD
+#undef MATCH_FIELD
+
+ if (DD.NumBases != MergeDD.NumBases || DD.NumVBases != MergeDD.NumVBases)
+ DetectedOdrViolation = true;
+ // FIXME: Issue a diagnostic if the base classes don't match when we come
+ // to lazily load them.
+
+ // FIXME: Issue a diagnostic if the list of conversion functions doesn't
+ // match when we come to lazily load them.
+ if (MergeDD.ComputedVisibleConversions && !DD.ComputedVisibleConversions) {
+ DD.VisibleConversions = std::move(MergeDD.VisibleConversions);
+ DD.ComputedVisibleConversions = true;
+ }
+
+ // FIXME: Issue a diagnostic if FirstFriend doesn't match when we come to
+ // 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).
+ }
+
+ if (DetectedOdrViolation)
+ Reader.PendingOdrMergeFailures[DD.Definition].push_back(MergeDD.Definition);
+}
+
+void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D) {
+ 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[Idx++];
+ if (IsLambda)
+ DD = new (C) CXXRecordDecl::LambdaDefinitionData(D, nullptr, false, false,
+ LCD_None);
+ else
+ DD = new (C) struct CXXRecordDecl::DefinitionData(D);
+
+ ReadCXXDefinitionData(*DD, Record, Idx);
+
+ // If we're reading an update record, we might already have a definition for
+ // this record. If so, just merge into it.
+ if (D->DefinitionData.getNotUpdated()) {
+ MergeDefinitionData(D, *DD);
+ return;
+ }
+
+ // Propagate the DefinitionData pointer to the canonical declaration, so
+ // that all other deserialized declarations will see it.
+ CXXRecordDecl *Canon = D->getCanonicalDecl();
+ if (Canon == D) {
+ D->DefinitionData = DD;
+ D->IsCompleteDefinition = true;
+ } else if (auto *CanonDD = Canon->DefinitionData.getNotUpdated()) {
+ // We have already deserialized a definition of this record. This
+ // definition is no longer really a definition. Note that the pre-existing
+ // definition is the *real* definition.
+ Reader.MergedDeclContexts.insert(
+ std::make_pair(D, CanonDD->Definition));
+ D->DefinitionData = Canon->DefinitionData;
+ D->IsCompleteDefinition = false;
+ MergeDefinitionData(D, *DD);
+ } else {
+ Canon->DefinitionData = DD;
+ D->DefinitionData = Canon->DefinitionData;
+ D->IsCompleteDefinition = true;
+
+ // Note that we have deserialized a definition. Any declarations
+ // deserialized before this one will be be given the DefinitionData
+ // pointer at the end.
+ Reader.PendingDefinitions.insert(D);
+ }
+}
+
ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
RedeclarableResult Redecl = VisitRecordDeclImpl(D);
ASTContext &C = Reader.getContext();
- bool WasDefinition = Record[Idx++];
- if (WasDefinition) {
- // Determine whether this is a lambda closure type, so that we can
- // allocate the appropriate DefinitionData structure.
- bool IsLambda = Record[Idx++];
- if (IsLambda)
- D->DefinitionData = new (C) CXXRecordDecl::LambdaDefinitionData(D, 0,
- false,
- false, LCD_None);
- else
- D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D);
-
- ReadCXXDefinitionData(*D->DefinitionData, Record, Idx);
-
- // Propagate the DefinitionData pointer to the canonical declaration, so
- // that all other deserialized declarations will see it.
- CXXRecordDecl *Canon = D->getCanonicalDecl();
- if (Canon == D) {
- // Nothing to do.
- } else if (!Canon->DefinitionData) {
- Canon->DefinitionData = D->DefinitionData;
-
- // Note that we have deserialized a definition. Any declarations
- // deserialized before this one will be be given the DefinitionData
- // pointer at the end.
- Reader.PendingDefinitions.insert(D);
- } else {
- // We have already deserialized a definition of this record. This
- // definition is no longer really a definition. Note that the pre-existing
- // definition is the *real* definition.
- // FIXME: Check DefinitionData for consistency with prior definition.
- Reader.MergedDeclContexts.insert(
- std::make_pair(D, D->getCanonicalDecl()->DefinitionData->Definition));
- D->IsCompleteDefinition = false;
- D->DefinitionData = D->getCanonicalDecl()->DefinitionData;
- }
- } else {
- // Propagate DefinitionData pointer from the canonical declaration.
- D->DefinitionData = D->getCanonicalDecl()->DefinitionData;
- }
enum CXXRecKind {
CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization
};
switch ((CXXRecKind)Record[Idx++]) {
case CXXRecNotTemplate:
+ // Merged when we merge the folding set entry in the primary template.
+ if (!isa<ClassTemplateSpecializationDecl>(D))
+ mergeRedeclarable(D, Redecl);
+ break;
+ case CXXRecTemplate: {
+ // Merged when we merge the template.
+ ClassTemplateDecl *Template = ReadDeclAs<ClassTemplateDecl>(Record, Idx);
+ D->TemplateOrInstantiation = Template;
+ if (!Template->getTemplatedDecl()) {
+ // We've not actually loaded the ClassTemplateDecl yet, because we're
+ // currently being loaded as its pattern. Rely on it to set up our
+ // TypeForDecl (see VisitClassTemplateDecl).
+ //
+ // Beware: we do not yet know our canonical declaration, and may still
+ // get merged once the surrounding class template has got off the ground.
+ TypeIDForTypeDecl = 0;
+ }
break;
- case CXXRecTemplate:
- D->TemplateOrInstantiation = ReadDeclAs<ClassTemplateDecl>(Record, Idx);
- break;
+ }
case CXXRecMemberSpecialization: {
CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(Record, Idx);
TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
@@ -1317,15 +1465,26 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
MemberSpecializationInfo *MSI = new (C) MemberSpecializationInfo(RD, TSK);
MSI->setPointOfInstantiation(POI);
D->TemplateOrInstantiation = MSI;
+ mergeRedeclarable(D, Redecl);
break;
}
}
+ bool WasDefinition = Record[Idx++];
+ if (WasDefinition)
+ ReadCXXRecordDefinition(D);
+ else
+ // Propagate DefinitionData pointer from the canonical declaration.
+ D->DefinitionData = D->getCanonicalDecl()->DefinitionData;
+
// Lazily load the key function to avoid deserializing every method so we can
// compute it.
if (WasDefinition) {
DeclID KeyFn = ReadDeclID(Record, Idx);
if (KeyFn && 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;
}
@@ -1345,10 +1504,13 @@ void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
VisitCXXMethodDecl(D);
-
+
+ if (auto *CD = ReadDeclAs<CXXConstructorDecl>(Record, Idx))
+ D->setInheritedConstructor(CD);
D->IsExplicitSpecified = Record[Idx++];
- llvm::tie(D->CtorInitializers, D->NumCtorInitializers)
- = Reader.ReadCXXCtorInitializers(F, Record, Idx);
+ // FIXME: We should defer loading this until we need the constructor's body.
+ std::tie(D->CtorInitializers, D->NumCtorInitializers) =
+ Reader.ReadCXXCtorInitializers(F, Record, Idx);
}
void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
@@ -1404,16 +1566,19 @@ void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
D->FriendLoc = ReadSourceLocation(Record, Idx);
}
-void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
+DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
VisitNamedDecl(D);
- NamedDecl *TemplatedDecl = ReadDeclAs<NamedDecl>(Record, Idx);
+ DeclID PatternID = ReadDeclID(Record, Idx);
+ NamedDecl *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID));
TemplateParameterList* TemplateParams
= Reader.ReadTemplateParameterList(F, Record, Idx);
D->init(TemplatedDecl, TemplateParams);
// FIXME: If this is a redeclaration of a template from another module, handle
// inheritance of default template arguments.
+
+ return PatternID;
}
ASTDeclReader::RedeclarableResult
@@ -1442,10 +1607,10 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
}
}
- VisitTemplateDecl(D);
+ DeclID PatternID = VisitTemplateDecl(D);
D->IdentifierNamespace = Record[Idx++];
- mergeRedeclarable(D, Redecl);
+ mergeRedeclarable(D, Redecl, PatternID);
// If we merged the template with a prior declaration chain, merge the common
// pointer.
@@ -1486,8 +1651,14 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
memcpy(CommonPtr->LazySpecializations, SpecIDs.data(),
SpecIDs.size() * sizeof(DeclID));
}
-
- CommonPtr->InjectedClassNameType = Reader.readType(F, Record, Idx);
+ }
+
+ if (D->getTemplatedDecl()->TemplateOrInstantiation) {
+ // We were loaded before our templated declaration was. We've not set up
+ // its corresponding type yet (see VisitCXXRecordDeclImpl), so reconstruct
+ // it now.
+ Reader.Context.getInjectedClassNameType(
+ D->getTemplatedDecl(), D->getInjectedClassNameSpecialization());
}
}
@@ -1580,18 +1751,18 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
// This declaration might be a definition. Merge with any existing
// definition.
- if (D->DefinitionData) {
- if (!CanonSpec->DefinitionData) {
- CanonSpec->DefinitionData = D->DefinitionData;
- } else {
- // FIXME: Check DefinitionData for consistency with prior definition
+ if (auto *DDD = D->DefinitionData.getNotUpdated()) {
+ if (auto *CanonDD = CanonSpec->DefinitionData.getNotUpdated()) {
+ MergeDefinitionData(CanonSpec, *DDD);
Reader.PendingDefinitions.erase(D);
Reader.MergedDeclContexts.insert(
- std::make_pair(D, CanonSpec->DefinitionData->Definition));
+ std::make_pair(D, CanonDD->Definition));
D->IsCompleteDefinition = false;
- D->DefinitionData = CanonSpec->DefinitionData;
+ } else {
+ CanonSpec->DefinitionData = D->DefinitionData;
}
}
+ D->DefinitionData = CanonSpec->DefinitionData;
}
}
}
@@ -1838,65 +2009,111 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
/// \brief Attempts to merge the given declaration (D) with another declaration
/// of the same entity.
template<typename T>
-void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D,
- RedeclarableResult &Redecl) {
+void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase,
+ RedeclarableResult &Redecl,
+ DeclID TemplatePatternID) {
+ T *D = static_cast<T*>(DBase);
+ T *DCanon = D->getCanonicalDecl();
+ if (D != DCanon &&
+ (!Reader.getContext().getLangOpts().Modules ||
+ Reader.getOwningModuleFile(DCanon) == Reader.getOwningModuleFile(D))) {
+ // All redeclarations between this declaration and its originally-canonical
+ // declaration get pulled in when we load DCanon; we don't need to
+ // perform any more merging now.
+ Redecl.suppress();
+ }
+
// If modules are not available, there is no reason to perform this merge.
if (!Reader.getContext().getLangOpts().Modules)
return;
- if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D)))
+ if (FindExistingResult ExistingRes = findExisting(D))
if (T *Existing = ExistingRes)
- mergeRedeclarable(D, Existing, Redecl);
+ mergeRedeclarable(D, Existing, Redecl, TemplatePatternID);
+}
+
+/// \brief "Cast" to type T, asserting if we don't have an implicit conversion.
+/// We use this to put code in a template that will only be valid for certain
+/// instantiations.
+template<typename T> static T assert_cast(T t) { return t; }
+template<typename T> static T assert_cast(...) {
+ llvm_unreachable("bad assert_cast");
+}
+
+/// \brief Merge together the pattern declarations from two template
+/// declarations.
+void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D,
+ RedeclarableTemplateDecl *Existing,
+ DeclID DsID) {
+ auto *DPattern = D->getTemplatedDecl();
+ auto *ExistingPattern = Existing->getTemplatedDecl();
+ RedeclarableResult Result(Reader, DPattern->getCanonicalDecl()->getGlobalID(),
+ DPattern->getKind());
+ if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern)) {
+ // Merge with any existing definition.
+ // FIXME: This is duplicated in several places. Refactor.
+ auto *ExistingClass =
+ cast<CXXRecordDecl>(ExistingPattern)->getCanonicalDecl();
+ if (auto *DDD = DClass->DefinitionData.getNotUpdated()) {
+ if (auto *ExistingDD = ExistingClass->DefinitionData.getNotUpdated()) {
+ MergeDefinitionData(ExistingClass, *DDD);
+ Reader.PendingDefinitions.erase(DClass);
+ Reader.MergedDeclContexts.insert(
+ std::make_pair(DClass, ExistingDD->Definition));
+ DClass->IsCompleteDefinition = false;
+ } else {
+ ExistingClass->DefinitionData = DClass->DefinitionData;
+ }
+ }
+ DClass->DefinitionData = ExistingClass->DefinitionData;
+
+ return mergeRedeclarable(DClass, cast<TagDecl>(ExistingPattern),
+ Result);
+ }
+ if (auto *DFunction = dyn_cast<FunctionDecl>(DPattern))
+ return mergeRedeclarable(DFunction, cast<FunctionDecl>(ExistingPattern),
+ Result);
+ if (auto *DVar = dyn_cast<VarDecl>(DPattern))
+ return mergeRedeclarable(DVar, cast<VarDecl>(ExistingPattern), Result);
+ llvm_unreachable("merged an unknown kind of redeclarable template");
}
/// \brief Attempts to merge the given declaration (D) with another declaration
/// of the same entity.
template<typename T>
-void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D, T *Existing,
- RedeclarableResult &Redecl) {
+void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
+ RedeclarableResult &Redecl,
+ DeclID TemplatePatternID) {
+ T *D = static_cast<T*>(DBase);
T *ExistingCanon = Existing->getCanonicalDecl();
- T *DCanon = static_cast<T*>(D)->getCanonicalDecl();
+ T *DCanon = D->getCanonicalDecl();
if (ExistingCanon != DCanon) {
+ assert(DCanon->getGlobalID() == Redecl.getFirstID());
+
// Have our redeclaration link point back at the canonical declaration
- // of the existing declaration, so that this declaration has the
+ // of the existing declaration, so that this declaration has the
// appropriate canonical declaration.
D->RedeclLink = Redeclarable<T>::PreviousDeclLink(ExistingCanon);
// When we merge a namespace, update its pointer to the first namespace.
- if (NamespaceDecl *Namespace
- = dyn_cast<NamespaceDecl>(static_cast<T*>(D))) {
+ if (auto *Namespace = dyn_cast<NamespaceDecl>(D))
Namespace->AnonOrFirstNamespaceAndInline.setPointer(
- static_cast<NamespaceDecl *>(static_cast<void*>(ExistingCanon)));
- }
+ assert_cast<NamespaceDecl*>(ExistingCanon));
- // Don't introduce DCanon into the set of pending declaration chains.
- Redecl.suppress();
-
- // Introduce ExistingCanon into the set of pending declaration chains,
- // if in fact it came from a module file.
- if (ExistingCanon->isFromASTFile()) {
- GlobalDeclID ExistingCanonID = ExistingCanon->getGlobalID();
- assert(ExistingCanonID && "Unrecorded canonical declaration ID?");
- if (Reader.PendingDeclChainsKnown.insert(ExistingCanonID))
- Reader.PendingDeclChains.push_back(ExistingCanonID);
- }
+ // When we merge a template, merge its pattern.
+ if (auto *DTemplate = dyn_cast<RedeclarableTemplateDecl>(D))
+ mergeTemplatePattern(
+ DTemplate, assert_cast<RedeclarableTemplateDecl*>(ExistingCanon),
+ TemplatePatternID);
// If this declaration was the canonical declaration, make a note of
// that. We accept the linear algorithm here because the number of
// unique canonical declarations of an entity should always be tiny.
- if (DCanon == static_cast<T*>(D)) {
+ if (DCanon == D) {
SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon];
if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID())
== Merged.end())
Merged.push_back(Redecl.getFirstID());
-
- // If ExistingCanon did not come from a module file, introduce the
- // first declaration that *does* come from a module file to the
- // set of pending declaration chains, so that we merge this
- // declaration.
- if (!ExistingCanon->isFromASTFile() &&
- Reader.PendingDeclChainsKnown.insert(Redecl.getFirstID()))
- Reader.PendingDeclChains.push_back(Merged[0]);
}
}
}
@@ -1942,7 +2159,7 @@ void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
void ASTReader::ReadAttributes(ModuleFile &F, AttrVec &Attrs,
const RecordData &Record, unsigned &Idx) {
for (unsigned i = 0, e = Record[Idx++]; i != e; ++i) {
- Attr *New = 0;
+ Attr *New = nullptr;
attr::Kind Kind = (attr::Kind)Record[Idx++];
SourceRange Range = ReadSourceRange(F, Record, Idx);
@@ -1981,7 +2198,8 @@ static bool isConsumerInterestedIn(Decl *D, bool HasBody) {
if (isa<FileScopeAsmDecl>(D) ||
isa<ObjCProtocolDecl>(D) ||
- isa<ObjCImplDecl>(D))
+ isa<ObjCImplDecl>(D) ||
+ isa<ImportDecl>(D))
return true;
if (VarDecl *Var = dyn_cast<VarDecl>(D))
return Var->isFileVarDecl() &&
@@ -2143,9 +2361,7 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
// Fields with the same name and the same type match.
if (FieldDecl *FDX = dyn_cast<FieldDecl>(X)) {
FieldDecl *FDY = cast<FieldDecl>(Y);
- // FIXME: Diagnose if the types don't match. More generally, diagnose if we
- // get a declaration in a class definition that isn't in the canonical class
- // definition.
+ // FIXME: Diagnose if the types don't match.
// FIXME: Also check the bitwidth is odr-equivalent, if any.
return X->getASTContext().hasSameType(FDX->getType(), FDY->getType());
}
@@ -2175,9 +2391,10 @@ static DeclContext *getPrimaryContextForMerging(DeclContext *DC) {
return RD->getDefinition();
if (EnumDecl *ED = dyn_cast<EnumDecl>(DC))
- return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition() : 0;
+ return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition()
+ : nullptr;
- return 0;
+ return nullptr;
}
ASTDeclReader::FindExistingResult::~FindExistingResult() {
@@ -2198,7 +2415,9 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
DeclarationName Name = D->getDeclName();
if (!Name) {
// Don't bother trying to find unnamed declarations.
- FindExistingResult Result(Reader, D, /*Existing=*/0);
+ FindExistingResult Result(Reader, D, /*Existing=*/nullptr);
+ // FIXME: We may still need to pull in the redeclaration chain; there can
+ // be redeclarations via 'decltype'.
Result.suppress();
return Result;
}
@@ -2252,33 +2471,34 @@ 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.
+ //
+ // FIXME: We should do something similar if we merge two definitions of the
+ // same template specialization into the same CXXRecordDecl.
if (Reader.MergedDeclContexts.count(D->getLexicalDeclContext()))
Reader.PendingOdrMergeChecks.push_back(D);
- return FindExistingResult(Reader, D, /*Existing=*/0);
+ return FindExistingResult(Reader, D, /*Existing=*/nullptr);
}
-void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) {
- assert(D && previous);
- if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
- TD->RedeclLink.setNext(cast<TagDecl>(previous));
- } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- FD->RedeclLink.setNext(cast<FunctionDecl>(previous));
- } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
- VD->RedeclLink.setNext(cast<VarDecl>(previous));
- } else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
- TD->RedeclLink.setNext(cast<TypedefNameDecl>(previous));
- } else if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) {
- USD->RedeclLink.setNext(cast<UsingShadowDecl>(previous));
- } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
- ID->RedeclLink.setNext(cast<ObjCInterfaceDecl>(previous));
- } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
- PD->RedeclLink.setNext(cast<ObjCProtocolDecl>(previous));
- } else if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) {
- ND->RedeclLink.setNext(cast<NamespaceDecl>(previous));
- } else {
- RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
- TD->RedeclLink.setNext(cast<RedeclarableTemplateDecl>(previous));
+template<typename DeclT>
+void ASTDeclReader::attachPreviousDeclImpl(Redeclarable<DeclT> *D,
+ Decl *Previous) {
+ D->RedeclLink.setPrevious(cast<DeclT>(Previous));
+}
+void ASTDeclReader::attachPreviousDeclImpl(...) {
+ llvm_unreachable("attachPreviousDecl on non-redeclarable declaration");
+}
+
+void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *Previous) {
+ assert(D && Previous);
+
+ switch (D->getKind()) {
+#define ABSTRACT_DECL(TYPE)
+#define DECL(TYPE, BASE) \
+ case Decl::TYPE: \
+ attachPreviousDeclImpl(cast<TYPE##Decl>(D), Previous); \
+ break;
+#include "clang/AST/DeclNodes.inc"
}
// If the declaration was visible in one module, a redeclaration of it in
@@ -2287,46 +2507,78 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) {
// FIXME: In this case, the declaration should only be visible if a module
// that makes it visible has been imported.
D->IdentifierNamespace |=
- previous->IdentifierNamespace &
+ Previous->IdentifierNamespace &
(Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type);
+
+ // If the previous declaration is marked as used, then this declaration should
+ // be too.
+ if (Previous->Used)
+ D->Used = true;
+
+ // If the previous declaration is an inline function declaration, then this
+ // declaration is too.
+ if (auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (cast<FunctionDecl>(Previous)->IsInline != FD->IsInline) {
+ // FIXME: [dcl.fct.spec]p4:
+ // If a function with external linkage is declared inline in one
+ // translation unit, it shall be declared inline in all translation
+ // units in which it appears.
+ //
+ // Be careful of this case:
+ //
+ // module A:
+ // template<typename T> struct X { void f(); };
+ // template<typename T> inline void X<T>::f() {}
+ //
+ // module B instantiates the declaration of X<int>::f
+ // module C instantiates the definition of X<int>::f
+ //
+ // If module B and C are merged, we do not have a violation of this rule.
+ //
+ //if (!FD->IsInline || Previous->getOwningModule())
+ // Diag(FD->getLocation(), diag::err_odr_differing_inline);
+ FD->IsInline = true;
+ }
+ }
+}
+
+template<typename DeclT>
+void ASTDeclReader::attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest) {
+ D->RedeclLink.setLatest(cast<DeclT>(Latest));
+}
+void ASTDeclReader::attachLatestDeclImpl(...) {
+ llvm_unreachable("attachLatestDecl on non-redeclarable declaration");
}
void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) {
assert(D && Latest);
- if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
- TD->RedeclLink
- = Redeclarable<TagDecl>::LatestDeclLink(cast<TagDecl>(Latest));
- } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- FD->RedeclLink
- = Redeclarable<FunctionDecl>::LatestDeclLink(cast<FunctionDecl>(Latest));
- } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
- VD->RedeclLink
- = Redeclarable<VarDecl>::LatestDeclLink(cast<VarDecl>(Latest));
- } else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
- TD->RedeclLink
- = Redeclarable<TypedefNameDecl>::LatestDeclLink(
- cast<TypedefNameDecl>(Latest));
- } else if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) {
- USD->RedeclLink
- = Redeclarable<UsingShadowDecl>::LatestDeclLink(
- cast<UsingShadowDecl>(Latest));
- } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
- ID->RedeclLink
- = Redeclarable<ObjCInterfaceDecl>::LatestDeclLink(
- cast<ObjCInterfaceDecl>(Latest));
- } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
- PD->RedeclLink
- = Redeclarable<ObjCProtocolDecl>::LatestDeclLink(
- cast<ObjCProtocolDecl>(Latest));
- } else if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D)) {
- ND->RedeclLink
- = Redeclarable<NamespaceDecl>::LatestDeclLink(
- cast<NamespaceDecl>(Latest));
- } else {
- RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
- TD->RedeclLink
- = Redeclarable<RedeclarableTemplateDecl>::LatestDeclLink(
- cast<RedeclarableTemplateDecl>(Latest));
+
+ switch (D->getKind()) {
+#define ABSTRACT_DECL(TYPE)
+#define DECL(TYPE, BASE) \
+ case Decl::TYPE: \
+ attachLatestDeclImpl(cast<TYPE##Decl>(D), Latest); \
+ break;
+#include "clang/AST/DeclNodes.inc"
+ }
+}
+
+template<typename DeclT>
+void ASTDeclReader::markIncompleteDeclChainImpl(Redeclarable<DeclT> *D) {
+ D->RedeclLink.markIncomplete();
+}
+void ASTDeclReader::markIncompleteDeclChainImpl(...) {
+ llvm_unreachable("markIncompleteDeclChain on non-redeclarable declaration");
+}
+
+void ASTReader::markIncompleteDeclChain(Decl *D) {
+ switch (D->getKind()) {
+#define ABSTRACT_DECL(TYPE)
+#define DECL(TYPE, BASE) \
+ case Decl::TYPE: \
+ ASTDeclReader::markIncompleteDeclChainImpl(cast<TYPE##Decl>(D)); \
+ break;
+#include "clang/AST/DeclNodes.inc"
}
}
@@ -2374,7 +2626,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
unsigned Idx = 0;
ASTDeclReader Reader(*this, *Loc.F, ID, RawLocation, Record,Idx);
- Decl *D = 0;
+ Decl *D = nullptr;
switch ((DeclCode)DeclsCursor.readRecord(Code, Record)) {
case DECL_CONTEXT_LEXICAL:
case DECL_CONTEXT_VISIBLE:
@@ -2556,7 +2808,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
break;
case DECL_CXX_BASE_SPECIFIERS:
Error("attempt to read a C++ base-specifier record as a declaration");
- return 0;
+ return nullptr;
case DECL_IMPORT:
// Note: last entry of the ImportDecl record is the number of stored source
// locations.
@@ -2595,7 +2847,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
LookupDC->setHasExternalVisibleStorage(true);
if (ReadDeclContextStorage(*Loc.F, DeclsCursor, Offsets,
Loc.F->DeclContextInfos[DC]))
- return 0;
+ return nullptr;
}
// Now add the pending visible updates for this decl context, if it has any.
@@ -2605,12 +2857,10 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
// There are updates. This means the context has external visible
// storage, even if the original stored version didn't.
LookupDC->setHasExternalVisibleStorage(true);
- DeclContextVisibleUpdates &U = I->second;
- for (DeclContextVisibleUpdates::iterator UI = U.begin(), UE = U.end();
- UI != UE; ++UI) {
- DeclContextInfo &Info = UI->second->DeclContextInfos[DC];
+ for (const auto &Update : I->second) {
+ DeclContextInfo &Info = Update.second->DeclContextInfos[DC];
delete Info.NameLookupTableData;
- Info.NameLookupTableData = UI->first;
+ Info.NameLookupTableData = Update.first;
}
PendingVisibleUpdates.erase(I);
}
@@ -2618,7 +2868,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
assert(Idx == Record.size());
// Load any relevant update records.
- loadDeclUpdateRecords(ID, D);
+ PendingUpdateRecords.push_back(std::make_pair(ID, D));
// Load the categories after recursive loading is finished.
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D))
@@ -2642,6 +2892,7 @@ void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) {
DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID);
if (UpdI != DeclUpdateOffsets.end()) {
FileOffsetsTy &UpdateOffsets = UpdI->second;
+ bool WasInteresting = isConsumerInterestedIn(D, false);
for (FileOffsetsTy::iterator
I = UpdateOffsets.begin(), E = UpdateOffsets.end(); I != E; ++I) {
ModuleFile *F = I->first;
@@ -2654,33 +2905,23 @@ void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) {
unsigned RecCode = Cursor.readRecord(Code, Record);
(void)RecCode;
assert(RecCode == DECL_UPDATES && "Expected DECL_UPDATES record!");
-
+
unsigned Idx = 0;
ASTDeclReader Reader(*this, *F, ID, 0, Record, Idx);
Reader.UpdateDecl(D, *F, Record);
+
+ // We might have made this declaration interesting. If so, remember that
+ // we need to hand it off to the consumer.
+ if (!WasInteresting &&
+ isConsumerInterestedIn(D, Reader.hasPendingBody())) {
+ InterestingDecls.push_back(D);
+ WasInteresting = true;
+ }
}
}
}
namespace {
- struct CompareLocalRedeclarationsInfoToID {
- bool operator()(const LocalRedeclarationsInfo &X, DeclID Y) {
- return X.FirstID < Y;
- }
-
- bool operator()(DeclID X, const LocalRedeclarationsInfo &Y) {
- return X < Y.FirstID;
- }
-
- bool operator()(const LocalRedeclarationsInfo &X,
- const LocalRedeclarationsInfo &Y) {
- return X.FirstID < Y.FirstID;
- }
- bool operator()(DeclID X, DeclID Y) {
- return X < Y;
- }
- };
-
/// \brief Module visitor class that finds all of the redeclarations of a
///
class RedeclChainVisitor {
@@ -2724,10 +2965,11 @@ namespace {
// Perform a binary search to find the local redeclarations for this
// declaration (if any).
+ const LocalRedeclarationsInfo Compare = { ID, 0 };
const LocalRedeclarationsInfo *Result
= std::lower_bound(M.RedeclarationsMap,
M.RedeclarationsMap + M.LocalNumRedeclarationsInMap,
- ID, CompareLocalRedeclarationsInfoToID());
+ Compare);
if (Result == M.RedeclarationsMap + M.LocalNumRedeclarationsInMap ||
Result->FirstID != ID) {
// If we have a previously-canonical singleton declaration that was
@@ -2755,6 +2997,8 @@ namespace {
// Visit each of the declarations.
for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I)
searchForID(M, SearchDecls[I]);
+ // FIXME: If none of the SearchDecls had local IDs in this module, can
+ // we avoid searching any ancestor module files?
return false;
}
@@ -2802,24 +3046,6 @@ void ASTReader::loadPendingDeclChain(serialization::GlobalDeclID ID) {
}
namespace {
- struct CompareObjCCategoriesInfo {
- bool operator()(const ObjCCategoriesInfo &X, DeclID Y) {
- return X.DefinitionID < Y;
- }
-
- bool operator()(DeclID X, const ObjCCategoriesInfo &Y) {
- return X < Y.DefinitionID;
- }
-
- bool operator()(const ObjCCategoriesInfo &X,
- const ObjCCategoriesInfo &Y) {
- return X.DefinitionID < Y.DefinitionID;
- }
- bool operator()(DeclID X, DeclID Y) {
- return X < Y;
- }
- };
-
/// \brief Given an ObjC interface, goes through the modules and links to the
/// interface all the categories for it.
class ObjCCategoriesVisitor {
@@ -2878,18 +3104,15 @@ namespace {
unsigned PreviousGeneration)
: Reader(Reader), InterfaceID(InterfaceID), Interface(Interface),
Deserialized(Deserialized), PreviousGeneration(PreviousGeneration),
- Tail(0)
+ Tail(nullptr)
{
// Populate the name -> category map with the set of known categories.
- for (ObjCInterfaceDecl::known_categories_iterator
- Cat = Interface->known_categories_begin(),
- CatEnd = Interface->known_categories_end();
- Cat != CatEnd; ++Cat) {
+ for (auto *Cat : Interface->known_categories()) {
if (Cat->getDeclName())
- NameCategoryMap[Cat->getDeclName()] = *Cat;
+ NameCategoryMap[Cat->getDeclName()] = Cat;
// Keep track of the tail of the category list.
- Tail = *Cat;
+ Tail = Cat;
}
}
@@ -2912,10 +3135,11 @@ namespace {
// Perform a binary search to find the local redeclarations for this
// declaration (if any).
+ const ObjCCategoriesInfo Compare = { LocalID, 0 };
const ObjCCategoriesInfo *Result
= std::lower_bound(M.ObjCCategoriesMap,
M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap,
- LocalID, CompareObjCCategoriesInfo());
+ Compare);
if (Result == M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap ||
Result->DefinitionID != LocalID) {
// We didn't find anything. If the class definition is in this module
@@ -2946,12 +3170,14 @@ void ASTReader::loadObjCCategories(serialization::GlobalDeclID ID,
void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
const RecordData &Record) {
- unsigned Idx = 0;
while (Idx < Record.size()) {
switch ((DeclUpdateKind)Record[Idx++]) {
- case UPD_CXX_ADDED_IMPLICIT_MEMBER:
- cast<CXXRecordDecl>(D)->addedMember(Reader.ReadDecl(ModuleFile, Record, Idx));
+ case UPD_CXX_ADDED_IMPLICIT_MEMBER: {
+ Decl *MD = Reader.ReadDecl(ModuleFile, Record, Idx);
+ assert(MD && "couldn't read decl from update record");
+ cast<CXXRecordDecl>(D)->addedMember(MD);
break;
+ }
case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
// It will be added to the template's specializations set when loaded.
@@ -2979,6 +3205,96 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
Reader.ReadSourceLocation(ModuleFile, Record, Idx));
break;
+ case UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION: {
+ FunctionDecl *FD = cast<FunctionDecl>(D);
+ if (Reader.PendingBodies[FD]) {
+ // FIXME: Maybe check for ODR violations.
+ // It's safe to stop now because this update record is always last.
+ return;
+ }
+
+ if (Record[Idx++]) {
+ // Maintain AST consistency: any later redeclarations of this function
+ // are inline if this one is. (We might have merged another declaration
+ // into this one.)
+ for (auto *D = FD->getMostRecentDecl(); /**/;
+ D = D->getPreviousDecl()) {
+ D->setImplicitlyInline();
+ if (D == FD)
+ break;
+ }
+ }
+ FD->setInnerLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
+ if (auto *CD = dyn_cast<CXXConstructorDecl>(FD))
+ std::tie(CD->CtorInitializers, CD->NumCtorInitializers) =
+ Reader.ReadCXXCtorInitializers(ModuleFile, Record, Idx);
+ // Store the offset of the body so we can lazily load it later.
+ Reader.PendingBodies[FD] = GetCurrentCursorOffset();
+ HasPendingBody = true;
+ assert(Idx == Record.size() && "lazy body must be last");
+ break;
+ }
+
+ case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: {
+ auto *RD = cast<CXXRecordDecl>(D);
+ bool HadDefinition = RD->getDefinition();
+ ReadCXXRecordDefinition(RD);
+ // Visible update is handled separately.
+ uint64_t LexicalOffset = Record[Idx++];
+ if (!HadDefinition && LexicalOffset) {
+ RD->setHasExternalLexicalStorage(true);
+ Reader.ReadDeclContextStorage(ModuleFile, ModuleFile.DeclsCursor,
+ std::make_pair(LexicalOffset, 0),
+ ModuleFile.DeclContextInfos[RD]);
+ }
+
+ auto TSK = (TemplateSpecializationKind)Record[Idx++];
+ SourceLocation POI = Reader.ReadSourceLocation(ModuleFile, Record, Idx);
+ if (MemberSpecializationInfo *MSInfo =
+ RD->getMemberSpecializationInfo()) {
+ MSInfo->setTemplateSpecializationKind(TSK);
+ MSInfo->setPointOfInstantiation(POI);
+ } else {
+ ClassTemplateSpecializationDecl *Spec =
+ cast<ClassTemplateSpecializationDecl>(RD);
+ Spec->setTemplateSpecializationKind(TSK);
+ Spec->setPointOfInstantiation(POI);
+
+ if (Record[Idx++]) {
+ auto PartialSpec =
+ ReadDeclAs<ClassTemplatePartialSpecializationDecl>(Record, Idx);
+ SmallVector<TemplateArgument, 8> TemplArgs;
+ Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
+ auto *TemplArgList = TemplateArgumentList::CreateCopy(
+ Reader.getContext(), TemplArgs.data(), TemplArgs.size());
+ Spec->setInstantiationOf(PartialSpec, TemplArgList);
+ }
+ }
+
+ RD->setTagKind((TagTypeKind)Record[Idx++]);
+ RD->setLocation(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
+ RD->setLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
+ RD->setRBraceLoc(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
+
+ if (Record[Idx++]) {
+ AttrVec Attrs;
+ Reader.ReadAttributes(F, Attrs, Record, Idx);
+ D->setAttrsImpl(Attrs, Reader.getContext());
+ }
+ break;
+ }
+
+ case UPD_CXX_RESOLVED_EXCEPTION_SPEC: {
+ auto *FD = cast<FunctionDecl>(D);
+ auto *FPT = FD->getType()->castAs<FunctionProtoType>();
+ auto EPI = FPT->getExtProtoInfo();
+ SmallVector<QualType, 8> ExceptionStorage;
+ Reader.readExceptionSpec(ModuleFile, ExceptionStorage, EPI, Record, Idx);
+ FD->setType(Reader.Context.getFunctionType(FPT->getReturnType(),
+ FPT->getParamTypes(), EPI));
+ break;
+ }
+
case UPD_CXX_DEDUCED_RETURN_TYPE: {
FunctionDecl *FD = cast<FunctionDecl>(D);
Reader.Context.adjustDeducedFunctionResultType(
@@ -2989,9 +3305,28 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
case UPD_DECL_MARKED_USED: {
// FIXME: This doesn't send the right notifications if there are
// ASTMutationListeners other than an ASTWriter.
- D->Used = true;
+
+ // FIXME: We can't both pull in declarations (and thus create new pending
+ // redeclaration chains) *and* walk redeclaration chains in this function.
+ // We should defer the updates that require walking redecl chains.
+
+ // Maintain AST consistency: any later redeclarations are used too.
+ for (auto *Redecl = D->getMostRecentDecl(); /**/;
+ Redecl = Redecl->getPreviousDecl()) {
+ Redecl->Used = true;
+ if (Redecl == D)
+ break;
+ }
break;
}
+
+ case UPD_MANGLING_NUMBER:
+ Reader.Context.setManglingNumber(cast<NamedDecl>(D), Record[Idx++]);
+ break;
+
+ case UPD_STATIC_LOCAL_NUMBER:
+ Reader.Context.setStaticLocalNumber(cast<VarDecl>(D), Record[Idx++]);
+ break;
}
}
}
OpenPOWER on IntegriCloud