Introduce basic support for dependent types, type-dependent
expressions, and value-dependent expressions. This permits us to parse
some template definitions.

This is not a complete solution; we're missing type- and
value-dependent computations for most of the expression types, and
we're missing checks for dependent types and type-dependent
expressions throughout Sema.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60615 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 7c8b4b1..35647cf 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -183,7 +183,14 @@
   InitBuiltinType(WCharTy,             BuiltinType::WChar);
 
   // Placeholder type for functions.
-  InitBuiltinType(OverloadTy,         BuiltinType::Overload);
+  InitBuiltinType(OverloadTy,          BuiltinType::Overload);
+
+  // Placeholder type for type-dependent expressions whose type is
+  // completely unknown. No code should ever check a type against
+  // DependentTy and users should never see it; however, it is here to
+  // help diagnose failures to properly check for type-dependent
+  // expressions.
+  InitBuiltinType(DependentTy,         BuiltinType::Dependent);
 
   // C99 6.2.5p11.
   FloatComplexTy      = getComplexType(FloatTy);
@@ -235,6 +242,8 @@
     assert(0 && "Incomplete types have no size!");
   case Type::VariableArray:
     assert(0 && "VLAs not implemented yet!");
+  case Type::DependentSizedArray:
+    assert(0 && "Dependently-sized arrays don't have a known size");
   case Type::ConstantArray: {
     const ConstantArrayType *CAT = cast<ConstantArrayType>(T);
     
@@ -759,6 +768,28 @@
   return QualType(New, 0);
 }
 
+/// getDependentSizedArrayType - Returns a non-unique reference to
+/// the type for a dependently-sized array of the specified element
+/// type. FIXME: We will need these to be uniqued, or at least
+/// comparable, at some point.
+QualType ASTContext::getDependentSizedArrayType(QualType EltTy, Expr *NumElts,
+                                                ArrayType::ArraySizeModifier ASM,
+                                                unsigned EltTypeQuals) {
+  assert((NumElts->isTypeDependent() || NumElts->isValueDependent()) && 
+         "Size must be type- or value-dependent!");
+
+  // Since we don't unique expressions, it isn't possible to unique
+  // dependently-sized array types.
+
+  DependentSizedArrayType *New 
+    = new DependentSizedArrayType(EltTy, QualType(), NumElts, 
+                                  ASM, EltTypeQuals);
+
+  DependentSizedArrayTypes.push_back(New);
+  Types.push_back(New);
+  return QualType(New, 0);
+}
+
 QualType ASTContext::getIncompleteArrayType(QualType EltTy,
                                             ArrayType::ArraySizeModifier ASM,
                                             unsigned EltTypeQuals) {
@@ -1174,6 +1205,11 @@
     return getIncompleteArrayType(NewEltTy, IAT->getSizeModifier(),
                                   IAT->getIndexTypeQualifier());
   
+  if (DependentSizedArrayType *DSAT = dyn_cast<DependentSizedArrayType>(AT))
+    return getDependentSizedArrayType(NewEltTy, DSAT->getSizeExpr(),
+                                      DSAT->getSizeModifier(),
+                                      DSAT->getIndexTypeQualifier());    
+
   // FIXME: What is the ownership of size expressions in VLAs?
   VariableArrayType *VAT = cast<VariableArrayType>(AT);
   return getVariableArrayType(NewEltTy, VAT->getSizeExpr(),
@@ -1246,6 +1282,16 @@
     return cast<ArrayType>(getIncompleteArrayType(NewEltTy,
                                                   IAT->getSizeModifier(),
                                                  IAT->getIndexTypeQualifier()));
+
+  // FIXME: What is the ownership of size expressions in
+  // dependent-sized array types?
+  if (const DependentSizedArrayType *DSAT 
+        = dyn_cast<DependentSizedArrayType>(ATy))
+    return cast<ArrayType>(
+                     getDependentSizedArrayType(NewEltTy, 
+                                                DSAT->getSizeExpr(),
+                                                DSAT->getSizeModifier(),
+                                                DSAT->getIndexTypeQualifier()));
   
   // FIXME: What is the ownership of size expressions in VLAs?
   const VariableArrayType *VAT = cast<VariableArrayType>(ATy);
diff --git a/lib/AST/CFG.cpp b/lib/AST/CFG.cpp
index 82336a4..69e82f2 100644
--- a/lib/AST/CFG.cpp
+++ b/lib/AST/CFG.cpp
@@ -154,6 +154,8 @@
   bool badCFG;
 };
   
+// FIXME: Add support for dependent-sized array types in C++?
+// Does it even make sense to build a CFG for an uninstantiated template?
 static VariableArrayType* FindVA(Type* t) {
   while (ArrayType* vt = dyn_cast<ArrayType>(t)) {
     if (VariableArrayType* vat = dyn_cast<VariableArrayType>(vt))
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index a3264b0..14db18c 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -103,7 +103,10 @@
 
 CallExpr::CallExpr(StmtClass SC, Expr *fn, Expr **args, unsigned numargs, 
                    QualType t, SourceLocation rparenloc)
-  : Expr(SC, t), NumArgs(numargs) {
+  : Expr(SC, t, 
+         fn->isTypeDependent() || hasAnyTypeDependentArguments(args, numargs),
+         fn->isValueDependent() || hasAnyValueDependentArguments(args, numargs)),
+    NumArgs(numargs) {
   SubExprs = new Stmt*[numargs+1];
   SubExprs[FN] = fn;
   for (unsigned i = 0; i != numargs; ++i)
@@ -113,7 +116,10 @@
 
 CallExpr::CallExpr(Expr *fn, Expr **args, unsigned numargs, QualType t,
                    SourceLocation rparenloc)
-  : Expr(CallExprClass, t), NumArgs(numargs) {
+  : Expr(CallExprClass, t,
+         fn->isTypeDependent() || hasAnyTypeDependentArguments(args, numargs),
+         fn->isValueDependent() || hasAnyValueDependentArguments(args, numargs)),
+    NumArgs(numargs) {
   SubExprs = new Stmt*[numargs+1];
   SubExprs[FN] = fn;
   for (unsigned i = 0; i != numargs; ++i)
@@ -631,6 +637,26 @@
   }
 }
 
+/// hasAnyTypeDependentArguments - Determines if any of the expressions
+/// in Exprs is type-dependent.
+bool Expr::hasAnyTypeDependentArguments(Expr** Exprs, unsigned NumExprs) {
+  for (unsigned I = 0; I < NumExprs; ++I)
+    if (Exprs[I]->isTypeDependent())
+      return true;
+
+  return false;
+}
+
+/// hasAnyValueDependentArguments - Determines if any of the expressions
+/// in Exprs is value-dependent.
+bool Expr::hasAnyValueDependentArguments(Expr** Exprs, unsigned NumExprs) {
+  for (unsigned I = 0; I < NumExprs; ++I)
+    if (Exprs[I]->isValueDependent())
+      return true;
+
+  return false;
+}
+
 bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const {
   switch (getStmtClass()) {
   default:
diff --git a/lib/AST/StmtIterator.cpp b/lib/AST/StmtIterator.cpp
index 4688242..4800345 100644
--- a/lib/AST/StmtIterator.cpp
+++ b/lib/AST/StmtIterator.cpp
@@ -16,6 +16,8 @@
 
 using namespace clang;
 
+// FIXME: Add support for dependent-sized array types in C++?
+// Does it even make sense to build a CFG for an uninstantiated template?
 static inline VariableArrayType* FindVA(Type* t) {
   while (ArrayType* vt = dyn_cast<ArrayType>(t)) {
     if (VariableArrayType* vat = dyn_cast<VariableArrayType>(vt))
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 303fc7e..5909c97 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -43,6 +43,10 @@
   delete this;  
 }
 
+void DependentSizedArrayType::Destroy(ASTContext& C) {
+  SizeExpr->Destroy(C);
+  delete this;
+}
 
 /// getArrayElementTypeNoTypeQual - If this is an array type, return the
 /// element type of the array, potentially with type qualifiers missing.
@@ -634,11 +638,12 @@
 
 /// isConstantSizeType - Return true if this is not a variable sized type,
 /// according to the rules of C99 6.7.5p3.  It is not legal to call this on
-/// incomplete types.
+/// incomplete types or dependent types.
 bool Type::isConstantSizeType() const {
   if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
     return ASQT->getBaseType()->isConstantSizeType();
   assert(!isIncompleteType() && "This doesn't make sense for incomplete types");
+  assert(!isDependentType() && "This doesn't make sense for dependent types");
   // The VAT must have a size, as it is known to be complete.
   return !isa<VariableArrayType>(CanonicalType);
 }
@@ -706,6 +711,7 @@
   case LongDouble:        return "long double";
   case WChar:             return "wchar_t";
   case Overload:          return "<overloaded function type>";
+  case Dependent:         return "<dependent type>";
   }
 }
 
@@ -780,6 +786,11 @@
   }
 }
 
+TypeOfExpr::TypeOfExpr(Expr *E, QualType can)
+  : Type(TypeOfExp, can, E->isTypeDependent()), TOExpr(E) {
+  assert(!isa<TypedefType>(can) && "Invalid canonical type");
+}
+
 bool RecordType::classof(const TagType *TT) {
   return isa<RecordDecl>(TT->getDecl());
 }
@@ -932,6 +943,30 @@
   getElementType().getAsStringInternal(S);
 }
 
+void DependentSizedArrayType::getAsStringInternal(std::string &S) const {
+  S += '[';
+  
+  if (getIndexTypeQualifier()) {
+    AppendTypeQualList(S, getIndexTypeQualifier());
+    S += ' ';
+  }
+  
+  if (getSizeModifier() == Static)
+    S += "static";
+  else if (getSizeModifier() == Star)
+    S += '*';
+  
+  if (getSizeExpr()) {
+    std::string SStr;
+    llvm::raw_string_ostream s(SStr);
+    getSizeExpr()->printPretty(s);
+    S += s.str();
+  }
+  S += ']';
+  
+  getElementType().getAsStringInternal(S);
+}
+
 void VectorType::getAsStringInternal(std::string &S) const {
   // FIXME: We prefer to print the size directly here, but have no way
   // to get the size of the type.
diff --git a/lib/AST/TypeSerialization.cpp b/lib/AST/TypeSerialization.cpp
index 3bdc946..8e35f18 100644
--- a/lib/AST/TypeSerialization.cpp
+++ b/lib/AST/TypeSerialization.cpp
@@ -315,6 +315,26 @@
 }
 
 //===----------------------------------------------------------------------===//
+// DependentSizedArrayType
+//===----------------------------------------------------------------------===//
+
+void DependentSizedArrayType::EmitImpl(Serializer& S) const {
+  S.Emit(getElementType());
+  S.EmitInt(getSizeModifier());
+  S.EmitInt(getIndexTypeQualifier());
+  S.EmitOwnedPtr(SizeExpr);
+}
+
+Type* DependentSizedArrayType::CreateImpl(ASTContext& Context, Deserializer& D) {
+  QualType ElTy = QualType::ReadVal(D);
+  ArraySizeModifier am = static_cast<ArraySizeModifier>(D.ReadInt());
+  unsigned ITQ = D.ReadInt();  
+  Expr* SizeExpr = D.ReadOwnedPtr<Expr>(Context);
+  
+  return Context.getDependentSizedArrayType(ElTy,SizeExpr,am,ITQ).getTypePtr();
+}
+
+//===----------------------------------------------------------------------===//
 // IncompleteArrayType
 //===----------------------------------------------------------------------===//
 
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index fbf1120..85b1039 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -191,6 +191,7 @@
   switch (Ty.getTypeClass()) {
   case Type::TypeName:        // typedef isn't canonical.
   case Type::TemplateTypeParm:// template type parameters never generated
+  case Type::DependentSizedArray: // dependent types are never generated
   case Type::TypeOfExp:       // typeof isn't canonical.
   case Type::TypeOfTyp:       // typeof isn't canonical.
     assert(0 && "Non-canonical type, shouldn't happen");
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index c893d27..e581b10 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -870,9 +870,8 @@
 
   if (PrevDecl && isTemplateParameterDecl(PrevDecl)) {
     // Maybe we will complain about the shadowed template parameter.
-    InvalidDecl 
-      = InvalidDecl || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), 
-						       PrevDecl);
+    InvalidDecl = InvalidDecl 
+      || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
     // Just pretend that we didn't see the previous declaration.
     PrevDecl = 0;
   }
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index ec86b9f..e4beb74 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -490,7 +490,52 @@
   }
   // If this reference is not in a block or if the referenced variable is
   // within the block, create a normal DeclRefExpr.
-  return new DeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc);
+
+  // C++ [temp.dep.expr]p3:
+  //   An id-expression is type-dependent if it contains:   
+  bool TypeDependent = false;
+
+  //     - an identifier that was declared with a dependent type,
+  if (VD->getType()->isDependentType())
+    TypeDependent = true;
+  //     - FIXME: a template-id that is dependent,
+  //     - a conversion-function-id that specifies a dependent type,
+  else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName &&
+           Name.getCXXNameType()->isDependentType())
+    TypeDependent = true;
+  //     - a nested-name-specifier that contains a class-name that
+  //       names a dependent type.
+  else if (SS && !SS->isEmpty()) {
+    for (DeclContext *DC = static_cast<DeclContext*>(SS->getScopeRep()); 
+         DC; DC = DC->getParent()) {
+      // FIXME: could stop early at namespace scope.
+      if (DC->isCXXRecord()) {
+        CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
+        if (Context.getTypeDeclType(Record)->isDependentType()) {
+          TypeDependent = true;
+          break;
+        }
+      }
+    }
+  }
+
+  // C++ [temp.dep.constexpr]p2:
+  //
+  //   An identifier is value-dependent if it is:
+  bool ValueDependent = false;
+  
+  //     - a name declared with a dependent type,
+  if (TypeDependent)
+    ValueDependent = true;
+  //     - the name of a non-type template parameter,
+  else if (isa<NonTypeTemplateParmDecl>(VD))
+    ValueDependent = true;
+  //    - a constant with integral or enumeration type and is
+  //      initialized with an expression that is value-dependent
+  //      (FIXME!).
+
+  return new DeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc,
+                         TypeDependent, ValueDependent);
 }
 
 Sema::ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
@@ -1279,6 +1324,11 @@
   FunctionDecl *FDecl = NULL;
   OverloadedFunctionDecl *Ovl = NULL;
 
+  // FIXME: Will need to cache the results of name lookup (including
+  // ADL) in Fn.
+  if (Fn->isTypeDependent() || Expr::hasAnyTypeDependentArguments(Args, NumArgs))
+    return new CallExpr(Fn, Args, NumArgs, Context.DependentTy, RParenLoc);
+
   // If we're directly calling a function or a set of overloaded
   // functions, get the appropriate declaration.
   {
@@ -1318,6 +1368,7 @@
   // of arguments and function on error.
   llvm::OwningPtr<CallExpr> TheCall(new CallExpr(Fn, Args, NumArgs,
                                                  Context.BoolTy, RParenLoc));
+  
   const FunctionType *FuncT;
   if (!Fn->getType()->isBlockPointerType()) {
     // C99 6.5.2.2p1 - "The expression that denotes the called function shall
@@ -1470,6 +1521,8 @@
   // type needs to be scalar.
   if (castType->isVoidType()) {
     // Cast to void allows any expr type.
+  } else if (castType->isDependentType() || castExpr->isTypeDependent()) {
+    // We can't check any more until template instantiation time.
   } else if (!castType->isScalarType() && !castType->isVectorType()) {
     // GCC struct/union extension: allow cast to self.
     if (Context.getCanonicalType(castType) !=
@@ -1541,13 +1594,17 @@
   QualType rexT = rex->getType();
 
   // first, check the condition.
-  if (!condT->isScalarType()) { // C99 6.5.15p2
-    Diag(cond->getLocStart(), diag::err_typecheck_cond_expect_scalar) << condT;
-    return QualType();
+  if (!cond->isTypeDependent()) {
+    if (!condT->isScalarType()) { // C99 6.5.15p2
+      Diag(cond->getLocStart(), diag::err_typecheck_cond_expect_scalar) << condT;
+      return QualType();
+    }
   }
   
   // Now check the two expressions.
-  
+  if ((lex && lex->isTypeDependent()) || (rex && rex->isTypeDependent()))
+    return Context.DependentTy;
+
   // If both operands have arithmetic type, do the usual arithmetic conversions
   // to find a common type: C99 6.5.15p3,5.
   if (lexT->isArithmeticType() && rexT->isArithmeticType()) {
@@ -2959,6 +3016,17 @@
   assert((lhs != 0) && "ActOnBinOp(): missing left expression");
   assert((rhs != 0) && "ActOnBinOp(): missing right expression");
 
+  // If either expression is type-dependent, just build the AST.
+  // FIXME: We'll need to perform some caching of the result of name
+  // lookup for operator+.
+  if (lhs->isTypeDependent() || rhs->isTypeDependent()) {
+    if (Opc > BinaryOperator::Assign && Opc <= BinaryOperator::OrAssign)
+      return new CompoundAssignOperator(lhs, rhs, Opc, Context.DependentTy, 
+                                        Context.DependentTy, TokLoc);
+    else
+      return new BinaryOperator(lhs, rhs, Opc, Context.DependentTy, TokLoc);
+  }
+
   if (getLangOptions().CPlusPlus &&
       (lhs->getType()->isRecordType() || lhs->getType()->isEnumeralType() ||
        rhs->getType()->isRecordType() || rhs->getType()->isEnumeralType())) {
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 1e9b945..c4cab33 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -163,9 +163,9 @@
   //
   if (Ty->isArrayType())
     return Diag(TyBeginLoc, diag::err_value_init_for_array_type) << FullRange;
-  if (Ty->isIncompleteType() && !Ty->isVoidType())
+  if (!Ty->isDependentType() && Ty->isIncompleteType() && !Ty->isVoidType())
     return Diag(TyBeginLoc, diag::err_invalid_incomplete_type_use) 
-      << Ty << FullRange;
+             << Ty << FullRange;
 
   return new CXXZeroInitValueExpr(Ty, TyBeginLoc, RParenLoc);
 }
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 0159f5f..21f897f 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -782,21 +782,23 @@
     return new ReturnStmt(ReturnLoc, (Expr*)0);
   }
   
-  // we have a non-void function with an expression, continue checking
-  QualType RetValType = RetValExp->getType();
-
-  // C99 6.8.6.4p3(136): The return statement is not an assignment. The 
-  // overlap restriction of subclause 6.5.16.1 does not apply to the case of 
-  // function return.  
-
-  // In C++ the return statement is handled via a copy initialization.
-  // the C version of which boils down to
-  // CheckSingleAssignmentConstraints.
-  if (PerformCopyInitialization(RetValExp, FnRetType, "returning"))
-    return true;
+  if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) {
+    // we have a non-void function with an expression, continue checking
+    QualType RetValType = RetValExp->getType();
+    
+    // C99 6.8.6.4p3(136): The return statement is not an assignment. The 
+    // overlap restriction of subclause 6.5.16.1 does not apply to the case of 
+    // function return.  
+    
+    // In C++ the return statement is handled via a copy initialization.
+    // the C version of which boils down to
+    // CheckSingleAssignmentConstraints.
+    if (PerformCopyInitialization(RetValExp, FnRetType, "returning"))
+      return true;
   
-  if (RetValExp) CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
-  
+    if (RetValExp) CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
+  }
+
   return new ReturnStmt(ReturnLoc, (Expr*)RetValExp);
 }
 
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 749d181..092c9d2 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -12,6 +12,7 @@
 //+//===----------------------------------------------------------------------===/
 
 #include "Sema.h"
+#include "clang/AST/Expr.h"
 #include "clang/Parse/DeclSpec.h"
 #include "clang/Basic/LangOptions.h"
 
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 4487c1e..2423e12 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -391,6 +391,8 @@
       llvm::APSInt ConstVal(32);
       if (!ArraySize) {
         T = Context.getIncompleteArrayType(T, ASM, ATI.TypeQuals);
+      } else if (ArraySize->isValueDependent()) {
+        T = Context.getDependentSizedArrayType(T, ArraySize, ASM, ATI.TypeQuals);
       } else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) ||
                  !T->isConstantSizeType()) {
         // Per C99, a variable array is an array with either a non-constant
@@ -416,7 +418,8 @@
       // If this is not C99, extwarn about VLA's and C99 array size modifiers.
       if (!getLangOptions().C99 &&
           (ASM != ArrayType::Normal ||
-           (ArraySize && !ArraySize->isIntegerConstantExpr(Context))))
+           (ArraySize && !ArraySize->isValueDependent() && 
+            !ArraySize->isIntegerConstantExpr(Context))))
         Diag(D.getIdentifierLoc(), diag::ext_vla);
       break;
     }