aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ExprCXX.h2
-rw-r--r--lib/AST/ExprCXX.cpp13
-rw-r--r--lib/Sema/SemaExpr.cpp15
-rw-r--r--lib/Sema/TreeTransform.h11
-rw-r--r--test/SemaTemplate/default-expr-arguments.cpp22
5 files changed, 61 insertions, 2 deletions
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 1424d8899b..6a3d307b08 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -1136,6 +1136,8 @@ public:
Expr *getArgument() { return cast<Expr>(Argument); }
const Expr *getArgument() const { return cast<Expr>(Argument); }
+ QualType getDestroyedType() const;
+
virtual SourceRange getSourceRange() const {
return SourceRange(Loc, Argument->getLocEnd());
}
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index a6aeef1ba8..6e73b9cbc2 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -149,6 +149,19 @@ Stmt::child_iterator CXXNewExpr::child_end() {
}
// CXXDeleteExpr
+QualType CXXDeleteExpr::getDestroyedType() const {
+ const Expr *Arg = getArgument();
+ while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
+ if (ICE->getCastKind() != CK_UserDefinedConversion &&
+ ICE->getType()->isVoidPointerType())
+ Arg = ICE->getSubExpr();
+ else
+ break;
+ }
+
+ return Arg->getType()->getAs<PointerType>()->getPointeeType();
+}
+
Stmt::child_iterator CXXDeleteExpr::child_begin() { return &Argument; }
Stmt::child_iterator CXXDeleteExpr::child_end() { return &Argument+1; }
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 9a394aeeb9..533d04f7ec 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -3454,8 +3454,12 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
// be properly destroyed.
// FIXME: We should really be rebuilding the default argument with new
// bound temporaries; see the comment in PR5810.
- for (unsigned i = 0, e = Param->getNumDefaultArgTemporaries(); i != e; ++i)
- ExprTemporaries.push_back(Param->getDefaultArgTemporary(i));
+ for (unsigned i = 0, e = Param->getNumDefaultArgTemporaries(); i != e; ++i) {
+ CXXTemporary *Temporary = Param->getDefaultArgTemporary(i);
+ MarkDeclarationReferenced(Param->getDefaultArg()->getLocStart(),
+ const_cast<CXXDestructorDecl*>(Temporary->getDestructor()));
+ ExprTemporaries.push_back(Temporary);
+ }
// We already type-checked the argument, so we know it works.
// Just mark all of the declarations in this potentially-evaluated expression
@@ -7838,6 +7842,13 @@ namespace {
void VisitCXXDeleteExpr(CXXDeleteExpr *E) {
if (E->getOperatorDelete())
S.MarkDeclarationReferenced(E->getLocStart(), E->getOperatorDelete());
+ QualType Destroyed = S.Context.getBaseElementType(E->getDestroyedType());
+ if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl());
+ S.MarkDeclarationReferenced(E->getLocStart(),
+ S.LookupDestructor(Record));
+ }
+
Inherited::VisitCXXDeleteExpr(E);
}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 765ce0f5e8..a865348e49 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -5395,6 +5395,17 @@ TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) {
// FIXME: instantiation-specific.
if (OperatorDelete)
SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorDelete);
+
+ if (!E->getArgument()->isTypeDependent()) {
+ QualType Destroyed = SemaRef.Context.getBaseElementType(
+ E->getDestroyedType());
+ if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl());
+ SemaRef.MarkDeclarationReferenced(E->getLocStart(),
+ SemaRef.LookupDestructor(Record));
+ }
+ }
+
return SemaRef.Owned(E->Retain());
}
diff --git a/test/SemaTemplate/default-expr-arguments.cpp b/test/SemaTemplate/default-expr-arguments.cpp
index 8fc241d5b2..eff59a84e3 100644
--- a/test/SemaTemplate/default-expr-arguments.cpp
+++ b/test/SemaTemplate/default-expr-arguments.cpp
@@ -252,3 +252,25 @@ namespace PR8127 {
void foo( PointerClass<ExternallyImplementedClass> = 0 );
};
}
+
+namespace rdar8427926 {
+ template<typename T>
+ struct Boom {
+ ~Boom() {
+ T t;
+ double *******ptr = t; // expected-error 2{{cannot initialize}}
+ }
+ };
+
+ Boom<float> *bfp;
+
+ struct X {
+ void f(Boom<int> = Boom<int>()) { } // expected-note{{requested here}}
+ void g(int x = (delete bfp, 0)); // expected-note{{requested here}}
+ };
+
+ void test(X *x) {
+ x->f();
+ x->g();
+ }
+}