forked from OSchip/llvm-project
Maintain type source information for functions through template
instantiation. Based on a patch by Enea Zaffanella! I found a way to reduce some of the redundancy between TreeTransform's "standard" FunctionProtoType transformation and TemplateInstantiator's override, and I killed off the old SubstFunctionType by adding type source info for the last cases where we were creating FunctionDecls without TSI (at least that get passed through template instantiation). llvm-svn: 98252
This commit is contained in:
parent
8c4df8160e
commit
58f10c3380
|
@ -3593,6 +3593,8 @@ public:
|
|||
DeclContext *FindInstantiatedContext(SourceLocation Loc, DeclContext *DC,
|
||||
const MultiLevelTemplateArgumentList &TemplateArgs);
|
||||
|
||||
bool CheckInstantiatedParams(llvm::SmallVectorImpl<ParmVarDecl *> &Params);
|
||||
|
||||
// Objective-C declarations.
|
||||
virtual DeclPtrTy ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
||||
IdentifierInfo *ClassName,
|
||||
|
|
|
@ -2718,6 +2718,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
D.getIdentifierLoc(), Name, R,
|
||||
isInline,
|
||||
/*isImplicitlyDeclared=*/false);
|
||||
NewFD->setTypeSourceInfo(TInfo);
|
||||
|
||||
isVirtualOkay = true;
|
||||
} else {
|
||||
|
|
|
@ -2392,16 +2392,17 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
|
|||
// If a class has no user-declared destructor, a destructor is
|
||||
// declared implicitly. An implicitly-declared destructor is an
|
||||
// inline public member of its class.
|
||||
QualType Ty = Context.getFunctionType(Context.VoidTy,
|
||||
0, 0, false, 0,
|
||||
/*FIXME:*/false,
|
||||
false, 0, 0, false,
|
||||
CC_Default);
|
||||
|
||||
DeclarationName Name
|
||||
= Context.DeclarationNames.getCXXDestructorName(ClassType);
|
||||
CXXDestructorDecl *Destructor
|
||||
= CXXDestructorDecl::Create(Context, ClassDecl,
|
||||
ClassDecl->getLocation(), Name,
|
||||
Context.getFunctionType(Context.VoidTy,
|
||||
0, 0, false, 0,
|
||||
/*FIXME:*/false,
|
||||
false, 0, 0, false,
|
||||
CC_Default),
|
||||
ClassDecl->getLocation(), Name, Ty,
|
||||
/*isInline=*/true,
|
||||
/*isImplicitlyDeclared=*/true);
|
||||
Destructor->setAccess(AS_public);
|
||||
|
@ -2409,6 +2410,9 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
|
|||
Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
|
||||
ClassDecl->addDecl(Destructor);
|
||||
|
||||
// This could be uniqued if it ever proves significant.
|
||||
Destructor->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(Ty));
|
||||
|
||||
AddOverriddenMethods(ClassDecl, Destructor);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -567,6 +567,15 @@ namespace {
|
|||
Sema::OwningExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
|
||||
NonTypeTemplateParmDecl *D);
|
||||
|
||||
/// \brief Transforms a function proto type by performing
|
||||
/// substitution in the function parameters, possibly adjusting
|
||||
/// their types and marking default arguments as uninstantiated.
|
||||
bool TransformFunctionTypeParams(FunctionProtoTypeLoc TL,
|
||||
llvm::SmallVectorImpl<QualType> &PTypes,
|
||||
llvm::SmallVectorImpl<ParmVarDecl*> &PVars);
|
||||
|
||||
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm);
|
||||
|
||||
/// \brief Transforms a template type parameter type by performing
|
||||
/// substitution of the corresponding template type argument.
|
||||
QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
|
||||
|
@ -859,6 +868,59 @@ Sema::OwningExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
|
|||
}
|
||||
|
||||
|
||||
bool
|
||||
TemplateInstantiator::TransformFunctionTypeParams(FunctionProtoTypeLoc TL,
|
||||
llvm::SmallVectorImpl<QualType> &PTypes,
|
||||
llvm::SmallVectorImpl<ParmVarDecl*> &PVars) {
|
||||
// Create a local instantiation scope for the parameters.
|
||||
Sema::LocalInstantiationScope
|
||||
Scope(SemaRef, SemaRef.CurrentInstantiationScope != 0);
|
||||
|
||||
if (TreeTransform<TemplateInstantiator>::
|
||||
TransformFunctionTypeParams(TL, PTypes, PVars))
|
||||
return true;
|
||||
|
||||
// Check instantiated parameters.
|
||||
if (SemaRef.CheckInstantiatedParams(PVars))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ParmVarDecl *
|
||||
TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm) {
|
||||
TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
|
||||
TypeSourceInfo *NewDI = getDerived().TransformType(OldDI);
|
||||
if (!NewDI)
|
||||
return 0;
|
||||
|
||||
// TODO: do we have to clone this decl if the types match and
|
||||
// there's no default argument?
|
||||
|
||||
ParmVarDecl *NewParm
|
||||
= ParmVarDecl::Create(SemaRef.Context,
|
||||
OldParm->getDeclContext(),
|
||||
OldParm->getLocation(),
|
||||
OldParm->getIdentifier(),
|
||||
NewDI->getType(),
|
||||
NewDI,
|
||||
OldParm->getStorageClass(),
|
||||
/* DefArg */ NULL);
|
||||
|
||||
// Maybe adjust new parameter type.
|
||||
NewParm->setType(SemaRef.adjustParameterType(NewParm->getType()));
|
||||
|
||||
// Mark the (new) default argument as uninstantiated (if any).
|
||||
if (OldParm->hasUninstantiatedDefaultArg()) {
|
||||
Expr *Arg = OldParm->getUninstantiatedDefaultArg();
|
||||
NewParm->setUninstantiatedDefaultArg(Arg);
|
||||
} else if (Expr *Arg = OldParm->getDefaultArg())
|
||||
NewParm->setUninstantiatedDefaultArg(Arg);
|
||||
|
||||
SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParm, NewParm);
|
||||
return NewParm;
|
||||
}
|
||||
|
||||
QualType
|
||||
TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
|
||||
TemplateTypeParmTypeLoc TL,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "clang/AST/DeclVisitor.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
#include "clang/AST/TypeLoc.h"
|
||||
#include "clang/Basic/PrettyStackTrace.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
|
||||
|
@ -89,7 +90,7 @@ namespace {
|
|||
}
|
||||
|
||||
// Helper functions for instantiating methods.
|
||||
QualType SubstFunctionType(FunctionDecl *D,
|
||||
TypeSourceInfo *SubstFunctionType(FunctionDecl *D,
|
||||
llvm::SmallVectorImpl<ParmVarDecl *> &Params);
|
||||
bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl);
|
||||
bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);
|
||||
|
@ -797,9 +798,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
|
|||
Sema::LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
|
||||
|
||||
llvm::SmallVector<ParmVarDecl *, 4> Params;
|
||||
QualType T = SubstFunctionType(D, Params);
|
||||
if (T.isNull())
|
||||
TypeSourceInfo *TInfo = D->getTypeSourceInfo();
|
||||
TInfo = SubstFunctionType(D, Params);
|
||||
if (!TInfo)
|
||||
return 0;
|
||||
QualType T = TInfo->getType();
|
||||
|
||||
// If we're instantiating a local function declaration, put the result
|
||||
// in the owner; otherwise we need to find the instantiated context.
|
||||
|
@ -812,7 +815,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
|
|||
|
||||
FunctionDecl *Function =
|
||||
FunctionDecl::Create(SemaRef.Context, DC, D->getLocation(),
|
||||
D->getDeclName(), T, D->getTypeSourceInfo(),
|
||||
D->getDeclName(), T, TInfo,
|
||||
D->getStorageClass(),
|
||||
D->isInlineSpecified(), D->hasWrittenPrototype());
|
||||
Function->setLexicalDeclContext(Owner);
|
||||
|
@ -932,9 +935,11 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
|
|||
Sema::LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
|
||||
|
||||
llvm::SmallVector<ParmVarDecl *, 4> Params;
|
||||
QualType T = SubstFunctionType(D, Params);
|
||||
if (T.isNull())
|
||||
TypeSourceInfo *TInfo = D->getTypeSourceInfo();
|
||||
TInfo = SubstFunctionType(D, Params);
|
||||
if (!TInfo)
|
||||
return 0;
|
||||
QualType T = TInfo->getType();
|
||||
|
||||
// Build the instantiated method declaration.
|
||||
CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
|
||||
|
@ -947,8 +952,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
|
|||
SemaRef.Context.getCanonicalType(ClassTy));
|
||||
Method = CXXConstructorDecl::Create(SemaRef.Context, Record,
|
||||
Constructor->getLocation(),
|
||||
Name, T,
|
||||
Constructor->getTypeSourceInfo(),
|
||||
Name, T, TInfo,
|
||||
Constructor->isExplicit(),
|
||||
Constructor->isInlineSpecified(), false);
|
||||
} else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
|
||||
|
@ -966,12 +970,12 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
|
|||
ConvTy);
|
||||
Method = CXXConversionDecl::Create(SemaRef.Context, Record,
|
||||
Conversion->getLocation(), Name,
|
||||
T, Conversion->getTypeSourceInfo(),
|
||||
T, TInfo,
|
||||
Conversion->isInlineSpecified(),
|
||||
Conversion->isExplicit());
|
||||
} else {
|
||||
Method = CXXMethodDecl::Create(SemaRef.Context, Record, D->getLocation(),
|
||||
D->getDeclName(), T, D->getTypeSourceInfo(),
|
||||
D->getDeclName(), T, TInfo,
|
||||
D->isStatic(), D->isInlineSpecified());
|
||||
}
|
||||
|
||||
|
@ -1514,60 +1518,49 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
|
|||
return false;
|
||||
}
|
||||
|
||||
/// \brief Does substitution on the type of the given function, including
|
||||
/// all of the function parameters.
|
||||
///
|
||||
/// \param D The function whose type will be the basis of the substitution
|
||||
///
|
||||
/// \param Params the instantiated parameter declarations
|
||||
|
||||
/// \returns the instantiated function's type if successful, a NULL
|
||||
/// type if there was an error.
|
||||
QualType
|
||||
TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
|
||||
llvm::SmallVectorImpl<ParmVarDecl *> &Params) {
|
||||
bool InvalidDecl = false;
|
||||
|
||||
// Substitute all of the function's formal parameter types.
|
||||
TemplateDeclInstantiator ParamInstantiator(SemaRef, 0, TemplateArgs);
|
||||
llvm::SmallVector<QualType, 4> ParamTys;
|
||||
for (FunctionDecl::param_iterator P = D->param_begin(),
|
||||
PEnd = D->param_end();
|
||||
P != PEnd; ++P) {
|
||||
if (ParmVarDecl *PInst = ParamInstantiator.VisitParmVarDecl(*P)) {
|
||||
if (PInst->getType()->isVoidType()) {
|
||||
SemaRef.Diag(PInst->getLocation(), diag::err_param_with_void_type);
|
||||
bool
|
||||
Sema::CheckInstantiatedParams(llvm::SmallVectorImpl<ParmVarDecl*> &Params) {
|
||||
bool Invalid = false;
|
||||
for (unsigned i = 0, i_end = Params.size(); i != i_end; ++i)
|
||||
if (ParmVarDecl *PInst = Params[i]) {
|
||||
if (PInst->isInvalidDecl())
|
||||
Invalid = true;
|
||||
else if (PInst->getType()->isVoidType()) {
|
||||
Diag(PInst->getLocation(), diag::err_param_with_void_type);
|
||||
PInst->setInvalidDecl();
|
||||
} else if (SemaRef.RequireNonAbstractType(PInst->getLocation(),
|
||||
Invalid = true;
|
||||
}
|
||||
else if (RequireNonAbstractType(PInst->getLocation(),
|
||||
PInst->getType(),
|
||||
diag::err_abstract_type_in_decl,
|
||||
Sema::AbstractParamType))
|
||||
Sema::AbstractParamType)) {
|
||||
PInst->setInvalidDecl();
|
||||
|
||||
Params.push_back(PInst);
|
||||
ParamTys.push_back(PInst->getType());
|
||||
|
||||
if (PInst->isInvalidDecl())
|
||||
InvalidDecl = true;
|
||||
} else
|
||||
InvalidDecl = true;
|
||||
Invalid = true;
|
||||
}
|
||||
}
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
// FIXME: Deallocate dead declarations.
|
||||
if (InvalidDecl)
|
||||
return QualType();
|
||||
TypeSourceInfo*
|
||||
TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
|
||||
llvm::SmallVectorImpl<ParmVarDecl *> &Params) {
|
||||
TypeSourceInfo *OldTInfo = D->getTypeSourceInfo();
|
||||
assert(OldTInfo && "substituting function without type source info");
|
||||
assert(Params.empty() && "parameter vector is non-empty at start");
|
||||
TypeSourceInfo *NewTInfo = SemaRef.SubstType(OldTInfo, TemplateArgs,
|
||||
D->getTypeSpecStartLoc(),
|
||||
D->getDeclName());
|
||||
if (!NewTInfo)
|
||||
return 0;
|
||||
|
||||
const FunctionProtoType *Proto = D->getType()->getAs<FunctionProtoType>();
|
||||
assert(Proto && "Missing prototype?");
|
||||
QualType ResultType
|
||||
= SemaRef.SubstType(Proto->getResultType(), TemplateArgs,
|
||||
D->getLocation(), D->getDeclName());
|
||||
if (ResultType.isNull())
|
||||
return QualType();
|
||||
// Get parameters from the new type info.
|
||||
TypeLoc NewTL = NewTInfo->getTypeLoc();
|
||||
FunctionProtoTypeLoc *NewProtoLoc = cast<FunctionProtoTypeLoc>(&NewTL);
|
||||
assert(NewProtoLoc && "Missing prototype?");
|
||||
for (unsigned i = 0, i_end = NewProtoLoc->getNumArgs(); i != i_end; ++i)
|
||||
Params.push_back(NewProtoLoc->getArg(i));
|
||||
|
||||
return SemaRef.BuildFunctionType(ResultType, ParamTys.data(), ParamTys.size(),
|
||||
Proto->isVariadic(), Proto->getTypeQuals(),
|
||||
D->getLocation(), D->getDeclName());
|
||||
return NewTInfo;
|
||||
}
|
||||
|
||||
/// \brief Initializes the common fields of an instantiation function
|
||||
|
|
|
@ -315,6 +315,21 @@ public:
|
|||
QualType ObjectType = QualType());
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
|
||||
/// \brief Transforms the parameters of a function type into the
|
||||
/// given vectors.
|
||||
///
|
||||
/// The result vectors should be kept in sync; null entries in the
|
||||
/// variables vector are acceptable.
|
||||
///
|
||||
/// Return true on error.
|
||||
bool TransformFunctionTypeParams(FunctionProtoTypeLoc TL,
|
||||
llvm::SmallVectorImpl<QualType> &PTypes,
|
||||
llvm::SmallVectorImpl<ParmVarDecl*> &PVars);
|
||||
|
||||
/// \brief Transforms a single function-type parameter. Return null
|
||||
/// on error.
|
||||
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm);
|
||||
|
||||
QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL,
|
||||
QualType ObjectType);
|
||||
|
||||
|
@ -2519,6 +2534,66 @@ QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB,
|
|||
return Result;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
ParmVarDecl *
|
||||
TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm) {
|
||||
TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
|
||||
TypeSourceInfo *NewDI = getDerived().TransformType(OldDI);
|
||||
if (!NewDI)
|
||||
return 0;
|
||||
|
||||
if (NewDI == OldDI)
|
||||
return OldParm;
|
||||
else
|
||||
return ParmVarDecl::Create(SemaRef.Context,
|
||||
OldParm->getDeclContext(),
|
||||
OldParm->getLocation(),
|
||||
OldParm->getIdentifier(),
|
||||
NewDI->getType(),
|
||||
NewDI,
|
||||
OldParm->getStorageClass(),
|
||||
/* DefArg */ NULL);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
bool TreeTransform<Derived>::
|
||||
TransformFunctionTypeParams(FunctionProtoTypeLoc TL,
|
||||
llvm::SmallVectorImpl<QualType> &PTypes,
|
||||
llvm::SmallVectorImpl<ParmVarDecl*> &PVars) {
|
||||
FunctionProtoType *T = TL.getTypePtr();
|
||||
|
||||
for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
|
||||
ParmVarDecl *OldParm = TL.getArg(i);
|
||||
|
||||
QualType NewType;
|
||||
ParmVarDecl *NewParm;
|
||||
|
||||
if (OldParm) {
|
||||
assert(OldParm->getTypeSourceInfo()->getType() == T->getArgType(i));
|
||||
|
||||
NewParm = getDerived().TransformFunctionTypeParam(OldParm);
|
||||
if (!NewParm)
|
||||
return true;
|
||||
NewType = NewParm->getType();
|
||||
|
||||
// Deal with the possibility that we don't have a parameter
|
||||
// declaration for this parameter.
|
||||
} else {
|
||||
NewParm = 0;
|
||||
|
||||
QualType OldType = T->getArgType(i);
|
||||
NewType = getDerived().TransformType(OldType);
|
||||
if (NewType.isNull())
|
||||
return true;
|
||||
}
|
||||
|
||||
PTypes.push_back(NewType);
|
||||
PVars.push_back(NewParm);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
QualType
|
||||
TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
|
||||
|
@ -2532,48 +2607,9 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
|
|||
// Transform the parameters.
|
||||
llvm::SmallVector<QualType, 4> ParamTypes;
|
||||
llvm::SmallVector<ParmVarDecl*, 4> ParamDecls;
|
||||
for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
|
||||
ParmVarDecl *OldParm = TL.getArg(i);
|
||||
|
||||
QualType NewType;
|
||||
ParmVarDecl *NewParm;
|
||||
|
||||
if (OldParm) {
|
||||
TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
|
||||
assert(OldDI->getType() == T->getArgType(i));
|
||||
|
||||
TypeSourceInfo *NewDI = getDerived().TransformType(OldDI);
|
||||
if (!NewDI)
|
||||
if (getDerived().TransformFunctionTypeParams(TL, ParamTypes, ParamDecls))
|
||||
return QualType();
|
||||
|
||||
if (NewDI == OldDI)
|
||||
NewParm = OldParm;
|
||||
else
|
||||
NewParm = ParmVarDecl::Create(SemaRef.Context,
|
||||
OldParm->getDeclContext(),
|
||||
OldParm->getLocation(),
|
||||
OldParm->getIdentifier(),
|
||||
NewDI->getType(),
|
||||
NewDI,
|
||||
OldParm->getStorageClass(),
|
||||
/* DefArg */ NULL);
|
||||
NewType = NewParm->getType();
|
||||
|
||||
// Deal with the possibility that we don't have a parameter
|
||||
// declaration for this parameter.
|
||||
} else {
|
||||
NewParm = 0;
|
||||
|
||||
QualType OldType = T->getArgType(i);
|
||||
NewType = getDerived().TransformType(OldType);
|
||||
if (NewType.isNull())
|
||||
return QualType();
|
||||
}
|
||||
|
||||
ParamTypes.push_back(NewType);
|
||||
ParamDecls.push_back(NewParm);
|
||||
}
|
||||
|
||||
QualType Result = TL.getType();
|
||||
if (getDerived().AlwaysRebuild() ||
|
||||
ResultType != T->getResultType() ||
|
||||
|
|
Loading…
Reference in New Issue