diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/Sema/Sema.h | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 16 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 62 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 111 | ||||
| -rw-r--r-- | clang/lib/Sema/TreeTransform.h | 96 | 
6 files changed, 193 insertions, 95 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index a94d07a6acc..c9f39e2b992 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -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, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 94fcfc6c29e..76081992027 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -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 { diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e694cb470c2..830d2e5eef9 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2392,22 +2392,26 @@ 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);      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);    } diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 8f73337e436..19c257d5b7c 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -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,  diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index cf8d38c0958..e8bcb8be89b 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -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(), -                                                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 diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 17f94193fed..61091cdcc04 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -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); @@ -2520,18 +2535,33 @@ QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB,  }  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 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,      ParmVarDecl *NewParm;      if (OldParm) { -      TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); -      assert(OldDI->getType() == T->getArgType(i)); +      assert(OldParm->getTypeSourceInfo()->getType() == T->getArgType(i)); -      TypeSourceInfo *NewDI = getDerived().TransformType(OldDI); -      if (!NewDI) -        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); +      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 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,        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() ||  | 

