diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-04-24 02:25:27 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-04-24 02:25:27 +0000 |
commit | f17fdbd791d78a37cd8f2559247670915d6dcc11 (patch) | |
tree | 91dfccdbca53bb2136418e80ccb9e3be098be8cf /clang/lib/Serialization/ASTReaderDecl.cpp | |
parent | 807cf41e2f2f22e0b5d2a2fa63ecb0124c8c97b2 (diff) | |
download | bcm5719-llvm-f17fdbd791d78a37cd8f2559247670915d6dcc11.tar.gz bcm5719-llvm-f17fdbd791d78a37cd8f2559247670915d6dcc11.zip |
When two templates get merged together, also merge their pattern declarations
together. This is extremely hairy, because in general we need to have loaded
both the template and the pattern before we can determine whether either should
be merged, so we temporarily violate the rule that all merging happens before
reading a decl ends, but *only* in the case where a template's pattern is being
loaded while loading the template itself.
In order to accomodate this for class templates, delay loading the injected
class name type for the pattern of the template until after we've loaded the
template itself, if we happen to load the template first.
llvm-svn: 207063
Diffstat (limited to 'clang/lib/Serialization/ASTReaderDecl.cpp')
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 117 |
1 files changed, 91 insertions, 26 deletions
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 4823cbcdfd9..96253ca301f 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -267,7 +267,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); @@ -288,20 +288,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); @@ -340,7 +346,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. @@ -985,10 +991,6 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { 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) { @@ -1003,8 +1005,12 @@ 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) + mergeRedeclarable(VD, Redecl); break; case VarTemplate: + // Merged when we merge the template. VD->setDescribedVarTemplate(ReadDeclAs<VarTemplateDecl>(Record, Idx)); break; case StaticDataMemberSpecialization: { // HasMemberSpecializationInfo. @@ -1012,6 +1018,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; } } @@ -1414,9 +1421,21 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { case CXXRecNotTemplate: mergeRedeclarable(D, Redecl); break; - case CXXRecTemplate: - D->TemplateOrInstantiation = ReadDeclAs<ClassTemplateDecl>(Record, Idx); + 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 CXXRecMemberSpecialization: { CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(Record, Idx); TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; @@ -1522,16 +1541,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 @@ -1560,10 +1582,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. @@ -1607,6 +1629,14 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { 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->getCommonPtr()->InjectedClassNameType); + } } /// TODO: Unify with ClassTemplateDecl version? @@ -1957,23 +1987,54 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { /// of the same entity. template<typename T> void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D, - RedeclarableResult &Redecl) { + RedeclarableResult &Redecl, + DeclID TemplatePatternID) { // 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) - 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, DsID, DPattern->getKind()); + if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern)) + // FIXME: Merge definitions here, if both declarations had definitions. + 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) { // Have our redeclaration link point back at the canonical declaration // of the existing declaration, so that this declaration has the @@ -1981,11 +2042,15 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D, T *Existing, 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)); + + // When we merge a template, merge its pattern. + if (auto *DTemplate = dyn_cast<RedeclarableTemplateDecl>(D)) + mergeTemplatePattern( + DTemplate, assert_cast<RedeclarableTemplateDecl*>(ExistingCanon), + TemplatePatternID); // Don't introduce DCanon into the set of pending declaration chains. Redecl.suppress(); @@ -2002,7 +2067,7 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D, T *Existing, // 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()) |