[cfe-commits] r58040 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp lib/AST/InheritViz.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaInherit.cpp

Douglas Gregor doug.gregor at gmail.com
Thu Oct 23 11:13:29 PDT 2008


Author: dgregor
Date: Thu Oct 23 13:13:27 2008
New Revision: 58040

URL: http://llvm.org/viewvc/llvm-project?rev=58040&view=rev
Log:
Clean up and document the representation of C++ base classes

Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/AST/InheritViz.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaInherit.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=58040&r1=58039&r2=58040&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Thu Oct 23 13:13:27 2008
@@ -40,10 +40,29 @@
   static bool classof(const CXXFieldDecl *D) { return true; }
 };
 
-/// BaseSpecifier - A base class of a C++ class.
+/// CXXBaseSpecifier - A base class of a C++ class.
+///
+/// Each CXXBaseSpecifier represents a single, direct base class (or
+/// struct) of a C++ class (or struct). It specifies the type of that
+/// base class, whether it is a virtual or non-virtual base, and what
+/// level of access (public, protected, private) is used for the
+/// derivation. For example:
+///
+/// @code
+///   class A { };
+///   class B { };
+///   class C : public virtual A, protected B { };
+/// @endcode
+///
+/// In this code, C will have two CXXBaseSpecifiers, one for "public
+/// virtual A" and the other for "protected B".
 class CXXBaseSpecifier {
+  /// Range - The source code range that covers the full base
+  /// specifier, including the "virtual" (if present) and access
+  /// specifier (if present).
   SourceRange Range;
 
+  /// Virtual - Whether this is a virtual base class or not.
   bool Virtual : 1;
 
   /// BaseOfClass - Whether this is the base of a class (true) or of a
@@ -52,21 +71,22 @@
   /// used for semantic analysis.
   bool BaseOfClass : 1; 
 
-  /// Access specifier as written in the source code (which may be
-  /// AS_none). The actual type of data stored here is an
+  /// Access - Access specifier as written in the source code (which
+  /// may be AS_none). The actual type of data stored here is an
   /// AccessSpecifier, but we use "unsigned" here to work around a
   /// VC++ bug.
   unsigned Access : 2;
 
+  /// BaseType - The type of the base class. This will be a class or
+  /// struct (or a typedef of such).
   QualType BaseType;
   
+public:
+  CXXBaseSpecifier() { }
+
   CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A, QualType T)
     : Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseType(T) { }
 
-public:
-  static CXXBaseSpecifier *Create(ASTContext &C, SourceRange R, bool V, bool BC, 
-                                  AccessSpecifier A, QualType T);
-
   /// getSourceRange - Retrieves the source range that contains the
   /// entire base specifier.
   SourceRange getSourceRange() const { return Range; }
@@ -108,7 +128,7 @@
 class CXXRecordDecl : public RecordDecl, public DeclContext {
   /// Bases - Base classes of this class.
   /// FIXME: This is wasted space for a union.
-  CXXBaseSpecifier **Bases;
+  CXXBaseSpecifier *Bases;
 
   /// NumBases - The number of base class specifiers in Bases.
   unsigned NumBases;
@@ -121,31 +141,30 @@
   ~CXXRecordDecl();
 
 public:
+  /// base_class_iterator - Iterator that traverses the base classes
+  /// of a clas.
+  typedef CXXBaseSpecifier*       base_class_iterator;
+
+  /// base_class_const_iterator - Iterator that traverses the base
+  /// classes of a clas.
+  typedef const CXXBaseSpecifier* base_class_const_iterator;
+
   static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
                                SourceLocation L, IdentifierInfo *Id,
                                CXXRecordDecl* PrevDecl=0);
   
   /// setBases - Sets the base classes of this struct or class.
-  void setBases(CXXBaseSpecifier **Bases, unsigned NumBases) {
-    this->Bases = Bases;
-    this->NumBases = NumBases;
-  }
+  void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases);
 
   /// getNumBases - Retrieves the number of base classes of this
   /// class.
   unsigned getNumBases() const { return NumBases; }
 
-  /// getBase - Retrieve the ith base class.
-  CXXBaseSpecifier *getBase(unsigned i) { 
-    assert(i < NumBases && "Base index out of range");
-    return Bases[i];
-  }
+  base_class_iterator       bases_begin()       { return Bases; }
+  base_class_const_iterator bases_begin() const { return Bases; }
+  base_class_iterator       bases_end()         { return Bases + NumBases; }
+  base_class_const_iterator bases_end()   const { return Bases + NumBases; }
 
-  /// getBase - Retrieve the ith base class.
-  const CXXBaseSpecifier *getBase(unsigned i) const { 
-    assert(i < NumBases && "Base index out of range");
-    return Bases[i];
-  }
 
   const CXXFieldDecl *getMember(unsigned i) const {
     return cast<const CXXFieldDecl>(RecordDecl::getMember(i));

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=58040&r1=58039&r2=58040&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Thu Oct 23 13:13:27 2008
@@ -26,14 +26,6 @@
   return new (Mem) CXXFieldDecl(RD, L, Id, T, BW);
 }
 
-CXXBaseSpecifier *CXXBaseSpecifier::Create(ASTContext &C, SourceRange R, bool V, 
-                                           bool BC, AccessSpecifier A, QualType T)
-{
-  void *Mem = C.getAllocator().Allocate<CXXBaseSpecifier>();
-  CXXBaseSpecifier* BS = new (Mem) CXXBaseSpecifier(R, V, BC, A, T);
-  return BS;
-}
-
 CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
                                      SourceLocation L, IdentifierInfo *Id,
                                      CXXRecordDecl* PrevDecl) {
@@ -44,11 +36,21 @@
 }
 
 CXXRecordDecl::~CXXRecordDecl() {
-  for (unsigned i = 0; i < NumBases; ++i)
-    delete Bases[i];
   delete [] Bases;
 }
 
+void 
+CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, 
+                        unsigned NumBases) {
+  if (this->Bases)
+    delete [] this->Bases;
+
+  this->Bases = new CXXBaseSpecifier[NumBases];
+  this->NumBases = NumBases;
+  for (unsigned i = 0; i < NumBases; ++i)
+    this->Bases[i] = *Bases[i];
+}
+
 CXXMethodDecl *
 CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
                       SourceLocation L, IdentifierInfo *Id,

Modified: cfe/trunk/lib/AST/InheritViz.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/InheritViz.cpp?rev=58040&r1=58039&r2=58040&view=diff

==============================================================================
--- cfe/trunk/lib/AST/InheritViz.cpp (original)
+++ cfe/trunk/lib/AST/InheritViz.cpp Thu Oct 23 13:13:27 2008
@@ -92,8 +92,8 @@
   // Display the base classes.
   const CXXRecordDecl *Decl 
     = static_cast<const CXXRecordDecl *>(Type->getAsRecordType()->getDecl());
-  for (unsigned idx = 0; idx < Decl->getNumBases(); ++idx) {
-    const CXXBaseSpecifier *Base = Decl->getBase(idx);
+  for (CXXRecordDecl::base_class_const_iterator Base = Decl->bases_begin();
+       Base != Decl->bases_end(); ++Base) {
     QualType CanonBaseType = Context.getCanonicalType(Base->getType());
 
     // If this is not virtual inheritance, bump the direct base

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=58040&r1=58039&r2=58040&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Oct 23 13:13:27 2008
@@ -299,11 +299,8 @@
   }
 
   // Create the base specifier.
-  CXXBaseSpecifier *BS = CXXBaseSpecifier::Create(Context, SpecifierRange, 
-                                                  Virtual, 
-                                                  BaseType->isClassType(),
-                                                  Access, BaseType);
-  return BS;
+  return new CXXBaseSpecifier(SpecifierRange, Virtual, 
+                              BaseType->isClassType(), Access, BaseType);
 }
 
 /// ActOnBaseSpecifiers - Attach the given base specifiers to the
@@ -316,34 +313,45 @@
 
   // Used to keep track of which base types we have already seen, so
   // that we can properly diagnose redundant direct base types. Note
-  // that the key is always the canonical type.
+  // that the key is always the unqualified canonical type of the base
+  // class.
   std::map<QualType, CXXBaseSpecifier*, QualTypeOrdering> KnownBaseTypes;
 
   // Copy non-redundant base specifiers into permanent storage.
-  CXXBaseSpecifier **InBaseSpecs = (CXXBaseSpecifier **)Bases;
-  CXXBaseSpecifier **StoredBaseSpecs = new CXXBaseSpecifier* [NumBases];
-  unsigned outIdx = 0;
-  for (unsigned inIdx = 0; inIdx < NumBases; ++inIdx) {
+  CXXBaseSpecifier **BaseSpecs = (CXXBaseSpecifier **)Bases;
+  unsigned NumGoodBases = 0;
+  for (unsigned idx = 0; idx < NumBases; ++idx) {
     QualType NewBaseType 
-      = Context.getCanonicalType(InBaseSpecs[inIdx]->getType());
+      = Context.getCanonicalType(BaseSpecs[idx]->getType());
+    NewBaseType = NewBaseType.getUnqualifiedType();
+
     if (KnownBaseTypes[NewBaseType]) {
       // C++ [class.mi]p3:
       //   A class shall not be specified as a direct base class of a
       //   derived class more than once.
-      Diag(InBaseSpecs[inIdx]->getSourceRange().getBegin(),
+      Diag(BaseSpecs[idx]->getSourceRange().getBegin(),
            diag::err_duplicate_base_class, 
            KnownBaseTypes[NewBaseType]->getType().getAsString(),
-           InBaseSpecs[inIdx]->getSourceRange());
+           BaseSpecs[idx]->getSourceRange());
+
+      // Delete the duplicate base class specifier; we're going to
+      // overwrite its pointer later.
+      delete BaseSpecs[idx];
     } else {
       // Okay, add this new base class.
-      KnownBaseTypes[NewBaseType] = InBaseSpecs[inIdx];
-      StoredBaseSpecs[outIdx++] = InBaseSpecs[inIdx];
+      KnownBaseTypes[NewBaseType] = BaseSpecs[idx];
+      BaseSpecs[NumGoodBases++] = BaseSpecs[idx];
     }
   }
 
   // Attach the remaining base class specifiers to the derived class.
   CXXRecordDecl *Decl = (CXXRecordDecl*)ClassDecl;
-  Decl->setBases(StoredBaseSpecs, outIdx);
+  Decl->setBases(BaseSpecs, NumGoodBases);
+
+  // Delete the remaining (good) base class specifiers, since their
+  // data has been copied into the CXXRecordDecl.
+  for (unsigned idx = 0; idx < NumGoodBases; ++idx)
+    delete BaseSpecs[idx];
 }
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/Sema/SemaInherit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInherit.cpp?rev=58040&r1=58039&r2=58040&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaInherit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInherit.cpp Thu Oct 23 13:13:27 2008
@@ -39,8 +39,8 @@
   if (const RecordType *DerivedType = Derived->getAsRecordType()) {
     const CXXRecordDecl *Decl 
       = static_cast<const CXXRecordDecl *>(DerivedType->getDecl());
-    for (unsigned idx = 0; idx < Decl->getNumBases(); ++idx) {
-      const CXXBaseSpecifier *BaseSpec = Decl->getBase(idx);
+    for (CXXRecordDecl::base_class_const_iterator BaseSpec = Decl->bases_begin();
+         BaseSpec != Decl->bases_end(); ++BaseSpec) {
       if (Context.getCanonicalType(BaseSpec->getType()) == Base
           || IsDerivedFrom(BaseSpec->getType(), Base))
         return true;





More information about the cfe-commits mailing list