]> granicus.if.org Git - clang/commitdiff
Store a parameter index and function prototype depth in every
authorJohn McCall <rjmccall@apple.com>
Sun, 1 May 2011 22:35:37 +0000 (22:35 +0000)
committerJohn McCall <rjmccall@apple.com>
Sun, 1 May 2011 22:35:37 +0000 (22:35 +0000)
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

14 files changed:
include/clang/AST/Decl.h
include/clang/Sema/Scope.h
include/clang/Sema/Sema.h
lib/AST/ItaniumMangle.cpp
lib/AST/StmtProfile.cpp
lib/Sema/CMakeLists.txt
lib/Sema/Scope.cpp [new file with mode: 0644]
lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriterDecl.cpp
test/CodeGenCXX/mangle-exprs.cpp

index 04fbe19a92f032bd62dea9d83a9f051d6f1ef2bd..eb89a0d914e0f6ed211da6a74e84f9155314211e 100644 (file)
@@ -1137,14 +1137,27 @@ public:
   static bool classofKind(Kind K) { return K == ImplicitParam; }
 };
 
-/// ParmVarDecl - Represent a parameter to a function.
+/// ParmVarDecl - Represents a parameter to a function.
 class ParmVarDecl : public VarDecl {
+  // FIXME: I'm convinced that there's some reasonable way to encode
+  // these that doesn't require extra storage, but I don't know what
+  // it is right now.
+
+  /// The number of function parameter scopes enclosing the function
+  /// parameter scope in which this parameter was declared.
+  unsigned FunctionScopeDepth : 16;
+
+  /// The number of parameters preceding this parameter in the
+  /// function parameter scope in which it was declared.
+  unsigned FunctionScopeIndex : 16;
+
 protected:
   ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
               SourceLocation IdLoc, IdentifierInfo *Id,
               QualType T, TypeSourceInfo *TInfo,
               StorageClass S, StorageClass SCAsWritten, Expr *DefArg)
-    : VarDecl(DK, DC, StartLoc, IdLoc, Id, T, TInfo, S, SCAsWritten) {
+    : VarDecl(DK, DC, StartLoc, IdLoc, Id, T, TInfo, S, SCAsWritten),
+      FunctionScopeDepth(0), FunctionScopeIndex(0) {
     assert(ParmVarDeclBits.ObjCDeclQualifier == OBJC_TQ_None);
     assert(ParmVarDeclBits.HasInheritedDefaultArg == false);
     assert(ParmVarDeclBits.IsKNRPromoted == false);
@@ -1159,6 +1172,22 @@ public:
                              StorageClass S, StorageClass SCAsWritten,
                              Expr *DefArg);
 
+  void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex) {
+    FunctionScopeDepth = scopeDepth;
+    assert(FunctionScopeDepth == scopeDepth && "truncation!");
+
+    FunctionScopeIndex = parameterIndex;
+    assert(FunctionScopeIndex == parameterIndex && "truncation!");
+  }
+
+  unsigned getFunctionScopeDepth() const {
+    return FunctionScopeDepth;
+  }
+
+  unsigned getFunctionScopeIndex() const {
+    return FunctionScopeIndex;
+  }
+
   ObjCDeclQualifier getObjCDeclQualifier() const {
     return ObjCDeclQualifier(ParmVarDeclBits.ObjCDeclQualifier);
   }
index f70016cbfdbc74626cac48d0024e9b5abcc9ec29..6588a1d92dfa29d4998bbd9b94455332e3657915 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "clang/Basic/Diagnostic.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
 
 namespace clang {
 
@@ -93,6 +94,14 @@ private:
   /// interrelates with other control flow statements.
   unsigned short Flags;
 
+  /// PrototypeDepth - This is the number of function prototype scopes
+  /// enclosing this scope, including this scope.
+  unsigned short PrototypeDepth;
+
+  /// PrototypeIndex - This is the number of parameters currently
+  /// declared in this scope.
+  unsigned short PrototypeIndex;
+
   /// FnParent - If this scope has a parent scope that is a function body, this
   /// pointer is non-null and points to it.  This is used for label processing.
   Scope *FnParent;
@@ -196,6 +205,19 @@ public:
   Scope *getTemplateParamParent() { return TemplateParamParent; }
   const Scope *getTemplateParamParent() const { return TemplateParamParent; }
 
+  /// Returns the number of function prototype scopes in this scope
+  /// chain.
+  unsigned getFunctionPrototypeDepth() const {
+    return PrototypeDepth;
+  }
+
+  /// Return the number of parameters declared in this function
+  /// prototype, increasing it by one for the next call.
+  unsigned getNextFunctionPrototypeIndex() {
+    assert(isFunctionPrototypeScope());
+    return PrototypeIndex++;
+  }
+
   typedef DeclSetTy::iterator decl_iterator;
   decl_iterator decl_begin() const { return DeclsInScope.begin(); }
   decl_iterator decl_end()   const { return DeclsInScope.end(); }
@@ -302,36 +324,7 @@ public:
 
   /// Init - This is used by the parser to implement scope caching.
   ///
-  void Init(Scope *Parent, unsigned ScopeFlags) {
-    AnyParent = Parent;
-    Depth = AnyParent ? AnyParent->Depth+1 : 0;
-    Flags = ScopeFlags;
-    
-    if (AnyParent) {
-      FnParent       = AnyParent->FnParent;
-      BreakParent    = AnyParent->BreakParent;
-      ContinueParent = AnyParent->ContinueParent;
-      ControlParent = AnyParent->ControlParent;
-      BlockParent  = AnyParent->BlockParent;
-      TemplateParamParent = AnyParent->TemplateParamParent;
-    } else {
-      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;
-    DeclsInScope.clear();
-    UsingDirectives.clear();
-    Entity = 0;
-    ErrorTrap.reset();
-  }
+  void Init(Scope *parent, unsigned flags);
 };
 
 }  // end namespace clang
index 7dc42b9c569750233e90d9514717ba03a9f1df1f..07a14d2dca3b271e2110ff477e78eb7797c35327 100644 (file)
@@ -4527,6 +4527,7 @@ public:
                                         DeclarationName Entity);
   ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D,
                             const MultiLevelTemplateArgumentList &TemplateArgs,
+                                int indexAdjustment,
                                 llvm::Optional<unsigned> NumExpansions);
   bool SubstParmTypes(SourceLocation Loc, 
                       ParmVarDecl **Params, unsigned NumParams,
index 04d705eb1ab8fb0a621fd6ca8346d311a334a919..c460929c461d754f2964da63e0bd4688126b58eb 100644 (file)
@@ -21,6 +21,7 @@
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/TypeLoc.h"
 #include "clang/Basic/ABI.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
@@ -50,18 +51,16 @@ static const CXXRecordDecl *GetLocalClassDecl(const NamedDecl *ND) {
   return 0;
 }
 
-static const CXXMethodDecl *getStructor(const CXXMethodDecl *MD) {
-  assert((isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) &&
-         "Passed in decl is not a ctor or dtor!");
+static const FunctionDecl *getStructor(const FunctionDecl *fn) {
+  if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate())
+    return ftd->getTemplatedDecl();
 
-  if (const TemplateDecl *TD = MD->getPrimaryTemplate()) {
-    MD = cast<CXXMethodDecl>(TD->getTemplatedDecl());
-
-    assert((isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) &&
-           "Templated decl is not a ctor or dtor!");
-  }
+  return fn;
+}
 
-  return MD;
+static const NamedDecl *getStructor(const NamedDecl *decl) {
+  const FunctionDecl *fn = dyn_cast_or_null<FunctionDecl>(decl);
+  return (fn ? getStructor(fn) : decl);
 }
 
 static const unsigned UnknownArity = ~0U;
@@ -138,27 +137,75 @@ class CXXNameMangler {
   ItaniumMangleContext &Context;
   llvm::raw_ostream &Out;
 
-  const CXXMethodDecl *Structor;
+  /// The "structor" is the top-level declaration being mangled, if
+  /// that's not a template specialization; otherwise it's the pattern
+  /// for that specialization.
+  const NamedDecl *Structor;
   unsigned StructorType;
 
   /// SeqID - The next subsitution sequence number.
   unsigned SeqID;
 
+  class FunctionTypeDepthState {
+    unsigned Bits;
+
+    enum { InResultTypeMask = 1 };
+
+  public:
+    FunctionTypeDepthState() : Bits(0) {}
+
+    /// The number of function types we're inside.
+    unsigned getDepth() const {
+      return Bits >> 1;
+    }
+
+    /// True if we're in the return type of the innermost function type.
+    bool isInResultType() const {
+      return Bits & InResultTypeMask;
+    }
+
+    FunctionTypeDepthState push() {
+      FunctionTypeDepthState tmp = *this;
+      Bits = (Bits & ~InResultTypeMask) + 2;
+      return tmp;
+    }
+
+    void enterResultType() {
+      Bits |= InResultTypeMask;
+    }
+
+    void leaveResultType() {
+      Bits &= ~InResultTypeMask;
+    }
+
+    void pop(FunctionTypeDepthState saved) {
+      assert(getDepth() == saved.getDepth() + 1);
+      Bits = saved.Bits;
+    }
+
+  } FunctionTypeDepth;
+
   llvm::DenseMap<uintptr_t, unsigned> Substitutions;
 
   ASTContext &getASTContext() const { return Context.getASTContext(); }
 
 public:
-  CXXNameMangler(ItaniumMangleContext &C, llvm::raw_ostream &Out_)
-    : Context(C), Out(Out_), Structor(0), StructorType(0), SeqID(0) { }
+  CXXNameMangler(ItaniumMangleContext &C, llvm::raw_ostream &Out_,
+                 const NamedDecl *D = 0)
+    : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(0),
+      SeqID(0) {
+    // These can't be mangled without a ctor type or dtor type.
+    assert(!D || (!isa<CXXDestructorDecl>(D) &&
+                  !isa<CXXConstructorDecl>(D)));
+  }
   CXXNameMangler(ItaniumMangleContext &C, llvm::raw_ostream &Out_,
                  const CXXConstructorDecl *D, CXXCtorType Type)
     : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
-    SeqID(0) { }
+      SeqID(0) { }
   CXXNameMangler(ItaniumMangleContext &C, llvm::raw_ostream &Out_,
                  const CXXDestructorDecl *D, CXXDtorType Type)
     : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
-    SeqID(0) { }
+      SeqID(0) { }
 
 #if MANGLE_CHECKER
   ~CXXNameMangler() {
@@ -272,6 +319,8 @@ private:
   void mangleTemplateArg(const NamedDecl *P, const TemplateArgument &A);
 
   void mangleTemplateParameter(unsigned Index);
+
+  void mangleFunctionParam(const ParmVarDecl *parm);
 };
 
 }
@@ -1473,8 +1522,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
   case BuiltinType::Dependent:
   case BuiltinType::BoundMember:
   case BuiltinType::UnknownAny:
-    assert(false &&
-           "Overloaded and dependent types shouldn't get to name mangling");
+    llvm_unreachable("mangling a placeholder type");
     break;
   case BuiltinType::ObjCId: Out << "11objc_object"; break;
   case BuiltinType::ObjCClass: Out << "10objc_class"; break;
@@ -1499,13 +1547,22 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionType *T,
   // We should never be mangling something without a prototype.
   const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
 
+  // Record that we're in a function type.  See mangleFunctionParam
+  // for details on what we're trying to achieve here.
+  FunctionTypeDepthState saved = FunctionTypeDepth.push();
+
   // <bare-function-type> ::= <signature type>+
-  if (MangleReturnType)
+  if (MangleReturnType) {
+    FunctionTypeDepth.enterResultType();
     mangleType(Proto->getResultType());
+    FunctionTypeDepth.leaveResultType();
+  }
 
   if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) {
     //   <builtin-type> ::= v   # void
     Out << 'v';
+
+    FunctionTypeDepth.pop(saved);
     return;
   }
 
@@ -1514,6 +1571,8 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionType *T,
        Arg != ArgEnd; ++Arg)
     mangleType(*Arg);
 
+  FunctionTypeDepth.pop(saved);
+
   // <builtin-type>      ::= z  # ellipsis
   if (Proto->isVariadic())
     Out << 'z';
@@ -2227,6 +2286,10 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
       Out << 'E';
       break;
 
+    case Decl::ParmVar:
+      mangleFunctionParam(cast<ParmVarDecl>(D));
+      break;
+
     case Decl::EnumConstant: {
       const EnumConstantDecl *ED = cast<EnumConstantDecl>(D);
       mangleIntegerLiteral(ED->getType(), ED->getInitVal());
@@ -2388,6 +2451,67 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
   }
 }
 
+/// Mangle an expression which refers to a parameter variable.
+///
+/// <expression>     ::= <function-param>
+/// <function-param> ::= fp <top-level CV-qualifiers> _      # L == 0, I == 0
+/// <function-param> ::= fp <top-level CV-qualifiers>
+///                      <parameter-2 non-negative number> _ # L == 0, I > 0
+/// <function-param> ::= fL <L-1 non-negative number>
+///                      p <top-level CV-qualifiers> _       # L > 0, I == 0
+/// <function-param> ::= fL <L-1 non-negative number>
+///                      p <top-level CV-qualifiers>
+///                      <I-1 non-negative number> _         # L > 0, I > 0
+///
+/// L is the nesting depth of the parameter, defined as 1 if the
+/// parameter comes from the innermost function prototype scope
+/// enclosing the current context, 2 if from the next enclosing
+/// function prototype scope, and so on, with one special case: if
+/// we've processed the full parameter clause for the innermost
+/// function type, then L is one less.  This definition conveniently
+/// makes it irrelevant whether a function's result type was written
+/// trailing or leading, but is otherwise overly complicated; the
+/// numbering was first designed without considering references to
+/// parameter in locations other than return types, and then the
+/// mangling had to be generalized without changing the existing
+/// manglings.
+///
+/// I is the zero-based index of the parameter within its parameter
+/// declaration clause.  Note that the original ABI document describes
+/// this using 1-based ordinals.
+void CXXNameMangler::mangleFunctionParam(const ParmVarDecl *parm) {
+  unsigned parmDepth = parm->getFunctionScopeDepth();
+  unsigned parmIndex = parm->getFunctionScopeIndex();
+
+  // Compute 'L'.
+  // parmDepth does not include the declaring function prototype.
+  // FunctionTypeDepth does account for that.
+  assert(parmDepth < FunctionTypeDepth.getDepth());
+  unsigned nestingDepth = FunctionTypeDepth.getDepth() - parmDepth;
+  if (FunctionTypeDepth.isInResultType())
+    nestingDepth--;
+
+  if (nestingDepth == 0) {
+    Out << "fp";
+  } else {
+    Out << "fL" << (nestingDepth - 1) << 'p';
+  }
+
+  // Top-level qualifiers.  We don't have to worry about arrays here,
+  // because parameters declared as arrays should already have been
+  // tranformed to have pointer type. FIXME: apparently these don't
+  // get mangled if used as an rvalue of a known non-class type?
+  assert(!parm->getType()->isArrayType()
+         && "parameter's type is still an array type?");
+  mangleQualifiers(parm->getType().getQualifiers());
+
+  // Parameter index.
+  if (parmIndex != 0) {
+    Out << (parmIndex - 1);
+  }
+  Out << '_';
+}
+
 void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) {
   // <ctor-dtor-name> ::= C1  # complete object constructor
   //                  ::= C2  # base object constructor
@@ -2794,7 +2918,7 @@ void ItaniumMangleContext::mangleName(const NamedDecl *D,
                                  getASTContext().getSourceManager(),
                                  "Mangling declaration");
 
-  CXXNameMangler Mangler(*this, Out);
+  CXXNameMangler Mangler(*this, Out, D);
   return Mangler.mangle(D);
 }
 
index 17383c137a25a5027f0d27b436db1d3aafbfc2ed..44818e8c0847cc29cb1db3a201be57e9c438d049 100644 (file)
@@ -961,12 +961,16 @@ void StmtProfiler::VisitDecl(Decl *D) {
     }
 
     if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
-      // The Itanium C++ ABI uses the type of a parameter when mangling
-      // expressions that involve function parameters, so we will use the
-      // parameter's type for establishing function parameter identity. That
-      // way, our definition of "equivalent" (per C++ [temp.over.link])
-      // matches the definition of "equivalent" used for name mangling.
+      // The Itanium C++ ABI uses the type, scope depth, and scope
+      // index of a parameter when mangling expressions that involve
+      // function parameters, so we will use the parameter's type for
+      // establishing function parameter identity. That way, our
+      // definition of "equivalent" (per C++ [temp.over.link]) is at
+      // least as strong as the definition of "equivalent" used for
+      // name mangling.
       VisitType(Parm->getType());
+      ID.AddInteger(Parm->getFunctionScopeDepth());
+      ID.AddInteger(Parm->getFunctionScopeIndex());
       return;
     }
 
index e1f0cb660babfdf98451da81048075be04ffe902..0a670197d7efa6cdb8b5bf9e841dee53cb73fa87 100644 (file)
@@ -8,6 +8,7 @@ add_clang_library(clangSema
   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 (file)
index 0000000..833a59f
--- /dev/null
@@ -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();
+}
index f589b2d4a9517d282489032b3204fb9b2e0b3e53..7214988bdafc9e027bdfd6fc0904982872713e0a 100644 (file)
@@ -1247,11 +1247,15 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
   // 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 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
                                                  *ParamType, /*TInfo=*/0,
                                                  SC_None, SC_None,
                                                  0);
+        Param->setScopeInfo(0, Params.size());
         Param->setImplicit();
         Params.push_back(Param);
       }
@@ -4431,6 +4436,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
          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 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
                                     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);
index dbe51a825239150c93469c55986598a62a15dcbe..92ba095cd6c84d284e09393ce9802a7677ecf9ef 100644 (file)
@@ -757,6 +757,7 @@ namespace {
     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 @@ QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
 
 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 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
 
 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 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
   // 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;  
 }
index e38ecd43b1095d51c3b8db2352340cbd037b742a..5412d1325a7edf693e958ab8ddaa69e67d1b87b1 100644 (file)
@@ -1468,7 +1468,8 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
 }
 
 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(
index 9f38f2aa3d563029861830cfba561b7226c247c1..2a71e14265a8c7ec481b097b3b8dba417bc75184 100644 (file)
@@ -524,7 +524,11 @@ public:
 
   /// \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 @@ QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB,
 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 @@ TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm,
   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 @@ bool TreeTransform<Derived>::
                               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 @@ bool TreeTransform<Derived>::
             Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
             ParmVarDecl *NewParm 
               = getDerived().TransformFunctionTypeParam(OldParm,
+                                                        indexAdjustment++,
                                                         OrigNumExpansions);
             if (!NewParm)
               return true;
@@ -3792,6 +3805,7 @@ bool TreeTransform<Derived>::
             ForgetPartiallySubstitutedPackRAII Forget(getDerived());
             ParmVarDecl *NewParm 
               = getDerived().TransformFunctionTypeParam(OldParm,
+                                                        indexAdjustment++,
                                                         OrigNumExpansions);
             if (!NewParm)
               return true;
@@ -3801,6 +3815,12 @@ bool TreeTransform<Derived>::
               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 @@ bool TreeTransform<Derived>::
         // 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 @@ bool TreeTransform<Derived>::
       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
index 0645b278ac2b4b1b9831e048968891d595e882aa..665516470e9e3a6b194940e3daa1e468806d6252 100644 (file)
@@ -710,6 +710,8 @@ void ASTDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) {
 
 void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
   VisitVarDecl(PD);
+  unsigned scopeDepth = Record[Idx++], scopeIndex = Record[Idx++];
+  PD->setScopeInfo(scopeDepth, scopeIndex);
   PD->ParmVarDeclBits.ObjCDeclQualifier = (Decl::ObjCDeclQualifier)Record[Idx++];
   PD->ParmVarDeclBits.IsKNRPromoted = Record[Idx++];
   PD->ParmVarDeclBits.HasInheritedDefaultArg = Record[Idx++];
index 31eb003d00633eb991279bdf46edfe3558794351..63cffb243a41d6dd8a85603ee2235c62bfd8f075 100644 (file)
@@ -587,6 +587,8 @@ void ASTDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
 
 void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
   VisitVarDecl(D);
+  Record.push_back(D->getFunctionScopeDepth());
+  Record.push_back(D->getFunctionScopeIndex());
   Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding
   Record.push_back(D->isKNRPromoted());
   Record.push_back(D->hasInheritedDefaultArg());
@@ -1174,6 +1176,8 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
   Abv->Add(BitCodeAbbrevOp(0));                       // HasInit
   Abv->Add(BitCodeAbbrevOp(0));                   // HasMemberSpecializationInfo
   // ParmVarDecl
+  Abv->Add(BitCodeAbbrevOp(0));                       // ScopeDepth
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ScopeIndex
   Abv->Add(BitCodeAbbrevOp(0));                       // ObjCDeclQualifier
   Abv->Add(BitCodeAbbrevOp(0));                       // KNRPromoted
   Abv->Add(BitCodeAbbrevOp(0));                       // HasInheritedDefaultArg
index 5014a9145e889700114bde673cde2382fb3ef410..46c46f04a8a241ef7dfe54a260afc2794d00c909 100644 (file)
@@ -65,3 +65,47 @@ namespace test1 {
     b(s);
   }
 }
+
+namespace test2 {
+  template <class T> void a(T x, decltype(x()) y) {}
+  template <class T> auto b(T x) -> decltype(x()) { return x(); }
+  template <class T> void c(T x, void (*p)(decltype(x()))) {}
+  template <class T> void d(T x, auto (*p)() -> decltype(x())) {}
+  template <class T> void e(auto (*p)(T y) -> decltype(y())) {}
+  template <class T> void f(void (*p)(T x, decltype(x()) y)) {}
+  template <class T> void g(T x, decltype(x()) y) {
+    static decltype(x()) variable;
+    variable = 0;
+  }
+  template <class T> void h(T x, decltype((decltype(x())(*)()) 0) y) {}
+  template <class T> void i(decltype((auto (*)(T x) -> decltype(x())) 0) y) {}
+
+  float foo();
+  void bar(float);
+  float baz(float(*)());
+  void fred(float(*)(), float);
+
+  // CHECK: define void @_ZN5test211instantiateEv
+  void instantiate() {
+    // CHECK: call void @_ZN5test21aIPFfvEEEvT_DTclfL0p_EE(
+    a(foo, 0.0f);
+    // CHECK: call float @_ZN5test21bIPFfvEEEDTclfp_EET_(
+    (void) b(foo);
+    // CHECK: call void @_ZN5test21cIPFfvEEEvT_PFvDTclfL1p_EEE(
+    c(foo, bar);
+    // CHECK: call void @_ZN5test21dIPFfvEEEvT_PFDTclfL0p_EEvE(
+    d(foo, foo);
+    // CHECK: call void @_ZN5test21eIPFfvEEEvPFDTclfp_EET_E(
+    e(baz);
+    // CHECK: call void @_ZN5test21fIPFfvEEEvPFvT_DTclfL0p_EEE(
+    f(fred);
+    // CHECK: call void @_ZN5test21gIPFfvEEEvT_DTclfL0p_EE(
+    g(foo, 0.0f);
+    // CHECK: call void @_ZN5test21hIPFfvEEEvT_DTcvPFDTclfL0p_EEvELi0EE(
+    h(foo, foo);
+    // CHECK: call void @_ZN5test21iIPFfvEEEvDTcvPFDTclfp_EET_ELi0EE(
+    i<float(*)()>(baz);
+  }
+
+  // CHECK: store float {{.*}}, float* @_ZZN5test21gIPFfvEEEvT_DTclfL0p_EEE8variable,
+}