forked from OSchip/llvm-project
parent
722f5fc567
commit
3671ad4571
|
@ -2672,7 +2672,7 @@ public:
|
||||||
QualType CheckConstructorDeclarator(Declarator &D, QualType R,
|
QualType CheckConstructorDeclarator(Declarator &D, QualType R,
|
||||||
FunctionDecl::StorageClass& SC);
|
FunctionDecl::StorageClass& SC);
|
||||||
void CheckConstructor(CXXConstructorDecl *Constructor);
|
void CheckConstructor(CXXConstructorDecl *Constructor);
|
||||||
QualType CheckDestructorDeclarator(Declarator &D, QualType R,
|
QualType CheckDestructorDeclarator(Declarator &D,
|
||||||
FunctionDecl::StorageClass& SC);
|
FunctionDecl::StorageClass& SC);
|
||||||
bool CheckDestructor(CXXDestructorDecl *Destructor);
|
bool CheckDestructor(CXXDestructorDecl *Destructor);
|
||||||
void CheckConversionDeclarator(Declarator &D, QualType &R,
|
void CheckConversionDeclarator(Declarator &D, QualType &R,
|
||||||
|
|
|
@ -3023,7 +3023,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||||
} else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
|
} else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
|
||||||
// This is a C++ destructor declaration.
|
// This is a C++ destructor declaration.
|
||||||
if (DC->isRecord()) {
|
if (DC->isRecord()) {
|
||||||
R = CheckDestructorDeclarator(D, R, SC);
|
R = CheckDestructorDeclarator(D, SC);
|
||||||
|
|
||||||
NewFD = CXXDestructorDecl::Create(Context,
|
NewFD = CXXDestructorDecl::Create(Context,
|
||||||
cast<CXXRecordDecl>(DC),
|
cast<CXXRecordDecl>(DC),
|
||||||
|
|
|
@ -2990,7 +2990,9 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
|
||||||
|
|
||||||
// Rebuild the function type "R" without any type qualifiers (in
|
// Rebuild the function type "R" without any type qualifiers (in
|
||||||
// case any of the errors above fired) and with "void" as the
|
// case any of the errors above fired) and with "void" as the
|
||||||
// return type, since constructors don't have return types.
|
// return type, since constructors don't have return types. We
|
||||||
|
// *always* have to do this, because GetTypeForDeclarator will
|
||||||
|
// put in a result type of "int" when none was specified.
|
||||||
const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
|
const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
|
||||||
return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(),
|
return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(),
|
||||||
Proto->getNumArgs(),
|
Proto->getNumArgs(),
|
||||||
|
@ -3085,7 +3087,7 @@ FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) {
|
||||||
/// emit diagnostics and set the declarator to invalid. Even if this happens,
|
/// emit diagnostics and set the declarator to invalid. Even if this happens,
|
||||||
/// will be updated to reflect a well-formed type for the destructor and
|
/// will be updated to reflect a well-formed type for the destructor and
|
||||||
/// returned.
|
/// returned.
|
||||||
QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
|
QualType Sema::CheckDestructorDeclarator(Declarator &D,
|
||||||
FunctionDecl::StorageClass& SC) {
|
FunctionDecl::StorageClass& SC) {
|
||||||
// C++ [class.dtor]p1:
|
// C++ [class.dtor]p1:
|
||||||
// [...] A typedef-name that names a class is a class-name
|
// [...] A typedef-name that names a class is a class-name
|
||||||
|
@ -3093,9 +3095,11 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
|
||||||
// be used as the identifier in the declarator for a destructor
|
// be used as the identifier in the declarator for a destructor
|
||||||
// declaration.
|
// declaration.
|
||||||
QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName);
|
QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName);
|
||||||
if (isa<TypedefType>(DeclaratorType))
|
if (isa<TypedefType>(DeclaratorType)) {
|
||||||
Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
|
Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
|
||||||
<< DeclaratorType;
|
<< DeclaratorType;
|
||||||
|
D.setInvalidType();
|
||||||
|
}
|
||||||
|
|
||||||
// C++ [class.dtor]p2:
|
// C++ [class.dtor]p2:
|
||||||
// A destructor is used to destroy objects of its class type. A
|
// A destructor is used to destroy objects of its class type. A
|
||||||
|
@ -3109,10 +3113,9 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
|
||||||
if (!D.isInvalidType())
|
if (!D.isInvalidType())
|
||||||
Diag(D.getIdentifierLoc(), diag::err_destructor_cannot_be)
|
Diag(D.getIdentifierLoc(), diag::err_destructor_cannot_be)
|
||||||
<< "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
|
<< "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
|
||||||
<< SourceRange(D.getIdentifierLoc())
|
<< SourceRange(D.getIdentifierLoc());
|
||||||
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
|
|
||||||
|
|
||||||
SC = FunctionDecl::None;
|
SC = FunctionDecl::None;
|
||||||
|
D.setInvalidType();
|
||||||
}
|
}
|
||||||
if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
|
if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
|
||||||
// Destructors don't have return types, but the parser will
|
// Destructors don't have return types, but the parser will
|
||||||
|
@ -3160,17 +3163,11 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
|
||||||
// Rebuild the function type "R" without any type qualifiers or
|
// Rebuild the function type "R" without any type qualifiers or
|
||||||
// parameters (in case any of the errors above fired) and with
|
// parameters (in case any of the errors above fired) and with
|
||||||
// "void" as the return type, since destructors don't have return
|
// "void" as the return type, since destructors don't have return
|
||||||
// types.
|
// types. We *always* have to do this, because GetTypeForDeclarator
|
||||||
const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
|
// will put in a result type of "int" when none was specified.
|
||||||
if (!Proto)
|
// FIXME: Exceptions!
|
||||||
return QualType();
|
|
||||||
|
|
||||||
return Context.getFunctionType(Context.VoidTy, 0, 0, false, 0,
|
return Context.getFunctionType(Context.VoidTy, 0, 0, false, 0,
|
||||||
Proto->hasExceptionSpec(),
|
false, false, 0, 0, FunctionType::ExtInfo());
|
||||||
Proto->hasAnyExceptionSpec(),
|
|
||||||
Proto->getNumExceptions(),
|
|
||||||
Proto->exception_begin(),
|
|
||||||
Proto->getExtInfo());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CheckConversionDeclarator - Called by ActOnDeclarator to check the
|
/// CheckConversionDeclarator - Called by ActOnDeclarator to check the
|
||||||
|
|
|
@ -32,17 +32,6 @@ struct C {
|
||||||
|
|
||||||
C::~C() { }
|
C::~C() { }
|
||||||
|
|
||||||
namespace PR7526 {
|
|
||||||
extern void foo();
|
|
||||||
struct allocator {
|
|
||||||
~allocator() throw();
|
|
||||||
};
|
|
||||||
|
|
||||||
// CHECK: define void @_ZN6PR75269allocatorD2Ev
|
|
||||||
// CHECK: call void @__cxa_call_unexpected
|
|
||||||
allocator::~allocator() throw() { foo(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
// PR5084
|
// PR5084
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class A1 {
|
class A1 {
|
||||||
|
|
|
@ -19,9 +19,7 @@ struct D {
|
||||||
// expected-error{{type qualifier is not allowed on this function}} \
|
// expected-error{{type qualifier is not allowed on this function}} \
|
||||||
// expected-error{{destructor cannot be declared 'static'}} \
|
// expected-error{{destructor cannot be declared 'static'}} \
|
||||||
// expected-error{{destructor cannot have any parameters}} \
|
// expected-error{{destructor cannot have any parameters}} \
|
||||||
// expected-error{{destructor cannot be variadic}} \
|
// expected-error{{destructor cannot be variadic}}
|
||||||
// expected-error{{destructor cannot have a return type}} \
|
|
||||||
// expected-error{{'const' qualifier is not allowed on a destructor}}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct D2 {
|
struct D2 {
|
||||||
|
|
|
@ -590,8 +590,9 @@ void g(Base *base) {
|
||||||
downcast.mm:6:3: error: no matching function for call to 'f'
|
downcast.mm:6:3: error: no matching function for call to 'f'
|
||||||
f(base);
|
f(base);
|
||||||
^
|
^
|
||||||
downcast.mm:4:6: note: candidate function not viable: cannot convert from
|
downcast.mm:4:6: note: candidate function not viable: cannot convert from base
|
||||||
superclass 'Base *' to subclass 'Derived *' for 1st argument
|
class pointer 'Base *' to derived class pointer 'Derived *' for 1st
|
||||||
|
argument
|
||||||
void f(Derived *);
|
void f(Derived *);
|
||||||
^
|
^
|
||||||
</pre>
|
</pre>
|
||||||
|
|
Loading…
Reference in New Issue