[cfe-commits] r90605 - in /cfe/trunk: lib/Sema/SemaDecl.cpp test/CodeGenCXX/mangle.cpp test/SemaCXX/implicit-member-functions.cpp
Anders Carlsson
andersca at mac.com
Fri Dec 4 14:33:25 PST 2009
Author: andersca
Date: Fri Dec 4 16:33:25 2009
New Revision: 90605
URL: http://llvm.org/viewvc/llvm-project?rev=90605&view=rev
Log:
Diagnose declarations of implicit member functions.
Added:
cfe/trunk/test/SemaCXX/implicit-member-functions.cpp
Modified:
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/CodeGenCXX/mangle.cpp
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=90605&r1=90604&r2=90605&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Dec 4 16:33:25 2009
@@ -762,6 +762,24 @@
QualType PromotedType;
};
+
+/// getSpecialMember - get the special member enum for a method.
+static Sema::CXXSpecialMember getSpecialMember(ASTContext &Ctx,
+ const CXXMethodDecl *MD) {
+ if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) {
+ if (Ctor->isDefaultConstructor())
+ return Sema::CXXDefaultConstructor;
+ if (Ctor->isCopyConstructor(Ctx))
+ return Sema::CXXCopyConstructor;
+ }
+
+ if (isa<CXXDestructorDecl>(MD))
+ return Sema::CXXDestructor;
+
+ assert(MD->isCopyAssignment() && "Must have copy assignment operator");
+ return Sema::CXXCopyAssignment;
+}
+
/// MergeFunctionDecl - We just parsed a function 'New' from
/// declarator D which has the same name and scope as a previous
/// declaration 'Old'. Figure out how to resolve this situation,
@@ -827,33 +845,45 @@
const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
const CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
- if (OldMethod && NewMethod && !NewMethod->getFriendObjectKind() &&
- NewMethod->getLexicalDeclContext()->isRecord()) {
- // -- Member function declarations with the same name and the
- // same parameter types cannot be overloaded if any of them
- // is a static member function declaration.
- if (OldMethod->isStatic() || NewMethod->isStatic()) {
- Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member);
+ if (OldMethod && NewMethod) {
+ if (!NewMethod->getFriendObjectKind() &&
+ NewMethod->getLexicalDeclContext()->isRecord()) {
+ // -- Member function declarations with the same name and the
+ // same parameter types cannot be overloaded if any of them
+ // is a static member function declaration.
+ if (OldMethod->isStatic() || NewMethod->isStatic()) {
+ Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member);
+ Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+ return true;
+ }
+
+ // C++ [class.mem]p1:
+ // [...] A member shall not be declared twice in the
+ // member-specification, except that a nested class or member
+ // class template can be declared and then later defined.
+ unsigned NewDiag;
+ if (isa<CXXConstructorDecl>(OldMethod))
+ NewDiag = diag::err_constructor_redeclared;
+ else if (isa<CXXDestructorDecl>(NewMethod))
+ NewDiag = diag::err_destructor_redeclared;
+ else if (isa<CXXConversionDecl>(NewMethod))
+ NewDiag = diag::err_conv_function_redeclared;
+ else
+ NewDiag = diag::err_member_redeclared;
+
+ Diag(New->getLocation(), NewDiag);
Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
- return true;
+ } else {
+ if (OldMethod->isImplicit()) {
+ Diag(NewMethod->getLocation(),
+ diag::err_definition_of_implicitly_declared_member)
+ << New << getSpecialMember(Context, OldMethod);
+
+ Diag(OldMethod->getLocation(),
+ diag::note_previous_implicit_declaration);
+ return true;
+ }
}
-
- // C++ [class.mem]p1:
- // [...] A member shall not be declared twice in the
- // member-specification, except that a nested class or member
- // class template can be declared and then later defined.
- unsigned NewDiag;
- if (isa<CXXConstructorDecl>(OldMethod))
- NewDiag = diag::err_constructor_redeclared;
- else if (isa<CXXDestructorDecl>(NewMethod))
- NewDiag = diag::err_destructor_redeclared;
- else if (isa<CXXConversionDecl>(NewMethod))
- NewDiag = diag::err_conv_function_redeclared;
- else
- NewDiag = diag::err_member_redeclared;
-
- Diag(New->getLocation(), NewDiag);
- Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
}
// (C++98 8.3.5p3):
Modified: cfe/trunk/test/CodeGenCXX/mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle.cpp?rev=90605&r1=90604&r2=90605&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle.cpp Fri Dec 4 16:33:25 2009
@@ -208,8 +208,9 @@
void extern_f(void) { }
struct S7 {
- struct S { S(); };
+ S7();
+ struct S { S(); };
struct {
S s;
} a;
Added: cfe/trunk/test/SemaCXX/implicit-member-functions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/implicit-member-functions.cpp?rev=90605&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/implicit-member-functions.cpp (added)
+++ cfe/trunk/test/SemaCXX/implicit-member-functions.cpp Fri Dec 4 16:33:25 2009
@@ -0,0 +1,14 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct A { }; // expected-note {{previous implicit declaration is here}}
+A::A() { } // expected-error {{definition of implicitly declared constructor}}
+
+struct B { }; // expected-note {{previous implicit declaration is here}}
+B::B(const B&) { } // expected-error {{definition of implicitly declared copy constructor}}
+
+struct C { }; // expected-note {{previous implicit declaration is here}}
+C& C::operator=(const C&) { return *this; } // expected-error {{definition of implicitly declared copy assignment operator}}
+
+struct D { }; // expected-note {{previous implicit declaration is here}}
+D::~D() { } // expected-error {{definition of implicitly declared destructor}}
+
More information about the cfe-commits
mailing list