Make more AST nodes and semantic checkers dependent-expression-aware.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65529 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index c8671bc..6023469 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -134,6 +134,8 @@
                                                TyBeginLoc, Exprs[0], RParenLoc);
   }
 
+  // FIXME: What AST node to create when the type is dependent?
+
   if (const RecordType *RT = Ty->getAsRecordType()) {
     CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl());
     
@@ -220,14 +222,16 @@
   if (CheckAllocatedType(AllocType, D))
     return true;
 
-  QualType ResultType = Context.getPointerType(AllocType);
+  QualType ResultType = AllocType->isDependentType()
+                          ? Context.DependentTy
+                          : Context.getPointerType(AllocType);
 
   // That every array dimension except the first is constant was already
   // checked by the type check above.
 
   // C++ 5.3.4p6: "The expression in a direct-new-declarator shall have integral
   //   or enumeration type with a non-negative value."
-  if (ArraySize) {
+  if (ArraySize && !ArraySize->isTypeDependent()) {
     QualType SizeType = ArraySize->getType();
     if (!SizeType->isIntegralType() && !SizeType->isEnumeralType())
       return Diag(ArraySize->getSourceRange().getBegin(),
@@ -236,20 +240,24 @@
     // Let's see if this is a constant < 0. If so, we reject it out of hand.
     // We don't care about special rules, so we tell the machinery it's not
     // evaluated - it gives us a result in more cases.
-    llvm::APSInt Value;
-    if (ArraySize->isIntegerConstantExpr(Value, Context, 0, false)) {
-      if (Value < llvm::APSInt(
-                      llvm::APInt::getNullValue(Value.getBitWidth()), false))
-        return Diag(ArraySize->getSourceRange().getBegin(),
-                    diag::err_typecheck_negative_array_size)
-          << ArraySize->getSourceRange();
+    if (!ArraySize->isValueDependent()) {
+      llvm::APSInt Value;
+      if (ArraySize->isIntegerConstantExpr(Value, Context, 0, false)) {
+        if (Value < llvm::APSInt(
+                        llvm::APInt::getNullValue(Value.getBitWidth()), false))
+          return Diag(ArraySize->getSourceRange().getBegin(),
+                      diag::err_typecheck_negative_array_size)
+            << ArraySize->getSourceRange();
+      }
     }
   }
 
   FunctionDecl *OperatorNew = 0;
   FunctionDecl *OperatorDelete = 0;
   Expr **PlaceArgs = (Expr**)PlacementArgs;
-  if (FindAllocationFunctions(StartLoc,
+  if (!AllocType->isDependentType() &&
+      !Expr::hasAnyTypeDependentArguments(PlaceArgs, NumPlaceArgs) &&
+      FindAllocationFunctions(StartLoc,
                               SourceRange(PlacementLParen, PlacementRParen),
                               UseGlobal, AllocType, ArraySize, PlaceArgs,
                               NumPlaceArgs, OperatorNew, OperatorDelete))
@@ -275,8 +283,11 @@
   // 2) Otherwise, the object is direct-initialized.
   CXXConstructorDecl *Constructor = 0;
   Expr **ConsArgs = (Expr**)ConstructorArgs;
+  if (AllocType->isDependentType()) {
+    // Skip all the checks.
+  }
   // FIXME: Should check for primitive/aggregate here, not record.
-  if (const RecordType *RT = AllocType->getAsRecordType()) {
+  else if (const RecordType *RT = AllocType->getAsRecordType()) {
     // FIXME: This is incorrect for when there is an empty initializer and
     // no user-defined constructor. Must zero-initialize, not default-construct.
     Constructor = PerformInitializationByConstructor(
@@ -570,32 +581,34 @@
   // DR599 amends "pointer type" to "pointer to object type" in both cases.
 
   Expr *Ex = (Expr *)Operand;
-  QualType Type = Ex->getType();
+  if (!Ex->isTypeDependent()) {
+    QualType Type = Ex->getType();
 
-  if (Type->isRecordType()) {
-    // FIXME: Find that one conversion function and amend the type.
+    if (Type->isRecordType()) {
+      // FIXME: Find that one conversion function and amend the type.
+    }
+
+    if (!Type->isPointerType()) {
+      Diag(StartLoc, diag::err_delete_operand) << Type << Ex->getSourceRange();
+      return true;
+    }
+
+    QualType Pointee = Type->getAsPointerType()->getPointeeType();
+    if (!Pointee->isVoidType() && 
+        DiagnoseIncompleteType(StartLoc, Pointee, diag::warn_delete_incomplete,
+                               Ex->getSourceRange()))
+      return true;
+    else if (!Pointee->isObjectType()) {
+      Diag(StartLoc, diag::err_delete_operand)
+        << Type << Ex->getSourceRange();
+      return true;
+    }
+
+    // FIXME: Look up the correct operator delete overload and pass a pointer
+    // along.
+    // FIXME: Check access and ambiguity of operator delete and destructor.
   }
 
-  if (!Type->isPointerType()) {
-    Diag(StartLoc, diag::err_delete_operand) << Type << Ex->getSourceRange();
-    return true;
-  }
-
-  QualType Pointee = Type->getAsPointerType()->getPointeeType();
-  if (!Pointee->isVoidType() && 
-      DiagnoseIncompleteType(StartLoc, Pointee, diag::warn_delete_incomplete,
-                             Ex->getSourceRange()))
-    return true;
-  else if (!Pointee->isObjectType()) {
-    Diag(StartLoc, diag::err_delete_operand)
-      << Type << Ex->getSourceRange();
-    return true;
-  }
-
-  // FIXME: Look up the correct operator delete overload and pass a pointer
-  // along.
-  // FIXME: Check access and ambiguity of operator delete and destructor.
-
   return new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm, 0,
                                      Ex, StartLoc);
 }