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

Eli Friedman eli.friedman at gmail.com
Wed Jul 29 12:44:27 PDT 2009


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) {}
+};
+





More information about the cfe-commits mailing list