diff options
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
| -rw-r--r-- | lib/Sema/SemaTemplate.cpp | 238 | 
1 files changed, 190 insertions, 48 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 51ce2a1345a5..c8e45016671d 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -354,12 +354,14 @@ void Sema::LookupTemplateName(LookupResult &Found,      return;    } -  if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope) { -    // C++ [basic.lookup.classref]p1: +  if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope && +      !(getLangOpts().CPlusPlus0x && !Found.empty())) { +    // C++03 [basic.lookup.classref]p1:      //   [...] If the lookup in the class of the object expression finds a      //   template, the name is also looked up in the context of the entire      //   postfix-expression and [...]      // +    // Note: C++11 does not perform this second lookup.      LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(),                              LookupOrdinaryName);      LookupName(FoundOuter, S); @@ -743,7 +745,7 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,  }  /// ActOnTemplateTemplateParameter - Called when a C++ template template -/// parameter (e.g. T in template <template <typename> class T> class array) +/// parameter (e.g. T in template <template \<typename> class T> class array)  /// has been parsed. S is the current scope.  Decl *Sema::ActOnTemplateTemplateParameter(Scope* S,                                             SourceLocation TmpLoc, @@ -865,9 +867,13 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,      return true;    } -  // Find any previous declaration with this name. +  // Find any previous declaration with this name. For a friend with no +  // scope explicitly specified, we only look for tag declarations (per +  // C++11 [basic.lookup.elab]p2).    DeclContext *SemanticContext; -  LookupResult Previous(*this, Name, NameLoc, LookupOrdinaryName, +  LookupResult Previous(*this, Name, NameLoc, +                        (SS.isEmpty() && TUK == TUK_Friend) +                          ? LookupTagName : LookupOrdinaryName,                          ForRedeclaration);    if (SS.isNotEmpty() && !SS.isInvalid()) {      SemanticContext = computeDeclContext(SS, true); @@ -893,7 +899,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,          Invalid = true;      } else if (TUK != TUK_Friend && TUK != TUK_Reference)        diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc); -         +      LookupQualifiedName(Previous, SemanticContext);    } else {      SemanticContext = CurContext; @@ -948,22 +954,32 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,          // declaration.          PrevDecl = PrevClassTemplate = 0;          SemanticContext = OutermostContext; -      } -    } -    if (CurContext->isDependentContext()) { -      // If this is a dependent context, we don't want to link the friend -      // class template to the template in scope, because that would perform -      // checking of the template parameter lists that can't be performed -      // until the outer context is instantiated. -      PrevDecl = PrevClassTemplate = 0; +        // Check that the chosen semantic context doesn't already contain a +        // declaration of this name as a non-tag type. +        LookupResult Previous(*this, Name, NameLoc, LookupOrdinaryName, +                              ForRedeclaration); +        DeclContext *LookupContext = SemanticContext; +        while (LookupContext->isTransparentContext()) +          LookupContext = LookupContext->getLookupParent(); +        LookupQualifiedName(Previous, LookupContext); + +        if (Previous.isAmbiguous()) +          return true; + +        if (Previous.begin() != Previous.end()) +          PrevDecl = (*Previous.begin())->getUnderlyingDecl(); +      }      }    } else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S))      PrevDecl = PrevClassTemplate = 0;    if (PrevClassTemplate) { -    // Ensure that the template parameter lists are compatible. -    if (!TemplateParameterListsAreEqual(TemplateParams, +    // Ensure that the template parameter lists are compatible. Skip this check +    // for a friend in a dependent context: the template parameter list itself +    // could be dependent. +    if (!(TUK == TUK_Friend && CurContext->isDependentContext()) && +        !TemplateParameterListsAreEqual(TemplateParams,                                     PrevClassTemplate->getTemplateParameters(),                                          /*Complain=*/true,                                          TPL_TemplateMatch)) @@ -1012,8 +1028,10 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,    // Check the template parameter list of this declaration, possibly    // merging in the template parameter list from the previous class -  // template declaration. -  if (CheckTemplateParameterList(TemplateParams, +  // template declaration. Skip this check for a friend in a dependent +  // context, because the template parameter list might be dependent. +  if (!(TUK == TUK_Friend && CurContext->isDependentContext()) && +      CheckTemplateParameterList(TemplateParams,              PrevClassTemplate? PrevClassTemplate->getTemplateParameters() : 0,                                   (SS.isSet() && SemanticContext &&                                    SemanticContext->isRecord() && @@ -1025,9 +1043,9 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,    if (SS.isSet()) {      // If the name of the template was qualified, we must be defining the      // template out-of-line. -    if (!SS.isInvalid() && !Invalid && !PrevClassTemplate && -        !(TUK == TUK_Friend && CurContext->isDependentContext())) { -      Diag(NameLoc, diag::err_member_def_does_not_match) +    if (!SS.isInvalid() && !Invalid && !PrevClassTemplate) { +      Diag(NameLoc, TUK == TUK_Friend ? diag::err_friend_decl_does_not_match +                                      : diag::err_member_def_does_not_match)          << Name << SemanticContext << SS.getRange();        Invalid = true;      } @@ -1046,8 +1064,10 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,    // Add alignment attributes if necessary; these attributes are checked when    // the ASTContext lays out the structure. -  AddAlignmentAttributesForRecord(NewClass); -  AddMsStructLayoutForRecord(NewClass); +  if (TUK == TUK_Definition) { +    AddAlignmentAttributesForRecord(NewClass); +    AddMsStructLayoutForRecord(NewClass); +  }    ClassTemplateDecl *NewTemplate      = ClassTemplateDecl::Create(Context, SemanticContext, NameLoc, @@ -1084,6 +1104,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,    if (Attr)      ProcessDeclAttributeList(S, NewClass, Attr); +  AddPushedVisibilityAttribute(NewClass); +    if (TUK != TUK_Friend)      PushOnScopeChains(NewTemplate, S);    else { @@ -1116,6 +1138,11 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,      NewTemplate->setInvalidDecl();      NewClass->setInvalidDecl();    } +  if (PrevClassTemplate) +    mergeDeclAttributes(NewClass, PrevClassTemplate->getTemplatedDecl()); + +  ActOnDocumentableDecl(NewTemplate); +    return NewTemplate;  } @@ -1972,6 +1999,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,        TemplateArgLists.addOuterTemplateArguments(0, 0);      InstantiatingTemplate Inst(*this, TemplateLoc, Template); +    if (Inst) +      return QualType();      CanonType = SubstType(Pattern->getUnderlyingType(),                            TemplateArgLists, AliasTemplate->getLocation(),                            AliasTemplate->getDeclName()); @@ -2420,6 +2449,43 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,      return true;    } +  case TemplateArgument::Expression: { +    // We have a template type parameter but the template argument is an +    // expression; see if maybe it is missing the "typename" keyword. +    CXXScopeSpec SS; +    DeclarationNameInfo NameInfo; + +    if (DeclRefExpr *ArgExpr = dyn_cast<DeclRefExpr>(Arg.getAsExpr())) { +      SS.Adopt(ArgExpr->getQualifierLoc()); +      NameInfo = ArgExpr->getNameInfo(); +    } else if (DependentScopeDeclRefExpr *ArgExpr = +               dyn_cast<DependentScopeDeclRefExpr>(Arg.getAsExpr())) { +      SS.Adopt(ArgExpr->getQualifierLoc()); +      NameInfo = ArgExpr->getNameInfo(); +    } else if (CXXDependentScopeMemberExpr *ArgExpr = +               dyn_cast<CXXDependentScopeMemberExpr>(Arg.getAsExpr())) { +      if (ArgExpr->isImplicitAccess()) { +        SS.Adopt(ArgExpr->getQualifierLoc()); +        NameInfo = ArgExpr->getMemberNameInfo(); +      } +    } + +    if (NameInfo.getName().isIdentifier()) { +      LookupResult Result(*this, NameInfo, LookupOrdinaryName); +      LookupParsedName(Result, CurScope, &SS); + +      if (Result.getAsSingle<TypeDecl>() || +          Result.getResultKind() == +            LookupResult::NotFoundInCurrentInstantiation) { +        // FIXME: Add a FixIt and fix up the template argument for recovery. +        SourceLocation Loc = AL.getSourceRange().getBegin(); +        Diag(Loc, diag::err_template_arg_must_be_type_suggest); +        Diag(Param->getLocation(), diag::note_template_param_here); +        return true; +      } +    } +    // fallthrough +  }    default: {      // We have a template type parameter but the template argument      // is not a type. @@ -2492,9 +2558,10 @@ SubstDefaultTemplateArgument(Sema &SemaRef,        = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);      Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, -                                     Template, Converted.data(), -                                     Converted.size(), +                                     Template, Converted,                                       SourceRange(TemplateLoc, RAngleLoc)); +    if (Inst) +      return 0;      Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());      ArgType = SemaRef.SubstType(ArgType, AllTemplateArgs, @@ -2541,9 +2608,10 @@ SubstDefaultTemplateArgument(Sema &SemaRef,      = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);    Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, -                                   Template, Converted.data(), -                                   Converted.size(), +                                   Template, Converted,                                     SourceRange(TemplateLoc, RAngleLoc)); +  if (Inst) +    return ExprError();    Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());    EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); @@ -2590,9 +2658,10 @@ SubstDefaultTemplateArgument(Sema &SemaRef,      = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);    Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, -                                   Template, Converted.data(), -                                   Converted.size(), +                                   Template, Converted,                                     SourceRange(TemplateLoc, RAngleLoc)); +  if (Inst) +    return TemplateName();    Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());    // Substitute into the nested-name-specifier first,  @@ -2724,8 +2793,10 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,          !Template->getDeclContext()->isDependentContext()) {        // Do substitution on the type of the non-type template parameter.        InstantiatingTemplate Inst(*this, TemplateLoc, Template, -                                 NTTP, Converted.data(), Converted.size(), +                                 NTTP, Converted,                                   SourceRange(TemplateLoc, RAngleLoc)); +      if (Inst) +        return true;        TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,                                          Converted.data(), Converted.size()); @@ -2856,8 +2927,10 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,      // Set up a template instantiation context.      LocalInstantiationScope Scope(*this);      InstantiatingTemplate Inst(*this, TemplateLoc, Template, -                               TempParm, Converted.data(), Converted.size(), +                               TempParm, Converted,                                 SourceRange(TemplateLoc, RAngleLoc)); +    if (Inst) +      return true;      TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,                                        Converted.data(), Converted.size()); @@ -3086,9 +3159,11 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,      // Introduce an instantiation record that describes where we are using      // the default template argument. -    InstantiatingTemplate Instantiating(*this, RAngleLoc, Template, *Param, -                                        Converted.data(), Converted.size(), +    InstantiatingTemplate Instantiating(*this, RAngleLoc, Template, +                                        *Param, Converted,                                          SourceRange(TemplateLoc, RAngleLoc)); +    if (Instantiating) +      return true;      // Check the default template argument.      if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc, @@ -3574,6 +3649,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,    if (ParamType->isPointerType() || ParamType->isNullPtrType()) {      switch (isNullPointerValueTemplateArgument(S, Param, ParamType, Arg)) {      case NPV_NullPointer: +      S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);        Converted = TemplateArgument((Decl *)0);        return false; @@ -3870,6 +3946,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,    case NPV_Error:      return true;    case NPV_NullPointer: +    S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);      Converted = TemplateArgument((Decl *)0);      return false;    case NPV_NotNullPointer: @@ -4066,7 +4143,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,          IntegerType = Enum->getDecl()->getIntegerType();        Value = Value.extOrTrunc(Context.getTypeSize(IntegerType)); -      Converted = TemplateArgument(Value, Context.getCanonicalType(ParamType)); +      Converted = TemplateArgument(Context, Value, +                                   Context.getCanonicalType(ParamType));        return ArgResult;      } @@ -4093,8 +4171,20 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,        Diag(Param->getLocation(), diag::note_template_param_here);        return ExprError();      } else if (!Arg->isValueDependent()) { -      Arg = VerifyIntegerConstantExpression(Arg, &Value, -        PDiag(diag::err_template_arg_not_ice) << ArgType, false).take(); +      class TmplArgICEDiagnoser : public VerifyICEDiagnoser { +        QualType T; +         +      public: +        TmplArgICEDiagnoser(QualType T) : T(T) { } +         +        virtual void diagnoseNotICE(Sema &S, SourceLocation Loc, +                                    SourceRange SR) { +          S.Diag(Loc, diag::err_template_arg_not_ice) << T << SR; +        } +      } Diagnoser(ArgType); + +      Arg = VerifyIntegerConstantExpression(Arg, &Value, Diagnoser, +                                            false).take();        if (!Arg)          return ExprError();      } @@ -4180,7 +4270,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,        }      } -    Converted = TemplateArgument(Value, +    Converted = TemplateArgument(Context, Value,                                   ParamType->isEnumeralType()                                      ? Context.getCanonicalType(ParamType)                                     : IntegerType); @@ -4305,6 +4395,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,        return ExprError();      case NPV_NullPointer: +      Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);        Converted = TemplateArgument((Decl *)0);        return Owned(Arg);;      } @@ -4497,13 +4588,13 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,        Kind = CharacterLiteral::Ascii;      return Owned(new (Context) CharacterLiteral( -                                            Arg.getAsIntegral()->getZExtValue(), +                                            Arg.getAsIntegral().getZExtValue(),                                              Kind, T, Loc));    }    if (T->isBooleanType())      return Owned(new (Context) CXXBoolLiteralExpr( -                                            Arg.getAsIntegral()->getBoolValue(), +                                            Arg.getAsIntegral().getBoolValue(),                                              T, Loc));    if (T->isNullPtrType()) @@ -4518,7 +4609,7 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,    else      BT = T; -  Expr *E = IntegerLiteral::Create(Context, *Arg.getAsIntegral(), BT, Loc); +  Expr *E = IntegerLiteral::Create(Context, Arg.getAsIntegral(), BT, Loc);    if (T->isEnumeralType()) {      // FIXME: This is a hack. We need a better way to handle substituted      // non-type template parameters. @@ -5041,7 +5132,7 @@ static bool CheckNonTypeClassTemplatePartialSpecializationArgs(Sema &S,  /// \param TemplateParams the template parameters of the primary class  /// template.  /// -/// \param TemplateArg the template arguments of the class template +/// \param TemplateArgs the template arguments of the class template  /// partial specialization.  ///  /// \returns true if there was an error, false otherwise. @@ -5481,7 +5572,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,  Decl *Sema::ActOnTemplateDeclarator(Scope *S,                                MultiTemplateParamsArg TemplateParameterLists,                                      Declarator &D) { -  return HandleDeclarator(S, D, move(TemplateParameterLists)); +  Decl *NewDecl = HandleDeclarator(S, D, move(TemplateParameterLists)); +  ActOnDocumentableDecl(NewDecl); +  return NewDecl;  }  Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, @@ -5719,14 +5812,17 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,  }  /// \brief Perform semantic analysis for the given dependent function -/// template specialization.  The only possible way to get a dependent -/// function template specialization is with a friend declaration, -/// like so: +/// template specialization. +/// +/// The only possible way to get a dependent function template specialization +/// is with a friend declaration, like so:  /// -///   template <class T> void foo(T); -///   template <class T> class A { +/// \code +///   template \<class T> void foo(T); +///   template \<class T> class A {  ///     friend void foo<>(T);  ///   }; +/// \endcode  ///  /// There really isn't any useful analysis we can do here, so we  /// just store the information. @@ -6890,6 +6986,42 @@ Sema::ActOnTypenameType(Scope *S,  } +/// Determine whether this failed name lookup should be treated as being +/// disabled by a usage of std::enable_if. +static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II, +                       SourceRange &CondRange) { +  // We must be looking for a ::type... +  if (!II.isStr("type")) +    return false; + +  // ... within an explicitly-written template specialization... +  if (!NNS || !NNS.getNestedNameSpecifier()->getAsType()) +    return false; +  TypeLoc EnableIfTy = NNS.getTypeLoc(); +  TemplateSpecializationTypeLoc *EnableIfTSTLoc = +    dyn_cast<TemplateSpecializationTypeLoc>(&EnableIfTy); +  if (!EnableIfTSTLoc || EnableIfTSTLoc->getNumArgs() == 0) +    return false; +  const TemplateSpecializationType *EnableIfTST = +    cast<TemplateSpecializationType>(EnableIfTSTLoc->getTypePtr()); + +  // ... which names a complete class template declaration... +  const TemplateDecl *EnableIfDecl = +    EnableIfTST->getTemplateName().getAsTemplateDecl(); +  if (!EnableIfDecl || EnableIfTST->isIncompleteType()) +    return false; + +  // ... called "enable_if". +  const IdentifierInfo *EnableIfII = +    EnableIfDecl->getDeclName().getAsIdentifierInfo(); +  if (!EnableIfII || !EnableIfII->isStr("enable_if")) +    return false; + +  // Assume the first template argument is the condition. +  CondRange = EnableIfTSTLoc->getArgLoc(0).getSourceRange(); +  return true; +} +  /// \brief Build the type that describes a C++ typename specifier,  /// e.g., "typename T::type".  QualType @@ -6926,9 +7058,19 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,    unsigned DiagID = 0;    Decl *Referenced = 0;    switch (Result.getResultKind()) { -  case LookupResult::NotFound: +  case LookupResult::NotFound: { +    // If we're looking up 'type' within a template named 'enable_if', produce +    // a more specific diagnostic. +    SourceRange CondRange; +    if (isEnableIf(QualifierLoc, II, CondRange)) { +      Diag(CondRange.getBegin(), diag::err_typename_nested_not_found_enable_if) +        << Ctx << CondRange; +      return QualType(); +    } +      DiagID = diag::err_typename_nested_not_found;      break; +  }    case LookupResult::FoundUnresolvedValue: {      // We found a using declaration that is a value. Most likely, the using  | 
