[cfe-commits] r114899 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclBase.cpp lib/AST/DeclCXX.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp
Douglas Gregor
dgregor at apple.com
Mon Sep 27 15:06:20 PDT 2010
Author: dgregor
Date: Mon Sep 27 17:06:20 2010
New Revision: 114899
URL: http://llvm.org/viewvc/llvm-project?rev=114899&view=rev
Log:
Centralize the handling of
CXXRecordDecl::DefinitionData::DeclaredCopyAssignment, for
copy-assignment operators. Another step toward <rdar://problem/8459981>.
Modified:
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/lib/AST/DeclBase.cpp
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=114899&r1=114898&r2=114899&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Sep 27 17:06:20 2010
@@ -406,13 +406,12 @@
friend class DeclContext;
- /// \brief Notify the class that another constructor has
- /// been added.
+ /// \brief Notify the class that member has been added.
///
/// This routine helps maintain information about the class based on which
- /// constructors have been added. It will be invoked by DeclContext::addDecl()
- /// whenever a constructor is added to this record.
- void addedConstructor(CXXConstructorDecl *ConDecl);
+ /// members have been added. It will be invoked by DeclContext::addDecl()
+ /// whenever a member is added to this record.
+ void addedMember(Decl *D);
protected:
CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
@@ -610,11 +609,6 @@
return data().DeclaredCopyConstructor;
}
- /// 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.
- void addedAssignmentOperator(ASTContext &Context, CXXMethodDecl *OpDecl);
-
/// hasUserDeclaredCopyAssignment - Whether this class has a
/// user-declared copy assignment operator. When false, a copy
/// assigment operator will be implicitly declared.
@@ -630,12 +624,6 @@
return data().DeclaredCopyAssignment;
}
- /// \brief Note whether this class has already had its copy assignment
- /// operator declared.
- void setDeclaredCopyAssignment(bool DCA) {
- data().DeclaredCopyAssignment = DCA;
- }
-
/// hasUserDeclaredDestructor - Whether this class has a
/// user-declared destructor. When false, a destructor will be
/// implicitly declared.
Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=114899&r1=114898&r2=114899&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Mon Sep 27 17:06:20 2010
@@ -778,14 +778,11 @@
} else {
FirstDecl = LastDecl = D;
}
-
- if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this)) {
- Decl *InnerD = D;
- if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
- InnerD = FunTmpl->getTemplatedDecl();
- if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(InnerD))
- Record->addedConstructor(Constructor);
- }
+
+ // Notify a C++ record declaration that we've added a member, so it can
+ // update it's class-specific state.
+ if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this))
+ Record->addedMember(D);
}
void DeclContext::addDecl(Decl *D) {
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=114899&r1=114898&r2=114899&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Sep 27 17:06:20 2010
@@ -259,99 +259,126 @@
}
void
-CXXRecordDecl::addedConstructor(CXXConstructorDecl *Constructor) {
- // Ignore friends.
- if (Constructor->getFriendObjectKind())
+CXXRecordDecl::addedMember(Decl *D) {
+ // Ignore friends and invalid declarations.
+ if (D->getFriendObjectKind() || D->isInvalidDecl())
return;
- if (Constructor->isImplicit()) {
- // If this is the implicit default constructor, note that we have now
- // declared it.
- if (Constructor->isDefaultConstructor())
- data().DeclaredDefaultConstructor = true;
- // If this is the implicit copy constructor, note that we have now
- // declared it.
- else if (Constructor->isCopyConstructor())
- data().DeclaredCopyConstructor = true;
+ FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
+ if (FunTmpl)
+ D = FunTmpl->getTemplatedDecl();
+
+ if (D->isImplicit()) {
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+ // If this is the implicit default constructor, note that we have now
+ // declared it.
+ if (Constructor->isDefaultConstructor())
+ data().DeclaredDefaultConstructor = true;
+ // If this is the implicit copy constructor, note that we have now
+ // declared it.
+ else if (Constructor->isCopyConstructor())
+ data().DeclaredCopyConstructor = true;
+ }
+ // FIXME: Destructors
+ else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ // If this is the implicit copy constructor, note that we have now
+ // declared it.
+ // FIXME: Move constructors
+ if (Method->getOverloadedOperator() == OO_Equal) {
+ data().DeclaredCopyAssignment = true;
+ Method->setCopyAssignment(true);
+ }
+ }
- // Nothing else to do for implicitly-declared constructors.
+ // Nothing else to do for implicitly-declared members.
return;
}
- // Note that we have a user-declared constructor.
- data().UserDeclaredConstructor = true;
+ // Handle (user-declared) constructors.
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+ // 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) [...].
- data().Aggregate = false;
-
- // C++ [class]p4:
- // A POD-struct is an aggregate class [...]
- data().PlainOldData = false;
-
- // C++ [class.ctor]p5:
- // A constructor is trivial if it is an implicitly-declared default
- // constructor.
- // FIXME: C++0x: don't do this for "= default" default constructors.
- data().HasTrivialConstructor = false;
-
- // Note when we have a user-declared copy constructor, which will
- // suppress the implicit declaration of a copy constructor.
- if (!Constructor->getDescribedFunctionTemplate() &&
- Constructor->isCopyConstructor()) {
- data().UserDeclaredCopyConstructor = true;
- data().DeclaredCopyConstructor = true;
+ // Note that we have no need of an implicitly-declared default constructor.
+ data().DeclaredDefaultConstructor = 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;
+ // C++ [dcl.init.aggr]p1:
+ // An aggregate is an array or a class (clause 9) with no
+ // user-declared constructors (12.1) [...].
+ data().Aggregate = false;
+
+ // C++ [class]p4:
+ // A POD-struct is an aggregate class [...]
+ data().PlainOldData = false;
+
+ // C++ [class.ctor]p5:
+ // A constructor is trivial if it is an implicitly-declared default
+ // constructor.
+ // FIXME: C++0x: don't do this for "= default" default constructors.
+ data().HasTrivialConstructor = false;
+
+ // Note when we have a user-declared copy constructor, which will
+ // suppress the implicit declaration of a copy constructor.
+ if (!FunTmpl && Constructor->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;
+ }
+
+ return;
}
-}
-void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
- CXXMethodDecl *OpDecl) {
- // We're interested specifically in copy assignment operators.
- const FunctionProtoType *FnType = OpDecl->getType()->getAs<FunctionProtoType>();
- assert(FnType && "Overloaded operator has no proto function type.");
- assert(FnType->getNumArgs() == 1 && !FnType->isVariadic());
+ // FIXME: Destructors.
- // Copy assignment operators must be non-templates.
- if (OpDecl->getPrimaryTemplate() || OpDecl->getDescribedFunctionTemplate())
- return;
-
- QualType ArgType = FnType->getArgType(0);
- if (const LValueReferenceType *Ref = ArgType->getAs<LValueReferenceType>())
- ArgType = Ref->getPointeeType();
-
- ArgType = ArgType.getUnqualifiedType();
- QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
- const_cast<CXXRecordDecl*>(this)));
-
- if (!Context.hasSameUnqualifiedType(ClassType, ArgType))
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ if (Method->getOverloadedOperator() == OO_Equal) {
+ // We're interested specifically in copy assignment operators.
+ const FunctionProtoType *FnType
+ = Method->getType()->getAs<FunctionProtoType>();
+ assert(FnType && "Overloaded operator has no proto function type.");
+ assert(FnType->getNumArgs() == 1 && !FnType->isVariadic());
+
+ // Copy assignment operators must be non-templates.
+ if (Method->getPrimaryTemplate() || FunTmpl)
+ return;
+
+ ASTContext &Context = getASTContext();
+ QualType ArgType = FnType->getArgType(0);
+ if (const LValueReferenceType *Ref =ArgType->getAs<LValueReferenceType>())
+ ArgType = Ref->getPointeeType();
+
+ ArgType = ArgType.getUnqualifiedType();
+ QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
+ const_cast<CXXRecordDecl*>(this)));
+
+ if (!Context.hasSameUnqualifiedType(ClassType, ArgType))
+ return;
+
+ // This is a copy assignment operator.
+ // Note on the decl that it is a copy assignment operator.
+ Method->setCopyAssignment(true);
+
+ // Suppress the implicit declaration of a copy constructor.
+ data().UserDeclaredCopyAssignment = true;
+ data().DeclaredCopyAssignment = true;
+
+ // C++ [class.copy]p11:
+ // A copy assignment operator is trivial if it is implicitly declared.
+ // FIXME: C++0x: don't do this for "= default" copy operators.
+ data().HasTrivialCopyAssignment = false;
+
+ // C++ [class]p4:
+ // A POD-struct is an aggregate class that [...] has no user-defined copy
+ // assignment operator [...].
+ data().PlainOldData = false;
+ }
+
return;
-
- // This is a copy assignment operator.
- // Note on the decl that it is a copy assignment operator.
- OpDecl->setCopyAssignment(true);
-
- // Suppress the implicit declaration of a copy constructor.
- data().UserDeclaredCopyAssignment = true;
- data().DeclaredCopyAssignment = true;
-
- // C++ [class.copy]p11:
- // A copy assignment operator is trivial if it is implicitly declared.
- // FIXME: C++0x: don't do this for "= default" copy operators.
- data().HasTrivialCopyAssignment = false;
-
- // C++ [class]p4:
- // A POD-struct is an aggregate class that [...] has no user-defined copy
- // assignment operator [...].
- data().PlainOldData = false;
+ }
}
static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=114899&r1=114898&r2=114899&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Sep 27 17:06:20 2010
@@ -544,7 +544,9 @@
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D))
return CD->isCopyConstructor();
- return D->isCopyAssignment();
+ if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
+ return Method->isCopyAssignmentOperator();
+ return false;
}
bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=114899&r1=114898&r2=114899&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Sep 27 17:06:20 2010
@@ -4942,7 +4942,6 @@
CopyAssignment->setParams(&FromParam, 1);
// Note that we have added this copy-assignment operator.
- ClassDecl->setDeclaredCopyAssignment(true);
++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared;
if (Scope *S = getScopeForContext(ClassDecl))
@@ -5952,15 +5951,6 @@
<< LastParam->getType() << (Op == OO_MinusMinus);
}
- // Notify the class if it got an assignment operator.
- if (Op == OO_Equal) {
- // Would have returned earlier otherwise.
- assert(isa<CXXMethodDecl>(FnDecl) &&
- "Overloaded = not member, but not filtered.");
- CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
- Method->getParent()->addedAssignmentOperator(Context, Method);
- }
-
return false;
}
More information about the cfe-commits
mailing list