diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index badf6345ecb2..04d0ce530c30 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -178,10 +178,12 @@ public: 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: diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 29d636fabdca..2c5e46afa0e7 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -246,6 +246,24 @@ Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S, } else if (LookupCtx) { assert(getLangOptions().CPlusPlus && "No qualified name lookup in C"); + switch (Name.getNameKind()) { + case DeclarationName::CXXConstructorName: + if (const CXXRecordDecl *Record = dyn_cast(LookupCtx)) + return const_cast(Record)->getConstructors(); + else + return 0; + + case DeclarationName::CXXDestructorName: + if (const CXXRecordDecl *Record = dyn_cast(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 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) { // 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) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 1b189f87fcba..40fcecfb1cda 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1104,16 +1104,16 @@ Sema::DeclTy *Sema::ActOnConstructorDeclarator(CXXConstructorDecl *ConDecl) { // Check default arguments on the constructor CheckCXXDefaultArguments(ConDecl); - CXXRecordDecl *ClassDecl = dyn_cast_or_null(CurContext); - if (!ClassDecl) { - ConDecl->setInvalidDecl(); - return ConDecl; - } + // Set the lexical context of this constructor + ConDecl->setLexicalDeclContext(CurContext); + + CXXRecordDecl *ClassDecl = cast(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 @@ Sema::DeclTy *Sema::ActOnConstructorDeclarator(CXXConstructorDecl *ConDecl) { 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::ActOnConstructorDeclarator(CXXConstructorDecl *ConDecl) { Sema::DeclTy *Sema::ActOnDestructorDeclarator(CXXDestructorDecl *Destructor) { assert(Destructor && "Expected to receive a destructor declaration"); - CXXRecordDecl *ClassDecl = cast(CurContext); + CXXRecordDecl *ClassDecl = cast(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::ActOnDestructorDeclarator(CXXDestructorDecl *Destructor) { Sema::DeclTy *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { assert(Conversion && "Expected to receive a conversion function declaration"); - CXXRecordDecl *ClassDecl = cast(CurContext); + // Set the lexical context of this conversion function + Conversion->setLexicalDeclContext(CurContext); + + CXXRecordDecl *ClassDecl = cast(Conversion->getDeclContext()); // Make sure we aren't redeclaring the conversion function. QualType ConvType = Context.getCanonicalType(Conversion->getConversionType()); diff --git a/clang/test/SemaCXX/constructor.cpp b/clang/test/SemaCXX/constructor.cpp index fc398e28ba4c..4c4d67fa872a 100644 --- a/clang/test/SemaCXX/constructor.cpp +++ b/clang/test/SemaCXX/constructor.cpp @@ -18,3 +18,6 @@ class Foo { int Foo(int, int); // expected-error{{constructor cannot have a return type}} }; + +Foo::Foo(const Foo&) { } + diff --git a/clang/test/SemaCXX/destructor.cpp b/clang/test/SemaCXX/destructor.cpp index 7f791daf5ee8..2134f4ec5c75 100644 --- a/clang/test/SemaCXX/destructor.cpp +++ b/clang/test/SemaCXX/destructor.cpp @@ -38,3 +38,10 @@ struct F { ~; // 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() { } +