[cfe-commits] r107510 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/DeclCXX.h lib/AST/ASTContext.cpp lib/AST/DeclCXX.cpp lib/Frontend/PCHReaderDecl.cpp lib/Frontend/PCHWriterDecl.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaLookup.cpp
Douglas Gregor
dgregor at apple.com
Fri Jul 2 13:37:36 PDT 2010
Author: dgregor
Date: Fri Jul 2 15:37:36 2010
New Revision: 107510
URL: http://llvm.org/viewvc/llvm-project?rev=107510&view=rev
Log:
Lazily declare the implicitly-declared destructor in a C++ class.
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaLookup.cpp
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=107510&r1=107509&r2=107510&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Jul 2 15:37:36 2010
@@ -1322,6 +1322,17 @@
/// \brief Data Pointer data that will be provided to the callback function
/// when it is called.
void AddDeallocation(void (*Callback)(void*), void *Data);
+
+ //===--------------------------------------------------------------------===//
+ // Statistics
+ //===--------------------------------------------------------------------===//
+
+ /// \brief The number of implicitly-declared destructors.
+ static unsigned NumImplicitDestructors;
+
+ /// \brief The number of implicitly-declared destructors for which
+ /// declarations were built.
+ static unsigned NumImplicitDestructorsDeclared;
private:
ASTContext(const ASTContext&); // DO NOT IMPLEMENT
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=107510&r1=107509&r2=107510&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Jul 2 15:37:36 2010
@@ -319,6 +319,9 @@
/// already computed and are available.
bool ComputedVisibleConversions : 1;
+ /// \brief Whether we have already declared a destructor within the class.
+ bool DeclaredDestructor : 1;
+
/// Bases - Base classes of this class.
/// FIXME: This is wasted space for a union.
CXXBaseSpecifier *Bases;
@@ -600,8 +603,21 @@
/// fully defined, a destructor will be implicitly declared.
void setUserDeclaredDestructor(bool UCD) {
data().UserDeclaredDestructor = UCD;
+ if (UCD)
+ data().DeclaredDestructor = true;
}
+ /// \brief Determine whether this class has had its destructor declared,
+ /// either via the user or via an implicit declaration.
+ ///
+ /// This value is used for lazy creation of destructors.
+ bool hasDeclaredDestructor() const { return data().DeclaredDestructor; }
+
+ /// \brief Note whether this class has already had its destructor declared.
+ void setDeclaredDestructor(bool DD) {
+ data().DeclaredDestructor = DD;
+ }
+
/// getConversions - Retrieve the overload set containing all of the
/// conversion functions in this class.
UnresolvedSetImpl *getConversionFunctions() {
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=107510&r1=107509&r2=107510&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Jul 2 15:37:36 2010
@@ -31,6 +31,9 @@
using namespace clang;
+unsigned ASTContext::NumImplicitDestructors;
+unsigned ASTContext::NumImplicitDestructorsDeclared;
+
enum FloatingRank {
FloatRank, DoubleRank, LongDoubleRank
};
@@ -253,6 +256,10 @@
fprintf(stderr, "Total bytes = %d\n", int(TotalBytes));
+ // Implicit special member functions.
+ fprintf(stderr, " %u/%u implicit destructors created\n",
+ NumImplicitDestructorsDeclared, NumImplicitDestructors);
+
if (ExternalSource.get()) {
fprintf(stderr, "\n");
ExternalSource->PrintStats();
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=107510&r1=107509&r2=107510&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Jul 2 15:37:36 2010
@@ -32,6 +32,7 @@
Abstract(false), HasTrivialConstructor(true),
HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true),
HasTrivialDestructor(true), ComputedVisibleConversions(false),
+ DeclaredDestructor(false),
Bases(0), NumBases(0), VBases(0), NumVBases(0),
Definition(D), FirstFriend(0) {
}
Modified: cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderDecl.cpp?rev=107510&r1=107509&r2=107510&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderDecl.cpp Fri Jul 2 15:37:36 2010
@@ -668,6 +668,7 @@
Data.HasTrivialCopyAssignment = Record[Idx++];
Data.HasTrivialDestructor = Record[Idx++];
Data.ComputedVisibleConversions = Record[Idx++];
+ Data.DeclaredDestructor = Record[Idx++];
// setBases() is unsuitable since it may try to iterate the bases of an
// unitialized base.
Modified: cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriterDecl.cpp?rev=107510&r1=107509&r2=107510&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriterDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriterDecl.cpp Fri Jul 2 15:37:36 2010
@@ -664,6 +664,7 @@
Record.push_back(Data.HasTrivialCopyAssignment);
Record.push_back(Data.HasTrivialDestructor);
Record.push_back(Data.ComputedVisibleConversions);
+ Record.push_back(Data.DeclaredDestructor);
Record.push_back(D->getNumBases());
for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=107510&r1=107509&r2=107510&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Jul 2 15:37:36 2010
@@ -2282,6 +2282,10 @@
void DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
CXXMethodDecl *MethodDecl);
+ /// \brief Force the declaration of any implicitly-declared members of this
+ /// class.
+ void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class);
+
/// MaybeBindToTemporary - If the passed in expression has a record type with
/// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise
/// it simply returns the passed in expression.
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=107510&r1=107509&r2=107510&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Jul 2 15:37:36 2010
@@ -3676,7 +3676,7 @@
CXXRecordDecl *Record = Destructor->getParent();
QualType ClassType = Context.getTypeDeclType(Record);
- // FIXME: Shouldn't we be able to perform thisc heck even when the class
+ // FIXME: Shouldn't we be able to perform this check even when the class
// type is dependent? Both gcc and edg can handle that.
if (!ClassType->isDependentType()) {
DeclarationName Name
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=107510&r1=107509&r2=107510&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Jul 2 15:37:36 2010
@@ -2662,8 +2662,16 @@
if (!ClassDecl->hasUserDeclaredCopyAssignment())
DeclareImplicitCopyAssignment(ClassDecl);
- if (!ClassDecl->hasUserDeclaredDestructor())
- DeclareImplicitDestructor(ClassDecl);
+ if (!ClassDecl->hasUserDeclaredDestructor()) {
+ ++ASTContext::NumImplicitDestructors;
+
+ // If we have a dynamic class, then the destructor may be virtual, so we
+ // have to declare the destructor immediately. This ensures that, e.g., it
+ // shows up in the right place in the vtable and that we diagnose problems
+ // with the implicit exception specification.
+ if (ClassDecl->isDynamicClass())
+ DeclareImplicitDestructor(ClassDecl);
+ }
}
void Sema::ActOnReenterTemplateScope(Scope *S, DeclPtrTy TemplateD) {
@@ -4274,6 +4282,7 @@
LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl())));
}
+ // Create the actual destructor declaration.
QualType Ty = Context.getFunctionType(Context.VoidTy,
0, 0, false, 0,
ExceptSpec.hasExceptionSpecification(),
@@ -4294,15 +4303,21 @@
Destructor->setAccess(AS_public);
Destructor->setImplicit();
Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
+
+ // Note that we have declared this destructor.
+ ClassDecl->setDeclaredDestructor(true);
+ ++ASTContext::NumImplicitDestructorsDeclared;
+
+ // Introduce this destructor into its scope.
if (Scope *S = getScopeForContext(ClassDecl))
- PushOnScopeChains(Destructor, S, true);
- else
- ClassDecl->addDecl(Destructor);
+ PushOnScopeChains(Destructor, S, false);
+ ClassDecl->addDecl(Destructor);
// This could be uniqued if it ever proves significant.
Destructor->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(Ty));
AddOverriddenMethods(ClassDecl, Destructor);
+
return Destructor;
}
Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=107510&r1=107509&r2=107510&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Fri Jul 2 15:37:36 2010
@@ -447,11 +447,52 @@
return false;
}
+/// \brief Determine whether we can declare a special member function within
+/// the class at this point.
+static bool CanDeclareSpecialMemberFunction(ASTContext &Context,
+ const CXXRecordDecl *Class) {
+ // We need to have a definition for the class.
+ if (!Class->getDefinition() || Class->isDependentContext())
+ return false;
+
+ // We can't be in the middle of defining the class.
+ if (const RecordType *RecordTy
+ = Context.getTypeDeclType(Class)->getAs<RecordType>())
+ return !RecordTy->isBeingDefined();
+
+ return false;
+}
+
+void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) {
+ // If the destructor has not yet been declared, do so now.
+ if (CanDeclareSpecialMemberFunction(Context, Class) &&
+ !Class->hasDeclaredDestructor())
+ DeclareImplicitDestructor(Class);
+}
+
+
// Adds all qualifying matches for a name within a decl context to the
// given lookup result. Returns true if any matches were found.
static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) {
bool Found = false;
+ // Lazily declare C++ special member functions.
+ if (S.getLangOptions().CPlusPlus) {
+ switch (R.getLookupName().getNameKind()) {
+ case DeclarationName::CXXDestructorName:
+ if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
+ if (Record->getDefinition() && !Record->hasDeclaredDestructor() &&
+ CanDeclareSpecialMemberFunction(S.Context, Record))
+ S.DeclareImplicitDestructor(const_cast<CXXRecordDecl *>(Record));
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // Perform lookup into this declaration context.
DeclContext::lookup_const_iterator I, E;
for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) {
NamedDecl *D = *I;
@@ -1904,6 +1945,11 @@
///
/// \returns The destructor for this class.
CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) {
+ // If the destructor has not yet been declared, do so now.
+ if (CanDeclareSpecialMemberFunction(Context, Class) &&
+ !Class->hasDeclaredDestructor())
+ DeclareImplicitDestructor(Class);
+
return Class->getDestructor();
}
@@ -2205,6 +2251,9 @@
if (Visited.visitedContext(Ctx->getPrimaryContext()))
return;
+ if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx))
+ Result.getSema().ForceDeclarationOfImplicitMembers(Class);
+
// Enumerate all of the results in this context.
for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx;
CurCtx = CurCtx->getNextContext()) {
More information about the cfe-commits
mailing list