[cfe-commits] r130669 - in /cfe/trunk: 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 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
John McCall
rjmccall at apple.com
Sun May 1 15:35:37 PDT 2011
Author: rjmccall
Date: Sun May 1 17:35:37 2011
New Revision: 130669
URL: http://llvm.org/viewvc/llvm-project?rev=130669&view=rev
Log:
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.
Added:
cfe/trunk/lib/Sema/Scope.cpp
Modified:
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/include/clang/Sema/Scope.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/AST/ItaniumMangle.cpp
cfe/trunk/lib/AST/StmtProfile.cpp
cfe/trunk/lib/Sema/CMakeLists.txt
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
cfe/trunk/test/CodeGenCXX/mangle-exprs.cpp
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=130669&r1=130668&r2=130669&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Sun May 1 17:35:37 2011
@@ -1137,14 +1137,27 @@
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 @@
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);
}
Modified: cfe/trunk/include/clang/Sema/Scope.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Scope.h?rev=130669&r1=130668&r2=130669&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Scope.h (original)
+++ cfe/trunk/include/clang/Sema/Scope.h Sun May 1 17:35:37 2011
@@ -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 @@
/// 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 @@
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 @@
/// 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
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=130669&r1=130668&r2=130669&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Sun May 1 17:35:37 2011
@@ -4527,6 +4527,7 @@
DeclarationName Entity);
ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D,
const MultiLevelTemplateArgumentList &TemplateArgs,
+ int indexAdjustment,
llvm::Optional<unsigned> NumExpansions);
bool SubstParmTypes(SourceLocation Loc,
ParmVarDecl **Params, unsigned NumParams,
Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=130669&r1=130668&r2=130669&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Sun May 1 17:35:37 2011
@@ -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 @@
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 @@
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 @@
void mangleTemplateArg(const NamedDecl *P, const TemplateArgument &A);
void mangleTemplateParameter(unsigned Index);
+
+ void mangleFunctionParam(const ParmVarDecl *parm);
};
}
@@ -1473,8 +1522,7 @@
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 @@
// 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 @@
Arg != ArgEnd; ++Arg)
mangleType(*Arg);
+ FunctionTypeDepth.pop(saved);
+
// <builtin-type> ::= z # ellipsis
if (Proto->isVariadic())
Out << 'z';
@@ -2227,6 +2286,10 @@
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 @@
}
}
+/// 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 @@
getASTContext().getSourceManager(),
"Mangling declaration");
- CXXNameMangler Mangler(*this, Out);
+ CXXNameMangler Mangler(*this, Out, D);
return Mangler.mangle(D);
}
Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=130669&r1=130668&r2=130669&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Sun May 1 17:35:37 2011
@@ -961,12 +961,16 @@
}
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;
}
Modified: cfe/trunk/lib/Sema/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=130669&r1=130668&r2=130669&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/CMakeLists.txt (original)
+++ cfe/trunk/lib/Sema/CMakeLists.txt Sun May 1 17:35:37 2011
@@ -8,6 +8,7 @@
DelayedDiagnostic.cpp
IdentifierResolver.cpp
JumpDiagnostics.cpp
+ Scope.cpp
Sema.cpp
SemaAccess.cpp
SemaAttr.cpp
Added: cfe/trunk/lib/Sema/Scope.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Scope.cpp?rev=130669&view=auto
==============================================================================
--- cfe/trunk/lib/Sema/Scope.cpp (added)
+++ cfe/trunk/lib/Sema/Scope.cpp Sun May 1 17:35:37 2011
@@ -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();
+}
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=130669&r1=130668&r2=130669&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun May 1 17:35:37 2011
@@ -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);
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=130669&r1=130668&r2=130669&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Sun May 1 17:35:37 2011
@@ -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;
}
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=130669&r1=130668&r2=130669&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sun May 1 17:35:37 2011
@@ -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(
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=130669&r1=130668&r2=130669&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Sun May 1 17:35:37 2011
@@ -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
Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=130669&r1=130668&r2=130669&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Sun May 1 17:35:37 2011
@@ -710,6 +710,8 @@
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++];
Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=130669&r1=130668&r2=130669&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Sun May 1 17:35:37 2011
@@ -587,6 +587,8 @@
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 @@
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
Modified: cfe/trunk/test/CodeGenCXX/mangle-exprs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-exprs.cpp?rev=130669&r1=130668&r2=130669&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-exprs.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-exprs.cpp Sun May 1 17:35:37 2011
@@ -65,3 +65,47 @@
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,
+}
More information about the cfe-commits
mailing list