[cfe-commits] r98252 - in /cfe/trunk/lib/Sema: Sema.h SemaDecl.cpp SemaDeclCXX.cpp SemaTemplateInstantiate.cpp SemaTemplateInstantiateDecl.cpp TreeTransform.h
John McCall
rjmccall at apple.com
Thu Mar 11 01:03:00 PST 2010
Author: rjmccall
Date: Thu Mar 11 03:03:00 2010
New Revision: 98252
URL: http://llvm.org/viewvc/llvm-project?rev=98252&view=rev
Log:
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).
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/lib/Sema/TreeTransform.h
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=98252&r1=98251&r2=98252&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Mar 11 03:03:00 2010
@@ -3593,6 +3593,8 @@
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,
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=98252&r1=98251&r2=98252&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Mar 11 03:03:00 2010
@@ -2718,6 +2718,7 @@
D.getIdentifierLoc(), Name, R,
isInline,
/*isImplicitlyDeclared=*/false);
+ NewFD->setTypeSourceInfo(TInfo);
isVirtualOkay = true;
} else {
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=98252&r1=98251&r2=98252&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Mar 11 03:03:00 2010
@@ -2392,22 +2392,26 @@
// 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);
Destructor->setImplicit();
Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
ClassDecl->addDecl(Destructor);
+
+ // This could be uniqued if it ever proves significant.
+ Destructor->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(Ty));
AddOverriddenMethods(ClassDecl, Destructor);
}
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=98252&r1=98251&r2=98252&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Mar 11 03:03:00 2010
@@ -567,6 +567,15 @@
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 @@
}
+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,
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=98252&r1=98251&r2=98252&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Mar 11 03:03:00 2010
@@ -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 @@
}
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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(),
- PInst->getType(),
- diag::err_abstract_type_in_decl,
- Sema::AbstractParamType))
+ Invalid = true;
+ }
+ else if (RequireNonAbstractType(PInst->getLocation(),
+ PInst->getType(),
+ diag::err_abstract_type_in_decl,
+ Sema::AbstractParamType)) {
PInst->setInvalidDecl();
+ Invalid = true;
+ }
+ }
+ return Invalid;
+}
- Params.push_back(PInst);
- ParamTys.push_back(PInst->getType());
+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;
- if (PInst->isInvalidDecl())
- InvalidDecl = true;
- } else
- InvalidDecl = true;
- }
+ // 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));
- // FIXME: Deallocate dead declarations.
- if (InvalidDecl)
- return QualType();
-
- 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();
-
- 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
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=98252&r1=98251&r2=98252&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Mar 11 03:03:00 2010
@@ -315,6 +315,21 @@
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);
@@ -2520,18 +2535,33 @@
}
template<typename Derived>
-QualType
-TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
- FunctionProtoTypeLoc TL,
- QualType ObjectType) {
+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();
- QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
- if (ResultType.isNull())
- return QualType();
- // 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);
@@ -2539,24 +2569,11 @@
ParmVarDecl *NewParm;
if (OldParm) {
- TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
- assert(OldDI->getType() == T->getArgType(i));
-
- TypeSourceInfo *NewDI = getDerived().TransformType(OldDI);
- if (!NewDI)
- return QualType();
+ assert(OldParm->getTypeSourceInfo()->getType() == T->getArgType(i));
- if (NewDI == OldDI)
- NewParm = OldParm;
- else
- NewParm = ParmVarDecl::Create(SemaRef.Context,
- OldParm->getDeclContext(),
- OldParm->getLocation(),
- OldParm->getIdentifier(),
- NewDI->getType(),
- NewDI,
- OldParm->getStorageClass(),
- /* DefArg */ NULL);
+ NewParm = getDerived().TransformFunctionTypeParam(OldParm);
+ if (!NewParm)
+ return true;
NewType = NewParm->getType();
// Deal with the possibility that we don't have a parameter
@@ -2567,13 +2584,32 @@
QualType OldType = T->getArgType(i);
NewType = getDerived().TransformType(OldType);
if (NewType.isNull())
- return QualType();
+ return true;
}
- ParamTypes.push_back(NewType);
- ParamDecls.push_back(NewParm);
+ PTypes.push_back(NewType);
+ PVars.push_back(NewParm);
}
+ return false;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL,
+ QualType ObjectType) {
+ FunctionProtoType *T = TL.getTypePtr();
+ QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+ if (ResultType.isNull())
+ return QualType();
+
+ // Transform the parameters.
+ llvm::SmallVector<QualType, 4> ParamTypes;
+ llvm::SmallVector<ParmVarDecl*, 4> ParamDecls;
+ if (getDerived().TransformFunctionTypeParams(TL, ParamTypes, ParamDecls))
+ return QualType();
+
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() ||
ResultType != T->getResultType() ||
More information about the cfe-commits
mailing list