diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-04-02 08:55:10 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-04-02 08:55:10 +0000 |
commit | 07b2cfcdb817cc0790420f159a313d61e7241cb9 (patch) | |
tree | d374cdca417e76f1bf101f139dba2db1d10ee8f7 /lib/Sema/SemaTemplate.cpp | |
parent | 1e255aab650a7fa2047fd953cae65b12215280af (diff) | |
download | FreeBSD-src-07b2cfcdb817cc0790420f159a313d61e7241cb9.zip FreeBSD-src-07b2cfcdb817cc0790420f159a313d61e7241cb9.tar.gz |
Update clang to r100181.
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 672 |
1 files changed, 444 insertions, 228 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 434d556..40ec4bcb 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -161,7 +161,7 @@ bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II, NestedNameSpecifier *Qualifier = (NestedNameSpecifier*)SS->getScopeRep(); Diag(IILoc, diag::err_template_kw_missing) << Qualifier << II.getName() - << CodeModificationHint::CreateInsertion(IILoc, "template "); + << FixItHint::CreateInsertion(IILoc, "template "); SuggestedTemplate = TemplateTy::make(Context.getDependentTemplateName(Qualifier, &II)); SuggestedKind = TNK_Dependent_template_name; @@ -240,12 +240,12 @@ void Sema::LookupTemplateName(LookupResult &Found, if (LookupCtx) Diag(Found.getNameLoc(), diag::err_no_member_template_suggest) << Name << LookupCtx << Found.getLookupName() << SS.getRange() - << CodeModificationHint::CreateReplacement(Found.getNameLoc(), + << FixItHint::CreateReplacement(Found.getNameLoc(), Found.getLookupName().getAsString()); else Diag(Found.getNameLoc(), diag::err_no_template_suggest) << Name << Found.getLookupName() - << CodeModificationHint::CreateReplacement(Found.getNameLoc(), + << FixItHint::CreateReplacement(Found.getNameLoc(), Found.getLookupName().getAsString()); if (TemplateDecl *Template = Found.getAsSingle<TemplateDecl>()) Diag(Template->getLocation(), diag::note_previous_decl) @@ -822,8 +822,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, if (!isAcceptableTagRedeclaration(PrevRecordDecl, Kind, KWLoc, *Name)) { Diag(KWLoc, diag::err_use_with_wrong_tag) << Name - << CodeModificationHint::CreateReplacement(KWLoc, - PrevRecordDecl->getKindName()); + << FixItHint::CreateReplacement(KWLoc, PrevRecordDecl->getKindName()); Diag(PrevRecordDecl->getLocation(), diag::note_previous_use); Kind = PrevRecordDecl->getTagKind(); } @@ -1295,8 +1294,7 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, } else { Diag(SS.getRange().getBegin(), diag::err_template_spec_needs_header) << SS.getRange() - << CodeModificationHint::CreateInsertion(FirstTemplateLoc, - "template<> "); + << FixItHint::CreateInsertion(FirstTemplateLoc, "template<> "); IsExplicitSpecialization = true; } return 0; @@ -1499,8 +1497,7 @@ Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult, if (!isAcceptableTagRedeclaration(D, TagKind, TagLoc, *Id)) { Diag(TagLoc, diag::err_use_with_wrong_tag) << Type - << CodeModificationHint::CreateReplacement(SourceRange(TagLoc), - D->getKindName()); + << FixItHint::CreateReplacement(SourceRange(TagLoc), D->getKindName()); Diag(D->getLocation(), diag::note_previous_use); } } @@ -1897,7 +1894,8 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation RAngleLoc, - TemplateArgumentListBuilder &Converted) { + TemplateArgumentListBuilder &Converted, + CheckTemplateArgumentKind CTAK) { // Check template type parameters. if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) return CheckTemplateTypeArgument(TTP, Arg, Converted); @@ -1937,7 +1935,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, case TemplateArgument::Expression: { Expr *E = Arg.getArgument().getAsExpr(); TemplateArgument Result; - if (CheckTemplateArgument(NTTP, NTTPType, E, Result)) + if (CheckTemplateArgument(NTTP, NTTPType, E, Result, CTAK)) return true; Converted.Append(Result); @@ -2268,18 +2266,20 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param, /// \brief Checks whether the given template argument is the address /// of an object or function according to C++ [temp.arg.nontype]p1. -bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, - NamedDecl *&Entity) { +static bool +CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, + NonTypeTemplateParmDecl *Param, + QualType ParamType, + Expr *ArgIn, + TemplateArgument &Converted) { bool Invalid = false; + Expr *Arg = ArgIn; + QualType ArgType = Arg->getType(); // See through any implicit casts we added to fix the type. while (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg)) Arg = Cast->getSubExpr(); - // C++0x allows nullptr, and there's no further checking to be done for that. - if (Arg->getType()->isNullPtrType()) - return false; - // C++ [temp.arg.nontype]p1: // // A template-argument for a non-type, non-template @@ -2296,8 +2296,8 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, // Ignore (and complain about) any excess parentheses. while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) { if (!Invalid) { - Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_extra_parens) + S.Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_extra_parens) << Arg->getSourceRange(); Invalid = true; } @@ -2305,77 +2305,227 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, Arg = Parens->getSubExpr(); } + bool AddressTaken = false; + SourceLocation AddrOpLoc; if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) { - if (UnOp->getOpcode() == UnaryOperator::AddrOf) + if (UnOp->getOpcode() == UnaryOperator::AddrOf) { DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr()); + AddressTaken = true; + AddrOpLoc = UnOp->getOperatorLoc(); + } } else DRE = dyn_cast<DeclRefExpr>(Arg); - if (!DRE) - return Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_not_decl_ref) - << Arg->getSourceRange(); + if (!DRE) { + if (S.Context.hasSameUnqualifiedType(ArgType, S.Context.OverloadTy)) { + S.Diag(Arg->getLocStart(), + diag::err_template_arg_unresolved_overloaded_function) + << ParamType << Arg->getSourceRange(); + } else { + S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref) + << Arg->getSourceRange(); + } + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } // Stop checking the precise nature of the argument if it is value dependent, // it should be checked when instantiated. - if (Arg->isValueDependent()) + if (Arg->isValueDependent()) { + Converted = TemplateArgument(ArgIn->Retain()); return false; + } - if (!isa<ValueDecl>(DRE->getDecl())) - return Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_not_object_or_func_form) + if (!isa<ValueDecl>(DRE->getDecl())) { + S.Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_not_object_or_func_form) << Arg->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + + NamedDecl *Entity = 0; // Cannot refer to non-static data members - if (FieldDecl *Field = dyn_cast<FieldDecl>(DRE->getDecl())) - return Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_field) + if (FieldDecl *Field = dyn_cast<FieldDecl>(DRE->getDecl())) { + S.Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_field) << Field << Arg->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } // Cannot refer to non-static member functions if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(DRE->getDecl())) - if (!Method->isStatic()) - return Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_method) + if (!Method->isStatic()) { + S.Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_method) << Method << Arg->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } // Functions must have external linkage. if (FunctionDecl *Func = dyn_cast<FunctionDecl>(DRE->getDecl())) { if (!isExternalLinkage(Func->getLinkage())) { - Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_function_not_extern) + S.Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_function_not_extern) << Func << Arg->getSourceRange(); - Diag(Func->getLocation(), diag::note_template_arg_internal_object) + S.Diag(Func->getLocation(), diag::note_template_arg_internal_object) << true; return true; } // Okay: we've named a function with external linkage. Entity = Func; - return Invalid; - } - if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { + // If the template parameter has pointer type, the function decays. + if (ParamType->isPointerType() && !AddressTaken) + ArgType = S.Context.getPointerType(Func->getType()); + else if (AddressTaken && ParamType->isReferenceType()) { + // If we originally had an address-of operator, but the + // parameter has reference type, complain and (if things look + // like they will work) drop the address-of operator. + if (!S.Context.hasSameUnqualifiedType(Func->getType(), + ParamType.getNonReferenceType())) { + S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) + << ParamType; + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + + S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) + << ParamType + << FixItHint::CreateRemoval(AddrOpLoc); + S.Diag(Param->getLocation(), diag::note_template_param_here); + + ArgType = Func->getType(); + } + } else if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { if (!isExternalLinkage(Var->getLinkage())) { - Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_object_not_extern) + S.Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_object_not_extern) << Var << Arg->getSourceRange(); - Diag(Var->getLocation(), diag::note_template_arg_internal_object) + S.Diag(Var->getLocation(), diag::note_template_arg_internal_object) << true; return true; } + // A value of reference type is not an object. + if (Var->getType()->isReferenceType()) { + S.Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_reference_var) + << Var->getType() << Arg->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + // Okay: we've named an object with external linkage Entity = Var; - return Invalid; - } - // We found something else, but we don't know specifically what it is. - Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_not_object_or_func) + // If the template parameter has pointer type, we must have taken + // the address of this object. + if (ParamType->isReferenceType()) { + if (AddressTaken) { + // If we originally had an address-of operator, but the + // parameter has reference type, complain and (if things look + // like they will work) drop the address-of operator. + if (!S.Context.hasSameUnqualifiedType(Var->getType(), + ParamType.getNonReferenceType())) { + S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) + << ParamType; + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + + S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) + << ParamType + << FixItHint::CreateRemoval(AddrOpLoc); + S.Diag(Param->getLocation(), diag::note_template_param_here); + + ArgType = Var->getType(); + } + } else if (!AddressTaken && ParamType->isPointerType()) { + if (Var->getType()->isArrayType()) { + // Array-to-pointer decay. + ArgType = S.Context.getArrayDecayedType(Var->getType()); + } else { + // If the template parameter has pointer type but the address of + // this object was not taken, complain and (possibly) recover by + // taking the address of the entity. + ArgType = S.Context.getPointerType(Var->getType()); + if (!S.Context.hasSameUnqualifiedType(ArgType, ParamType)) { + S.Diag(Arg->getLocStart(), diag::err_template_arg_not_address_of) + << ParamType; + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + + S.Diag(Arg->getLocStart(), diag::err_template_arg_not_address_of) + << ParamType + << FixItHint::CreateInsertion(Arg->getLocStart(), "&"); + + S.Diag(Param->getLocation(), diag::note_template_param_here); + } + } + } else { + // We found something else, but we don't know specifically what it is. + S.Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_not_object_or_func) << Arg->getSourceRange(); - Diag(DRE->getDecl()->getLocation(), - diag::note_template_arg_refers_here); - return true; + S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here); + return true; + } + + if (ParamType->isPointerType() && + !ParamType->getAs<PointerType>()->getPointeeType()->isFunctionType() && + S.IsQualificationConversion(ArgType, ParamType)) { + // For pointer-to-object types, qualification conversions are + // permitted. + } else { + if (const ReferenceType *ParamRef = ParamType->getAs<ReferenceType>()) { + if (!ParamRef->getPointeeType()->isFunctionType()) { + // C++ [temp.arg.nontype]p5b3: + // For a non-type template-parameter of type reference to + // object, no conversions apply. The type referred to by the + // reference may be more cv-qualified than the (otherwise + // identical) type of the template- argument. The + // template-parameter is bound directly to the + // template-argument, which shall be an lvalue. + + // FIXME: Other qualifiers? + unsigned ParamQuals = ParamRef->getPointeeType().getCVRQualifiers(); + unsigned ArgQuals = ArgType.getCVRQualifiers(); + + if ((ParamQuals | ArgQuals) != ParamQuals) { + S.Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_ref_bind_ignores_quals) + << ParamType << Arg->getType() + << Arg->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + } + } + + // At this point, the template argument refers to an object or + // function with external linkage. We now need to check whether the + // argument and parameter types are compatible. + if (!S.Context.hasSameUnqualifiedType(ArgType, + ParamType.getNonReferenceType())) { + // We can't perform this conversion or binding. + if (ParamType->isReferenceType()) + S.Diag(Arg->getLocStart(), diag::err_template_arg_no_ref_bind) + << ParamType << Arg->getType() << Arg->getSourceRange(); + else + S.Diag(Arg->getLocStart(), diag::err_template_arg_not_convertible) + << Arg->getType() << ParamType << Arg->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + } + + // Create the template argument. + Converted = TemplateArgument(Entity->getCanonicalDecl()); + return false; } /// \brief Checks whether the given template argument is a pointer to @@ -2388,10 +2538,6 @@ bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, while (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg)) Arg = Cast->getSubExpr(); - // C++0x allows nullptr, and there's no further checking to be done for that. - if (Arg->getType()->isNullPtrType()) - return false; - // C++ [temp.arg.nontype]p1: // // A template-argument for a non-type, non-template @@ -2478,12 +2624,12 @@ bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, /// If no error was detected, Converted receives the converted template argument. bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType InstantiatedParamType, Expr *&Arg, - TemplateArgument &Converted) { + TemplateArgument &Converted, + CheckTemplateArgumentKind CTAK) { SourceLocation StartLoc = Arg->getSourceRange().getBegin(); // If either the parameter has a dependent type or the argument is // type-dependent, there's nothing we can check now. - // FIXME: Add template argument to Converted! if (InstantiatedParamType->isDependentType() || Arg->isTypeDependent()) { // FIXME: Produce a cloned, canonical expression? Converted = TemplateArgument(Arg); @@ -2525,17 +2671,27 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return true; } - // FIXME: We need some way to more easily get the unqualified form - // of the types without going all the way to the - // canonical type. - if (Context.getCanonicalType(ParamType).getCVRQualifiers()) - ParamType = Context.getCanonicalType(ParamType).getUnqualifiedType(); - if (Context.getCanonicalType(ArgType).getCVRQualifiers()) - ArgType = Context.getCanonicalType(ArgType).getUnqualifiedType(); + // From here on out, all we care about are the unqualified forms + // of the parameter and argument types. + ParamType = ParamType.getUnqualifiedType(); + ArgType = ArgType.getUnqualifiedType(); // Try to convert the argument to the parameter's type. if (Context.hasSameType(ParamType, ArgType)) { // Okay: no conversion necessary + } else if (CTAK == CTAK_Deduced) { + // C++ [temp.deduct.type]p17: + // If, in the declaration of a function template with a non-type + // template-parameter, the non-type template- parameter is used + // in an expression in the function parameter-list and, if the + // corresponding template-argument is deduced, the + // template-argument type shall match the type of the + // template-parameter exactly, except that a template-argument + // deduced from an array bound may be of any integral type. + Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch) + << ArgType << ParamType; + Diag(Param->getLocation(), diag::note_template_param_here); + return true; } else if (IsIntegralPromotion(Arg, ArgType, ParamType) || !ParamType->isEnumeralType()) { // This is an integral promotion or conversion. @@ -2554,38 +2710,39 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, IntegerType = Context.getCanonicalType(Enum->getDecl()->getIntegerType()); if (!Arg->isValueDependent()) { - // Check that an unsigned parameter does not receive a negative - // value. + llvm::APSInt OldValue = Value; + + // Coerce the template argument's value to the value it will have + // based on the template parameter's type. + unsigned AllowedBits = Context.getTypeSize(IntegerType); + if (Value.getBitWidth() != AllowedBits) + Value.extOrTrunc(AllowedBits); + Value.setIsSigned(IntegerType->isSignedIntegerType()); + + // Complain if an unsigned parameter received a negative value. if (IntegerType->isUnsignedIntegerType() - && (Value.isSigned() && Value.isNegative())) { - Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_negative) - << Value.toString(10) << Param->getType() + && (OldValue.isSigned() && OldValue.isNegative())) { + Diag(Arg->getSourceRange().getBegin(), diag::warn_template_arg_negative) + << OldValue.toString(10) << Value.toString(10) << Param->getType() << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); - return true; } - // Check that we don't overflow the template parameter type. - unsigned AllowedBits = Context.getTypeSize(IntegerType); + // Complain if we overflowed the template parameter's type. unsigned RequiredBits; if (IntegerType->isUnsignedIntegerType()) - RequiredBits = Value.getActiveBits(); - else if (Value.isUnsigned()) - RequiredBits = Value.getActiveBits() + 1; + RequiredBits = OldValue.getActiveBits(); + else if (OldValue.isUnsigned()) + RequiredBits = OldValue.getActiveBits() + 1; else - RequiredBits = Value.getMinSignedBits(); + RequiredBits = OldValue.getMinSignedBits(); if (RequiredBits > AllowedBits) { Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_too_large) - << Value.toString(10) << Param->getType() + diag::warn_template_arg_too_large) + << OldValue.toString(10) << Value.toString(10) << Param->getType() << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); - return true; } - - if (Value.getBitWidth() != AllowedBits) - Value.extOrTrunc(AllowedBits); - Value.setIsSigned(IntegerType->isSignedIntegerType()); } // Add the value of this argument to the list of converted @@ -2604,6 +2761,18 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return false; } + DeclAccessPair FoundResult; // temporary for ResolveOverloadedFunction + + // C++0x [temp.arg.nontype]p5 bullets 2, 4 and 6 permit conversion + // from a template argument of type std::nullptr_t to a non-type + // template parameter of type pointer to object, pointer to + // function, or pointer-to-member, respectively. + if (ArgType->isNullPtrType() && + (ParamType->isPointerType() || ParamType->isMemberPointerType())) { + Converted = TemplateArgument((NamedDecl *)0); + return false; + } + // Handle pointer-to-function, reference-to-function, and // pointer-to-member-function all in (roughly) the same way. if (// -- For a non-type template-parameter of type pointer to @@ -2611,7 +2780,6 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // applied. If the template-argument represents a set of // overloaded functions (or a pointer to such), the matching // function is selected from the set (13.4). - // In C++0x, any std::nullptr_t value can be converted. (ParamType->isPointerType() && ParamType->getAs<PointerType>()->getPointeeType()->isFunctionType()) || // -- For a non-type template-parameter of type reference to @@ -2625,38 +2793,30 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // template-argument represents a set of overloaded member // functions, the matching member function is selected from // the set (13.4). - // Again, C++0x allows a std::nullptr_t value. (ParamType->isMemberPointerType() && ParamType->getAs<MemberPointerType>()->getPointeeType() ->isFunctionType())) { - if (Context.hasSameUnqualifiedType(ArgType, - ParamType.getNonReferenceType())) { - // We don't have to do anything: the types already match. - } else if (ArgType->isNullPtrType() && (ParamType->isPointerType() || - ParamType->isMemberPointerType())) { - ArgType = ParamType; - if (ParamType->isMemberPointerType()) - ImpCastExprToType(Arg, ParamType, CastExpr::CK_NullToMemberPointer); - else - ImpCastExprToType(Arg, ParamType, CastExpr::CK_BitCast); - } else if (ArgType->isFunctionType() && ParamType->isPointerType()) { - ArgType = Context.getPointerType(ArgType); - ImpCastExprToType(Arg, ArgType, CastExpr::CK_FunctionToPointerDecay); - } else if (FunctionDecl *Fn - = ResolveAddressOfOverloadedFunction(Arg, ParamType, true)) { + + if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType, + true, + FoundResult)) { if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin())) return true; - Arg = FixOverloadedFunctionReference(Arg, Fn); + Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn); ArgType = Arg->getType(); - if (ArgType->isFunctionType() && ParamType->isPointerType()) { - ArgType = Context.getPointerType(Arg->getType()); - ImpCastExprToType(Arg, ArgType, CastExpr::CK_FunctionToPointerDecay); - } } - if (!Context.hasSameUnqualifiedType(ArgType, - ParamType.getNonReferenceType())) { + if (!ParamType->isMemberPointerType()) + return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, + ParamType, + Arg, Converted); + + if (IsQualificationConversion(ArgType, ParamType.getNonReferenceType())) { + ImpCastExprToType(Arg, ParamType, CastExpr::CK_NoOp, + Arg->isLvalue(Context) == Expr::LV_Valid); + } else if (!Context.hasSameUnqualifiedType(ArgType, + ParamType.getNonReferenceType())) { // We can't perform this conversion. Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_not_convertible) @@ -2665,21 +2825,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return true; } - if (ParamType->isMemberPointerType()) - return CheckTemplateArgumentPointerToMember(Arg, Converted); - - NamedDecl *Entity = 0; - if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity)) - return true; - - if (Arg->isValueDependent()) { - Converted = TemplateArgument(Arg); - } else { - if (Entity) - Entity = cast<NamedDecl>(Entity->getCanonicalDecl()); - Converted = TemplateArgument(Entity); - } - return false; + return CheckTemplateArgumentPointerToMember(Arg, Converted); } if (ParamType->isPointerType()) { @@ -2690,40 +2836,9 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, assert(ParamType->getAs<PointerType>()->getPointeeType()->isObjectType() && "Only object pointers allowed here"); - if (ArgType->isNullPtrType()) { - ArgType = ParamType; - ImpCastExprToType(Arg, ParamType, CastExpr::CK_BitCast); - } else if (ArgType->isArrayType()) { - ArgType = Context.getArrayDecayedType(ArgType); - ImpCastExprToType(Arg, ArgType, CastExpr::CK_ArrayToPointerDecay); - } - - if (IsQualificationConversion(ArgType, ParamType)) { - ArgType = ParamType; - ImpCastExprToType(Arg, ParamType, CastExpr::CK_NoOp); - } - - if (!Context.hasSameUnqualifiedType(ArgType, ParamType)) { - // We can't perform this conversion. - Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_not_convertible) - << Arg->getType() << InstantiatedParamType << Arg->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); - return true; - } - - NamedDecl *Entity = 0; - if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity)) - return true; - - if (Arg->isValueDependent()) { - Converted = TemplateArgument(Arg); - } else { - if (Entity) - Entity = cast<NamedDecl>(Entity->getCanonicalDecl()); - Converted = TemplateArgument(Entity); - } - return false; + return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, + ParamType, + Arg, Converted); } if (const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>()) { @@ -2736,53 +2851,31 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, assert(ParamRefType->getPointeeType()->isObjectType() && "Only object references allowed here"); - QualType ReferredType = ParamRefType->getPointeeType(); - if (!Context.hasSameUnqualifiedType(ReferredType, ArgType)) { - Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_no_ref_bind) - << InstantiatedParamType << Arg->getType() - << Arg->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); - return true; - } - - unsigned ParamQuals - = Context.getCanonicalType(ReferredType).getCVRQualifiers(); - unsigned ArgQuals = Context.getCanonicalType(ArgType).getCVRQualifiers(); + if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, + ParamRefType->getPointeeType(), + true, + FoundResult)) { + if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin())) + return true; - if ((ParamQuals | ArgQuals) != ParamQuals) { - Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_ref_bind_ignores_quals) - << InstantiatedParamType << Arg->getType() - << Arg->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); - return true; + Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn); + ArgType = Arg->getType(); } - NamedDecl *Entity = 0; - if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity)) - return true; - - if (Arg->isValueDependent()) { - Converted = TemplateArgument(Arg); - } else { - Entity = cast<NamedDecl>(Entity->getCanonicalDecl()); - Converted = TemplateArgument(Entity); - } - return false; + return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, + ParamType, + Arg, Converted); } // -- For a non-type template-parameter of type pointer to data // member, qualification conversions (4.4) are applied. - // C++0x allows std::nullptr_t values. assert(ParamType->isMemberPointerType() && "Only pointers to members remain"); if (Context.hasSameUnqualifiedType(ParamType, ArgType)) { // Types match exactly: nothing more to do here. - } else if (ArgType->isNullPtrType()) { - ImpCastExprToType(Arg, ParamType, CastExpr::CK_NullToMemberPointer); } else if (IsQualificationConversion(ArgType, ParamType)) { - ImpCastExprToType(Arg, ParamType, CastExpr::CK_NoOp); + ImpCastExprToType(Arg, ParamType, CastExpr::CK_NoOp, + Arg->isLvalue(Context) == Expr::LV_Valid); } else { // We can't perform this conversion. Diag(Arg->getSourceRange().getBegin(), @@ -2837,6 +2930,109 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, Arg.getLocation()); } +/// \brief Given a non-type template argument that refers to a +/// declaration and the type of its corresponding non-type template +/// parameter, produce an expression that properly refers to that +/// declaration. +Sema::OwningExprResult +Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, + QualType ParamType, + SourceLocation Loc) { + assert(Arg.getKind() == TemplateArgument::Declaration && + "Only declaration template arguments permitted here"); + ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl()); + + if (VD->getDeclContext()->isRecord() && + (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD))) { + // If the value is a class member, we might have a pointer-to-member. + // Determine whether the non-type template template parameter is of + // pointer-to-member type. If so, we need to build an appropriate + // expression for a pointer-to-member, since a "normal" DeclRefExpr + // would refer to the member itself. + if (ParamType->isMemberPointerType()) { + QualType ClassType + = Context.getTypeDeclType(cast<RecordDecl>(VD->getDeclContext())); + NestedNameSpecifier *Qualifier + = NestedNameSpecifier::Create(Context, 0, false, ClassType.getTypePtr()); + CXXScopeSpec SS; + SS.setScopeRep(Qualifier); + OwningExprResult RefExpr = BuildDeclRefExpr(VD, + VD->getType().getNonReferenceType(), + Loc, + &SS); + if (RefExpr.isInvalid()) + return ExprError(); + + RefExpr = CreateBuiltinUnaryOp(Loc, UnaryOperator::AddrOf, move(RefExpr)); + assert(!RefExpr.isInvalid() && + Context.hasSameType(((Expr*) RefExpr.get())->getType(), + ParamType)); + return move(RefExpr); + } + } + + QualType T = VD->getType().getNonReferenceType(); + if (ParamType->isPointerType()) { + // When the non-type template parameter is a pointer, take the + // address of the declaration. + OwningExprResult RefExpr = BuildDeclRefExpr(VD, T, Loc); + if (RefExpr.isInvalid()) + return ExprError(); + + if (T->isFunctionType() || T->isArrayType()) { + // Decay functions and arrays. + Expr *RefE = (Expr *)RefExpr.get(); + DefaultFunctionArrayConversion(RefE); + if (RefE != RefExpr.get()) { + RefExpr.release(); + RefExpr = Owned(RefE); + } + + return move(RefExpr); + } + + // Take the address of everything else + return CreateBuiltinUnaryOp(Loc, UnaryOperator::AddrOf, move(RefExpr)); + } + + // If the non-type template parameter has reference type, qualify the + // resulting declaration reference with the extra qualifiers on the + // type that the reference refers to. + if (const ReferenceType *TargetRef = ParamType->getAs<ReferenceType>()) + T = Context.getQualifiedType(T, TargetRef->getPointeeType().getQualifiers()); + + return BuildDeclRefExpr(VD, T, Loc); +} + +/// \brief Construct a new expression that refers to the given +/// integral template argument with the given source-location +/// information. +/// +/// This routine takes care of the mapping from an integral template +/// argument (which may have any integral type) to the appropriate +/// literal value. +Sema::OwningExprResult +Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, + SourceLocation Loc) { + assert(Arg.getKind() == TemplateArgument::Integral && + "Operation is only value for integral template arguments"); + QualType T = Arg.getIntegralType(); + if (T->isCharType() || T->isWideCharType()) + return Owned(new (Context) CharacterLiteral( + Arg.getAsIntegral()->getZExtValue(), + T->isWideCharType(), + T, + Loc)); + if (T->isBooleanType()) + return Owned(new (Context) CXXBoolLiteralExpr( + Arg.getAsIntegral()->getBoolValue(), + T, + Loc)); + + return Owned(new (Context) IntegerLiteral(*Arg.getAsIntegral(), T, Loc)); +} + + /// \brief Determine whether the given template parameter lists are /// equivalent. /// @@ -3341,7 +3537,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, } else if (TemplateParams) { if (TUK == TUK_Friend) Diag(KWLoc, diag::err_template_spec_friend) - << CodeModificationHint::CreateRemoval( + << FixItHint::CreateRemoval( SourceRange(TemplateParams->getTemplateLoc(), TemplateParams->getRAngleLoc())) << SourceRange(LAngleLoc, RAngleLoc); @@ -3349,7 +3545,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, isExplicitSpecialization = true; } else if (TUK != TUK_Friend) { Diag(KWLoc, diag::err_template_spec_needs_header) - << CodeModificationHint::CreateInsertion(KWLoc, "template<> "); + << FixItHint::CreateInsertion(KWLoc, "template<> "); isExplicitSpecialization = true; } @@ -3367,7 +3563,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, *ClassTemplate->getIdentifier())) { Diag(KWLoc, diag::err_use_with_wrong_tag) << ClassTemplate - << CodeModificationHint::CreateReplacement(KWLoc, + << FixItHint::CreateReplacement(KWLoc, ClassTemplate->getTemplatedDecl()->getKindName()); Diag(ClassTemplate->getTemplatedDecl()->getLocation(), diag::note_previous_use); @@ -3409,8 +3605,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // to the implicit argument list of the primary template. Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template) << (TUK == TUK_Definition) - << CodeModificationHint::CreateRemoval(SourceRange(LAngleLoc, - RAngleLoc)); + << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc)); return CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS, ClassTemplate->getIdentifier(), TemplateNameLoc, @@ -3644,7 +3839,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, if (TUK == TUK_Friend) { FriendDecl *Friend = FriendDecl::Create(Context, CurContext, TemplateNameLoc, - WrittenTy->getType().getTypePtr(), + WrittenTy, /*FIXME:*/KWLoc); Friend->setAccess(AS_public); CurContext->addDecl(Friend); @@ -3948,11 +4143,11 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, UnresolvedSetIterator Result = getMostSpecialized(Candidates.begin(), Candidates.end(), TPOC_Other, FD->getLocation(), - PartialDiagnostic(diag::err_function_template_spec_no_match) + PDiag(diag::err_function_template_spec_no_match) << FD->getDeclName(), - PartialDiagnostic(diag::err_function_template_spec_ambiguous) + PDiag(diag::err_function_template_spec_ambiguous) << FD->getDeclName() << (ExplicitTemplateArgs != 0), - PartialDiagnostic(diag::note_function_template_spec_matched)); + PDiag(diag::note_function_template_spec_matched)); if (Result == Candidates.end()) return true; @@ -3961,9 +4156,14 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, // FIXME: Check if the prior specialization has a point of instantiation. // If so, we have run afoul of . + + // If this is a friend declaration, then we're not really declaring + // an explicit specialization. + bool isFriend = (FD->getFriendObjectKind() != Decl::FOK_None); // Check the scope of this explicit specialization. - if (CheckTemplateSpecializationScope(*this, + if (!isFriend && + CheckTemplateSpecializationScope(*this, Specialization->getPrimaryTemplate(), Specialization, FD->getLocation(), false)) @@ -3980,7 +4180,8 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, assert(SpecInfo && "Function template specialization info missing?"); bool SuppressNew = false; - if (CheckSpecializationInstantiationRedecl(FD->getLocation(), + if (!isFriend && + CheckSpecializationInstantiationRedecl(FD->getLocation(), TSK_ExplicitSpecialization, Specialization, SpecInfo->getTemplateSpecializationKind(), @@ -3990,7 +4191,8 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, // Mark the prior declaration as an explicit specialization, so that later // clients know that this is an explicit specialization. - SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization); + if (!isFriend) + SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization); // Turn the given function declaration into a function template // specialization, with the template arguments from the previous @@ -3999,7 +4201,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, new (Context) TemplateArgumentList( *Specialization->getTemplateSpecializationArgs()), /*InsertPos=*/0, - TSK_ExplicitSpecialization); + SpecInfo->getTemplateSpecializationKind()); // The "previous declaration" for this function template specialization is // the prior function template specialization. @@ -4250,7 +4452,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, *ClassTemplate->getIdentifier())) { Diag(KWLoc, diag::err_use_with_wrong_tag) << ClassTemplate - << CodeModificationHint::CreateReplacement(KWLoc, + << FixItHint::CreateReplacement(KWLoc, ClassTemplate->getTemplatedDecl()->getKindName()); Diag(ClassTemplate->getTemplatedDecl()->getLocation(), diag::note_previous_use); @@ -4388,8 +4590,17 @@ Sema::ActOnExplicitInstantiation(Scope *S, // Instantiate the members of this class template specialization. Def = cast_or_null<ClassTemplateSpecializationDecl>( Specialization->getDefinition()); - if (Def) + if (Def) { + TemplateSpecializationKind Old_TSK = Def->getTemplateSpecializationKind(); + + // Fix a TSK_ExplicitInstantiationDeclaration followed by a + // TSK_ExplicitInstantiationDefinition + if (Old_TSK == TSK_ExplicitInstantiationDeclaration && + TSK == TSK_ExplicitInstantiationDefinition) + Def->setTemplateSpecializationKind(TSK); + InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK); + } return DeclPtrTy::make(Specialization); } @@ -4559,7 +4770,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (D.getDeclSpec().isInlineSpecified() && getLangOptions().CPlusPlus0x) Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_explicit_instantiation_inline) - <<CodeModificationHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc()); + <<FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc()); // FIXME: check for constexpr specifier. @@ -4699,9 +4910,9 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, UnresolvedSetIterator Result = getMostSpecialized(Matches.begin(), Matches.end(), TPOC_Other, D.getIdentifierLoc(), - PartialDiagnostic(diag::err_explicit_instantiation_not_known) << Name, - PartialDiagnostic(diag::err_explicit_instantiation_ambiguous) << Name, - PartialDiagnostic(diag::note_explicit_instantiation_candidate)); + PDiag(diag::err_explicit_instantiation_not_known) << Name, + PDiag(diag::err_explicit_instantiation_ambiguous) << Name, + PDiag(diag::note_explicit_instantiation_candidate)); if (Result == Matches.end()) return true; @@ -4781,14 +4992,16 @@ Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK, if (!NNS) return true; - QualType T = CheckTypenameType(NNS, *Name, SourceRange(TagLoc, NameLoc)); - if (T.isNull()) - return true; - - TagDecl::TagKind TagKind = TagDecl::getTagKindForTypeSpec(TagSpec); - QualType ElabType = Context.getElaboratedType(T, TagKind); + ElaboratedTypeKeyword Keyword = ETK_None; + switch (TagDecl::getTagKindForTypeSpec(TagSpec)) { + case TagDecl::TK_struct: Keyword = ETK_Struct; break; + case TagDecl::TK_class: Keyword = ETK_Class; break; + case TagDecl::TK_union: Keyword = ETK_Union; break; + case TagDecl::TK_enum: Keyword = ETK_Enum; break; + } + assert(Keyword != ETK_None && "Invalid tag kind!"); - return ElabType.getAsOpaquePtr(); + return Context.getDependentNameType(Keyword, NNS, Name).getAsOpaquePtr(); } Sema::TypeResult @@ -4824,7 +5037,8 @@ Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, return Context.getQualifiedNameType(NNS, T).getAsOpaquePtr(); } - return Context.getTypenameType(NNS, TemplateId).getAsOpaquePtr(); + return Context.getDependentNameType(ETK_Typename, NNS, TemplateId) + .getAsOpaquePtr(); } /// \brief Build the type that describes a C++ typename specifier, @@ -4839,7 +5053,7 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II, // If the nested-name-specifier does not refer to the current // instantiation, then build a typename type. if (!CurrentInstantiation) - return Context.getTypenameType(NNS, &II); + return Context.getDependentNameType(ETK_Typename, NNS, &II); // The nested-name-specifier refers to the current instantiation, so the // "typename" keyword itself is superfluous. In C++03, the program is @@ -4875,7 +5089,7 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II, case LookupResult::NotFoundInCurrentInstantiation: // Okay, it's a member of an unknown instantiation. - return Context.getTypenameType(NNS, &II); + return Context.getDependentNameType(ETK_Typename, NNS, &II); case LookupResult::Found: if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) { @@ -4960,16 +5174,16 @@ namespace { /// \brief Transforms a typename type by determining whether the type now /// refers to a member of the current instantiation, and then /// type-checking and building a QualifiedNameType (when possible). - QualType TransformTypenameType(TypeLocBuilder &TLB, TypenameTypeLoc TL, + QualType TransformDependentNameType(TypeLocBuilder &TLB, DependentNameTypeLoc TL, QualType ObjectType); }; } QualType -CurrentInstantiationRebuilder::TransformTypenameType(TypeLocBuilder &TLB, - TypenameTypeLoc TL, +CurrentInstantiationRebuilder::TransformDependentNameType(TypeLocBuilder &TLB, + DependentNameTypeLoc TL, QualType ObjectType) { - TypenameType *T = TL.getTypePtr(); + DependentNameType *T = TL.getTypePtr(); NestedNameSpecifier *NNS = TransformNestedNameSpecifier(T->getQualifier(), @@ -5001,15 +5215,17 @@ CurrentInstantiationRebuilder::TransformTypenameType(TypeLocBuilder &TLB, NewTemplateId == QualType(TemplateId, 0)) Result = QualType(T, 0); else - Result = getDerived().RebuildTypenameType(NNS, NewTemplateId); + Result = getDerived().RebuildDependentNameType(T->getKeyword(), + NNS, NewTemplateId); } else - Result = getDerived().RebuildTypenameType(NNS, T->getIdentifier(), - SourceRange(TL.getNameLoc())); + Result = getDerived().RebuildDependentNameType(T->getKeyword(), + NNS, T->getIdentifier(), + SourceRange(TL.getNameLoc())); if (Result.isNull()) return QualType(); - TypenameTypeLoc NewTL = TLB.push<TypenameTypeLoc>(Result); + DependentNameTypeLoc NewTL = TLB.push<DependentNameTypeLoc>(Result); NewTL.setNameLoc(TL.getNameLoc()); return Result; } @@ -5034,7 +5250,7 @@ CurrentInstantiationRebuilder::TransformTypenameType(TypeLocBuilder &TLB, /// typename X<T>::pointer X<T>::data() { ... } /// \endcode /// -/// Here, the type "typename X<T>::pointer" will be created as a TypenameType, +/// Here, the type "typename X<T>::pointer" will be created as a DependentNameType, /// since we do not know that we can look into X<T> when we parsed the type. /// This function will rebuild the type, performing the lookup of "pointer" /// in X<T> and returning a QualifiedNameType whose canonical type is the same |