]> granicus.if.org Git - clang/commitdiff
When marking the declarations in a default argument expression as
authorDouglas Gregor <dgregor@apple.com>
Tue, 14 Sep 2010 22:55:20 +0000 (22:55 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 14 Sep 2010 22:55:20 +0000 (22:55 +0000)
"used", at the time that the default argument itself is used, also
mark destructors that will be called by this expression. This fixes a
regression that I introduced in r113700, which broke WebKit, and fixes
<rdar://problem/8427926>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113883 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ExprCXX.h
lib/AST/ExprCXX.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/TreeTransform.h
test/SemaTemplate/default-expr-arguments.cpp

index 1424d8899b7e035d1152ef1ff361f662806cc9e8..6a3d307b08decca9d8f85458b30b3d8248be6f75 100644 (file)
@@ -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());
   }
index a6aeef1ba824d9480aea6e4bdfb03f9ae557b32d..6e73b9cbc209a5f8908cc24226a05ee8fc926496 100644 (file)
@@ -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; }
 
index 9a394aeeb9aebea513c4dae80ea636bb7c79e9ef..533d04f7ec9e04bc82c7a78f746008486008bbba 100644 (file)
@@ -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);
     }
     
index 765ce0f5e873e858dfad2199fc74a4c53a6ea771..a865348e4939b10771fdec2510974bd24772c310 100644 (file)
@@ -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());
   }
 
index 8fc241d5b2c5b3cb0b979db2bbb284fae935d36c..eff59a84e30d71027dddfdc611b7df44368acee9 100644 (file)
@@ -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();
+  }
+}