On Aug 29, 2009, at 3:22 PM, Eli Friedman wrote: > Author: efriedma > Date: Sat Aug 29 17:22:07 2009 > New Revision: 80446 > > URL: http://llvm.org/viewvc/llvm-project?rev=80446&view=rev > Log: > Make instantiating initializers for classes with a dependent base type > work correctly.
> The change in lib/AST/DeclCXX.cpp is mostly a large reindentation; I > couldn't figure out a good way to avoid it. > > > Modified: > cfe/trunk/lib/AST/DeclCXX.cpp > cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp > cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp > > Modified: cfe/trunk/lib/AST/DeclCXX.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=80446&r1=80445&r2=80446&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- cfe/trunk/lib/AST/DeclCXX.cpp (original) > +++ cfe/trunk/lib/AST/DeclCXX.cpp Sat Aug 29 17:22:07 2009 > @@ -595,66 +595,81 @@ > CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(getDeclContext()); > llvm::SmallVector<CXXBaseOrMemberInitializer*, 32> AllToInit; > llvm::DenseMap<const void *, CXXBaseOrMemberInitializer*> > AllBaseFields; > + bool HasDependentBaseInit = false; > > for (unsigned i = 0; i < NumInitializers; i++) { > CXXBaseOrMemberInitializer *Member = Initializers[i]; > - if (Member->isBaseInitializer()) > + if (Member->isBaseInitializer()) { > + if (Member->getBaseClass()->isDependentType()) > + HasDependentBaseInit = true; > AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = > Member; > - else > + } else { > AllBaseFields[Member->getMember()] = Member; > + } > } > + > + if (HasDependentBaseInit) { > + // If we have a dependent base initialization, we can't > determine the > + // association between initializers and bases; just dump the > known > + // initializers into the list, and don't try to deal with other > bases. Not knowing enough about instantiation, I assume that at instantiation time, the base initializer list is rescanned with actual types and the AST for the initializer list is built from scratch. So, I am wondering why this change was necessary? Unless it caused a crash and this patch is avoiding it! - fariborz > > + for (unsigned i = 0; i < NumInitializers; i++) { > + CXXBaseOrMemberInitializer *Member = Initializers[i]; > + if (Member->isBaseInitializer()) > + AllToInit.push_back(Member); > + } > + } else { > + // Push virtual bases before others. > + for (CXXRecordDecl::base_class_iterator VBase = > + ClassDecl->vbases_begin(), > + E = ClassDecl->vbases_end(); VBase != E; ++VBase) { > + if (VBase->getType()->isDependentType()) > + continue; > + if (CXXBaseOrMemberInitializer *Value = > + AllBaseFields.lookup(VBase->getType()- > >getAs<RecordType>())) > + AllToInit.push_back(Value); > + else { > + CXXRecordDecl *VBaseDecl = > + cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()- > >getDecl()); > + assert(VBaseDecl && "setBaseOrMemberInitializers - > VBaseDecl null"); > + if (!VBaseDecl->getDefaultConstructor(C)) > + Bases.push_back(VBase); > + CXXBaseOrMemberInitializer *Member = > + new (C) CXXBaseOrMemberInitializer(VBase->getType(), 0, 0, > + VBaseDecl- > >getDefaultConstructor(C), > + SourceLocation(), > + SourceLocation()); > + AllToInit.push_back(Member); > + } > + } > > - // Push virtual bases before others. > - for (CXXRecordDecl::base_class_iterator VBase = > - ClassDecl->vbases_begin(), > - E = ClassDecl->vbases_end(); VBase != E; ++VBase) { > - if (VBase->getType()->isDependentType()) > - continue; > - if (CXXBaseOrMemberInitializer *Value = > - AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) > - AllToInit.push_back(Value); > - else { > - CXXRecordDecl *VBaseDecl = > - cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()- > >getDecl()); > - assert(VBaseDecl && "setBaseOrMemberInitializers - VBaseDecl > null"); > - if (!VBaseDecl->getDefaultConstructor(C)) > - Bases.push_back(VBase); > - CXXBaseOrMemberInitializer *Member = > - new (C) CXXBaseOrMemberInitializer(VBase->getType(), 0, 0, > - VBaseDecl- > >getDefaultConstructor(C), > + for (CXXRecordDecl::base_class_iterator Base = > + ClassDecl->bases_begin(), > + E = ClassDecl->bases_end(); Base != E; ++Base) { > + // Virtuals are in the virtual base list and already > constructed. > + if (Base->isVirtual()) > + continue; > + // Skip dependent types. > + if (Base->getType()->isDependentType()) > + continue; > + if (CXXBaseOrMemberInitializer *Value = > + AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) > + AllToInit.push_back(Value); > + else { > + CXXRecordDecl *BaseDecl = > + cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()- > >getDecl()); > + assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl > null"); > + if (!BaseDecl->getDefaultConstructor(C)) > + Bases.push_back(Base); > + CXXBaseOrMemberInitializer *Member = > + new (C) CXXBaseOrMemberInitializer(Base->getType(), 0, 0, > + BaseDecl- > >getDefaultConstructor(C), > SourceLocation(), > SourceLocation()); > - AllToInit.push_back(Member); > - } > - } > - > - for (CXXRecordDecl::base_class_iterator Base = > - ClassDecl->bases_begin(), > - E = ClassDecl->bases_end(); Base != E; ++Base) { > - // Virtuals are in the virtual base list and already constructed. > - if (Base->isVirtual()) > - continue; > - // Skip dependent types. > - if (Base->getType()->isDependentType()) > - continue; > - if (CXXBaseOrMemberInitializer *Value = > - AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) > - AllToInit.push_back(Value); > - else { > - CXXRecordDecl *BaseDecl = > - cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()- > >getDecl()); > - assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl > null"); > - if (!BaseDecl->getDefaultConstructor(C)) > - Bases.push_back(Base); > - CXXBaseOrMemberInitializer *Member = > - new (C) CXXBaseOrMemberInitializer(Base->getType(), 0, 0, > - BaseDecl- > >getDefaultConstructor(C), > - SourceLocation(), > - SourceLocation()); > - AllToInit.push_back(Member); > + AllToInit.push_back(Member); > + } > } > } > - > + > // non-static data members. > for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), > E = ClassDecl->field_end(); Field != E; ++Field) { > > Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=80446&r1=80445&r2=80446&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) > +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sat Aug 29 > 17:22:07 2009 > @@ -1134,9 +1134,9 @@ > MemInitResult NewInit; > > if (Init->isBaseInitializer()) { > - // FIXME: Type needs to be instantiated. > - QualType BaseType = > - Context.getCanonicalType(QualType(Init->getBaseClass(), 0)); > + QualType BaseType(Init->getBaseClass(), 0); > + BaseType = SubstType(BaseType, TemplateArgs, Init- > >getSourceLocation(), > + New->getDeclName()); > > NewInit = BuildBaseInitializer(BaseType, > (Expr **)NewArgs.data(), > > Modified: cfe/trunk/test/SemaTemplate/instantiate-member- > initializers.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp?rev=80446&r1=80445&r2=80446&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp > (original) > +++ cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp > Sat Aug 29 17:22:07 2009 > @@ -18,3 +18,9 @@ > }; > > B<int> b0; > + > +template <class T> struct AA { AA(int); }; > +template <class T> class BB : public AA<T> { > + BB() : AA<T>(1) {} > +}; > +BB<int> x; > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
