[cfe-commits] r80846 - in /cfe/trunk: lib/Sema/SemaDeclCXX.cpp test/CodeGenCXX/constructor-template.cpp

Douglas Gregor dgregor at apple.com
Thu Sep 3 07:49:10 PDT 2009


On Sep 2, 2009, at 4:02 PM, Fariborz Jahanian wrote:

> Author: fjahanian
> Date: Wed Sep  2 18:02:57 2009
> New Revision: 80846
>
> URL: http://llvm.org/viewvc/llvm-project?rev=80846&view=rev
> Log:
> Referenced instatiated default constructors
> must be defined. Fixed pr4853.

Thanks! Some comments below.

> Modified:
>    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>    cfe/trunk/test/CodeGenCXX/constructor-template.cpp
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=80846&r1=80845&r2=80846&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Sep  2 18:02:57 2009
> @@ -1003,7 +1003,25 @@
>
>   if (Constructor->isDependentContext())
>     return;
> -
> +  // Mark all constructors used in initialization of class's members
> +  // as referenced.
> +  // FIXME. We can do this while building the initializer list. But
> +  // MarkDeclarationReferenced is not accessible in ASTContext.
> +  for (CXXConstructorDecl::init_const_iterator B = Constructor- 
> >init_begin(),
> +       E = Constructor->init_end();
> +       B != E; ++B) {

Shouldn't we just move the code from  
CXXConstructorDecl::setBaseOrMemberInitializers into Sema, so that it  
can call MarkDeclarationReferenced directly (rather than have to go  
through the whole list of initializers again later)?

Also, I wonder if CXXDestructorDecl::computeBaseOrMembersToDestroy  
will have the same problem. We'll need to call  
MarkDeclarationReferenced on each of the destructors it uses.

> +    CXXBaseOrMemberInitializer *Member = (*B);
> +    if (!Member->isMemberInitializer())
> +      continue;

We shouldn't skip out of this loop so soon, since base class  
initializers will need the same treatment as member initializers.  
Here's a tweaked version of the test case from PR4826 that is still  
missing a MarkDeclarationReferenced call:

template <typename T> class List {
   int i;
public:
   List(){ }	// List<BinomialNode<int>*>::List() remains undefined.
};

template<typename T> class BinomialNode
: List<BinomialNode<T>*> {
public:
   BinomialNode(T value) {}
   // nodes;
};

int main() {
   BinomialNode<int> *node = new BinomialNode<int>(1);
}

> +    FieldDecl *Field = Member->getMember();
> +    QualType FT = Context.getBaseElementType(Field->getType());
> +    if (const RecordType* RT = FT->getAs<RecordType>()) {
> +      CXXConstructorDecl *Ctor =
> +        cast<CXXRecordDecl>(RT->getDecl())->getDefaultConstructor 
> (Context);
> +      if (Ctor && !FT->isDependentType())
> +        MarkDeclarationReferenced(Ctor->getLocation(), Ctor);

The location that we pass to MarkDeclarationReferenced should be the  
location where the declaration was referenced from. For user-written  
base or member initializers, that's CXXBaseOrMemberInitializer::IdLoc.  
For synthesized base or member initializers, we should pick something  
easily recognizable as being part of the definition, e.g., the '{'  
that starts the constructor definition.

   - Doug



More information about the cfe-commits mailing list