diff options
author | Marco Antognini <marco.antognini@arm.com> | 2019-07-18 10:04:18 +0000 |
---|---|---|
committer | Marco Antognini <marco.antognini@arm.com> | 2019-07-18 10:04:18 +0000 |
commit | 83748cc5abc199a5219b0e7d9ba308984a8df613 (patch) | |
tree | 8abe72eb817fff18c645aec8d52fc22f610bf113 /clang/lib/Sema | |
parent | 46b55fa58dead05222211e327ed90ffab949040b (diff) | |
download | bcm5719-llvm-83748cc5abc199a5219b0e7d9ba308984a8df613.tar.gz bcm5719-llvm-83748cc5abc199a5219b0e7d9ba308984a8df613.zip |
[OpenCL] Improve destructor support in C++ for OpenCL
Summary:
This patch does mainly three things:
1. It fixes a false positive error detection in Sema that is similar to
D62156. The error happens when explicitly calling an overloaded
destructor for different address spaces.
2. It selects the correct destructor when multiple overloads for
address spaces are available.
3. It inserts the expected address space cast when invoking a
destructor, if needed, and therefore fixes a crash due to the unmet
assertion in llvm::CastInst::Create.
The following is a reproducer of the three issues:
struct MyType {
~MyType() {}
~MyType() __constant {}
};
__constant MyType myGlobal{};
kernel void foo() {
myGlobal.~MyType(); // 1 and 2.
// 1. error: cannot initialize object parameter of type
// '__generic MyType' with an expression of type '__constant MyType'
// 2. error: no matching member function for call to '~MyType'
}
kernel void bar() {
// 3. The implicit call to the destructor crashes due to:
// Assertion `castIsValid(op, S, Ty) && "Invalid cast!"' failed.
// in llvm::CastInst::Create.
MyType myLocal;
}
The added test depends on D62413 and covers a few more things than the
above reproducer.
Subscribers: yaxunl, Anastasia, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64569
llvm-svn: 366422
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 50 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 4 |
2 files changed, 26 insertions, 28 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index dd77fc55721..9a6385f2831 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -8190,6 +8190,27 @@ void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) { CheckCXXDefaultArguments(Method); } +// Emit the given diagnostic for each non-address-space qualifier. +// Common part of CheckConstructorDeclarator and CheckDestructorDeclarator. +static void checkMethodTypeQualifiers(Sema &S, Declarator &D, unsigned DiagID) { + const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); + if (FTI.hasMethodTypeQualifiers() && !D.isInvalidType()) { + bool DiagOccured = false; + FTI.MethodQualifiers->forEachQualifier( + [DiagID, &S, &DiagOccured](DeclSpec::TQ, StringRef QualName, + SourceLocation SL) { + // This diagnostic should be emitted on any qualifier except an addr + // space qualifier. However, forEachQualifier currently doesn't visit + // addr space qualifiers, so there's no way to write this condition + // right now; we just diagnose on everything. + S.Diag(SL, DiagID) << QualName << SourceRange(SL); + DiagOccured = true; + }); + if (DiagOccured) + D.setInvalidType(); + } +} + /// CheckConstructorDeclarator - Called by ActOnDeclarator to check /// the well-formedness of the constructor declarator @p D with type @p /// R. If there are any errors in the declarator, this routine will @@ -8230,25 +8251,11 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, D.setInvalidType(); } - DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); - if (FTI.hasMethodTypeQualifiers()) { - bool DiagOccured = false; - FTI.MethodQualifiers->forEachQualifier( - [&](DeclSpec::TQ TypeQual, StringRef QualName, SourceLocation SL) { - // This diagnostic should be emitted on any qualifier except an addr - // space qualifier. However, forEachQualifier currently doesn't visit - // addr space qualifiers, so there's no way to write this condition - // right now; we just diagnose on everything. - Diag(SL, diag::err_invalid_qualified_constructor) - << QualName << SourceRange(SL); - DiagOccured = true; - }); - if (DiagOccured) - D.setInvalidType(); - } + checkMethodTypeQualifiers(*this, D, diag::err_invalid_qualified_constructor); // C++0x [class.ctor]p4: // A constructor shall not be declared with a ref-qualifier. + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); if (FTI.hasRefQualifier()) { Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_constructor) << FTI.RefQualifierIsLValueRef @@ -8423,18 +8430,11 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, } } - DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); - if (FTI.hasMethodTypeQualifiers() && !D.isInvalidType()) { - FTI.MethodQualifiers->forEachQualifier( - [&](DeclSpec::TQ TypeQual, StringRef QualName, SourceLocation SL) { - Diag(SL, diag::err_invalid_qualified_destructor) - << QualName << SourceRange(SL); - }); - D.setInvalidType(); - } + checkMethodTypeQualifiers(*this, D, diag::err_invalid_qualified_destructor); // C++0x [class.dtor]p2: // A destructor shall not be declared with a ref-qualifier. + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); if (FTI.hasRefQualifier()) { Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_destructor) << FTI.RefQualifierIsLValueRef diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index d8c4ea48ebc..f632a4d3bd1 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -5093,12 +5093,10 @@ TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType, QualType ClassType = S.Context.getTypeDeclType(ActingContext); // [class.dtor]p2: A destructor can be invoked for a const, volatile or // const volatile object. - Qualifiers Quals; + Qualifiers Quals = Method->getMethodQualifiers(); if (isa<CXXDestructorDecl>(Method)) { Quals.addConst(); Quals.addVolatile(); - } else { - Quals = Method->getMethodQualifiers(); } QualType ImplicitParamType = S.Context.getQualifiedType(ClassType, Quals); |