[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