[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