Store a parameter index and function prototype depth in every
parameter node and use this to correctly mangle parameter
references in function template signatures.

A follow-up patch will improve the storage usage of these
fields;  here I've just done the lazy thing.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130669 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index e1f0cb6..0a67019 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -8,6 +8,7 @@
   DelayedDiagnostic.cpp
   IdentifierResolver.cpp
   JumpDiagnostics.cpp
+  Scope.cpp
   Sema.cpp
   SemaAccess.cpp
   SemaAttr.cpp
diff --git a/lib/Sema/Scope.cpp b/lib/Sema/Scope.cpp
new file mode 100644
index 0000000..833a59f
--- /dev/null
+++ b/lib/Sema/Scope.cpp
@@ -0,0 +1,57 @@
+//===- Scope.cpp - Lexical scope information --------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Scope class, which is used for recording
+// information about a lexical scope.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/Scope.h"
+
+using namespace clang;
+
+void Scope::Init(Scope *parent, unsigned flags) {
+  AnyParent = parent;
+  Flags = flags;
+    
+  if (parent) {
+    Depth = parent->Depth + 1;
+    PrototypeDepth = parent->PrototypeDepth;
+    PrototypeIndex = 0;
+    FnParent       = parent->FnParent;
+    BreakParent    = parent->BreakParent;
+    ContinueParent = parent->ContinueParent;
+    ControlParent  = parent->ControlParent;
+    BlockParent    = parent->BlockParent;
+    TemplateParamParent = parent->TemplateParamParent;
+  } else {
+    Depth = 0;
+    PrototypeDepth = 0;
+    PrototypeIndex = 0;
+    FnParent = BreakParent = ContinueParent = BlockParent = 0;
+    ControlParent = 0;
+    TemplateParamParent = 0;
+  }
+
+  // If this scope is a function or contains breaks/continues, remember it.
+  if (flags & FnScope)            FnParent = this;
+  if (flags & BreakScope)         BreakParent = this;
+  if (flags & ContinueScope)      ContinueParent = this;
+  if (flags & ControlScope)       ControlParent = this;
+  if (flags & BlockScope)         BlockParent = this;
+  if (flags & TemplateParamScope) TemplateParamParent = this;
+
+  // If this is a prototype scope, record that.
+  if (flags & FunctionPrototypeScope) PrototypeDepth++;
+
+  DeclsInScope.clear();
+  UsingDirectives.clear();
+  Entity = 0;
+  ErrorTrap.reset();
+}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index f589b2d..7214988 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1247,11 +1247,15 @@
   // FunctionDecl.
   if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(R)) {
     llvm::SmallVector<ParmVarDecl*, 16> Params;
-    for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i)
-      Params.push_back(ParmVarDecl::Create(Context, New, SourceLocation(),
-                                           SourceLocation(), 0,
-                                           FT->getArgType(i), /*TInfo=*/0,
-                                           SC_None, SC_None, 0));
+    for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) {
+      ParmVarDecl *parm =
+        ParmVarDecl::Create(Context, New, SourceLocation(),
+                            SourceLocation(), 0,
+                            FT->getArgType(i), /*TInfo=*/0,
+                            SC_None, SC_None, 0);
+      parm->setScopeInfo(0, i);
+      Params.push_back(parm);
+    }
     New->setParams(Params.data(), Params.size());
   }
 
@@ -1780,6 +1784,7 @@
                                                  *ParamType, /*TInfo=*/0,
                                                  SC_None, SC_None,
                                                  0);
+        Param->setScopeInfo(0, Params.size());
         Param->setImplicit();
         Params.push_back(Param);
       }
@@ -4431,6 +4436,7 @@
          AE = FT->arg_type_end(); AI != AE; ++AI) {
       ParmVarDecl *Param =
         BuildParmVarDeclForTypedef(NewFD, D.getIdentifierLoc(), *AI);
+      Param->setScopeInfo(0, Params.size());
       Params.push_back(Param);
     }
   } else {
@@ -5838,7 +5844,12 @@
                                     StorageClass, StorageClassAsWritten);
 
   if (D.isInvalidType())
-    New->setInvalidDecl();  
+    New->setInvalidDecl();
+
+  assert(S->isFunctionPrototypeScope());
+  assert(S->getFunctionPrototypeDepth() >= 1);
+  New->setScopeInfo(S->getFunctionPrototypeDepth() - 1,
+                    S->getNextFunctionPrototypeIndex());
   
   // Add the parameter declaration into this scope.
   S->AddDecl(New);
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index dbe51a8..92ba095 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -757,6 +757,7 @@
     QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
                                         FunctionProtoTypeLoc TL);
     ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
+                                            int indexAdjustment,
                                       llvm::Optional<unsigned> NumExpansions);
 
     /// \brief Transforms a template type parameter type by performing
@@ -1174,8 +1175,9 @@
 
 ParmVarDecl *
 TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm,
+                                                 int indexAdjustment,
                                        llvm::Optional<unsigned> NumExpansions) {
-  return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs,
+  return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment,
                                   NumExpansions);
 }
 
@@ -1422,6 +1424,7 @@
 
 ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, 
                             const MultiLevelTemplateArgumentList &TemplateArgs,
+                                    int indexAdjustment,
                                     llvm::Optional<unsigned> NumExpansions) {
   TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
   TypeSourceInfo *NewDI = 0;
@@ -1492,6 +1495,9 @@
   // FIXME: OldParm may come from a FunctionProtoType, in which case CurContext
   // can be anything, is this right ?
   NewParm->setDeclContext(CurContext);
+
+  NewParm->setScopeInfo(OldParm->getFunctionScopeDepth(),
+                        OldParm->getFunctionScopeIndex() + indexAdjustment);
   
   return NewParm;  
 }
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e38ecd4..5412d13 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1468,7 +1468,8 @@
 }
 
 ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
-  return SemaRef.SubstParmVarDecl(D, TemplateArgs, llvm::Optional<unsigned>());
+  return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0,
+                                  llvm::Optional<unsigned>());
 }
 
 Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 9f38f2a..2a71e14 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -524,7 +524,11 @@
 
   /// \brief Transforms a single function-type parameter.  Return null
   /// on error.
+  ///
+  /// \param indexAdjustment - A number to add to the parameter's
+  ///   scope index;  can be negative
   ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
+                                          int indexAdjustment,
                                         llvm::Optional<unsigned> NumExpansions);
 
   QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL);
@@ -3682,6 +3686,7 @@
 template<typename Derived>
 ParmVarDecl *
 TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm,
+                                                   int indexAdjustment,
                                        llvm::Optional<unsigned> NumExpansions) {
   TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
   TypeSourceInfo *NewDI = 0;
@@ -3716,19 +3721,22 @@
   if (!NewDI)
     return 0;
 
-  if (NewDI == OldDI)
+  if (NewDI == OldDI && indexAdjustment == 0)
     return OldParm;
-  else
-    return ParmVarDecl::Create(SemaRef.Context,
-                               OldParm->getDeclContext(),
-                               OldParm->getInnerLocStart(),
-                               OldParm->getLocation(),
-                               OldParm->getIdentifier(),
-                               NewDI->getType(),
-                               NewDI,
-                               OldParm->getStorageClass(),
-                               OldParm->getStorageClassAsWritten(),
-                               /* DefArg */ NULL);
+
+  ParmVarDecl *newParm = ParmVarDecl::Create(SemaRef.Context,
+                                             OldParm->getDeclContext(),
+                                             OldParm->getInnerLocStart(),
+                                             OldParm->getLocation(),
+                                             OldParm->getIdentifier(),
+                                             NewDI->getType(),
+                                             NewDI,
+                                             OldParm->getStorageClass(),
+                                             OldParm->getStorageClassAsWritten(),
+                                             /* DefArg */ NULL);
+  newParm->setScopeInfo(OldParm->getFunctionScopeDepth(),
+                        OldParm->getFunctionScopeIndex() + indexAdjustment);
+  return newParm;
 }
 
 template<typename Derived>
@@ -3738,8 +3746,12 @@
                               const QualType *ParamTypes,
                               llvm::SmallVectorImpl<QualType> &OutParamTypes,
                               llvm::SmallVectorImpl<ParmVarDecl*> *PVars) {
+  int indexAdjustment = 0;
+
   for (unsigned i = 0; i != NumParams; ++i) {
     if (ParmVarDecl *OldParm = Params[i]) {
+      assert(OldParm->getFunctionScopeIndex() == i);
+
       llvm::Optional<unsigned> NumExpansions;
       ParmVarDecl *NewParm = 0;
       if (OldParm->isParameterPack()) {
@@ -3777,6 +3789,7 @@
             Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
             ParmVarDecl *NewParm 
               = getDerived().TransformFunctionTypeParam(OldParm,
+                                                        indexAdjustment++,
                                                         OrigNumExpansions);
             if (!NewParm)
               return true;
@@ -3792,6 +3805,7 @@
             ForgetPartiallySubstitutedPackRAII Forget(getDerived());
             ParmVarDecl *NewParm 
               = getDerived().TransformFunctionTypeParam(OldParm,
+                                                        indexAdjustment++,
                                                         OrigNumExpansions);
             if (!NewParm)
               return true;
@@ -3801,6 +3815,12 @@
               PVars->push_back(NewParm);
           }
 
+          // The next parameter should have the same adjustment as the
+          // last thing we pushed, but we post-incremented indexAdjustment
+          // on every push.  Also, if we push nothing, the adjustment should
+          // go down by one.
+          indexAdjustment--;
+
           // We're done with the pack expansion.
           continue;
         }
@@ -3809,9 +3829,11 @@
         // expansion.
         Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
         NewParm = getDerived().TransformFunctionTypeParam(OldParm,
+                                                          indexAdjustment,
                                                           NumExpansions);
       } else {
         NewParm = getDerived().TransformFunctionTypeParam(OldParm,
+                                                          indexAdjustment,
                                                   llvm::Optional<unsigned>());
       }
 
@@ -3902,8 +3924,16 @@
       PVars->push_back(0);
   }
 
-  return false;
+#ifndef NDEBUG
+  if (PVars) {
+    for (unsigned i = 0, e = PVars->size(); i != e; ++i)
+      if (ParmVarDecl *parm = (*PVars)[i])
+        assert(parm->getFunctionScopeIndex() == i);
   }
+#endif
+
+  return false;
+}
 
 template<typename Derived>
 QualType