forked from OSchip/llvm-project
Enable out-of-line definitions of C++ constructors and destructors
llvm-svn: 60947
This commit is contained in:
parent
e4bcb8e2dd
commit
4287b37389
|
@ -178,10 +178,12 @@ public:
|
||||||
|
|
||||||
IdentifierNamespace getIdentifierNamespace() const {
|
IdentifierNamespace getIdentifierNamespace() const {
|
||||||
switch (DeclKind) {
|
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 ImplicitParam:
|
||||||
case Typedef:
|
case Typedef:
|
||||||
case Function:
|
|
||||||
case Var:
|
case Var:
|
||||||
case ParmVar:
|
case ParmVar:
|
||||||
case EnumConstant:
|
case EnumConstant:
|
||||||
|
|
|
@ -246,6 +246,24 @@ Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
|
||||||
} else if (LookupCtx) {
|
} else if (LookupCtx) {
|
||||||
assert(getLangOptions().CPlusPlus && "No qualified name lookup in C");
|
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.
|
// Perform qualified name lookup into the LookupCtx.
|
||||||
// FIXME: Will need to look into base classes and such.
|
// FIXME: Will need to look into base classes and such.
|
||||||
DeclContext::lookup_const_iterator I, E;
|
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
|
// after the point of declaration in a namespace that encloses the
|
||||||
// declarations namespace.
|
// 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) {
|
if (PrevDecl == 0) {
|
||||||
// No previous declaration in the qualifying scope.
|
// No previous declaration in the qualifying scope.
|
||||||
Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member)
|
Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member)
|
||||||
|
|
|
@ -1104,16 +1104,16 @@ Sema::DeclTy *Sema::ActOnConstructorDeclarator(CXXConstructorDecl *ConDecl) {
|
||||||
// Check default arguments on the constructor
|
// Check default arguments on the constructor
|
||||||
CheckCXXDefaultArguments(ConDecl);
|
CheckCXXDefaultArguments(ConDecl);
|
||||||
|
|
||||||
CXXRecordDecl *ClassDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext);
|
// Set the lexical context of this constructor
|
||||||
if (!ClassDecl) {
|
ConDecl->setLexicalDeclContext(CurContext);
|
||||||
ConDecl->setInvalidDecl();
|
|
||||||
return ConDecl;
|
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ConDecl->getDeclContext());
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure this constructor is an overload of the existing
|
// Make sure this constructor is an overload of the existing
|
||||||
// constructors.
|
// constructors.
|
||||||
OverloadedFunctionDecl::function_iterator MatchedDecl;
|
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)
|
Diag(ConDecl->getLocation(), diag::err_constructor_redeclared)
|
||||||
<< SourceRange(ConDecl->getLocation());
|
<< SourceRange(ConDecl->getLocation());
|
||||||
Diag((*MatchedDecl)->getLocation(), diag::note_previous_declaration)
|
Diag((*MatchedDecl)->getLocation(), diag::note_previous_declaration)
|
||||||
|
@ -1122,7 +1122,6 @@ Sema::DeclTy *Sema::ActOnConstructorDeclarator(CXXConstructorDecl *ConDecl) {
|
||||||
return ConDecl;
|
return ConDecl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// C++ [class.copy]p3:
|
// C++ [class.copy]p3:
|
||||||
// A declaration of a constructor for a class X is ill-formed if
|
// A declaration of a constructor for a class X is ill-formed if
|
||||||
// its first parameter is of type (optionally cv-qualified) X and
|
// 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) {
|
Sema::DeclTy *Sema::ActOnDestructorDeclarator(CXXDestructorDecl *Destructor) {
|
||||||
assert(Destructor && "Expected to receive a destructor declaration");
|
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.
|
// Make sure we aren't redeclaring the destructor.
|
||||||
if (CXXDestructorDecl *PrevDestructor = ClassDecl->getDestructor()) {
|
if (CXXDestructorDecl *PrevDestructor = ClassDecl->getDestructor()) {
|
||||||
Diag(Destructor->getLocation(), diag::err_destructor_redeclared);
|
if (CurContext == PrevDestructor->getLexicalDeclContext()) {
|
||||||
Diag(PrevDestructor->getLocation(),
|
Diag(Destructor->getLocation(), diag::err_destructor_redeclared);
|
||||||
PrevDestructor->isThisDeclarationADefinition() ?
|
Diag(PrevDestructor->getLocation(),
|
||||||
diag::note_previous_definition
|
PrevDestructor->isThisDeclarationADefinition() ?
|
||||||
: diag::note_previous_declaration);
|
diag::note_previous_definition
|
||||||
Destructor->setInvalidDecl();
|
: diag::note_previous_declaration);
|
||||||
|
Destructor->setInvalidDecl();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Just drop the definition (for now).
|
||||||
return Destructor;
|
return Destructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1179,7 +1185,10 @@ Sema::DeclTy *Sema::ActOnDestructorDeclarator(CXXDestructorDecl *Destructor) {
|
||||||
Sema::DeclTy *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
|
Sema::DeclTy *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
|
||||||
assert(Conversion && "Expected to receive a conversion function declaration");
|
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.
|
// Make sure we aren't redeclaring the conversion function.
|
||||||
QualType ConvType = Context.getCanonicalType(Conversion->getConversionType());
|
QualType ConvType = Context.getCanonicalType(Conversion->getConversionType());
|
||||||
|
|
|
@ -18,3 +18,6 @@ class Foo {
|
||||||
|
|
||||||
int Foo(int, int); // expected-error{{constructor cannot have a return type}}
|
int Foo(int, int); // expected-error{{constructor cannot have a return type}}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Foo::Foo(const Foo&) { }
|
||||||
|
|
||||||
|
|
|
@ -38,3 +38,10 @@ struct F {
|
||||||
~; // expected-error {{expected class name}}
|
~; // expected-error {{expected class name}}
|
||||||
~undef(); // expected-error {{expected class name}}
|
~undef(); // expected-error {{expected class name}}
|
||||||
~F(){} // expected-error {{destructor must be a non-static member function}}
|
~F(){} // expected-error {{destructor must be a non-static member function}}
|
||||||
|
|
||||||
|
struct G {
|
||||||
|
~G();
|
||||||
|
};
|
||||||
|
|
||||||
|
G::~G() { }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue