[cfe-commits] r107551 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/DeclCXX.h lib/AST/ASTContext.cpp lib/AST/DeclBase.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 17:47:01 PDT 2010
Author: dgregor
Date: Fri Jul 2 19:47:00 2010
New Revision: 107551
URL: http://llvm.org/viewvc/llvm-project?rev=107551&view=rev
Log:
Lazily declare default constructors. We now delay the construction of
declarations for implicit default constructors, copy constructors,
copy assignment operators, and destructors. On a "simple" translation
unit that includes a bunch of C++ standard library headers, we
generate relatively few of these implicit declarations now:
4/159 implicit default constructors created
18/236 implicit copy constructors created
70/241 implicit copy assignment operators created
0/173 implicit destructors created
And, on this translation unit, this optimization doesn't really
provide any benefit. I'll do some more performance measurements soon,
but this completes the implementation work for <rdar://problem/8151045>.
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/DeclBase.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=107551&r1=107550&r2=107551&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Jul 2 19:47:00 2010
@@ -1327,10 +1327,17 @@
// Statistics
//===--------------------------------------------------------------------===//
+ /// \brief The number of implicitly-declared default constructors.
+ static unsigned NumImplicitDefaultConstructors;
+
+ /// \brief The number of implicitly-declared default constructors for
+ /// which declarations were built.
+ static unsigned NumImplicitDefaultConstructorsDeclared;
+
/// \brief The number of implicitly-declared copy constructors.
static unsigned NumImplicitCopyConstructors;
- /// \brief The number of implicitly-declared constructors for
+ /// \brief The number of implicitly-declared copy constructors for
/// which declarations were built.
static unsigned NumImplicitCopyConstructorsDeclared;
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=107551&r1=107550&r2=107551&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Jul 2 19:47:00 2010
@@ -318,7 +318,11 @@
/// ComputedVisibleConversions - True when visible conversion functions are
/// already computed and are available.
bool ComputedVisibleConversions : 1;
-
+
+ /// \brief Whether we have already declared the default constructor or
+ /// do not need to have one declared.
+ bool DeclaredDefaultConstructor : 1;
+
/// \brief Whether we have already declared the copy constructor.
bool DeclaredCopyConstructor : 1;
@@ -540,6 +544,20 @@
return data().FirstFriend != 0;
}
+ /// \brief Determine whether this class has had its default constructor
+ /// declared implicitly or does not need one declared implicitly.
+ ///
+ /// This value is used for lazy creation of default constructors.
+ bool hasDeclaredDefaultConstructor() const {
+ return data().DeclaredDefaultConstructor;
+ }
+
+ /// \brief Note whether this class has already had its default constructor
+ /// implicitly declared or doesn't need one.
+ void setDeclaredDefaultConstructor(bool DDC) {
+ data().DeclaredDefaultConstructor = DDC;
+ }
+
/// hasConstCopyConstructor - Determines whether this class has a
/// copy constructor that accepts a const-qualified argument.
bool hasConstCopyConstructor(ASTContext &Context) const;
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=107551&r1=107550&r2=107551&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Jul 2 19:47:00 2010
@@ -31,6 +31,8 @@
using namespace clang;
+unsigned ASTContext::NumImplicitDefaultConstructors;
+unsigned ASTContext::NumImplicitDefaultConstructorsDeclared;
unsigned ASTContext::NumImplicitCopyConstructors;
unsigned ASTContext::NumImplicitCopyConstructorsDeclared;
unsigned ASTContext::NumImplicitCopyAssignmentOperators;
@@ -261,6 +263,9 @@
fprintf(stderr, "Total bytes = %d\n", int(TotalBytes));
// Implicit special member functions.
+ fprintf(stderr, " %u/%u implicit default constructors created\n",
+ NumImplicitDefaultConstructorsDeclared,
+ NumImplicitDefaultConstructors);
fprintf(stderr, " %u/%u implicit copy constructors created\n",
NumImplicitCopyConstructorsDeclared,
NumImplicitCopyConstructors);
Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=107551&r1=107550&r2=107551&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Fri Jul 2 19:47:00 2010
@@ -975,6 +975,12 @@
CreateStoredDeclsMap(*C);
}
+ // If there is an external AST source, load any declarations it knows about
+ // with this declaration's name.
+ if (ExternalASTSource *Source = getParentASTContext().getExternalSource())
+ if (hasExternalVisibleStorage())
+ Source->FindExternalVisibleDeclsByName(this, D->getDeclName());
+
// Insert this declaration into the map.
StoredDeclsList &DeclNameEntries = (*LookupPtr)[D->getDeclName()];
if (DeclNameEntries.isNull()) {
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=107551&r1=107550&r2=107551&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Jul 2 19:47:00 2010
@@ -32,7 +32,7 @@
Abstract(false), HasTrivialConstructor(true),
HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true),
HasTrivialDestructor(true), ComputedVisibleConversions(false),
- DeclaredCopyConstructor(false),
+ DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false),
DeclaredCopyAssignment(false), DeclaredDestructor(false),
Bases(0), NumBases(0), VBases(0), NumVBases(0),
Definition(D), FirstFriend(0) {
@@ -277,6 +277,9 @@
// Note that we have a user-declared constructor.
data().UserDeclaredConstructor = true;
+ // Note that we have no need of an implicitly-declared default constructor.
+ data().DeclaredDefaultConstructor = true;
+
// C++ [dcl.init.aggr]p1:
// An aggregate is an array or a class (clause 9) with no
// user-declared constructors (12.1) [...].
Modified: cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderDecl.cpp?rev=107551&r1=107550&r2=107551&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderDecl.cpp Fri Jul 2 19:47:00 2010
@@ -657,6 +657,7 @@
Data.HasTrivialCopyAssignment = Record[Idx++];
Data.HasTrivialDestructor = Record[Idx++];
Data.ComputedVisibleConversions = Record[Idx++];
+ Data.DeclaredDefaultConstructor = 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=107551&r1=107550&r2=107551&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriterDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriterDecl.cpp Fri Jul 2 19:47:00 2010
@@ -654,6 +654,7 @@
Record.push_back(Data.HasTrivialCopyAssignment);
Record.push_back(Data.HasTrivialDestructor);
Record.push_back(Data.ComputedVisibleConversions);
+ Record.push_back(Data.DeclaredDefaultConstructor);
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=107551&r1=107550&r2=107551&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Jul 2 19:47:00 2010
@@ -2654,7 +2654,7 @@
/// definition of the class is complete.
void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
if (!ClassDecl->hasUserDeclaredConstructor())
- DeclareImplicitDefaultConstructor(ClassDecl);
+ ++ASTContext::NumImplicitDefaultConstructors;
if (!ClassDecl->hasUserDeclaredCopyConstructor())
++ASTContext::NumImplicitCopyConstructors;
@@ -4156,6 +4156,19 @@
// user-declared constructor for class X, a default constructor is
// implicitly declared. An implicitly-declared default constructor
// is an inline public member of its class.
+ assert(!ClassDecl->hasUserDeclaredConstructor() &&
+ "Should not build implicit default constructor!");
+
+ // FIXME: HACK HACK HACK
+ if (Context.getExternalSource()) {
+ // This hack ensures that, when using precompiled headers, the lookup
+ // table in the DeclContext has already loaded the constructor declarations
+ // so that we can add a new one. The real fix will go into DeclContext,
+ // when I figure out what that is.
+ CanQualType T
+ = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+ ClassDecl->lookup(Context.DeclarationNames.getCXXConstructorName(T));
+ }
// C++ [except.spec]p14:
// An implicitly declared special member function (Clause 12) shall have an
@@ -4169,20 +4182,28 @@
if (B->isVirtual()) // Handled below.
continue;
- if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
- if (CXXConstructorDecl *Constructor
- = cast<CXXRecordDecl>(BaseType->getDecl())->getDefaultConstructor())
+ if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+ CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+ if (!BaseClassDecl->hasDeclaredDefaultConstructor())
+ ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl));
+ else if (CXXConstructorDecl *Constructor
+ = BaseClassDecl->getDefaultConstructor())
ExceptSpec.CalledDecl(Constructor);
+ }
}
// Virtual base-class destructors.
for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
BEnd = ClassDecl->vbases_end();
B != BEnd; ++B) {
- if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
- if (CXXConstructorDecl *Constructor
- = cast<CXXRecordDecl>(BaseType->getDecl())->getDefaultConstructor())
+ if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+ CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+ if (!BaseClassDecl->hasDeclaredDefaultConstructor())
+ ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl));
+ else if (CXXConstructorDecl *Constructor
+ = BaseClassDecl->getDefaultConstructor())
ExceptSpec.CalledDecl(Constructor);
+ }
}
// Field destructors.
@@ -4190,10 +4211,15 @@
FEnd = ClassDecl->field_end();
F != FEnd; ++F) {
if (const RecordType *RecordTy
- = Context.getBaseElementType(F->getType())->getAs<RecordType>())
- if (CXXConstructorDecl *Constructor
- = cast<CXXRecordDecl>(RecordTy->getDecl())->getDefaultConstructor())
+ = Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
+ CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
+ if (!FieldClassDecl->hasDeclaredDefaultConstructor())
+ ExceptSpec.CalledDecl(
+ DeclareImplicitDefaultConstructor(FieldClassDecl));
+ else if (CXXConstructorDecl *Constructor
+ = FieldClassDecl->getDefaultConstructor())
ExceptSpec.CalledDecl(Constructor);
+ }
}
@@ -4219,10 +4245,15 @@
DefaultCon->setAccess(AS_public);
DefaultCon->setImplicit();
DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor());
+
+ // Note that we have declared this constructor.
+ ClassDecl->setDeclaredDefaultConstructor(true);
+ ++ASTContext::NumImplicitDefaultConstructorsDeclared;
+
if (Scope *S = getScopeForContext(ClassDecl))
- PushOnScopeChains(DefaultCon, S, true);
- else
- ClassDecl->addDecl(DefaultCon);
+ PushOnScopeChains(DefaultCon, S, false);
+ ClassDecl->addDecl(DefaultCon);
+
return DefaultCon;
}
@@ -4612,7 +4643,17 @@
// constructor rules. Note that virtual bases are not taken into account
// for determining the argument type of the operator. Note also that
// operators taking an object instead of a reference are allowed.
- //
+
+
+ // FIXME: HACK HACK HACK
+ if (Context.getExternalSource()) {
+ // This hack ensures that, when using precompiled headers, the lookup
+ // table in the DeclContext has already loaded the assignment operator
+ // declarations so that we can add a new one. The real fix will go into
+ // DeclContext, when I figure out what that is.
+ ClassDecl->lookup(Context.DeclarationNames.getCXXOperatorName(OO_Equal));
+ }
+
// C++ [class.copy]p10:
// If the class definition does not explicitly declare a copy
// assignment operator, one is declared implicitly.
@@ -5045,6 +5086,17 @@
// If the class definition does not explicitly declare a copy
// constructor, one is declared implicitly.
+ // FIXME: HACK HACK HACK
+ if (Context.getExternalSource()) {
+ // This hack ensures that, when using precompiled headers, the lookup
+ // table in the DeclContext has already loaded the constructor declarations
+ // so that we can add a new one. The real fix will go into DeclContext,
+ // when I figure out what that is.
+ CanQualType T
+ = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+ ClassDecl->lookup(Context.DeclarationNames.getCXXConstructorName(T));
+ }
+
// C++ [class.copy]p5:
// The implicitly-declared copy constructor for a class X will
// have the form
Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=107551&r1=107550&r2=107551&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Fri Jul 2 19:47:00 2010
@@ -466,6 +466,10 @@
void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) {
if (!CanDeclareSpecialMemberFunction(Context, Class))
return;
+
+ // If the default constructor has not yet been declared, do so now.
+ if (!Class->hasDeclaredDefaultConstructor())
+ DeclareImplicitDefaultConstructor(Class);
// If the copy constructor has not yet been declared, do so now.
if (!Class->hasDeclaredCopyConstructor())
@@ -509,9 +513,14 @@
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));
+ if (Record->getDefinition() &&
+ CanDeclareSpecialMemberFunction(S.Context, Record)) {
+ if (!Record->hasDeclaredDefaultConstructor())
+ S.DeclareImplicitDefaultConstructor(
+ const_cast<CXXRecordDecl *>(Record));
+ if (!Record->hasDeclaredCopyConstructor())
+ S.DeclareImplicitCopyConstructor(const_cast<CXXRecordDecl *>(Record));
+ }
break;
case DeclarationName::CXXDestructorName:
@@ -2005,9 +2014,12 @@
/// \brief Look up the constructors for the given class.
DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {
// If the copy constructor has not yet been declared, do so now.
- if (CanDeclareSpecialMemberFunction(Context, Class) &&
- !Class->hasDeclaredCopyConstructor())
- DeclareImplicitCopyConstructor(Class);
+ if (CanDeclareSpecialMemberFunction(Context, Class)) {
+ if (!Class->hasDeclaredDefaultConstructor())
+ DeclareImplicitDefaultConstructor(Class);
+ if (!Class->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(Class);
+ }
CanQualType T = Context.getCanonicalType(Context.getTypeDeclType(Class));
DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(T);
More information about the cfe-commits
mailing list