aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorSean Hunt <scshunt@csclub.uwaterloo.ca>2011-05-10 00:49:42 +0000
committerSean Hunt <scshunt@csclub.uwaterloo.ca>2011-05-10 00:49:42 +0000
commit001cad932380419c6fbfecbeec63e0579f5ecbf3 (patch)
tree21e4c9eb7a332a47b4a5629ac85415dd7708691c /lib/Sema/SemaDecl.cpp
parenta780da70f74ab09ed1f91c1e992abf850e5268ea (diff)
Further implement defaulting constructors.
Focus is on default constructors for the time being. Currently the exception specification and prototype are processed correctly. Codegen might work but in all likelihood doesn't. Note that due to an error, out-of-line defaulting of member functions is currently impossible. It will continue to that until I muster up the courage to admit that I secretly pray to epimetheus and that I need to rework the way default gets from Parse -> Sema. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131115 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp65
1 files changed, 36 insertions, 29 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 5965181e5b..d3e0cdc12b 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1730,6 +1730,11 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
<< New << getSpecialMember(OldMethod);
return true;
}
+ } else if (OldMethod->isExplicitlyDefaulted()) {
+ Diag(NewMethod->getLocation(),
+ diag::err_definition_of_explicitly_defaulted_member)
+ << getSpecialMember(OldMethod);
+ return true;
}
}
@@ -4137,16 +4142,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
/*isImplicitlyDeclared=*/false);
NewFD = NewCD;
-
- if (DefaultLoc.isValid()) {
- if (NewCD->isDefaultConstructor() ||
- NewCD->isCopyOrMoveConstructor()) {
- NewFD->setDefaulted();
- NewFD->setExplicitlyDefaulted();
- } else {
- Diag(DefaultLoc, diag::err_default_special_members);
- }
- }
} else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
// This is a C++ destructor declaration.
if (DC->isRecord()) {
@@ -4159,11 +4154,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
isInline,
/*isImplicitlyDeclared=*/false);
isVirtualOkay = true;
-
- if (DefaultLoc.isValid()) {
- NewFD->setDefaulted();
- NewFD->setExplicitlyDefaulted();
- }
} else {
Diag(D.getIdentifierLoc(), diag::err_destructor_not_member);
@@ -4182,9 +4172,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
return 0;
}
- if (DefaultLoc.isValid())
- Diag(DefaultLoc, diag::err_default_special_members);
-
CheckConversionDeclarator(D, R, SC);
NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC),
D.getSourceRange().getBegin(),
@@ -4232,16 +4219,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
NewFD = NewMD;
isVirtualOkay = !isStatic;
-
- if (DefaultLoc.isValid()) {
- if (NewMD->isCopyAssignmentOperator() /* ||
- NewMD->isMoveAssignmentOperator() */) {
- NewFD->setDefaulted();
- NewFD->setExplicitlyDefaulted();
- } else {
- Diag(DefaultLoc, diag::err_default_special_members);
- }
- }
} else {
if (DefaultLoc.isValid())
Diag(DefaultLoc, diag::err_default_special_members);
@@ -4715,7 +4692,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
} else if (!IsFunctionDefinition && D.getCXXScopeSpec().isSet() &&
!isFriend && !isFunctionTemplateSpecialization &&
- !isExplicitSpecialization) {
+ !isExplicitSpecialization && !DefaultLoc.isValid()) {
// An out-of-line member function declaration must also be a
// definition (C++ [dcl.meaning]p1).
// Note that this is not the case for explicit specializations of
@@ -4800,6 +4777,36 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
}
+ // Check explicitly defaulted methods
+ // FIXME: This could be made better through CXXSpecialMember if it did
+ // default constructors (which it should rather than any constructor).
+ if (NewFD && DefaultLoc.isValid() && getLangOptions().CPlusPlus) {
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD)) {
+ if (CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(MD)) {
+ if (CD->isDefaultConstructor() || CD->isCopyOrMoveConstructor()) {
+ CD->setDefaulted();
+ CD->setExplicitlyDefaulted();
+ if (CD != CD->getCanonicalDecl() && CD->isDefaultConstructor())
+ CheckExplicitlyDefaultedDefaultConstructor(CD);
+ // FIXME: Do copy/move ctors here.
+ } else {
+ Diag(DefaultLoc, diag::err_default_special_members);
+ }
+ } else if (CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
+ DD->setDefaulted();
+ DD->setExplicitlyDefaulted();
+ // FIXME: Add a checking method
+ } else if (MD->isCopyAssignmentOperator() /* ||
+ MD->isMoveAssignmentOperator() */) {
+ MD->setDefaulted();
+ MD->setExplicitlyDefaulted();
+ // FIXME: Add a checking method
+ } else {
+ Diag(DefaultLoc, diag::err_default_special_members);
+ }
+ }
+ }
+
return NewFD;
}