Introduce the notion of instantiation dependence into Clang's AST. A
type/expression/template argument/etc. is instantiation-dependent if
it somehow involves a template parameter, even if it doesn't meet the
requirements for the more common kinds of dependence (dependent type,
type-dependent expression, value-dependent expression).

When we see an instantiation-dependent type, we know we always need to
perform substitution into that instantiation-dependent type. This
keeps us from short-circuiting evaluation in places where we
shouldn't, and lets us properly implement C++0x [temp.type]p2.

In theory, this would also allow us to properly mangle
instantiation-dependent-but-not-dependent decltype types per the
Itanium C++ ABI, but we aren't quite there because we still mangle
based on the canonical type in cases like, e.g.,

  template<unsigned> struct A { };
  template<typename T>
    void f(A<sizeof(sizeof(decltype(T() + T())))>) { }
  template void f<int>(A<sizeof(sizeof(int))>);

and therefore get the wrong answer.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134225 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 103da1d..56c6e7b 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -104,6 +104,45 @@
   return false;
 }
 
+bool TemplateArgument::isInstantiationDependent() const {
+  switch (getKind()) {
+  case Null:
+    assert(false && "Should not have a NULL template argument");
+    return false;
+    
+  case Type:
+    return getAsType()->isInstantiationDependentType();
+    
+  case Template:
+    return getAsTemplate().isInstantiationDependent();
+    
+  case TemplateExpansion:
+    return true;
+    
+  case Declaration:
+    if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
+      return DC->isDependentContext();
+    return getAsDecl()->getDeclContext()->isDependentContext();
+    
+  case Integral:
+    // Never dependent
+    return false;
+    
+  case Expression:
+    return getAsExpr()->isInstantiationDependent();
+    
+  case Pack:
+    for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
+      if (P->isInstantiationDependent())
+        return true;
+    }
+    
+    return false;
+  }
+  
+  return false;
+}
+
 bool TemplateArgument::isPackExpansion() const {
   switch (getKind()) {
   case Null: