[cfe-commits] r60947 - in /cfe/trunk: include/clang/AST/DeclBase.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/SemaCXX/constructor.cpp test/SemaCXX/destructor.cpp
Douglas Gregor
dgregor at apple.com
Fri Dec 12 00:25:50 PST 2008
Author: dgregor
Date: Fri Dec 12 02:25:50 2008
New Revision: 60947
URL: http://llvm.org/viewvc/llvm-project?rev=60947&view=rev
Log:
Enable out-of-line definitions of C++ constructors and destructors
Modified:
cfe/trunk/include/clang/AST/DeclBase.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/test/SemaCXX/constructor.cpp
cfe/trunk/test/SemaCXX/destructor.cpp
Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=60947&r1=60946&r2=60947&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Fri Dec 12 02:25:50 2008
@@ -178,10 +178,12 @@
IdentifierNamespace getIdentifierNamespace() const {
switch (DeclKind) {
- default: assert(0 && "Unknown decl kind!");
+ default:
+ if (DeclKind >= FunctionFirst && DeclKind <= FunctionLast)
+ return IDNS_Ordinary;
+ assert(0 && "Unknown decl kind!");
case ImplicitParam:
case Typedef:
- case Function:
case Var:
case ParmVar:
case EnumConstant:
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=60947&r1=60946&r2=60947&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Dec 12 02:25:50 2008
@@ -246,6 +246,24 @@
} else if (LookupCtx) {
assert(getLangOptions().CPlusPlus && "No qualified name lookup in C");
+ switch (Name.getNameKind()) {
+ case DeclarationName::CXXConstructorName:
+ if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(LookupCtx))
+ return const_cast<CXXRecordDecl *>(Record)->getConstructors();
+ else
+ return 0;
+
+ case DeclarationName::CXXDestructorName:
+ if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(LookupCtx))
+ return Record->getDestructor();
+ else
+ return 0;
+
+ default:
+ // Normal name lookup.
+ break;
+ }
+
// Perform qualified name lookup into the LookupCtx.
// FIXME: Will need to look into base classes and such.
DeclContext::lookup_const_iterator I, E;
@@ -932,6 +950,15 @@
// after the point of declaration in a namespace that encloses the
// declarations namespace.
//
+ // FIXME: We need to perform this check later, once we know that
+ // we've actually found a redeclaration. Otherwise, just the fact
+ // that there is some entity with the same name will suppress this
+ // diagnostic, e.g., we fail to diagnose:
+ // class X {
+ // void f();
+ // };
+ //
+ // void X::f(int) { } // ill-formed, but we don't complain.
if (PrevDecl == 0) {
// No previous declaration in the qualifying scope.
Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member)
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=60947&r1=60946&r2=60947&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Dec 12 02:25:50 2008
@@ -1104,16 +1104,16 @@
// Check default arguments on the constructor
CheckCXXDefaultArguments(ConDecl);
- CXXRecordDecl *ClassDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext);
- if (!ClassDecl) {
- ConDecl->setInvalidDecl();
- return ConDecl;
- }
+ // Set the lexical context of this constructor
+ ConDecl->setLexicalDeclContext(CurContext);
+
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ConDecl->getDeclContext());
// Make sure this constructor is an overload of the existing
// constructors.
OverloadedFunctionDecl::function_iterator MatchedDecl;
- if (!IsOverload(ConDecl, ClassDecl->getConstructors(), MatchedDecl)) {
+ if (!IsOverload(ConDecl, ClassDecl->getConstructors(), MatchedDecl) &&
+ CurContext == (*MatchedDecl)->getLexicalDeclContext()) {
Diag(ConDecl->getLocation(), diag::err_constructor_redeclared)
<< SourceRange(ConDecl->getLocation());
Diag((*MatchedDecl)->getLocation(), diag::note_previous_declaration)
@@ -1122,7 +1122,6 @@
return ConDecl;
}
-
// C++ [class.copy]p3:
// A declaration of a constructor for a class X is ill-formed if
// its first parameter is of type (optionally cv-qualified) X and
@@ -1155,16 +1154,23 @@
Sema::DeclTy *Sema::ActOnDestructorDeclarator(CXXDestructorDecl *Destructor) {
assert(Destructor && "Expected to receive a destructor declaration");
- CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CurContext);
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Destructor->getDeclContext());
+
+ // Set the lexical context of this destructor
+ Destructor->setLexicalDeclContext(CurContext);
// Make sure we aren't redeclaring the destructor.
if (CXXDestructorDecl *PrevDestructor = ClassDecl->getDestructor()) {
- Diag(Destructor->getLocation(), diag::err_destructor_redeclared);
- Diag(PrevDestructor->getLocation(),
- PrevDestructor->isThisDeclarationADefinition() ?
- diag::note_previous_definition
- : diag::note_previous_declaration);
- Destructor->setInvalidDecl();
+ if (CurContext == PrevDestructor->getLexicalDeclContext()) {
+ Diag(Destructor->getLocation(), diag::err_destructor_redeclared);
+ Diag(PrevDestructor->getLocation(),
+ PrevDestructor->isThisDeclarationADefinition() ?
+ diag::note_previous_definition
+ : diag::note_previous_declaration);
+ Destructor->setInvalidDecl();
+ }
+
+ // FIXME: Just drop the definition (for now).
return Destructor;
}
@@ -1179,7 +1185,10 @@
Sema::DeclTy *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
assert(Conversion && "Expected to receive a conversion function declaration");
- CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CurContext);
+ // Set the lexical context of this conversion function
+ Conversion->setLexicalDeclContext(CurContext);
+
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Conversion->getDeclContext());
// Make sure we aren't redeclaring the conversion function.
QualType ConvType = Context.getCanonicalType(Conversion->getConversionType());
Modified: cfe/trunk/test/SemaCXX/constructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constructor.cpp?rev=60947&r1=60946&r2=60947&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/constructor.cpp Fri Dec 12 02:25:50 2008
@@ -18,3 +18,6 @@
int Foo(int, int); // expected-error{{constructor cannot have a return type}}
};
+
+Foo::Foo(const Foo&) { }
+
Modified: cfe/trunk/test/SemaCXX/destructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/destructor.cpp?rev=60947&r1=60946&r2=60947&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/destructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/destructor.cpp Fri Dec 12 02:25:50 2008
@@ -38,3 +38,10 @@
~; // expected-error {{expected class name}}
~undef(); // expected-error {{expected class name}}
~F(){} // expected-error {{destructor must be a non-static member function}}
+
+struct G {
+ ~G();
+};
+
+G::~G() { }
+
More information about the cfe-commits
mailing list