diff options
author | dim <dim@FreeBSD.org> | 2012-08-15 20:02:54 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2012-08-15 20:02:54 +0000 |
commit | 554bcb69c2d785a011a30e7db87a36a87fe7db10 (patch) | |
tree | 9abb1a658a297776086f4e0dfa6ca533de02104e /lib/Sema/SemaTemplate.cpp | |
parent | bb67ca86b31f67faee50bd10c3b036d65751745a (diff) | |
download | FreeBSD-src-554bcb69c2d785a011a30e7db87a36a87fe7db10.zip FreeBSD-src-554bcb69c2d785a011a30e7db87a36a87fe7db10.tar.gz |
Vendor import of clang trunk r161861:
http://llvm.org/svn/llvm-project/cfe/trunk@161861
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 51ce2a1..c8e4501 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 |