[cfe-commits] r143410 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/AST/RecursiveASTVisitor.h include/clang/Sema/Sema.h lib/AST/DeclCXX.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp lib/Serialization/ASTReader.cpp lib/Serialization/ASTWriter.cpp test/SemaTemplate/delegating-constructors.cpp tools/libclang/CIndex.cpp

Douglas Gregor dgregor at apple.com
Mon Oct 31 18:16:04 PDT 2011


Author: dgregor
Date: Mon Oct 31 20:16:03 2011
New Revision: 143410

URL: http://llvm.org/viewvc/llvm-project?rev=143410&view=rev
Log:
Rework the AST for the initializer of a delegating constructor, so
that it retains source location information for the type. Aside from
general goodness (being able to walk the types described in that
information), we now have a proper representation for dependent
delegating constructors. Fixes PR10457 (for real).

Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/SemaTemplate/delegating-constructors.cpp
    cfe/trunk/tools/libclang/CIndex.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=143410&r1=143409&r2=143410&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Oct 31 20:16:03 2011
@@ -1445,11 +1445,10 @@
 /// };
 /// @endcode
 class CXXCtorInitializer {
-  /// \brief Either the base class name (stored as a TypeSourceInfo*), an normal
-  /// field (FieldDecl), anonymous field (IndirectFieldDecl*), or target
-  /// constructor (CXXConstructorDecl*) being initialized.
-  llvm::PointerUnion4<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *,
-                      CXXConstructorDecl *>
+  /// \brief Either the base class name/delegating constructor type (stored as
+  /// a TypeSourceInfo*), an normal field (FieldDecl), or an anonymous field 
+  /// (IndirectFieldDecl*) being initialized.
+  llvm::PointerUnion3<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *>
     Initializee;
   
   /// \brief The source location for the field name or, for a base initializer
@@ -1470,6 +1469,10 @@
   /// RParenLoc - Location of the right paren of the ctor-initializer.
   SourceLocation RParenLoc;
 
+  /// \brief If the initializee is a type, whether that type makes this
+  /// a delegating initialization.
+  bool IsDelegating : 1;
+  
   /// IsVirtual - If the initializer is a base initializer, this keeps track
   /// of whether the base is virtual or not.
   bool IsVirtual : 1;
@@ -1483,7 +1486,7 @@
   /// original sources, counting from 0; otherwise, if IsWritten is false,
   /// it stores the number of array index variables stored after this
   /// object in memory.
-  unsigned SourceOrderOrNumArrayIndices : 14;
+  unsigned SourceOrderOrNumArrayIndices : 13;
 
   CXXCtorInitializer(ASTContext &Context, FieldDecl *Member,
                      SourceLocation MemberLoc, SourceLocation L, Expr *Init,
@@ -1510,8 +1513,8 @@
 
   /// CXXCtorInitializer - Creates a new delegating Initializer.
   explicit
-  CXXCtorInitializer(ASTContext &Context, SourceLocation D, SourceLocation L,
-                     CXXConstructorDecl *Target, Expr *Init, SourceLocation R);
+  CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo,
+                     SourceLocation L, Expr *Init, SourceLocation R);
 
   /// \brief Creates a new member initializer that optionally contains 
   /// array indices used to describe an elementwise initialization.
@@ -1522,7 +1525,9 @@
   
   /// isBaseInitializer - Returns true when this initializer is
   /// initializing a base class.
-  bool isBaseInitializer() const { return Initializee.is<TypeSourceInfo*>(); }
+  bool isBaseInitializer() const { 
+    return Initializee.is<TypeSourceInfo*>() && !IsDelegating; 
+  }
 
   /// isMemberInitializer - Returns true when this initializer is
   /// initializing a non-static data member.
@@ -1546,7 +1551,7 @@
   /// isDelegatingInitializer - Returns true when this initializer is creating
   /// a delegating constructor.
   bool isDelegatingInitializer() const {
-    return Initializee.is<CXXConstructorDecl *>();
+    return Initializee.is<TypeSourceInfo*>() && IsDelegating; 
   }
 
   /// \brief Determine whether this initializer is a pack expansion.
@@ -1576,8 +1581,9 @@
     return IsVirtual;
   }
 
-  /// \brief Returns the declarator information for a base class initializer.
-  TypeSourceInfo *getBaseClassInfo() const {
+  /// \brief Returns the declarator information for a base class or delegating
+  /// initializer.
+  TypeSourceInfo *getTypeSourceInfo() const {
     return Initializee.dyn_cast<TypeSourceInfo *>();
   }
   
@@ -1606,13 +1612,6 @@
       return 0;
   }
 
-  CXXConstructorDecl *getTargetConstructor() const {
-    if (isDelegatingInitializer())
-      return Initializee.get<CXXConstructorDecl*>();
-    else
-      return 0;
-  }
-
   SourceLocation getMemberLocation() const { 
     return MemberOrEllipsisLocation;
   }
@@ -1821,11 +1820,7 @@
 
   /// getTargetConstructor - When this constructor delegates to
   /// another, retrieve the target
-  CXXConstructorDecl *getTargetConstructor() const {
-    assert(isDelegatingConstructor() &&
-           "A non-delegating constructor has no target");
-    return CtorInitializers[0]->getTargetConstructor();
-  }
+  CXXConstructorDecl *getTargetConstructor() const;
 
   /// isDefaultConstructor - Whether this constructor is a default
   /// constructor (C++ [class.ctor]p5), which can be used to

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=143410&r1=143409&r2=143410&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Mon Oct 31 20:16:03 2011
@@ -667,7 +667,9 @@
 template<typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer(
                                                      CXXCtorInitializer *Init) {
-  // FIXME: recurse on TypeLoc of the base initializer if isBaseInitializer()?
+  if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo())
+    TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
+  
   if (Init->isWritten())
     TRY_TO(TraverseStmt(Init->getInit()));
   return true;

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=143410&r1=143409&r2=143410&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Oct 31 20:16:03 2011
@@ -3518,7 +3518,6 @@
 
   MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo,
                                            const MultiInitializer &Args,
-                                           SourceLocation BaseLoc,
                                            CXXRecordDecl *ClassDecl);
 
   bool SetDelegatingInitializer(CXXConstructorDecl *Constructor,

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=143410&r1=143409&r2=143410&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Oct 31 20:16:03 2011
@@ -17,6 +17,7 @@
 #include "clang/AST/ASTMutationListener.h"
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "llvm/ADT/STLExtras.h"
@@ -1299,8 +1300,8 @@
                                        SourceLocation R,
                                        SourceLocation EllipsisLoc)
   : Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init), 
-    LParenLoc(L), RParenLoc(R), IsVirtual(IsVirtual), IsWritten(false),
-    SourceOrderOrNumArrayIndices(0)
+    LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual), 
+    IsWritten(false), SourceOrderOrNumArrayIndices(0)
 {
 }
 
@@ -1310,7 +1311,7 @@
                                        SourceLocation L, Expr *Init,
                                        SourceLocation R)
   : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
-    LParenLoc(L), RParenLoc(R), IsVirtual(false),
+    LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
     IsWritten(false), SourceOrderOrNumArrayIndices(0)
 {
 }
@@ -1321,17 +1322,17 @@
                                        SourceLocation L, Expr *Init,
                                        SourceLocation R)
   : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
-    LParenLoc(L), RParenLoc(R), IsVirtual(false),
+    LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
     IsWritten(false), SourceOrderOrNumArrayIndices(0)
 {
 }
 
 CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
-                                       SourceLocation D, SourceLocation L,
-                                       CXXConstructorDecl *Target, Expr *Init,
+                                       TypeSourceInfo *TInfo,
+                                       SourceLocation L, Expr *Init, 
                                        SourceLocation R)
-  : Initializee(Target), MemberOrEllipsisLocation(D), Init(Init),
-    LParenLoc(L), RParenLoc(R), IsVirtual(false),
+  : Initializee(TInfo), MemberOrEllipsisLocation(), Init(Init),
+    LParenLoc(L), RParenLoc(R), IsDelegating(true), IsVirtual(false),
     IsWritten(false), SourceOrderOrNumArrayIndices(0)
 {
 }
@@ -1380,13 +1381,16 @@
 }
 
 SourceLocation CXXCtorInitializer::getSourceLocation() const {
-  if (isAnyMemberInitializer() || isDelegatingInitializer())
+  if (isAnyMemberInitializer())
     return getMemberLocation();
 
   if (isInClassMemberInitializer())
     return getAnyMember()->getLocation();
   
-  return getBaseClassLoc().getLocalSourceRange().getBegin();
+  if (TypeSourceInfo *TSInfo = Initializee.get<TypeSourceInfo*>())
+    return TSInfo->getTypeLoc().getLocalSourceRange().getBegin();
+  
+  return SourceLocation();
 }
 
 SourceRange CXXCtorInitializer::getSourceRange() const {
@@ -1421,6 +1425,15 @@
                                     isConstexpr);
 }
 
+CXXConstructorDecl *CXXConstructorDecl::getTargetConstructor() const {
+  assert(isDelegatingConstructor() && "Not a delegating constructor!");
+  Expr *E = (*init_begin())->getInit()->IgnoreImplicit();
+  if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(E))
+    return Construct->getConstructor();
+  
+  return 0;
+}
+
 bool CXXConstructorDecl::isDefaultConstructor() const {
   // C++ [class.ctor]p5:
   //   A default constructor for a class X is a constructor of class

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=143410&r1=143409&r2=143410&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Oct 31 20:16:03 2011
@@ -2125,13 +2125,12 @@
 MemInitResult
 Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo,
                                  const MultiInitializer &Args,
-                                 SourceLocation NameLoc,
                                  CXXRecordDecl *ClassDecl) {
-  SourceLocation Loc = TInfo->getTypeLoc().getLocalSourceRange().getBegin();
+  SourceLocation NameLoc = TInfo->getTypeLoc().getLocalSourceRange().getBegin();
   if (!LangOpts.CPlusPlus0x)
-    return Diag(Loc, diag::err_delegating_ctor)
+    return Diag(NameLoc, diag::err_delegating_ctor)
       << TInfo->getTypeLoc().getLocalSourceRange();
-  Diag(Loc, diag::warn_cxx98_compat_delegating_ctor);
+  Diag(NameLoc, diag::warn_cxx98_compat_delegating_ctor);
 
   // Initialize the object.
   InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation(
@@ -2158,9 +2157,7 @@
   if (DelegationInit.isInvalid())
     return true;
 
-  assert(!CurContext->isDependentContext());
-  return new (Context) CXXCtorInitializer(Context, Loc, Args.getStartLoc(),
-                                          Constructor,
+  return new (Context) CXXCtorInitializer(Context, TInfo, Args.getStartLoc(), 
                                           DelegationInit.takeAs<Expr>(),
                                           Args.getEndLoc());
 }
@@ -2210,7 +2207,7 @@
   if (!Dependent) { 
     if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0),
                                        BaseType))
-      return BuildDelegatingInitializer(BaseTInfo, Args, BaseLoc, ClassDecl);
+      return BuildDelegatingInitializer(BaseTInfo, Args, ClassDecl);
 
     FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, 
                         VirtualBaseSpec);
@@ -3000,12 +2997,12 @@
       if (PrevInit->isAnyMemberInitializer())
         D << 0 << PrevInit->getAnyMember()->getDeclName();
       else
-        D << 1 << PrevInit->getBaseClassInfo()->getType();
+        D << 1 << PrevInit->getTypeSourceInfo()->getType();
       
       if (Init->isAnyMemberInitializer())
         D << 0 << Init->getAnyMember()->getDeclName();
       else
-        D << 1 << Init->getBaseClassInfo()->getType();
+        D << 1 << Init->getTypeSourceInfo()->getType();
 
       // Move back to the initializer's location in the ideal list.
       for (IdealIndex = 0; IdealIndex != NumIdealInits; ++IdealIndex)

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=143410&r1=143409&r2=143410&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Oct 31 20:16:03 2011
@@ -2744,7 +2744,7 @@
 
     if (Init->isPackExpansion()) {
       // This is a pack expansion. We should expand it now.
-      TypeLoc BaseTL = Init->getBaseClassInfo()->getTypeLoc();
+      TypeLoc BaseTL = Init->getTypeSourceInfo()->getTypeLoc();
       SmallVector<UnexpandedParameterPack, 2> Unexpanded;
       collectUnexpandedParameterPacks(BaseTL, Unexpanded);
       bool ShouldExpand = false;
@@ -2774,7 +2774,7 @@
         }
 
         // Instantiate the base type.
-        TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(),
+        TypeSourceInfo *BaseTInfo = SubstType(Init->getTypeSourceInfo(),
                                               TemplateArgs,
                                               Init->getSourceLocation(),
                                               New->getDeclName());
@@ -2809,20 +2809,25 @@
     }
 
     MemInitResult NewInit;
-    if (Init->isBaseInitializer()) {
-      TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(),
-                                            TemplateArgs,
-                                            Init->getSourceLocation(),
-                                            New->getDeclName());
-      if (!BaseTInfo) {
+    if (Init->isDelegatingInitializer() || Init->isBaseInitializer()) {
+      TypeSourceInfo *TInfo = SubstType(Init->getTypeSourceInfo(),
+                                        TemplateArgs,
+                                        Init->getSourceLocation(),
+                                        New->getDeclName());
+      if (!TInfo) {
         AnyErrors = true;
         New->setInvalidDecl();
         continue;
       }
 
       MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init));
-      NewInit = BuildBaseInitializer(BaseTInfo->getType(), BaseTInfo, MultiInit,
-                                     New->getParent(), EllipsisLoc);
+      
+      if (Init->isBaseInitializer())
+        NewInit = BuildBaseInitializer(TInfo->getType(), TInfo, MultiInit,
+                                       New->getParent(), EllipsisLoc);
+      else
+        NewInit = BuildDelegatingInitializer(TInfo, MultiInit, 
+                                  cast<CXXRecordDecl>(CurContext->getParent()));
     } else if (Init->isMemberInitializer()) {
       FieldDecl *Member = cast_or_null<FieldDecl>(FindInstantiatedDecl(
                                                      Init->getMemberLocation(),

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=143410&r1=143409&r2=143410&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Mon Oct 31 20:16:03 2011
@@ -5152,21 +5152,20 @@
     CtorInitializers
         = new (Context) CXXCtorInitializer*[NumInitializers];
     for (unsigned i=0; i != NumInitializers; ++i) {
-      TypeSourceInfo *BaseClassInfo = 0;
+      TypeSourceInfo *TInfo = 0;
       bool IsBaseVirtual = false;
       FieldDecl *Member = 0;
       IndirectFieldDecl *IndirectMember = 0;
-      CXXConstructorDecl *Target = 0;
 
       CtorInitializerType Type = (CtorInitializerType)Record[Idx++];
       switch (Type) {
-       case CTOR_INITIALIZER_BASE:
-        BaseClassInfo = GetTypeSourceInfo(F, Record, Idx);
+      case CTOR_INITIALIZER_BASE:
+        TInfo = GetTypeSourceInfo(F, Record, Idx);
         IsBaseVirtual = Record[Idx++];
         break;
-
-       case CTOR_INITIALIZER_DELEGATING:
-        Target = ReadDeclAs<CXXConstructorDecl>(F, Record, Idx);
+          
+      case CTOR_INITIALIZER_DELEGATING:
+        TInfo = GetTypeSourceInfo(F, Record, Idx);
         break;
 
        case CTOR_INITIALIZER_MEMBER:
@@ -5196,12 +5195,12 @@
 
       CXXCtorInitializer *BOMInit;
       if (Type == CTOR_INITIALIZER_BASE) {
-        BOMInit = new (Context) CXXCtorInitializer(Context, BaseClassInfo, IsBaseVirtual,
+        BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, IsBaseVirtual,
                                              LParenLoc, Init, RParenLoc,
                                              MemberOrEllipsisLoc);
       } else if (Type == CTOR_INITIALIZER_DELEGATING) {
-        BOMInit = new (Context) CXXCtorInitializer(Context, MemberOrEllipsisLoc, LParenLoc,
-                                             Target, Init, RParenLoc);
+        BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, LParenLoc,
+                                                   Init, RParenLoc);
       } else if (IsWritten) {
         if (Member)
           BOMInit = new (Context) CXXCtorInitializer(Context, Member, MemberOrEllipsisLoc,

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=143410&r1=143409&r2=143410&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Oct 31 20:16:03 2011
@@ -3881,11 +3881,11 @@
 
     if (Init->isBaseInitializer()) {
       Record.push_back(CTOR_INITIALIZER_BASE);
-      AddTypeSourceInfo(Init->getBaseClassInfo(), Record);
+      AddTypeSourceInfo(Init->getTypeSourceInfo(), Record);
       Record.push_back(Init->isBaseVirtual());
     } else if (Init->isDelegatingInitializer()) {
       Record.push_back(CTOR_INITIALIZER_DELEGATING);
-      AddDeclRef(Init->getTargetConstructor(), Record);
+      AddTypeSourceInfo(Init->getTypeSourceInfo(), Record);
     } else if (Init->isMemberInitializer()){
       Record.push_back(CTOR_INITIALIZER_MEMBER);
       AddDeclRef(Init->getMember(), Record);

Modified: cfe/trunk/test/SemaTemplate/delegating-constructors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/delegating-constructors.cpp?rev=143410&r1=143409&r2=143410&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/delegating-constructors.cpp (original)
+++ cfe/trunk/test/SemaTemplate/delegating-constructors.cpp Mon Oct 31 20:16:03 2011
@@ -15,4 +15,17 @@
   void f() {
     string s("hello");
   }
+
+  struct Foo {
+   Foo(int) { }
+
+
+   template <typename T>
+   Foo(T, int i) : Foo(i) { }
+};
+
+  void test_Foo()
+  {
+    Foo f(1, 1);
+  }
 }

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=143410&r1=143409&r2=143410&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Mon Oct 31 20:16:03 2011
@@ -828,8 +828,8 @@
           if (Visit(MakeCursorMemberRef(Init->getAnyMember(),
                                         Init->getMemberLocation(), TU)))
             return true;
-        } else if (TypeSourceInfo *BaseInfo = Init->getBaseClassInfo()) {
-          if (Visit(BaseInfo->getTypeLoc()))
+        } else if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) {
+          if (Visit(TInfo->getTypeLoc()))
             return true;
         }
         





More information about the cfe-commits mailing list