diff options
author | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
commit | 9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch) | |
tree | c978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp | |
parent | 03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff) | |
download | FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz |
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports
all of the features in the current working draft of the upcoming C++
standard, provisionally named C++1y.
The code generator's performance is greatly increased, and the loop
auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The
PowerPC backend has made several major improvements to code generation
quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ
backends have all seen major feature work.
Release notes for llvm and clang can be found here:
<http://llvm.org/releases/3.4/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html>
MFC 262121 (by emaste):
Update lldb for clang/llvm 3.4 import
This commit largely restores the lldb source to the upstream r196259
snapshot with the addition of threaded inferior support and a few bug
fixes.
Specific upstream lldb revisions restored include:
SVN git
181387 779e6ac
181703 7bef4e2
182099 b31044e
182650 f2dcf35
182683 0d91b80
183862 15c1774
183929 99447a6
184177 0b2934b
184948 4dc3761
184954 007e7bc
186990 eebd175
Sponsored by: DARPA, AFRL
MFC 262186 (by emaste):
Fix mismerge in r262121
A break statement was lost in the merge. The error had no functional
impact, but restore it to reduce the diff against upstream.
MFC 262303:
Pull in r197521 from upstream clang trunk (by rdivacky):
Use the integrated assembler by default on FreeBSD/ppc and ppc64.
Requested by: jhibbits
MFC 262611:
Pull in r196874 from upstream llvm trunk:
Fix a crash that occurs when PWD is invalid.
MCJIT needs to be able to run in hostile environments, even when PWD
is invalid. There's no need to crash MCJIT in this case.
The obvious fix is to simply leave MCContext's CompilationDir empty
when PWD can't be determined. This way, MCJIT clients,
and other clients that link with LLVM don't need a valid working directory.
If we do want to guarantee valid CompilationDir, that should be done
only for clients of getCompilationDir(). This is as simple as checking
for an empty string.
The only current use of getCompilationDir is EmitGenDwarfInfo, which
won't conceivably run with an invalid working dir. However, in the
purely hypothetically and untestable case that this happens, the
AT_comp_dir will be omitted from the compilation_unit DIE.
This should help fix assertions occurring with ports-mgmt/tinderbox,
when it is using jails, and sometimes invalidates clang's current
working directory.
Reported by: decke
MFC 262809:
Pull in r203007 from upstream clang trunk:
Don't produce an alias between destructors with different calling conventions.
Fixes pr19007.
(Please note that is an LLVM PR identifier, not a FreeBSD one.)
This should fix Firefox and/or libxul crashes (due to problems with
regparm/stdcall calling conventions) on i386.
Reported by: multiple users on freebsd-current
PR: bin/187103
MFC 263048:
Repair recognition of "CC" as an alias for the C++ compiler, since it
was silently broken by upstream for a Windows-specific use-case.
Apparently some versions of CMake still rely on this archaic feature...
Reported by: rakuco
MFC 263049:
Garbage collect the old way of adding the libstdc++ include directories
in clang's InitHeaderSearch.cpp. This has been superseded by David
Chisnall's commit in r255321.
Moreover, if libc++ is used, the libstdc++ include directories should
not be in the search path at all. These directories are now only used
if you pass -stdlib=libstdc++.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp | 772 |
1 files changed, 591 insertions, 181 deletions
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp index f7fa818..b8102d8 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp @@ -223,16 +223,29 @@ namespace clang { void VisitTypedefDecl(TypedefDecl *TD); void VisitTypeAliasDecl(TypeAliasDecl *TD); void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); - void VisitTagDecl(TagDecl *TD); + RedeclarableResult VisitTagDecl(TagDecl *TD); void VisitEnumDecl(EnumDecl *ED); - void VisitRecordDecl(RecordDecl *RD); - void VisitCXXRecordDecl(CXXRecordDecl *D); - void VisitClassTemplateSpecializationDecl( + RedeclarableResult VisitRecordDeclImpl(RecordDecl *RD); + void VisitRecordDecl(RecordDecl *RD) { VisitRecordDeclImpl(RD); } + RedeclarableResult VisitCXXRecordDeclImpl(CXXRecordDecl *D); + void VisitCXXRecordDecl(CXXRecordDecl *D) { VisitCXXRecordDeclImpl(D); } + RedeclarableResult VisitClassTemplateSpecializationDeclImpl( ClassTemplateSpecializationDecl *D); + void VisitClassTemplateSpecializationDecl( + ClassTemplateSpecializationDecl *D) { + VisitClassTemplateSpecializationDeclImpl(D); + } void VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D); void VisitClassScopeFunctionSpecializationDecl( ClassScopeFunctionSpecializationDecl *D); + RedeclarableResult + VisitVarTemplateSpecializationDeclImpl(VarTemplateSpecializationDecl *D); + void VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) { + VisitVarTemplateSpecializationDeclImpl(D); + } + void VisitVarTemplatePartialSpecializationDecl( + VarTemplatePartialSpecializationDecl *D); void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); void VisitValueDecl(ValueDecl *VD); void VisitEnumConstantDecl(EnumConstantDecl *ECD); @@ -246,13 +259,15 @@ namespace clang { void VisitFieldDecl(FieldDecl *FD); void VisitMSPropertyDecl(MSPropertyDecl *FD); void VisitIndirectFieldDecl(IndirectFieldDecl *FD); - void VisitVarDecl(VarDecl *VD); + RedeclarableResult VisitVarDeclImpl(VarDecl *D); + void VisitVarDecl(VarDecl *VD) { VisitVarDeclImpl(VD); } void VisitImplicitParamDecl(ImplicitParamDecl *PD); void VisitParmVarDecl(ParmVarDecl *PD); void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); void VisitTemplateDecl(TemplateDecl *D); RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D); + void VisitVarTemplateDecl(VarTemplateDecl *D); void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D); @@ -276,7 +291,14 @@ namespace clang { template<typename T> void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl); - + + template<typename T> + void mergeRedeclarable(Redeclarable<T> *D, T *Existing, + RedeclarableResult &Redecl); + + template<typename T> + void mergeMergeable(Mergeable<T> *D); + // FIXME: Reorder according to DeclNodes.td? void VisitObjCMethodDecl(ObjCMethodDecl *D); void VisitObjCContainerDecl(ObjCContainerDecl *D); @@ -348,9 +370,11 @@ void ASTDeclReader::VisitDecl(Decl *D) { } else { DeclContext *SemaDC = ReadDeclAs<DeclContext>(Record, Idx); DeclContext *LexicalDC = ReadDeclAs<DeclContext>(Record, Idx); + DeclContext *MergedSemaDC = Reader.MergedDeclContexts.lookup(SemaDC); // Avoid calling setLexicalDeclContext() directly because it uses // Decl::getASTContext() internally which is unsafe during derialization. - D->setDeclContextsImpl(SemaDC, LexicalDC, Reader.getContext()); + D->setDeclContextsImpl(MergedSemaDC ? MergedSemaDC : SemaDC, LexicalDC, + Reader.getContext()); } D->setLocation(Reader.ReadSourceLocation(F, RawLocation)); D->setInvalidDecl(Record[Idx++]); @@ -362,7 +386,7 @@ void ASTDeclReader::VisitDecl(Decl *D) { D->setAttrsImpl(Attrs, Reader.getContext()); } D->setImplicit(Record[Idx++]); - D->setUsed(Record[Idx++]); + D->Used = Record[Idx++]; D->setReferenced(Record[Idx++]); D->setTopLevelDeclInObjCContainer(Record[Idx++]); D->setAccess((AccessSpecifier)Record[Idx++]); @@ -411,8 +435,12 @@ void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) { void ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) { RedeclarableResult Redecl = VisitRedeclarable(TD); VisitTypeDecl(TD); - - TD->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); + TypeSourceInfo *TInfo = GetTypeSourceInfo(Record, Idx); + if (Record[Idx++]) { // isModed + QualType modedT = Reader.readType(F, Record, Idx); + TD->setModedTypeSourceInfo(TInfo, modedT); + } else + TD->setTypeSourceInfo(TInfo); mergeRedeclarable(TD, Redecl); } @@ -424,7 +452,7 @@ void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) { VisitTypedefNameDecl(TD); } -void ASTDeclReader::VisitTagDecl(TagDecl *TD) { +ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) { RedeclarableResult Redecl = VisitRedeclarable(TD); VisitTypeDecl(TD); @@ -433,16 +461,18 @@ void ASTDeclReader::VisitTagDecl(TagDecl *TD) { TD->setCompleteDefinition(Record[Idx++]); TD->setEmbeddedInDeclarator(Record[Idx++]); TD->setFreeStanding(Record[Idx++]); + TD->setCompleteDefinitionRequired(Record[Idx++]); TD->setRBraceLoc(ReadSourceLocation(Record, Idx)); if (Record[Idx++]) { // hasExtInfo TagDecl::ExtInfo *Info = new (Reader.getContext()) TagDecl::ExtInfo(); ReadQualifierInfo(*Info, Record, Idx); - TD->TypedefNameDeclOrQualifier = Info; + TD->NamedDeclOrQualifier = Info; } else - TD->setTypedefNameForAnonDecl(ReadDeclAs<TypedefNameDecl>(Record, Idx)); + TD->NamedDeclOrQualifier = ReadDeclAs<NamedDecl>(Record, Idx); - mergeRedeclarable(TD, Redecl); + mergeRedeclarable(TD, Redecl); + return Redecl; } void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { @@ -458,6 +488,19 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { ED->IsScopedUsingClassTag = Record[Idx++]; ED->IsFixed = Record[Idx++]; + // 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 (EnumDecl *&OldDef = Reader.EnumDefinitions[ED->getCanonicalDecl()]) { + Reader.MergedDeclContexts.insert(std::make_pair(ED, OldDef)); + ED->IsCompleteDefinition = false; + } else { + OldDef = ED; + } + } + if (EnumDecl *InstED = ReadDeclAs<EnumDecl>(Record, Idx)) { TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; SourceLocation POI = ReadSourceLocation(Record, Idx); @@ -466,12 +509,14 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { } } -void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) { - VisitTagDecl(RD); +ASTDeclReader::RedeclarableResult +ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) { + RedeclarableResult Redecl = VisitTagDecl(RD); RD->setHasFlexibleArrayMember(Record[Idx++]); RD->setAnonymousStructOrUnion(Record[Idx++]); RD->setHasObjectMember(Record[Idx++]); RD->setHasVolatileMember(Record[Idx++]); + return Redecl; } void ASTDeclReader::VisitValueDecl(ValueDecl *VD) { @@ -484,6 +529,7 @@ void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) { if (Record[Idx++]) ECD->setInitExpr(Reader.ReadExpr(F)); ECD->setInitVal(Reader.ReadAPSInt(Record, Idx)); + mergeMergeable(ECD); } void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) { @@ -521,8 +567,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->HasImplicitReturnZero = Record[Idx++]; FD->IsConstexpr = Record[Idx++]; FD->HasSkippedBody = Record[Idx++]; - FD->HasCachedLinkage = true; - FD->CachedLinkage = Record[Idx++]; + FD->IsLateTemplateParsed = Record[Idx++]; + FD->setCachedLinkage(Linkage(Record[Idx++])); FD->EndRangeLoc = ReadSourceLocation(Record, Idx); switch ((FunctionDecl::TemplatedKind)Record[Idx++]) { @@ -594,11 +640,16 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FunctionTemplateSpecializationInfo::Profile(ID, TemplArgs.data(), TemplArgs.size(), C); void *InsertPos = 0; - CanonTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); + FunctionTemplateDecl::Common *CommonPtr = CanonTemplate->getCommonPtr(); + CommonPtr->Specializations.FindNodeOrInsertPos(ID, InsertPos); if (InsertPos) - CanonTemplate->getSpecializations().InsertNode(FTInfo, InsertPos); - else - assert(0 && "Another specialization already inserted!"); + CommonPtr->Specializations.InsertNode(FTInfo, InsertPos); + else { + assert(Reader.getContext().getLangOpts().Modules && + "already deserialized this template specialization"); + // FIXME: This specialization is a redeclaration of one from another + // module. Merge it. + } } break; } @@ -747,6 +798,8 @@ void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { IVD->setNextIvar(0); bool synth = Record[Idx++]; IVD->setSynthesize(synth); + bool backingIvarReferencedInAccessor = Record[Idx++]; + IVD->setBackingIvarReferencedInAccessor(backingIvarReferencedInAccessor); } void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { @@ -880,6 +933,7 @@ void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) { if (FieldDecl *Tmpl = ReadDeclAs<FieldDecl>(Record, Idx)) Reader.getContext().setInstantiatedFromUnnamedFieldDecl(FD, Tmpl); } + mergeMergeable(FD); } void ASTDeclReader::VisitMSPropertyDecl(MSPropertyDecl *PD) { @@ -899,7 +953,7 @@ void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) { FD->Chaining[I] = ReadDeclAs<NamedDecl>(Record, Idx); } -void ASTDeclReader::VisitVarDecl(VarDecl *VD) { +ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { RedeclarableResult Redecl = VisitRedeclarable(VD); VisitDeclaratorDecl(VD); @@ -911,11 +965,18 @@ void ASTDeclReader::VisitVarDecl(VarDecl *VD) { VD->VarDeclBits.CXXForRangeDecl = Record[Idx++]; VD->VarDeclBits.ARCPseudoStrong = Record[Idx++]; VD->VarDeclBits.IsConstexpr = Record[Idx++]; - VD->HasCachedLinkage = true; - VD->CachedLinkage = Record[Idx++]; - + VD->VarDeclBits.IsInitCapture = Record[Idx++]; + VD->VarDeclBits.PreviousDeclInSameBlockScope = Record[Idx++]; + Linkage VarLinkage = Linkage(Record[Idx++]); + VD->setCachedLinkage(VarLinkage); + + // Reconstruct the one piece of the IdentifierNamespace that we need. + if (VarLinkage != NoLinkage && + VD->getLexicalDeclContext()->isFunctionOrMethod()) + VD->setLocalExternDecl(); + // Only true variables (not parameters or implicit parameters) can be merged. - if (VD->getKind() == Decl::Var) + if (VD->getKind() != Decl::ParmVar && VD->getKind() != Decl::ImplicitParam) mergeRedeclarable(VD, Redecl); if (uint64_t Val = Record[Idx++]) { @@ -927,12 +988,25 @@ void ASTDeclReader::VisitVarDecl(VarDecl *VD) { } } - if (Record[Idx++]) { // HasMemberSpecializationInfo. + enum VarKind { + VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization + }; + switch ((VarKind)Record[Idx++]) { + case VarNotTemplate: + break; + case VarTemplate: + VD->setDescribedVarTemplate(ReadDeclAs<VarTemplateDecl>(Record, Idx)); + break; + case StaticDataMemberSpecialization: { // HasMemberSpecializationInfo. VarDecl *Tmpl = ReadDeclAs<VarDecl>(Record, Idx); TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; SourceLocation POI = ReadSourceLocation(Record, Idx); Reader.getContext().setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI); + break; } + } + + return Redecl; } void ASTDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) { @@ -956,6 +1030,9 @@ void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) { PD->ParmVarDeclBits.HasInheritedDefaultArg = Record[Idx++]; if (Record[Idx++]) // hasUninstantiatedDefaultArg. PD->setUninstantiatedDefaultArg(Reader.ReadExpr(F)); + + // FIXME: If this is a redeclaration of a function from another module, handle + // inheritance of default arguments. } void ASTDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) { @@ -1022,6 +1099,7 @@ 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) { @@ -1034,7 +1112,7 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { } else { // Link this namespace back to the first declaration, which has already // been deserialized. - D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDeclaration()); + D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDecl()); } } @@ -1048,22 +1126,24 @@ void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { void ASTDeclReader::VisitUsingDecl(UsingDecl *D) { VisitNamedDecl(D); - D->setUsingLocation(ReadSourceLocation(Record, Idx)); + D->setUsingLoc(ReadSourceLocation(Record, Idx)); D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx); D->FirstUsingShadow.setPointer(ReadDeclAs<UsingShadowDecl>(Record, Idx)); - D->setTypeName(Record[Idx++]); + D->setTypename(Record[Idx++]); if (NamedDecl *Pattern = ReadDeclAs<NamedDecl>(Record, Idx)) Reader.getContext().setInstantiatedFromUsingDecl(D, Pattern); } void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) { + RedeclarableResult Redecl = VisitRedeclarable(D); VisitNamedDecl(D); D->setTargetDecl(ReadDeclAs<NamedDecl>(Record, Idx)); D->UsingOrNextShadow = ReadDeclAs<NamedDecl>(Record, Idx); UsingShadowDecl *Pattern = ReadDeclAs<UsingShadowDecl>(Record, Idx); if (Pattern) Reader.getContext().setInstantiatedFromUsingShadowDecl(D, Pattern); + mergeRedeclarable(D, Redecl); } void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { @@ -1128,8 +1208,6 @@ void ASTDeclReader::ReadCXXDefinitionData( Data.ImplicitCopyAssignmentHasConstParam = Record[Idx++]; Data.HasDeclaredCopyConstructorWithConstParam = Record[Idx++]; Data.HasDeclaredCopyAssignmentWithConstParam = Record[Idx++]; - Data.FailedImplicitMoveConstructor = Record[Idx++]; - Data.FailedImplicitMoveAssignment = Record[Idx++]; Data.NumBases = Record[Idx++]; if (Data.NumBases) @@ -1141,13 +1219,15 @@ void ASTDeclReader::ReadCXXDefinitionData( Reader.ReadUnresolvedSet(F, Data.Conversions, Record, Idx); Reader.ReadUnresolvedSet(F, Data.VisibleConversions, Record, Idx); assert(Data.Definition && "Data.Definition should be already set!"); - Data.FirstFriend = ReadDeclAs<FriendDecl>(Record, Idx); - + Data.FirstFriend = ReadDeclID(Record, Idx); + if (Data.IsLambda) { typedef LambdaExpr::Capture Capture; CXXRecordDecl::LambdaDefinitionData &Lambda = static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data); Lambda.Dependent = Record[Idx++]; + Lambda.IsGenericLambda = Record[Idx++]; + Lambda.CaptureDefault = Record[Idx++]; Lambda.NumCaptures = Record[Idx++]; Lambda.NumExplicitCaptures = Record[Idx++]; Lambda.ManglingNumber = Record[Idx++]; @@ -1160,41 +1240,65 @@ void ASTDeclReader::ReadCXXDefinitionData( SourceLocation Loc = ReadSourceLocation(Record, Idx); bool IsImplicit = Record[Idx++]; LambdaCaptureKind Kind = static_cast<LambdaCaptureKind>(Record[Idx++]); - VarDecl *Var = ReadDeclAs<VarDecl>(Record, Idx); - SourceLocation EllipsisLoc = ReadSourceLocation(Record, Idx); - *ToCapture++ = Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc); + switch (Kind) { + case LCK_This: + *ToCapture++ = Capture(Loc, IsImplicit, Kind, 0, SourceLocation()); + break; + case LCK_ByCopy: + case LCK_ByRef: + VarDecl *Var = ReadDeclAs<VarDecl>(Record, Idx); + SourceLocation EllipsisLoc = ReadSourceLocation(Record, Idx); + *ToCapture++ = Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc); + break; + } } } } -void ASTDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) { - VisitRecordDecl(D); +ASTDeclReader::RedeclarableResult +ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { + RedeclarableResult Redecl = VisitRecordDeclImpl(D); ASTContext &C = Reader.getContext(); - if (Record[Idx++]) { + 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, + 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. - // FIXME: Complain if there already is a DefinitionData! - D->getCanonicalDecl()->DefinitionData = D->DefinitionData; - - ReadCXXDefinitionData(*D->DefinitionData, Record, Idx); - - // 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); + 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; + D->DefinitionData = D->getCanonicalDecl()->DefinitionData; } enum CXXRecKind { @@ -1217,12 +1321,15 @@ void ASTDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) { } } - // Load the key function to avoid deserializing every method so we can + // Lazily load the key function to avoid deserializing every method so we can // compute it. - if (D->IsCompleteDefinition) { - if (CXXMethodDecl *Key = ReadDeclAs<CXXMethodDecl>(Record, Idx)) - C.KeyFunctions[D] = Key; + if (WasDefinition) { + DeclID KeyFn = ReadDeclID(Record, Idx); + if (KeyFn && D->IsCompleteDefinition) + C.KeyFunctions[D] = KeyFn; } + + return Redecl; } void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { @@ -1240,7 +1347,6 @@ void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) { VisitCXXMethodDecl(D); D->IsExplicitSpecified = Record[Idx++]; - D->ImplicitlyDefined = Record[Idx++]; llvm::tie(D->CtorInitializers, D->NumCtorInitializers) = Reader.ReadCXXCtorInitializers(F, Record, Idx); } @@ -1248,7 +1354,6 @@ void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) { void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { VisitCXXMethodDecl(D); - D->ImplicitlyDefined = Record[Idx++]; D->OperatorDelete = ReadDeclAs<FunctionDecl>(Record, Idx); } @@ -1280,7 +1385,7 @@ void ASTDeclReader::VisitFriendDecl(FriendDecl *D) { D->Friend = GetTypeSourceInfo(Record, Idx); for (unsigned i = 0; i != D->NumTPLists; ++i) D->getTPLists()[i] = Reader.ReadTemplateParameterList(F, Record, Idx); - D->NextFriend = Record[Idx++]; + D->NextFriend = ReadDeclID(Record, Idx); D->UnsupportedFriend = (Record[Idx++] != 0); D->FriendLoc = ReadSourceLocation(Record, Idx); } @@ -1306,6 +1411,9 @@ void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { 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. } ASTDeclReader::RedeclarableResult @@ -1339,6 +1447,11 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { 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; + return Redecl; } @@ -1378,9 +1491,47 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { } } -void ASTDeclReader::VisitClassTemplateSpecializationDecl( - ClassTemplateSpecializationDecl *D) { - VisitCXXRecordDecl(D); +/// TODO: Unify with ClassTemplateDecl version? +/// May require unifying ClassTemplateDecl and +/// VarTemplateDecl beyond TemplateDecl... +void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) { + RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); + + if (ThisDeclID == Redecl.getFirstID()) { + // This VarTemplateDecl owns a CommonPtr; read it to keep track of all of + // the specializations. + SmallVector<serialization::DeclID, 2> SpecIDs; + SpecIDs.push_back(0); + + // Specializations. + unsigned Size = Record[Idx++]; + SpecIDs[0] += Size; + for (unsigned I = 0; I != Size; ++I) + SpecIDs.push_back(ReadDeclID(Record, Idx)); + + // Partial specializations. + Size = Record[Idx++]; + SpecIDs[0] += Size; + for (unsigned I = 0; I != Size; ++I) + SpecIDs.push_back(ReadDeclID(Record, Idx)); + + VarTemplateDecl::Common *CommonPtr = D->getCommonPtr(); + if (SpecIDs[0]) { + typedef serialization::DeclID DeclID; + + // FIXME: Append specializations! + CommonPtr->LazySpecializations = + new (Reader.getContext()) DeclID[SpecIDs.size()]; + memcpy(CommonPtr->LazySpecializations, SpecIDs.data(), + SpecIDs.size() * sizeof(DeclID)); + } + } +} + +ASTDeclReader::RedeclarableResult +ASTDeclReader::VisitClassTemplateSpecializationDeclImpl( + ClassTemplateSpecializationDecl *D) { + RedeclarableResult Redecl = VisitCXXRecordDeclImpl(D); ASTContext &C = Reader.getContext(); if (Decl *InstD = ReadDecl(Record, Idx)) { @@ -1402,16 +1553,6 @@ void ASTDeclReader::VisitClassTemplateSpecializationDecl( } } - // Explicit info. - if (TypeSourceInfo *TyInfo = GetTypeSourceInfo(Record, Idx)) { - ClassTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo - = new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo; - ExplicitInfo->TypeAsWritten = TyInfo; - ExplicitInfo->ExternLoc = ReadSourceLocation(Record, Idx); - ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation(Record, Idx); - D->ExplicitInfo = ExplicitInfo; - } - SmallVector<TemplateArgument, 8> TemplArgs; Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx); D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs.data(), @@ -1423,35 +1564,60 @@ void ASTDeclReader::VisitClassTemplateSpecializationDecl( if (writtenAsCanonicalDecl) { ClassTemplateDecl *CanonPattern = ReadDeclAs<ClassTemplateDecl>(Record,Idx); if (D->isCanonicalDecl()) { // It's kept in the folding set. - if (ClassTemplatePartialSpecializationDecl *Partial - = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) { - CanonPattern->getCommonPtr()->PartialSpecializations.GetOrInsertNode(Partial); + // Set this as, or find, the canonical declaration for this specialization + ClassTemplateSpecializationDecl *CanonSpec; + if (ClassTemplatePartialSpecializationDecl *Partial = + dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) { + CanonSpec = CanonPattern->getCommonPtr()->PartialSpecializations + .GetOrInsertNode(Partial); } else { - CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D); + CanonSpec = + CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D); + } + // If there was already a canonical specialization, merge into it. + if (CanonSpec != D) { + mergeRedeclarable<TagDecl>(D, CanonSpec, Redecl); + + // 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 + Reader.PendingDefinitions.erase(D); + Reader.MergedDeclContexts.insert( + std::make_pair(D, CanonSpec->DefinitionData->Definition)); + D->IsCompleteDefinition = false; + D->DefinitionData = CanonSpec->DefinitionData; + } + } } } } + + // Explicit info. + if (TypeSourceInfo *TyInfo = GetTypeSourceInfo(Record, Idx)) { + ClassTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo + = new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo; + ExplicitInfo->TypeAsWritten = TyInfo; + ExplicitInfo->ExternLoc = ReadSourceLocation(Record, Idx); + ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation(Record, Idx); + D->ExplicitInfo = ExplicitInfo; + } + + return Redecl; } void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D) { - VisitClassTemplateSpecializationDecl(D); + RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D); - ASTContext &C = Reader.getContext(); D->TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx); - - unsigned NumArgs = Record[Idx++]; - if (NumArgs) { - D->NumArgsAsWritten = NumArgs; - D->ArgsAsWritten = new (C) TemplateArgumentLoc[NumArgs]; - for (unsigned i=0; i != NumArgs; ++i) - D->ArgsAsWritten[i] = Reader.ReadTemplateArgumentLoc(F, Record, Idx); - } - - D->SequenceNumber = Record[Idx++]; + D->ArgsAsWritten = Reader.ReadASTTemplateArgumentListInfo(F, Record, Idx); // These are read/set from/to the first declaration. - if (D->getPreviousDecl() == 0) { + if (ThisDeclID == Redecl.getFirstID()) { D->InstantiatedFromMember.setPointer( ReadDeclAs<ClassTemplatePartialSpecializationDecl>(Record, Idx)); D->InstantiatedFromMember.setInt(Record[Idx++]); @@ -1470,12 +1636,100 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { if (ThisDeclID == Redecl.getFirstID()) { // This FunctionTemplateDecl owns a CommonPtr; read it. - // Read the function specialization declarations. - // FunctionTemplateDecl's FunctionTemplateSpecializationInfos are filled - // when reading the specialized FunctionDecl. - unsigned NumSpecs = Record[Idx++]; - while (NumSpecs--) - (void)ReadDecl(Record, Idx); + // Read the function specialization declaration IDs. The specializations + // themselves will be loaded if they're needed. + if (unsigned NumSpecs = Record[Idx++]) { + // FIXME: Append specializations! + FunctionTemplateDecl::Common *CommonPtr = D->getCommonPtr(); + CommonPtr->LazySpecializations = new (Reader.getContext()) + serialization::DeclID[NumSpecs + 1]; + CommonPtr->LazySpecializations[0] = NumSpecs; + for (unsigned I = 0; I != NumSpecs; ++I) + CommonPtr->LazySpecializations[I + 1] = ReadDeclID(Record, Idx); + } + } +} + +/// TODO: Unify with ClassTemplateSpecializationDecl version? +/// May require unifying ClassTemplate(Partial)SpecializationDecl and +/// VarTemplate(Partial)SpecializationDecl with a new data +/// structure Template(Partial)SpecializationDecl, and +/// using Template(Partial)SpecializationDecl as input type. +ASTDeclReader::RedeclarableResult +ASTDeclReader::VisitVarTemplateSpecializationDeclImpl( + VarTemplateSpecializationDecl *D) { + RedeclarableResult Redecl = VisitVarDeclImpl(D); + + ASTContext &C = Reader.getContext(); + if (Decl *InstD = ReadDecl(Record, Idx)) { + if (VarTemplateDecl *VTD = dyn_cast<VarTemplateDecl>(InstD)) { + D->SpecializedTemplate = VTD; + } else { + SmallVector<TemplateArgument, 8> TemplArgs; + Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx); + TemplateArgumentList *ArgList = TemplateArgumentList::CreateCopy( + C, TemplArgs.data(), TemplArgs.size()); + VarTemplateSpecializationDecl::SpecializedPartialSpecialization *PS = + new (C) + VarTemplateSpecializationDecl::SpecializedPartialSpecialization(); + PS->PartialSpecialization = + cast<VarTemplatePartialSpecializationDecl>(InstD); + PS->TemplateArgs = ArgList; + D->SpecializedTemplate = PS; + } + } + + // Explicit info. + if (TypeSourceInfo *TyInfo = GetTypeSourceInfo(Record, Idx)) { + VarTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo = + new (C) VarTemplateSpecializationDecl::ExplicitSpecializationInfo; + ExplicitInfo->TypeAsWritten = TyInfo; + ExplicitInfo->ExternLoc = ReadSourceLocation(Record, Idx); + ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation(Record, Idx); + D->ExplicitInfo = ExplicitInfo; + } + + SmallVector<TemplateArgument, 8> TemplArgs; + Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx); + D->TemplateArgs = + TemplateArgumentList::CreateCopy(C, TemplArgs.data(), TemplArgs.size()); + D->PointOfInstantiation = ReadSourceLocation(Record, Idx); + D->SpecializationKind = (TemplateSpecializationKind)Record[Idx++]; + + bool writtenAsCanonicalDecl = Record[Idx++]; + if (writtenAsCanonicalDecl) { + VarTemplateDecl *CanonPattern = ReadDeclAs<VarTemplateDecl>(Record, Idx); + if (D->isCanonicalDecl()) { // It's kept in the folding set. + if (VarTemplatePartialSpecializationDecl *Partial = + dyn_cast<VarTemplatePartialSpecializationDecl>(D)) { + CanonPattern->getCommonPtr()->PartialSpecializations + .GetOrInsertNode(Partial); + } else { + CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D); + } + } + } + + return Redecl; +} + +/// TODO: Unify with ClassTemplatePartialSpecializationDecl version? +/// May require unifying ClassTemplate(Partial)SpecializationDecl and +/// VarTemplate(Partial)SpecializationDecl with a new data +/// structure Template(Partial)SpecializationDecl, and +/// using Template(Partial)SpecializationDecl as input type. +void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl( + VarTemplatePartialSpecializationDecl *D) { + RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D); + + D->TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx); + D->ArgsAsWritten = Reader.ReadASTTemplateArgumentListInfo(F, Record, Idx); + + // These are read/set from/to the first declaration. + if (ThisDeclID == Redecl.getFirstID()) { + D->InstantiatedFromMember.setPointer( + ReadDeclAs<VarTemplatePartialSpecializationDecl>(Record, Idx)); + D->InstantiatedFromMember.setInt(Record[Idx++]); } } @@ -1584,70 +1838,98 @@ 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, +void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl) { // 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 (T *Existing = ExistingRes) { - T *ExistingCanon = Existing->getCanonicalDecl(); - T *DCanon = static_cast<T*>(D)->getCanonicalDecl(); - if (ExistingCanon != DCanon) { - // Have our redeclaration link point back at the canonical declaration - // 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))) { - Namespace->AnonOrFirstNamespaceAndInline.setPointer( - static_cast<NamespaceDecl *>(static_cast<void*>(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); - } - - // 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)) { - 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]); - } - } + + if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D))) + if (T *Existing = ExistingRes) + mergeRedeclarable(D, Existing, Redecl); +} + +/// \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) { + T *ExistingCanon = Existing->getCanonicalDecl(); + T *DCanon = static_cast<T*>(D)->getCanonicalDecl(); + if (ExistingCanon != DCanon) { + // Have our redeclaration link point back at the canonical declaration + // 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))) { + Namespace->AnonOrFirstNamespaceAndInline.setPointer( + static_cast<NamespaceDecl *>(static_cast<void*>(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); + } + + // 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)) { + 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]); } } } +/// \brief Attempts to merge the given declaration (D) with another declaration +/// of the same entity, for the case where the entity is not actually +/// redeclarable. This happens, for instance, when merging the fields of +/// identical class definitions from two different modules. +template<typename T> +void ASTDeclReader::mergeMergeable(Mergeable<T> *D) { + // If modules are not available, there is no reason to perform this merge. + if (!Reader.getContext().getLangOpts().Modules) + return; + + // ODR-based merging is only performed in C++. In C, identically-named things + // in different translation units are not redeclarations (but may still have + // compatible types). + if (!Reader.getContext().getLangOpts().CPlusPlus) + return; + + if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D))) + if (T *Existing = ExistingRes) + Reader.Context.setPrimaryMergedDecl(static_cast<T*>(D), + Existing->getCanonicalDecl()); +} + void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { VisitDecl(D); unsigned NumVars = D->varlist_size(); - SmallVector<DeclRefExpr *, 16> Vars; + SmallVector<Expr *, 16> Vars; Vars.reserve(NumVars); for (unsigned i = 0; i != NumVars; ++i) { - Vars.push_back(cast<DeclRefExpr>(Reader.ReadExpr(F))); + Vars.push_back(Reader.ReadExpr(F)); } D->setVars(Vars); } @@ -1741,6 +2023,48 @@ uint64_t ASTReader::getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset) { return LocalOffset + M.GlobalBitOffset; } +static bool isSameTemplateParameterList(const TemplateParameterList *X, + const TemplateParameterList *Y); + +/// \brief 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 TemplateTypeParmDecl *TX = dyn_cast<TemplateTypeParmDecl>(X)) { + const TemplateTypeParmDecl *TY = cast<TemplateTypeParmDecl>(Y); + return TX->isParameterPack() == TY->isParameterPack(); + } + + if (const NonTypeTemplateParmDecl *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) { + const NonTypeTemplateParmDecl *TY = cast<NonTypeTemplateParmDecl>(Y); + return TX->isParameterPack() == TY->isParameterPack() && + TX->getASTContext().hasSameType(TX->getType(), TY->getType()); + } + + const TemplateTemplateParmDecl *TX = cast<TemplateTemplateParmDecl>(X); + const TemplateTemplateParmDecl *TY = cast<TemplateTemplateParmDecl>(Y); + return TX->isParameterPack() == TY->isParameterPack() && + isSameTemplateParameterList(TX->getTemplateParameters(), + TY->getTemplateParameters()); +} + +/// \brief Determine whether two template parameter lists are similar enough +/// that they may be used in declarations of the same template. +static bool isSameTemplateParameterList(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; + + return true; +} + /// \brief Determine whether the two declarations refer to the same entity. static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!"); @@ -1767,7 +2091,13 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { // 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 (TagDecl *TagX = dyn_cast<TagDecl>(X)) { TagDecl *TagY = cast<TagDecl>(Y); @@ -1777,48 +2107,90 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { (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 function templates, merging of - //prototyped/non-prototyped functions, etc. + // FIXME: This needs to cope with function template specializations, + // merging of prototyped/non-prototyped functions, etc. if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) { FunctionDecl *FuncY = cast<FunctionDecl>(Y); - return (FuncX->getLinkage() == FuncY->getLinkage()) && + return (FuncX->getLinkageInternal() == FuncY->getLinkageInternal()) && FuncX->getASTContext().hasSameType(FuncX->getType(), FuncY->getType()); } // Variables with the same type and linkage match. if (VarDecl *VarX = dyn_cast<VarDecl>(X)) { VarDecl *VarY = cast<VarDecl>(Y); - return (VarX->getLinkage() == VarY->getLinkage()) && + return (VarX->getLinkageInternal() == VarY->getLinkageInternal()) && VarX->getASTContext().hasSameType(VarX->getType(), VarY->getType()); } - + // Namespaces with the same name and inlinedness match. if (NamespaceDecl *NamespaceX = dyn_cast<NamespaceDecl>(X)) { NamespaceDecl *NamespaceY = cast<NamespaceDecl>(Y); return NamespaceX->isInline() == NamespaceY->isInline(); } - // Identical template names and kinds match. - if (isa<TemplateDecl>(X)) + // Identical template names and kinds match if their template parameter lists + // and patterns match. + if (TemplateDecl *TemplateX = dyn_cast<TemplateDecl>(X)) { + TemplateDecl *TemplateY = cast<TemplateDecl>(Y); + return isSameEntity(TemplateX->getTemplatedDecl(), + TemplateY->getTemplatedDecl()) && + isSameTemplateParameterList(TemplateX->getTemplateParameters(), + TemplateY->getTemplateParameters()); + } + + // 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: Also check the bitwidth is odr-equivalent, if any. + return X->getASTContext().hasSameType(FDX->getType(), FDY->getType()); + } + + // Enumerators with the same name match. + if (isa<EnumConstantDecl>(X)) + // FIXME: Also check the value is odr-equivalent. return true; + // Using shadow declarations with the same target match. + if (UsingShadowDecl *USX = dyn_cast<UsingShadowDecl>(X)) { + UsingShadowDecl *USY = cast<UsingShadowDecl>(Y); + return USX->getTargetDecl() == USY->getTargetDecl(); + } + // FIXME: Many other cases to implement. return false; } +/// Find the context in which we should search for previous declarations when +/// looking for declarations to merge. +static DeclContext *getPrimaryContextForMerging(DeclContext *DC) { + if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC)) + return ND->getOriginalNamespace(); + + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) + return RD->getDefinition(); + + if (EnumDecl *ED = dyn_cast<EnumDecl>(DC)) + return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition() : 0; + + return 0; +} + ASTDeclReader::FindExistingResult::~FindExistingResult() { if (!AddResult || Existing) return; - - if (New->getDeclContext()->getRedeclContext()->isTranslationUnit() - && Reader.SemaObj) { + + DeclContext *DC = New->getDeclContext()->getRedeclContext(); + if (DC->isTranslationUnit() && Reader.SemaObj) { Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, New->getDeclName()); - } else { - DeclContext *DC = New->getLexicalDeclContext(); - if (DC->isNamespace()) - DC->addDecl(New); + } else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) { + // Add the declaration to its redeclaration context so later merging + // lookups will find it. + MergeDC->makeDeclVisibleInContextImpl(New, /*Internal*/true); } } @@ -1830,11 +2202,11 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { Result.suppress(); return Result; } - + + // FIXME: Bail out for non-canonical declarations. We will have performed any + // necessary merging already. + DeclContext *DC = D->getDeclContext()->getRedeclContext(); - if (!DC->isFileContext()) - return FindExistingResult(Reader); - if (DC->isTranslationUnit() && Reader.SemaObj) { IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver; @@ -1867,17 +2239,22 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { if (isSameEntity(*I, D)) return FindExistingResult(Reader, D, *I); } - } - - if (DC->isNamespace()) { - DeclContext::lookup_result R = DC->lookup(Name); - for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; - ++I) { + } else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) { + DeclContext::lookup_result R = MergeDC->noload_lookup(Name); + for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) { if (isSameEntity(*I, D)) return FindExistingResult(Reader, D, *I); } + } else { + // Not in a mergeable context. + return FindExistingResult(Reader); } - + + // 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. + if (Reader.MergedDeclContexts.count(D->getLexicalDeclContext())) + Reader.PendingOdrMergeChecks.push_back(D); + return FindExistingResult(Reader, D, /*Existing=*/0); } @@ -1891,6 +2268,8 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) { 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)) { @@ -1901,6 +2280,15 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) { RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D); TD->RedeclLink.setNext(cast<RedeclarableTemplateDecl>(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. + // + // FIXME: In this case, the declaration should only be visible if a module + // that makes it visible has been imported. + D->IdentifierNamespace |= + previous->IdentifierNamespace & + (Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type); } void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) { @@ -1909,7 +2297,7 @@ void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) { TD->RedeclLink = Redeclarable<TagDecl>::LatestDeclLink(cast<TagDecl>(Latest)); } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - FD->RedeclLink + FD->RedeclLink = Redeclarable<FunctionDecl>::LatestDeclLink(cast<FunctionDecl>(Latest)); } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { VD->RedeclLink @@ -1918,6 +2306,10 @@ void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) { 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( @@ -1961,11 +2353,6 @@ ASTReader::combineStoredMergedDecls(Decl *Canon, GlobalDeclID CanonID) { return Pos; } -void ASTReader::loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID) { - Decl *previous = GetDecl(ID); - ASTDeclReader::attachPreviousDecl(D, previous); -} - /// \brief Read the declaration at the given offset from the AST file. Decl *ASTReader::ReadDeclRecord(DeclID ID) { unsigned Index = ID - NUM_PREDEF_DECL_IDS; @@ -2070,6 +2457,15 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION: D = ClassTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID); break; + case DECL_VAR_TEMPLATE: + D = VarTemplateDecl::CreateDeserialized(Context, ID); + break; + case DECL_VAR_TEMPLATE_SPECIALIZATION: + D = VarTemplateSpecializationDecl::CreateDeserialized(Context, ID); + break; + case DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION: + D = VarTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID); + break; case DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION: D = ClassScopeFunctionSpecializationDecl::CreateDeserialized(Context, ID); break; @@ -2397,7 +2793,7 @@ void ASTReader::loadPendingDeclChain(serialization::GlobalDeclID ID) { for (unsigned I = 0, N = Chain.size(); I != N; ++I) { if (Chain[I] == CanonDecl) continue; - + ASTDeclReader::attachPreviousDecl(Chain[I], MostRecent); MostRecent = Chain[I]; } @@ -2582,6 +2978,20 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, cast<VarDecl>(D)->getMemberSpecializationInfo()->setPointOfInstantiation( Reader.ReadSourceLocation(ModuleFile, Record, Idx)); break; + + case UPD_CXX_DEDUCED_RETURN_TYPE: { + FunctionDecl *FD = cast<FunctionDecl>(D); + Reader.Context.adjustDeducedFunctionResultType( + FD, Reader.readType(ModuleFile, Record, Idx)); + break; + } + + case UPD_DECL_MARKED_USED: { + // FIXME: This doesn't send the right notifications if there are + // ASTMutationListeners other than an ASTWriter. + D->Used = true; + break; + } } } } |