diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 5 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 35 | ||||
-rw-r--r-- | test/SemaCXX/pseudo-destructors.cpp | 13 |
3 files changed, 44 insertions, 9 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 1230f5b9d4..670a0d048a 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1554,6 +1554,11 @@ def err_throw_incomplete_ptr : Error< def err_return_in_constructor_handler : Error< "return in the catch of a function try block of a constructor is illegal">; +def err_ident_in_pseudo_dtor_not_a_type : Error< + "identifier %0 in pseudo-destructor expression does not name a type">; +def err_type_in_pseudo_dtor_not_a_class_type : Error< + "type %0 in pseudo-destructor expression is not a class type">; + def err_invalid_use_of_function_type : Error< "a function type is not allowed here">; def err_invalid_use_of_array_type : Error<"an array type is not allowed here">; diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index cf52bae86c..2b0749aec0 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1694,18 +1694,35 @@ Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base, const CXXScopeSpec *SS) { if (SS && SS->isInvalid()) return ExprError(); + + Expr *BaseExpr = (Expr *)Base.get(); - // Since this might be a postfix expression, get rid of ParenListExprs. - Base = MaybeConvertParenListExprToParenExpr(S, move(Base)); - - Expr *BaseExpr = Base.takeAs<Expr>(); - assert(BaseExpr && "no record expression"); + if (BaseExpr->isTypeDependent() || + (SS && isDependentScopeSpecifier(*SS))) { + // FIXME: Return an unresolved ref expr. + return ExprError(); + } + + TypeTy *BaseTy = getTypeName(*ClassName, ClassNameLoc, S, SS); + if (!BaseTy) { + Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type) + << ClassName; + return ExprError(); + } - // Perform default conversions. - DefaultFunctionArrayConversion(BaseExpr); + QualType BaseType = GetTypeFromParser(BaseTy); + if (!BaseType->isRecordType()) { + Diag(ClassNameLoc, diag::err_type_in_pseudo_dtor_not_a_class_type) + << BaseType; + return ExprError(); + } - QualType BaseType = BaseExpr->getType(); - return ExprError(); + CanQualType CanBaseType = Context.getCanonicalType(BaseType); + DeclarationName DtorName = + Context.DeclarationNames.getCXXDestructorName(CanBaseType); + + return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, ClassNameLoc, + DtorName, DeclPtrTy(), SS); } Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) { diff --git a/test/SemaCXX/pseudo-destructors.cpp b/test/SemaCXX/pseudo-destructors.cpp new file mode 100644 index 0000000000..8c41f2266d --- /dev/null +++ b/test/SemaCXX/pseudo-destructors.cpp @@ -0,0 +1,13 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct A {}; + +enum Foo { F }; +typedef Foo Bar; + +void f(A* a) { + a->~A(); + a->A::~A(); + + a->~foo(); // expected-error{{identifier 'foo' in pseudo-destructor expression does not name a type}} + a->~Bar(); // expected-error{{type 'Bar' (aka 'enum Foo') in pseudo-destructor expression is not a class type}} +} |