[cfe-commits] r77498 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp test/SemaTemplate/dependent-base-member-init.cpp

Daniel Dunbar daniel at zuster.org
Wed Jul 29 14:43:28 PDT 2009


For reasons I don't understand, this change caused
  test/SemaCXX/constructor-initializer.cpp
to start failing on Darwin. The failure is rather strange:
--
******************** TEST
'/Users/buildslave/zorg/smooshlab/slaves/clang/build.clang-i386-darwin9/llvm/tools/clang/test/SemaCXX/constructor-initializer.cpp'
FAILED ********************
Script:
--
/Users/buildslave/zorg/smooshlab/slaves/clang/build.clang-i386-darwin9/llvm/Debug/bin/clang-cc
-Wreorder -fsyntax-only -verify
/Users/buildslave/zorg/smooshlab/slaves/clang/build.clang-i386-darwin9/llvm/tools/clang/test/SemaCXX/constructor-initializer.cpp
--
Exit Code: 1
Command Output (stdout):
--
--
Command Output (stderr):
--
Errors expected but not seen:
  Line 30: base class initializer 'B' names both a direct base class
and an inherited virtual base class
Errors seen but not expected:
  Line 30: base class initializer 'class B' names both a direct base
class and an inherited virtual base class
--

********************
--

Which looks like some kind of non-determinism related to
Policy.SuppressSpecifiers (or isSpecifierType()), but I don't see what
the issue is.

 - Daniel

On Wed, Jul 29, 2009 at 12:44 PM, Eli Friedman<eli.friedman at gmail.com> wrote:
> Author: efriedma
> Date: Wed Jul 29 14:44:27 2009
> New Revision: 77498
>
> URL: http://llvm.org/viewvc/llvm-project?rev=77498&view=rev
> Log:
> Refactor base/member initializers, and construct them correctly in cases
> with dependent types.  Fixes PR4621 and PR4627.
>
>
> Added:
>    cfe/trunk/test/SemaTemplate/dependent-base-member-init.cpp
> Modified:
>    cfe/trunk/lib/Sema/Sema.h
>    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>
> Modified: cfe/trunk/lib/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=77498&r1=77497&r2=77498&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/Sema.h (original)
> +++ cfe/trunk/lib/Sema/Sema.h Wed Jul 29 14:44:27 2009
> @@ -1925,6 +1925,15 @@
>                                             SourceLocation *CommaLocs,
>                                             SourceLocation RParenLoc);
>
> +  MemInitResult BuildMemberInitializer(FieldDecl *Member, Expr **Args,
> +                                       unsigned NumArgs, SourceLocation IdLoc,
> +                                       SourceLocation RParenLoc);
> +
> +  MemInitResult BuildBaseInitializer(QualType BaseType, Expr **Args,
> +                                     unsigned NumArgs, SourceLocation IdLoc,
> +                                     SourceLocation RParenLoc,
> +                                     CXXRecordDecl *ClassDecl);
> +
>   void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
>
>   virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl,
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=77498&r1=77497&r2=77498&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Jul 29 14:44:27 2009
> @@ -716,28 +716,9 @@
>
>     // FIXME: Handle members of an anonymous union.
>
> -    if (Member) {
> -      CXXConstructorDecl *C = 0;
> -      QualType FieldType = Member->getType();
> -      if (const ArrayType *Array = Context.getAsArrayType(FieldType))
> -        FieldType = Array->getElementType();
> -      if (!FieldType->isDependentType() && FieldType->getAsRecordType())
> -        C = PerformInitializationByConstructor(
> -              FieldType, (Expr **)Args, NumArgs, IdLoc,
> -              SourceRange(IdLoc, RParenLoc), Member->getDeclName(), IK_Direct);
> -      else if (NumArgs != 1)
> -        return Diag(IdLoc, diag::err_mem_initializer_mismatch)
> -                    << MemberOrBase << SourceRange(IdLoc, RParenLoc);
> -      else {
> -        Expr * NewExp = (Expr*)Args[0];
> -        if (PerformCopyInitialization(NewExp, FieldType, "passing"))
> -          return true;
> -        Args[0] = NewExp;
> -      }
> -      // FIXME: Perform direct initialization of the member.
> -      return new (Context) CXXBaseOrMemberInitializer(Member, (Expr **)Args,
> -                                                      NumArgs, C, IdLoc);
> -    }
> +    if (Member)
> +      return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc,
> +                                    RParenLoc);
>   }
>   // It didn't name a member, so see if it names a class.
>   TypeTy *BaseTy = TemplateTypeTy ? TemplateTypeTy
> @@ -747,75 +728,124 @@
>       << MemberOrBase << SourceRange(IdLoc, RParenLoc);
>
>   QualType BaseType = QualType::getFromOpaquePtr(BaseTy);
> -  if (!BaseType->isRecordType() && !BaseType->isDependentType())
> -    return Diag(IdLoc, diag::err_base_init_does_not_name_class)
> -      << BaseType << SourceRange(IdLoc, RParenLoc);
> -
> -  // C++ [class.base.init]p2:
> -  //   [...] Unless the mem-initializer-id names a nonstatic data
> -  //   member of the constructor’s class or a direct or virtual base
> -  //   of that class, the mem-initializer is ill-formed. A
> -  //   mem-initializer-list can initialize a base class using any
> -  //   name that denotes that base class type.
> -
> -  // First, check for a direct base class.
> -  const CXXBaseSpecifier *DirectBaseSpec = 0;
> -  for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin();
> -       Base != ClassDecl->bases_end(); ++Base) {
> -    if (Context.getCanonicalType(BaseType).getUnqualifiedType() ==
> -        Context.getCanonicalType(Base->getType()).getUnqualifiedType()) {
> -      // We found a direct base of this type. That's what we're
> -      // initializing.
> -      DirectBaseSpec = &*Base;
> -      break;
> -    }
> +
> +  return BuildBaseInitializer(BaseType, (Expr **)Args, NumArgs, IdLoc,
> +                              RParenLoc, ClassDecl);
> +}
> +
> +Sema::MemInitResult
> +Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
> +                             unsigned NumArgs, SourceLocation IdLoc,
> +                             SourceLocation RParenLoc) {
> +  bool HasDependentArg = false;
> +  for (unsigned i = 0; i < NumArgs; i++)
> +    HasDependentArg |= Args[i]->isTypeDependent();
> +
> +  CXXConstructorDecl *C = 0;
> +  QualType FieldType = Member->getType();
> +  if (const ArrayType *Array = Context.getAsArrayType(FieldType))
> +    FieldType = Array->getElementType();
> +  if (FieldType->isDependentType()) {
> +    // Can't check init for dependent type.
> +  } else if (FieldType->getAsRecordType()) {
> +    if (!HasDependentArg)
> +      C = PerformInitializationByConstructor(
> +            FieldType, (Expr **)Args, NumArgs, IdLoc,
> +            SourceRange(IdLoc, RParenLoc), Member->getDeclName(), IK_Direct);
> +  } else if (NumArgs != 1) {
> +    return Diag(IdLoc, diag::err_mem_initializer_mismatch)
> +                << Member->getDeclName() << SourceRange(IdLoc, RParenLoc);
> +  } else if (!HasDependentArg) {
> +    Expr *NewExp = (Expr*)Args[0];
> +    if (PerformCopyInitialization(NewExp, FieldType, "passing"))
> +      return true;
> +    Args[0] = NewExp;
>   }
> -
> -  // Check for a virtual base class.
> -  // FIXME: We might be able to short-circuit this if we know in advance that
> -  // there are no virtual bases.
> -  const CXXBaseSpecifier *VirtualBaseSpec = 0;
> -  if (!DirectBaseSpec || !DirectBaseSpec->isVirtual()) {
> -    // We haven't found a base yet; search the class hierarchy for a
> -    // virtual base class.
> -    BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
> -                    /*DetectVirtual=*/false);
> -    if (IsDerivedFrom(Context.getTypeDeclType(ClassDecl), BaseType, Paths)) {
> -      for (BasePaths::paths_iterator Path = Paths.begin();
> -           Path != Paths.end(); ++Path) {
> -        if (Path->back().Base->isVirtual()) {
> -          VirtualBaseSpec = Path->back().Base;
> -          break;
> +  // FIXME: Perform direct initialization of the member.
> +  return new (Context) CXXBaseOrMemberInitializer(Member, (Expr **)Args,
> +                                                  NumArgs, C, IdLoc);
> +}
> +
> +Sema::MemInitResult
> +Sema::BuildBaseInitializer(QualType BaseType, Expr **Args,
> +                           unsigned NumArgs, SourceLocation IdLoc,
> +                           SourceLocation RParenLoc, CXXRecordDecl *ClassDecl) {
> +  bool HasDependentArg = false;
> +  for (unsigned i = 0; i < NumArgs; i++)
> +    HasDependentArg |= Args[i]->isTypeDependent();
> +
> +  if (!BaseType->isDependentType()) {
> +    if (!BaseType->isRecordType())
> +      return Diag(IdLoc, diag::err_base_init_does_not_name_class)
> +        << BaseType << SourceRange(IdLoc, RParenLoc);
> +
> +    // C++ [class.base.init]p2:
> +    //   [...] Unless the mem-initializer-id names a nonstatic data
> +    //   member of the constructor’s class or a direct or virtual base
> +    //   of that class, the mem-initializer is ill-formed. A
> +    //   mem-initializer-list can initialize a base class using any
> +    //   name that denotes that base class type.
> +
> +    // First, check for a direct base class.
> +    const CXXBaseSpecifier *DirectBaseSpec = 0;
> +    for (CXXRecordDecl::base_class_const_iterator Base =
> +         ClassDecl->bases_begin(); Base != ClassDecl->bases_end(); ++Base) {
> +      if (Context.getCanonicalType(BaseType).getUnqualifiedType() ==
> +          Context.getCanonicalType(Base->getType()).getUnqualifiedType()) {
> +        // We found a direct base of this type. That's what we're
> +        // initializing.
> +        DirectBaseSpec = &*Base;
> +        break;
> +      }
> +    }
> +
> +    // Check for a virtual base class.
> +    // FIXME: We might be able to short-circuit this if we know in advance that
> +    // there are no virtual bases.
> +    const CXXBaseSpecifier *VirtualBaseSpec = 0;
> +    if (!DirectBaseSpec || !DirectBaseSpec->isVirtual()) {
> +      // We haven't found a base yet; search the class hierarchy for a
> +      // virtual base class.
> +      BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
> +                      /*DetectVirtual=*/false);
> +      if (IsDerivedFrom(Context.getTypeDeclType(ClassDecl), BaseType, Paths)) {
> +        for (BasePaths::paths_iterator Path = Paths.begin();
> +             Path != Paths.end(); ++Path) {
> +          if (Path->back().Base->isVirtual()) {
> +            VirtualBaseSpec = Path->back().Base;
> +            break;
> +          }
>         }
>       }
>     }
> +
> +    // C++ [base.class.init]p2:
> +    //   If a mem-initializer-id is ambiguous because it designates both
> +    //   a direct non-virtual base class and an inherited virtual base
> +    //   class, the mem-initializer is ill-formed.
> +    if (DirectBaseSpec && VirtualBaseSpec)
> +      return Diag(IdLoc, diag::err_base_init_direct_and_virtual)
> +        << BaseType << SourceRange(IdLoc, RParenLoc);
> +    // C++ [base.class.init]p2:
> +    // Unless the mem-initializer-id names a nonstatic data membeer of the
> +    // constructor's class ot a direst or virtual base of that class, the
> +    // mem-initializer is ill-formed.
> +    if (!DirectBaseSpec && !VirtualBaseSpec)
> +      return Diag(IdLoc, diag::err_not_direct_base_or_virtual)
> +      << BaseType << ClassDecl->getNameAsCString()
> +      << SourceRange(IdLoc, RParenLoc);
>   }
>
> -  // C++ [base.class.init]p2:
> -  //   If a mem-initializer-id is ambiguous because it designates both
> -  //   a direct non-virtual base class and an inherited virtual base
> -  //   class, the mem-initializer is ill-formed.
> -  if (DirectBaseSpec && VirtualBaseSpec)
> -    return Diag(IdLoc, diag::err_base_init_direct_and_virtual)
> -      << MemberOrBase << SourceRange(IdLoc, RParenLoc);
> -  // C++ [base.class.init]p2:
> -  // Unless the mem-initializer-id names a nonstatic data membeer of the
> -  // constructor's class ot a direst or virtual base of that class, the
> -  // mem-initializer is ill-formed.
> -  if (!DirectBaseSpec && !VirtualBaseSpec)
> -    return Diag(IdLoc, diag::err_not_direct_base_or_virtual)
> -    << BaseType << ClassDecl->getNameAsCString()
> -    << SourceRange(IdLoc, RParenLoc);
> -  DeclarationName Name
> -    = Context.DeclarationNames.getCXXConstructorName(
> -        Context.getCanonicalType(BaseType));
>   CXXConstructorDecl *C = 0;
> -  if (!BaseType->isDependentType())
> -    C = PerformInitializationByConstructor(BaseType, (Expr **)Args, NumArgs, IdLoc,
> -                                       SourceRange(IdLoc, RParenLoc), Name,
> -                                       IK_Direct);
> -
> -  return new (Context) CXXBaseOrMemberInitializer(BaseType, (Expr **)Args,
> +  if (!BaseType->isDependentType() && !HasDependentArg) {
> +    DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(
> +                                            Context.getCanonicalType(BaseType));
> +    C = PerformInitializationByConstructor(BaseType, (Expr **)Args, NumArgs,
> +                                           IdLoc, SourceRange(IdLoc, RParenLoc),
> +                                           Name, IK_Direct);
> +  }
> +
> +  return new (Context) CXXBaseOrMemberInitializer(BaseType, (Expr **)Args,
>                                                   NumArgs, C, IdLoc);
>  }
>
>
> Added: cfe/trunk/test/SemaTemplate/dependent-base-member-init.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/dependent-base-member-init.cpp?rev=77498&view=auto
>
> ==============================================================================
> --- cfe/trunk/test/SemaTemplate/dependent-base-member-init.cpp (added)
> +++ cfe/trunk/test/SemaTemplate/dependent-base-member-init.cpp Wed Jul 29 14:44:27 2009
> @@ -0,0 +1,25 @@
> +// RUN: clang-cc -fsyntax-only -verify %s
> +
> +// PR4621
> +class A1 {
> +  A1(int x) {}
> +};
> +template<class C> class B1 : public A1 {
> +  B1(C x) : A1(x.x) {}
> +};
> +class A2 { A2(int x, int y); };
> +template <class C> class B2 {
> +  A2 x;
> +  B2(C x) : x(x.x, x.y) {}
> +};
> +template <class C> class B3 {
> +  C x;
> +  B3() : x(1,2) {}
> +};
> +
> +// PR4627
> +template<typename _Container> class insert_iterator {
> +    _Container* container;
> +    insert_iterator(_Container& __x) : container(&__x) {}
> +};
> +
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>




More information about the cfe-commits mailing list