[cfe-commits] r73922 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp lib/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExpr.cpp
Douglas Gregor
dgregor at apple.com
Tue Jun 23 13:52:51 PDT 2009
On Jun 22, 2009, at 4:34 PM, Fariborz Jahanian wrote:
> Author: fjahanian
> Date: Mon Jun 22 18:34:40 2009
> New Revision: 73922
>
> URL: http://llvm.org/viewvc/llvm-project?rev=73922&view=rev
> Log:
> patch to mark use of implicit copy constructors.
>
>
> Modified:
> cfe/trunk/include/clang/AST/DeclCXX.h
> cfe/trunk/lib/AST/DeclCXX.cpp
> cfe/trunk/lib/Sema/Sema.h
> cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> cfe/trunk/lib/Sema/SemaExpr.cpp
>
> Modified: cfe/trunk/include/clang/AST/DeclCXX.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=73922&r1=73921&r2=73922&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- cfe/trunk/include/clang/AST/DeclCXX.h (original)
> +++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Jun 22 18:34:40 2009
> @@ -283,6 +283,10 @@
> /// copy constructor that accepts a const-qualified argument.
> bool hasConstCopyConstructor(ASTContext &Context) const;
>
> + /// getCopyConstructor - Returns the copy constructor for this
> class
> + CXXConstructorDecl *getCopyConstructor(ASTContext &Context,
> + unsigned TypeQuals) const;
> +
> /// hasConstCopyAssignment - Determines whether this class has a
> /// copy assignment operator that accepts a const-qualified
> argument.
> bool hasConstCopyAssignment(ASTContext &Context) const;
>
> Modified: cfe/trunk/lib/AST/DeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=73922&r1=73921&r2=73922&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- cfe/trunk/lib/AST/DeclCXX.cpp (original)
> +++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Jun 22 18:34:40 2009
> @@ -66,21 +66,29 @@
> }
>
> bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context)
> const {
> + return getCopyConstructor(Context, QualType::Const) != 0;
> +}
> +
> +CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext
> &Context,
> + unsigned
> TypeQuals) const{
> QualType ClassType
> = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
> DeclarationName ConstructorName
> = Context.DeclarationNames.getCXXConstructorName(
> - Context.getCanonicalType
> (ClassType));
> - unsigned TypeQuals;
> + Context.getCanonicalType
> (ClassType));
> + unsigned FoundTQs;
> DeclContext::lookup_const_iterator Con, ConEnd;
> for (llvm::tie(Con, ConEnd) = this->lookup(Context,
> ConstructorName);
> Con != ConEnd; ++Con) {
> - if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context,
> TypeQuals) &&
> - (TypeQuals & QualType::Const) != 0)
> - return true;
> + if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context,
> +
> FoundTQs)) {
> + if (((TypeQuals & QualType::Const) == (FoundTQs &
> QualType::Const)) ||
> + (!(TypeQuals & QualType::Const) && (FoundTQs &
> QualType::Const)))
> + return cast<CXXConstructorDecl>(*Con);
> +
> + }
> }
> -
> - return false;
> + return 0;
> }
This looks like it's doing overload resolution... why not just use the
existing overload-resolution code in Sema instead? (Or am I
misunderstanding the role of this code?).
> bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context)
> const {
>
> Modified: cfe/trunk/lib/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=73922&r1=73921&r2=73922&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- cfe/trunk/lib/Sema/Sema.h (original)
> +++ cfe/trunk/lib/Sema/Sema.h Mon Jun 22 18:34:40 2009
> @@ -1582,10 +1582,16 @@
> QualType DeclInitType,
> Expr **Exprs, unsigned NumExprs);
>
> - /// DefineImplicitDefaultConstructor - Checks for feasibilityt of
> + /// DefineImplicitDefaultConstructor - Checks for feasibility of
> /// defining this constructor as the default constructor.
> void DefineImplicitDefaultConstructor(SourceLocation
> CurrentLocation,
> CXXConstructorDecl
> *Constructor);
> +
> + /// DefineImplicitCopyConstructor - Checks for feasibility of
> + /// defining this constructor as the copy constructor.
> + void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
> + CXXConstructorDecl *Constructor,
> + unsigned TypeQuals);
>
> /// MaybeBindToTemporary - If the passed in expression has a
> record type with
> /// a non-trivial destructor, this will return
> CXXBindTemporaryExpr. Otherwise
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=73922&r1=73921&r2=73922&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Jun 22 18:34:40 2009
> @@ -1878,7 +1878,7 @@
>
> CXXRecordDecl *ClassDecl
> = cast<CXXRecordDecl>(Constructor->getDeclContext());
> - assert(ClassDecl && "InitializeVarWithConstructor - invalid
> constructor");
> + assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid
> constructor");
> // Before the implicitly-declared default constructor for a class is
> // implicitly defined, all the implicitly-declared default
> constructors
> // for its base class and its non-static data members shall have
> been
> @@ -1891,7 +1891,7 @@
> if (!BaseClassDecl->hasTrivialConstructor()) {
> if (CXXConstructorDecl *BaseCtor =
> BaseClassDecl->getDefaultConstructor(Context)) {
> - if (BaseCtor->isImplicit())
> + if (BaseCtor->isImplicit() && !BaseCtor->isUsed())
> MarkDeclarationReferenced(CurrentLocation, BaseCtor);
> }
> else {
> @@ -1916,7 +1916,7 @@
> if (!FieldClassDecl->hasTrivialConstructor())
> if (CXXConstructorDecl *FieldCtor =
> FieldClassDecl->getDefaultConstructor(Context)) {
> - if (FieldCtor->isImplicit())
> + if (FieldCtor->isImplicit() && !FieldCtor->isUsed())
> MarkDeclarationReferenced(CurrentLocation, FieldCtor);
> }
We don't need the isImplicit or isUsed checks here; just call
MarkDeclarationReferenced to note that will check that. (And, it might
eventually be useful to know all of the uses of each declaration, for
other tasks).
> else {
> @@ -1945,6 +1945,48 @@
> Constructor->setUsed();
> }
>
> +void Sema::DefineImplicitCopyConstructor(SourceLocation
> CurrentLocation,
> + CXXConstructorDecl
> *CopyConstructor,
> + unsigned TypeQuals) {
> + assert((CopyConstructor->isImplicit() &&
> + CopyConstructor->isCopyConstructor(Context, TypeQuals) &&
> + !CopyConstructor->isUsed()) &&
> + "DefineImplicitCopyConstructor - call it for implicit copy
> ctor");
> +
> + CXXRecordDecl *ClassDecl
> + = cast<CXXRecordDecl>(CopyConstructor->getDeclContext());
> + assert(ClassDecl && "DefineImplicitCopyConstructor - invalid
> constructor");
> + // Before the implicitly-declared copy constructor for a class is
> + // implicitly defined, all the implicitly-declared copy
> constructors
> + // for its base class and its non-static data members shall have
> been
> + // implicitly defined.
Please add a reference to the paragraph in the standard when quoting
it, so we know where to look for more information, e.g.,
// C++ [class.cdtor]p7:
// <quote from the standard goes here>
It's really great for
http://t1.minormatter.com/~ddunbar/references.html
> + for (CXXRecordDecl::base_class_iterator Base = ClassDecl-
> >bases_begin();
> + Base != ClassDecl->bases_end(); ++Base) {
> + CXXRecordDecl *BaseClassDecl
> + = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()-
> >getDecl());
> + if (CXXConstructorDecl *BaseCopyCtor =
> + BaseClassDecl->getCopyConstructor(Context, TypeQuals))
> + if (BaseCopyCtor->isImplicit() && !BaseCopyCtor->isUsed())
> + MarkDeclarationReferenced(CurrentLocation, BaseCopyCtor);
> + }
We don't need the isImplicit/isUsed checks here either.
> + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin
> (Context);
> + Field != ClassDecl->field_end(Context);
> + ++Field) {
> + QualType FieldType = Context.getCanonicalType((*Field)->getType
> ());
> + if (const ArrayType *Array = Context.getAsArrayType(FieldType))
> + FieldType = Array->getElementType();
> + if (const RecordType *FieldClassType = FieldType-
> >getAsRecordType()) {
> + CXXRecordDecl *FieldClassDecl
> + = cast<CXXRecordDecl>(FieldClassType->getDecl());
> + if (CXXConstructorDecl *FieldCopyCtor =
> + FieldClassDecl->getCopyConstructor(Context, TypeQuals))
> + if (FieldCopyCtor->isImplicit() && !FieldCopyCtor->isUsed
> ())
> + MarkDeclarationReferenced(CurrentLocation,
> FieldCopyCtor);
> + }
> + }
> + CopyConstructor->setUsed();
> +}
> +
> void Sema::InitializeVarWithConstructor(VarDecl *VD,
> CXXConstructorDecl
> *Constructor,
> QualType DeclInitType,
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=73922&r1=73921&r2=73922&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Jun 22 18:34:40 2009
> @@ -5515,10 +5515,16 @@
>
> // Note that this declaration has been used.
> if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>
> (D)) {
> + unsigned TypeQuals;
> if (Constructor->isImplicit() && Constructor-
> >isDefaultConstructor()) {
> if (!Constructor->isUsed())
> DefineImplicitDefaultConstructor(Loc, Constructor);
> }
> + else if (Constructor->isImplicit() &&
> + Constructor->isCopyConstructor(Context, TypeQuals)) {
> + if (!Constructor->isUsed())
> + DefineImplicitCopyConstructor(Loc, Constructor, TypeQuals);
> + }
> // FIXME: more checking for other implicits go here.
> else
> Constructor->setUsed(true);
Okay.
- Doug
More information about the cfe-commits
mailing list