[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