Make sure to mark constructors, operator new, and operator delete as
used when we instantiate C++ new expressions, delete expressions, and
object-construction expressions. Fixes PR6424, although we can't test
all of it until we finish implementing lookup of "operator delete" for
new expressions (!).


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97195 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 0216621..95ec5a4 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -4588,11 +4588,48 @@
     ConstructorArgs.push_back(Arg.take());
   }
 
+  // Transform constructor, new operator, and delete operator.
+  CXXConstructorDecl *Constructor = 0;
+  if (E->getConstructor()) {
+    Constructor = cast_or_null<CXXConstructorDecl>(
+                               getDerived().TransformDecl(E->getConstructor()));
+    if (!Constructor)
+      return SemaRef.ExprError();
+  }
+
+  FunctionDecl *OperatorNew = 0;
+  if (E->getOperatorNew()) {
+    OperatorNew = cast_or_null<FunctionDecl>(
+                               getDerived().TransformDecl(E->getOperatorNew()));
+    if (!OperatorNew)
+      return SemaRef.ExprError();
+  }
+
+  FunctionDecl *OperatorDelete = 0;
+  if (E->getOperatorDelete()) {
+    OperatorDelete = cast_or_null<FunctionDecl>(
+                           getDerived().TransformDecl(E->getOperatorDelete()));
+    if (!OperatorDelete)
+      return SemaRef.ExprError();
+  }
+  
   if (!getDerived().AlwaysRebuild() &&
       AllocType == E->getAllocatedType() &&
       ArraySize.get() == E->getArraySize() &&
-      !ArgumentChanged)
+      Constructor == E->getConstructor() &&
+      OperatorNew == E->getOperatorNew() &&
+      OperatorDelete == E->getOperatorDelete() &&
+      !ArgumentChanged) {
+    // Mark any declarations we need as referenced.
+    // FIXME: instantiation-specific.
+    if (Constructor)
+      SemaRef.MarkDeclarationReferenced(E->getLocStart(), Constructor);
+    if (OperatorNew)
+      SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorNew);
+    if (OperatorDelete)
+      SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorDelete);
     return SemaRef.Owned(E->Retain());
+  }
 
   if (!ArraySize.get()) {
     // If no array size was specified, but the new expression was
@@ -4641,9 +4678,24 @@
   if (Operand.isInvalid())
     return SemaRef.ExprError();
 
+  // Transform the delete operator, if known.
+  FunctionDecl *OperatorDelete = 0;
+  if (E->getOperatorDelete()) {
+    OperatorDelete = cast_or_null<FunctionDecl>(
+                            getDerived().TransformDecl(E->getOperatorDelete()));
+    if (!OperatorDelete)
+      return SemaRef.ExprError();
+  }
+  
   if (!getDerived().AlwaysRebuild() &&
-      Operand.get() == E->getArgument())
+      Operand.get() == E->getArgument() &&
+      OperatorDelete == E->getOperatorDelete()) {
+    // Mark any declarations we need as referenced.
+    // FIXME: instantiation-specific.
+    if (OperatorDelete)
+      SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorDelete);
     return SemaRef.Owned(E->Retain());
+  }
 
   return getDerived().RebuildCXXDeleteExpr(E->getLocStart(),
                                            E->isGlobalDelete(),
@@ -4907,6 +4959,8 @@
       T == E->getType() &&
       Constructor == E->getConstructor() &&
       !ArgumentChanged) {
+    // Mark the constructor as referenced.
+    // FIXME: Instantiation-specific
     SemaRef.MarkDeclarationReferenced(E->getLocStart(), Constructor);
     return SemaRef.Owned(E->Retain());
   }
diff --git a/test/SemaTemplate/instantiate-expr-1.cpp b/test/SemaTemplate/instantiate-expr-1.cpp
index 4594621..37145b6 100644
--- a/test/SemaTemplate/instantiate-expr-1.cpp
+++ b/test/SemaTemplate/instantiate-expr-1.cpp
@@ -152,4 +152,21 @@
   };
   
   template void Y<3>::f(); 
+
+  template<int I> 
+  struct X2 {
+    void *operator new(__SIZE_TYPE__) { 
+      int *ip = I; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}}
+      return ip;
+    }
+  };
+
+  template<int> struct Y2 {
+    typedef X2<7> X;
+    void f() { 
+      new X(); // expected-note{{instantiation of}}
+    }
+  };
+
+  template void Y2<3>::f();
 }