[cfe-commits] r107543 - 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/SemaDeclCXX.cpp lib/Sema/SemaLookup.cpp
Douglas Gregor
dgregor at apple.com
Fri Jul 2 16:41:54 PDT 2010
Author: dgregor
Date: Fri Jul 2 18:41:54 2010
New Revision: 107543
URL: http://llvm.org/viewvc/llvm-project?rev=107543&view=rev
Log:
Lazily declare implicit copy constructors.
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/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=107543&r1=107542&r2=107543&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Jul 2 18:41:54 2010
@@ -1327,6 +1327,13 @@
// Statistics
//===--------------------------------------------------------------------===//
+ /// \brief The number of implicitly-declared copy constructors.
+ static unsigned NumImplicitCopyConstructors;
+
+ /// \brief The number of implicitly-declared constructors for
+ /// which declarations were built.
+ static unsigned NumImplicitCopyConstructorsDeclared;
+
/// \brief The number of implicitly-declared copy assignment operators.
static unsigned NumImplicitCopyAssignmentOperators;
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=107543&r1=107542&r2=107543&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Jul 2 18:41:54 2010
@@ -319,6 +319,9 @@
/// already computed and are available.
bool ComputedVisibleConversions : 1;
+ /// \brief Whether we have already declared the copy constructor.
+ bool DeclaredCopyConstructor : 1;
+
/// \brief Whether we have already declared the copy-assignment operator.
bool DeclaredCopyAssignment : 1;
@@ -576,6 +579,20 @@
return data().UserDeclaredCopyConstructor;
}
+ /// \brief Determine whether this class has had its copy constructor
+ /// declared, either via the user or via an implicit declaration.
+ ///
+ /// This value is used for lazy creation of copy constructors.
+ bool hasDeclaredCopyConstructor() const {
+ return data().DeclaredCopyConstructor;
+ }
+
+ /// \brief Note whether this class has already had its copy constructor
+ /// declared.
+ void setDeclaredCopyConstructor(bool DCC) {
+ data().DeclaredCopyConstructor = DCC;
+ }
+
/// addedAssignmentOperator - Notify the class that another assignment
/// operator has been added. This routine helps maintain information about the
/// class based on which operators have been added.
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=107543&r1=107542&r2=107543&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Jul 2 18:41:54 2010
@@ -31,6 +31,8 @@
using namespace clang;
+unsigned ASTContext::NumImplicitCopyConstructors;
+unsigned ASTContext::NumImplicitCopyConstructorsDeclared;
unsigned ASTContext::NumImplicitCopyAssignmentOperators;
unsigned ASTContext::NumImplicitCopyAssignmentOperatorsDeclared;
unsigned ASTContext::NumImplicitDestructors;
@@ -259,6 +261,9 @@
fprintf(stderr, "Total bytes = %d\n", int(TotalBytes));
// Implicit special member functions.
+ fprintf(stderr, " %u/%u implicit copy constructors created\n",
+ NumImplicitCopyConstructorsDeclared,
+ NumImplicitCopyConstructors);
fprintf(stderr, " %u/%u implicit copy assignment operators created\n",
NumImplicitCopyAssignmentOperatorsDeclared,
NumImplicitCopyAssignmentOperators);
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=107543&r1=107542&r2=107543&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Jul 2 18:41:54 2010
@@ -32,6 +32,7 @@
Abstract(false), HasTrivialConstructor(true),
HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true),
HasTrivialDestructor(true), ComputedVisibleConversions(false),
+ DeclaredCopyConstructor(false),
DeclaredCopyAssignment(false), DeclaredDestructor(false),
Bases(0), NumBases(0), VBases(0), NumVBases(0),
Definition(D), FirstFriend(0) {
@@ -295,11 +296,13 @@
// suppress the implicit declaration of a copy constructor.
if (ConDecl->isCopyConstructor()) {
data().UserDeclaredCopyConstructor = true;
-
+ data().DeclaredCopyConstructor = true;
+
// C++ [class.copy]p6:
// A copy constructor is trivial if it is implicitly declared.
// FIXME: C++0x: don't do this for "= default" copy constructors.
data().HasTrivialCopyConstructor = false;
+
}
}
Modified: cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderDecl.cpp?rev=107543&r1=107542&r2=107543&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderDecl.cpp Fri Jul 2 18:41:54 2010
@@ -657,6 +657,7 @@
Data.HasTrivialCopyAssignment = Record[Idx++];
Data.HasTrivialDestructor = Record[Idx++];
Data.ComputedVisibleConversions = Record[Idx++];
+ Data.DeclaredCopyConstructor = Record[Idx++];
Data.DeclaredCopyAssignment = Record[Idx++];
Data.DeclaredDestructor = Record[Idx++];
Modified: cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriterDecl.cpp?rev=107543&r1=107542&r2=107543&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriterDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriterDecl.cpp Fri Jul 2 18:41:54 2010
@@ -654,6 +654,7 @@
Record.push_back(Data.HasTrivialCopyAssignment);
Record.push_back(Data.HasTrivialDestructor);
Record.push_back(Data.ComputedVisibleConversions);
+ Record.push_back(Data.DeclaredCopyConstructor);
Record.push_back(Data.DeclaredCopyAssignment);
Record.push_back(Data.DeclaredDestructor);
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=107543&r1=107542&r2=107543&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Jul 2 18:41:54 2010
@@ -2657,7 +2657,7 @@
DeclareImplicitDefaultConstructor(ClassDecl);
if (!ClassDecl->hasUserDeclaredCopyConstructor())
- DeclareImplicitCopyConstructor(ClassDecl);
+ ++ASTContext::NumImplicitCopyConstructors;
if (!ClassDecl->hasUserDeclaredCopyAssignment()) {
++ASTContext::NumImplicitCopyAssignmentOperators;
@@ -5065,8 +5065,11 @@
if (Base->isVirtual())
continue;
- const CXXRecordDecl *BaseClassDecl
+ CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ if (!BaseClassDecl->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(BaseClassDecl);
+
HasConstCopyConstructor
= BaseClassDecl->hasConstCopyConstructor(Context);
}
@@ -5075,8 +5078,11 @@
BaseEnd = ClassDecl->vbases_end();
HasConstCopyConstructor && Base != BaseEnd;
++Base) {
- const CXXRecordDecl *BaseClassDecl
+ CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ if (!BaseClassDecl->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(BaseClassDecl);
+
HasConstCopyConstructor
= BaseClassDecl->hasConstCopyConstructor(Context);
}
@@ -5091,8 +5097,11 @@
++Field) {
QualType FieldType = Context.getBaseElementType((*Field)->getType());
if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
- const CXXRecordDecl *FieldClassDecl
+ CXXRecordDecl *FieldClassDecl
= cast<CXXRecordDecl>(FieldClassType->getDecl());
+ if (!FieldClassDecl->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(FieldClassDecl);
+
HasConstCopyConstructor
= FieldClassDecl->hasConstCopyConstructor(Context);
}
@@ -5121,8 +5130,11 @@
if (Base->isVirtual())
continue;
- const CXXRecordDecl *BaseClassDecl
+ CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ if (!BaseClassDecl->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(BaseClassDecl);
+
if (CXXConstructorDecl *CopyConstructor
= BaseClassDecl->getCopyConstructor(Context, Quals))
ExceptSpec.CalledDecl(CopyConstructor);
@@ -5131,8 +5143,11 @@
BaseEnd = ClassDecl->vbases_end();
Base != BaseEnd;
++Base) {
- const CXXRecordDecl *BaseClassDecl
+ CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ if (!BaseClassDecl->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(BaseClassDecl);
+
if (CXXConstructorDecl *CopyConstructor
= BaseClassDecl->getCopyConstructor(Context, Quals))
ExceptSpec.CalledDecl(CopyConstructor);
@@ -5143,8 +5158,11 @@
++Field) {
QualType FieldType = Context.getBaseElementType((*Field)->getType());
if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
- const CXXRecordDecl *FieldClassDecl
+ CXXRecordDecl *FieldClassDecl
= cast<CXXRecordDecl>(FieldClassType->getDecl());
+ if (!FieldClassDecl->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(FieldClassDecl);
+
if (CXXConstructorDecl *CopyConstructor
= FieldClassDecl->getCopyConstructor(Context, Quals))
ExceptSpec.CalledDecl(CopyConstructor);
@@ -5175,6 +5193,10 @@
CopyConstructor->setImplicit();
CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor());
+ // Note that we have declared this constructor.
+ ClassDecl->setDeclaredCopyConstructor(true);
+ ++ASTContext::NumImplicitCopyConstructorsDeclared;
+
// Add the parameter to the constructor.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
ClassDecl->getLocation(),
@@ -5184,9 +5206,8 @@
VarDecl::None, 0);
CopyConstructor->setParams(&FromParam, 1);
if (Scope *S = getScopeForContext(ClassDecl))
- PushOnScopeChains(CopyConstructor, S, true);
- else
- ClassDecl->addDecl(CopyConstructor);
+ PushOnScopeChains(CopyConstructor, S, false);
+ ClassDecl->addDecl(CopyConstructor);
return CopyConstructor;
}
Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=107543&r1=107542&r2=107543&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Fri Jul 2 18:41:54 2010
@@ -464,14 +464,19 @@
}
void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) {
+ if (!CanDeclareSpecialMemberFunction(Context, Class))
+ return;
+
+ // If the copy constructor has not yet been declared, do so now.
+ if (!Class->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(Class);
+
// If the copy assignment operator has not yet been declared, do so now.
- if (CanDeclareSpecialMemberFunction(Context, Class) &&
- !Class->hasDeclaredCopyAssignment())
+ if (!Class->hasDeclaredCopyAssignment())
DeclareImplicitCopyAssignment(Class);
// If the destructor has not yet been declared, do so now.
- if (CanDeclareSpecialMemberFunction(Context, Class) &&
- !Class->hasDeclaredDestructor())
+ if (!Class->hasDeclaredDestructor())
DeclareImplicitDestructor(Class);
}
@@ -479,6 +484,7 @@
/// special member function.
static bool isImplicitlyDeclaredMemberFunctionName(DeclarationName Name) {
switch (Name.getNameKind()) {
+ case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
return true;
@@ -501,12 +507,18 @@
return;
switch (Name.getNameKind()) {
+ case DeclarationName::CXXConstructorName:
+ if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
+ if (Record->getDefinition() && !Record->hasDeclaredCopyConstructor() &&
+ CanDeclareSpecialMemberFunction(S.Context, Record))
+ S.DeclareImplicitCopyConstructor(const_cast<CXXRecordDecl *>(Record));
+ break;
+
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;
case DeclarationName::CXXOperatorName:
@@ -1992,9 +2004,11 @@
/// \brief Look up the constructors for the given class.
DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {
- if (!Class->getDefinition())
- return DeclContext::lookup_result();
-
+ // If the copy constructor has not yet been declared, do so now.
+ if (CanDeclareSpecialMemberFunction(Context, Class) &&
+ !Class->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(Class);
+
CanQualType T = Context.getCanonicalType(Context.getTypeDeclType(Class));
DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(T);
return Class->lookup(Name);
More information about the cfe-commits
mailing list