diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 109 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 52 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 284 | ||||
-rw-r--r-- | lib/Sema/SemaExprMember.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 632 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 138 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 75 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 64 |
13 files changed, 978 insertions, 398 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 9c902959233f..49208e20a49d 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -1242,7 +1242,8 @@ bool Sema::CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { QualType RHSTy = RHS.get()->getType(); llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch(); - bool IsPolyUnsigned = Arch == llvm::Triple::aarch64; + bool IsPolyUnsigned = Arch == llvm::Triple::aarch64 || + Arch == llvm::Triple::aarch64_be; bool IsInt64Long = Context.getTargetInfo().getInt64Type() == TargetInfo::SignedLong; QualType EltTy = diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index f9b6a91a300f..c6a5bc74145c 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -32,6 +32,7 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaInternal.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/MathExtras.h" @@ -890,34 +891,117 @@ static void handleLocksExcludedAttr(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } -static void handleEnableIfAttr(Sema &S, Decl *D, const AttributeList &Attr) { - S.Diag(Attr.getLoc(), diag::ext_clang_enable_if); - - Expr *Cond = Attr.getArgAsExpr(0); +static bool checkFunctionConditionAttr(Sema &S, Decl *D, + const AttributeList &Attr, + Expr *&Cond, StringRef &Msg) { + Cond = Attr.getArgAsExpr(0); if (!Cond->isTypeDependent()) { ExprResult Converted = S.PerformContextuallyConvertToBool(Cond); if (Converted.isInvalid()) - return; + return false; Cond = Converted.get(); } - StringRef Msg; if (!S.checkStringLiteralArgumentAttr(Attr, 1, Msg)) - return; + return false; + + if (Msg.empty()) + Msg = "<no message provided>"; SmallVector<PartialDiagnosticAt, 8> Diags; if (!Cond->isValueDependent() && !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D), Diags)) { - S.Diag(Attr.getLoc(), diag::err_enable_if_never_constant_expr); + S.Diag(Attr.getLoc(), diag::err_attr_cond_never_constant_expr) + << Attr.getName(); for (const PartialDiagnosticAt &PDiag : Diags) S.Diag(PDiag.first, PDiag.second); + return false; + } + return true; +} + +static void handleEnableIfAttr(Sema &S, Decl *D, const AttributeList &Attr) { + S.Diag(Attr.getLoc(), diag::ext_clang_enable_if); + + Expr *Cond; + StringRef Msg; + if (checkFunctionConditionAttr(S, D, Attr, Cond, Msg)) + D->addAttr(::new (S.Context) + EnableIfAttr(Attr.getRange(), S.Context, Cond, Msg, + Attr.getAttributeSpellingListIndex())); +} + +namespace { +/// Determines if a given Expr references any of the given function's +/// ParmVarDecls, or the function's implicit `this` parameter (if applicable). +class ArgumentDependenceChecker + : public RecursiveASTVisitor<ArgumentDependenceChecker> { +#ifndef NDEBUG + const CXXRecordDecl *ClassType; +#endif + llvm::SmallPtrSet<const ParmVarDecl *, 16> Parms; + bool Result; + +public: + ArgumentDependenceChecker(const FunctionDecl *FD) { +#ifndef NDEBUG + if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) + ClassType = MD->getParent(); + else + ClassType = nullptr; +#endif + Parms.insert(FD->param_begin(), FD->param_end()); + } + + bool referencesArgs(Expr *E) { + Result = false; + TraverseStmt(E); + return Result; + } + + bool VisitCXXThisExpr(CXXThisExpr *E) { + assert(E->getType()->getPointeeCXXRecordDecl() == ClassType && + "`this` doesn't refer to the enclosing class?"); + Result = true; + return false; + } + + bool VisitDeclRefExpr(DeclRefExpr *DRE) { + if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) + if (Parms.count(PVD)) { + Result = true; + return false; + } + return true; + } +}; +} + +static void handleDiagnoseIfAttr(Sema &S, Decl *D, const AttributeList &Attr) { + S.Diag(Attr.getLoc(), diag::ext_clang_diagnose_if); + + Expr *Cond; + StringRef Msg; + if (!checkFunctionConditionAttr(S, D, Attr, Cond, Msg)) + return; + + StringRef DiagTypeStr; + if (!S.checkStringLiteralArgumentAttr(Attr, 2, DiagTypeStr)) + return; + + DiagnoseIfAttr::DiagnosticType DiagType; + if (!DiagnoseIfAttr::ConvertStrToDiagnosticType(DiagTypeStr, DiagType)) { + S.Diag(Attr.getArgAsExpr(2)->getLocStart(), + diag::err_diagnose_if_invalid_diagnostic_type); return; } - D->addAttr(::new (S.Context) - EnableIfAttr(Attr.getRange(), S.Context, Cond, Msg, - Attr.getAttributeSpellingListIndex())); + auto *FD = cast<FunctionDecl>(D); + bool ArgDependent = ArgumentDependenceChecker(FD).referencesArgs(Cond); + D->addAttr(::new (S.Context) DiagnoseIfAttr( + Attr.getRange(), S.Context, Cond, Msg, DiagType, ArgDependent, FD, + Attr.getAttributeSpellingListIndex())); } static void handlePassObjectSizeAttr(Sema &S, Decl *D, @@ -5682,6 +5766,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_EnableIf: handleEnableIfAttr(S, D, Attr); break; + case AttributeList::AT_DiagnoseIf: + handleDiagnoseIfAttr(S, D, Attr); + break; case AttributeList::AT_ExtVectorType: handleExtVectorTypeAttr(S, scope, D, Attr); break; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index a650621b573a..a70e16cce18c 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -5395,14 +5395,32 @@ static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) { } } -static void checkForMultipleExportedDefaultConstructors(Sema &S, CXXRecordDecl *Class) { +static void checkForMultipleExportedDefaultConstructors(Sema &S, + CXXRecordDecl *Class) { + // Only the MS ABI has default constructor closures, so we don't need to do + // this semantic checking anywhere else. + if (!S.Context.getTargetInfo().getCXXABI().isMicrosoft()) + return; + CXXConstructorDecl *LastExportedDefaultCtor = nullptr; for (Decl *Member : Class->decls()) { // Look for exported default constructors. auto *CD = dyn_cast<CXXConstructorDecl>(Member); - if (!CD || !CD->isDefaultConstructor() || !CD->hasAttr<DLLExportAttr>()) + if (!CD || !CD->isDefaultConstructor()) + continue; + auto *Attr = CD->getAttr<DLLExportAttr>(); + if (!Attr) continue; + // If the class is non-dependent, mark the default arguments as ODR-used so + // that we can properly codegen the constructor closure. + if (!Class->isDependentContext()) { + for (ParmVarDecl *PD : CD->parameters()) { + (void)S.CheckCXXDefaultArgExpr(Attr->getLocation(), CD, PD); + S.DiscardCleanupsInEvaluationContext(); + } + } + if (LastExportedDefaultCtor) { S.Diag(LastExportedDefaultCtor->getLocation(), diag::err_attribute_dll_ambiguous_default_ctor) @@ -9135,6 +9153,16 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, // invalid). if (R.empty() && NameInfo.getName().getNameKind() != DeclarationName::CXXConstructorName) { + // HACK: Work around a bug in libstdc++'s detection of ::gets. Sometimes + // it will believe that glibc provides a ::gets in cases where it does not, + // and will try to pull it into namespace std with a using-declaration. + // Just ignore the using-declaration in that case. + auto *II = NameInfo.getName().getAsIdentifierInfo(); + if (getLangOpts().CPlusPlus14 && II && II->isStr("gets") && + CurContext->isStdNamespace() && + isa<TranslationUnitDecl>(LookupContext) && + getSourceManager().isInSystemHeader(UsingLoc)) + return nullptr; if (TypoCorrection Corrected = CorrectTypo( R.getLookupNameInfo(), R.getLookupKind(), S, &SS, llvm::make_unique<UsingValidatorCCC>( @@ -9828,9 +9856,14 @@ Sema::ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc, } // Field constructors. - for (const auto *F : ClassDecl->fields()) { + for (auto *F : ClassDecl->fields()) { if (F->hasInClassInitializer()) { - if (Expr *E = F->getInClassInitializer()) + Expr *E = F->getInClassInitializer(); + if (!E) + // FIXME: It's a little wasteful to build and throw away a + // CXXDefaultInitExpr here. + E = BuildCXXDefaultInitExpr(Loc, F).get(); + if (E) ExceptSpec.CalledExpr(E); } else if (const RecordType *RecordTy = Context.getBaseElementType(F->getType())->getAs<RecordType>()) { @@ -12291,6 +12324,10 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { if (Field->getInClassInitializer()) return CXXDefaultInitExpr::Create(Context, Loc, Field); + // If we might have already tried and failed to instantiate, don't try again. + if (Field->isInvalidDecl()) + return ExprError(); + // Maybe we haven't instantiated the in-class initializer. Go check the // pattern FieldDecl to see if it has one. CXXRecordDecl *ParentRD = cast<CXXRecordDecl>(Field->getParent()); @@ -12320,8 +12357,11 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { } if (InstantiateInClassInitializer(Loc, Field, Pattern, - getTemplateInstantiationArgs(Field))) + getTemplateInstantiationArgs(Field))) { + // Don't diagnose this again. + Field->setInvalidDecl(); return ExprError(); + } return CXXDefaultInitExpr::Create(Context, Loc, Field); } @@ -12344,6 +12384,8 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { << OutermostClass << Field; Diag(Field->getLocEnd(), diag::note_in_class_initializer_not_yet_parsed); + // Don't diagnose this again. + Field->setInvalidDecl(); return ExprError(); } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 1509b22a9e5a..d62e8fd68b64 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -342,6 +342,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, } // See if this is a deleted function. + SmallVector<DiagnoseIfAttr *, 4> DiagnoseIfWarnings; if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { if (FD->isDeleted()) { auto *Ctor = dyn_cast<CXXConstructorDecl>(FD); @@ -363,6 +364,12 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, if (getLangOpts().CUDA && !CheckCUDACall(Loc, FD)) return true; + + if (const DiagnoseIfAttr *A = + checkArgIndependentDiagnoseIf(FD, DiagnoseIfWarnings)) { + emitDiagnoseIfDiagnostic(Loc, A); + return true; + } } // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions @@ -377,6 +384,10 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, Diag(D->getLocation(), diag::note_entity_declared_at) << D; return true; } + + for (const auto *W : DiagnoseIfWarnings) + emitDiagnoseIfDiagnostic(Loc, W); + DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass, ObjCPropertyAccess); @@ -5154,12 +5165,40 @@ static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context, return OverloadDecl; } -static bool isNumberOfArgsValidForCall(Sema &S, const FunctionDecl *Callee, - std::size_t NumArgs) { - if (S.TooManyArguments(Callee->getNumParams(), NumArgs, - /*PartialOverloading=*/false)) - return Callee->isVariadic(); - return Callee->getMinRequiredArguments() <= NumArgs; +static void checkDirectCallValidity(Sema &S, const Expr *Fn, + FunctionDecl *Callee, + MultiExprArg ArgExprs) { + // `Callee` (when called with ArgExprs) may be ill-formed. enable_if (and + // similar attributes) really don't like it when functions are called with an + // invalid number of args. + if (S.TooManyArguments(Callee->getNumParams(), ArgExprs.size(), + /*PartialOverloading=*/false) && + !Callee->isVariadic()) + return; + if (Callee->getMinRequiredArguments() > ArgExprs.size()) + return; + + if (const EnableIfAttr *Attr = S.CheckEnableIf(Callee, ArgExprs, true)) { + S.Diag(Fn->getLocStart(), + isa<CXXMethodDecl>(Callee) + ? diag::err_ovl_no_viable_member_function_in_call + : diag::err_ovl_no_viable_function_in_call) + << Callee << Callee->getSourceRange(); + S.Diag(Callee->getLocation(), + diag::note_ovl_candidate_disabled_by_function_cond_attr) + << Attr->getCond()->getSourceRange() << Attr->getMessage(); + return; + } + + SmallVector<DiagnoseIfAttr *, 4> Nonfatal; + if (const DiagnoseIfAttr *Attr = S.checkArgDependentDiagnoseIf( + Callee, ArgExprs, Nonfatal, /*MissingImplicitThis=*/true)) { + S.emitDiagnoseIfDiagnostic(Fn->getLocStart(), Attr); + return; + } + + for (const auto *W : Nonfatal) + S.emitDiagnoseIfDiagnostic(Fn->getLocStart(), W); } /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. @@ -5294,26 +5333,8 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, if (getLangOpts().OpenCL && checkOpenCLDisabledDecl(*FD, *Fn)) return ExprError(); - - // CheckEnableIf assumes that the we're passing in a sane number of args for - // FD, but that doesn't always hold true here. This is because, in some - // cases, we'll emit a diag about an ill-formed function call, but then - // we'll continue on as if the function call wasn't ill-formed. So, if the - // number of args looks incorrect, don't do enable_if checks; we should've - // already emitted an error about the bad call. - if (FD->hasAttr<EnableIfAttr>() && - isNumberOfArgsValidForCall(*this, FD, ArgExprs.size())) { - if (const EnableIfAttr *Attr = CheckEnableIf(FD, ArgExprs, true)) { - Diag(Fn->getLocStart(), - isa<CXXMethodDecl>(FD) - ? diag::err_ovl_no_viable_member_function_in_call - : diag::err_ovl_no_viable_function_in_call) - << FD << FD->getSourceRange(); - Diag(FD->getLocation(), - diag::note_ovl_candidate_disabled_by_enable_if_attr) - << Attr->getCond()->getSourceRange() << Attr->getMessage(); - } - } + + checkDirectCallValidity(*this, Fn, FD, ArgExprs); } return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs, RParenLoc, @@ -13097,8 +13118,16 @@ void Sema::PopExpressionEvaluationContext() { // evaluate [...] a lambda-expression. D = diag::err_lambda_in_constant_expression; } - for (const auto *L : Rec.Lambdas) - Diag(L->getLocStart(), D); + + // C++1z allows lambda expressions as core constant expressions. + // FIXME: In C++1z, reinstate the restrictions on lambda expressions (CWG + // 1607) from appearing within template-arguments and array-bounds that + // are part of function-signatures. Be mindful that P0315 (Lambdas in + // unevaluated contexts) might lift some of these restrictions in a + // future version. + if (Rec.Context != ConstantEvaluated || !getLangOpts().CPlusPlus1z) + for (const auto *L : Rec.Lambdas) + Diag(L->getLocStart(), D); } else { // Mark the capture expressions odr-used. This was deferred // during lambda expression creation. @@ -13150,41 +13179,63 @@ ExprResult Sema::HandleExprEvaluationContextForTypeof(Expr *E) { return TransformToPotentiallyEvaluated(E); } -static bool IsPotentiallyEvaluatedContext(Sema &SemaRef) { - // Do not mark anything as "used" within a dependent context; wait for - // an instantiation. - if (SemaRef.CurContext->isDependentContext()) - return false; - +/// Are we within a context in which some evaluation could be performed (be it +/// constant evaluation or runtime evaluation)? Sadly, this notion is not quite +/// captured by C++'s idea of an "unevaluated context". +static bool isEvaluatableContext(Sema &SemaRef) { switch (SemaRef.ExprEvalContexts.back().Context) { case Sema::Unevaluated: case Sema::UnevaluatedAbstract: - // We are in an expression that is not potentially evaluated; do nothing. - // (Depending on how you read the standard, we actually do need to do - // something here for null pointer constants, but the standard's - // definition of a null pointer constant is completely crazy.) + case Sema::DiscardedStatement: + // Expressions in this context are never evaluated. + return false; + + case Sema::UnevaluatedList: + case Sema::ConstantEvaluated: + case Sema::PotentiallyEvaluated: + // Expressions in this context could be evaluated. + return true; + + case Sema::PotentiallyEvaluatedIfUsed: + // Referenced declarations will only be used if the construct in the + // containing expression is used, at which point we'll be given another + // turn to mark them. return false; + } + llvm_unreachable("Invalid context"); +} +/// Are we within a context in which references to resolved functions or to +/// variables result in odr-use? +static bool isOdrUseContext(Sema &SemaRef, bool SkipDependentUses = true) { + // An expression in a template is not really an expression until it's been + // instantiated, so it doesn't trigger odr-use. + if (SkipDependentUses && SemaRef.CurContext->isDependentContext()) + return false; + + switch (SemaRef.ExprEvalContexts.back().Context) { + case Sema::Unevaluated: + case Sema::UnevaluatedList: + case Sema::UnevaluatedAbstract: case Sema::DiscardedStatement: - // These are technically a potentially evaluated but they have the effect - // of suppressing use marking. return false; case Sema::ConstantEvaluated: case Sema::PotentiallyEvaluated: - // We are in a potentially evaluated expression (or a constant-expression - // in C++03); we need to do implicit template instantiation, implicitly - // define class members, and mark most declarations as used. return true; case Sema::PotentiallyEvaluatedIfUsed: - // Referenced declarations will only be used if the construct in the - // containing expression is used. return false; } llvm_unreachable("Invalid context"); } +static bool isImplicitlyDefinableConstexprFunction(FunctionDecl *Func) { + CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Func); + return Func->isConstexpr() && + (Func->isImplicitlyInstantiable() || (MD && !MD->isUserProvided())); +} + /// \brief Mark a function referenced, and check whether it is odr-used /// (C++ [basic.def.odr]p2, C99 6.9p3) void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, @@ -13200,7 +13251,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, // // We (incorrectly) mark overload resolution as an unevaluated context, so we // can just check that here. - bool OdrUse = MightBeOdrUse && IsPotentiallyEvaluatedContext(*this); + bool OdrUse = MightBeOdrUse && isOdrUseContext(*this); // Determine whether we require a function definition to exist, per // C++11 [temp.inst]p3: @@ -13209,27 +13260,11 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, // specialization is implicitly instantiated when the specialization is // referenced in a context that requires a function definition to exist. // - // We consider constexpr function templates to be referenced in a context - // that requires a definition to exist whenever they are referenced. - // - // FIXME: This instantiates constexpr functions too frequently. If this is - // really an unevaluated context (and we're not just in the definition of a - // function template or overload resolution or other cases which we - // incorrectly consider to be unevaluated contexts), and we're not in a - // subexpression which we actually need to evaluate (for instance, a - // template argument, array bound or an expression in a braced-init-list), - // we are not permitted to instantiate this constexpr function definition. - // - // FIXME: This also implicitly defines special members too frequently. They - // are only supposed to be implicitly defined if they are odr-used, but they - // are not odr-used from constant expressions in unevaluated contexts. - // However, they cannot be referenced if they are deleted, and they are - // deleted whenever the implicit definition of the special member would - // fail (with very few exceptions). - CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Func); + // That is either when this is an odr-use, or when a usage of a constexpr + // function occurs within an evaluatable context. bool NeedDefinition = - OdrUse || (Func->isConstexpr() && (Func->isImplicitlyInstantiable() || - (MD && !MD->isUserProvided()))); + OdrUse || (isEvaluatableContext(*this) && + isImplicitlyDefinableConstexprFunction(Func)); // C++14 [temp.expl.spec]p6: // If a template [...] is explicitly specialized then that specialization @@ -14123,47 +14158,11 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, Var->setReferenced(); TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind(); - bool MarkODRUsed = true; - - // If the context is not potentially evaluated, this is not an odr-use and - // does not trigger instantiation. - if (!IsPotentiallyEvaluatedContext(SemaRef)) { - if (SemaRef.isUnevaluatedContext()) - return; - - // If we don't yet know whether this context is going to end up being an - // evaluated context, and we're referencing a variable from an enclosing - // scope, add a potential capture. - // - // FIXME: Is this necessary? These contexts are only used for default - // arguments, where local variables can't be used. - const bool RefersToEnclosingScope = - (SemaRef.CurContext != Var->getDeclContext() && - Var->getDeclContext()->isFunctionOrMethod() && Var->hasLocalStorage()); - if (RefersToEnclosingScope) { - if (LambdaScopeInfo *const LSI = - SemaRef.getCurLambda(/*IgnoreCapturedRegions=*/true)) { - // If a variable could potentially be odr-used, defer marking it so - // until we finish analyzing the full expression for any - // lvalue-to-rvalue - // or discarded value conversions that would obviate odr-use. - // Add it to the list of potential captures that will be analyzed - // later (ActOnFinishFullExpr) for eventual capture and odr-use marking - // unless the variable is a reference that was initialized by a constant - // expression (this will never need to be captured or odr-used). - assert(E && "Capture variable should be used in an expression."); - if (!Var->getType()->isReferenceType() || - !IsVariableNonDependentAndAConstantExpression(Var, SemaRef.Context)) - LSI->addPotentialCapture(E->IgnoreParens()); - } - } - if (!isTemplateInstantiation(TSK)) - return; - - // Instantiate, but do not mark as odr-used, variable templates. - MarkODRUsed = false; - } + bool OdrUseContext = isOdrUseContext(SemaRef); + bool NeedDefinition = + OdrUseContext || (isEvaluatableContext(SemaRef) && + Var->isUsableInConstantExpressions(SemaRef.Context)); VarTemplateSpecializationDecl *VarSpec = dyn_cast<VarTemplateSpecializationDecl>(Var); @@ -14173,14 +14172,15 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, // If this might be a member specialization of a static data member, check // the specialization is visible. We already did the checks for variable // template specializations when we created them. - if (TSK != TSK_Undeclared && !isa<VarTemplateSpecializationDecl>(Var)) + if (NeedDefinition && TSK != TSK_Undeclared && + !isa<VarTemplateSpecializationDecl>(Var)) SemaRef.checkSpecializationVisibility(Loc, Var); // Perform implicit instantiation of static data members, static data member // templates of class templates, and variable template specializations. Delay // instantiations of variable templates, except for those that could be used // in a constant expression. - if (isTemplateInstantiation(TSK)) { + if (NeedDefinition && isTemplateInstantiation(TSK)) { bool TryInstantiating = TSK == TSK_ImplicitInstantiation; if (TryInstantiating && !isa<VarTemplateSpecializationDecl>(Var)) { @@ -14219,9 +14219,6 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, } } - if (!MarkODRUsed) - return; - // Per C++11 [basic.def.odr], a variable is odr-used "unless it satisfies // the requirements for appearing in a constant expression (5.19) and, if // it is an object, the lvalue-to-rvalue conversion (4.1) @@ -14230,14 +14227,41 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, // Note that we use the C++11 definition everywhere because nothing in // C++03 depends on whether we get the C++03 version correct. The second // part does not apply to references, since they are not objects. - if (E && IsVariableAConstantExpression(Var, SemaRef.Context)) { + if (OdrUseContext && E && + IsVariableAConstantExpression(Var, SemaRef.Context)) { // A reference initialized by a constant expression can never be // odr-used, so simply ignore it. if (!Var->getType()->isReferenceType()) SemaRef.MaybeODRUseExprs.insert(E); - } else + } else if (OdrUseContext) { MarkVarDeclODRUsed(Var, Loc, SemaRef, /*MaxFunctionScopeIndex ptr*/ nullptr); + } else if (isOdrUseContext(SemaRef, /*SkipDependentUses*/false)) { + // If this is a dependent context, we don't need to mark variables as + // odr-used, but we may still need to track them for lambda capture. + // FIXME: Do we also need to do this inside dependent typeid expressions + // (which are modeled as unevaluated at this point)? + const bool RefersToEnclosingScope = + (SemaRef.CurContext != Var->getDeclContext() && + Var->getDeclContext()->isFunctionOrMethod() && Var->hasLocalStorage()); + if (RefersToEnclosingScope) { + if (LambdaScopeInfo *const LSI = + SemaRef.getCurLambda(/*IgnoreCapturedRegions=*/true)) { + // If a variable could potentially be odr-used, defer marking it so + // until we finish analyzing the full expression for any + // lvalue-to-rvalue + // or discarded value conversions that would obviate odr-use. + // Add it to the list of potential captures that will be analyzed + // later (ActOnFinishFullExpr) for eventual capture and odr-use marking + // unless the variable is a reference that was initialized by a constant + // expression (this will never need to be captured or odr-used). + assert(E && "Capture variable should be used in an expression."); + if (!Var->getType()->isReferenceType() || + !IsVariableNonDependentAndAConstantExpression(Var, SemaRef.Context)) + LSI->addPotentialCapture(E->IgnoreParens()); + } + } + } } /// \brief Mark a variable referenced, and check whether it is odr-used @@ -14333,9 +14357,13 @@ void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, } namespace { - // Mark all of the declarations referenced + // Mark all of the declarations used by a type as referenced. // FIXME: Not fully implemented yet! We need to have a better understanding - // of when we're entering + // of when we're entering a context we should not recurse into. + // FIXME: This is and EvaluatedExprMarker are more-or-less equivalent to + // TreeTransforms rebuilding the type in a new context. Rather than + // duplicating the TreeTransform logic, we should consider reusing it here. + // Currently that causes problems when rebuilding LambdaExprs. class MarkReferencedDecls : public RecursiveASTVisitor<MarkReferencedDecls> { Sema &S; SourceLocation Loc; @@ -14346,33 +14374,28 @@ namespace { MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) { } bool TraverseTemplateArgument(const TemplateArgument &Arg); - bool TraverseRecordType(RecordType *T); }; } bool MarkReferencedDecls::TraverseTemplateArgument( const TemplateArgument &Arg) { - if (Arg.getKind() == TemplateArgument::Declaration) { - if (Decl *D = Arg.getAsDecl()) - S.MarkAnyDeclReferenced(Loc, D, true); + { + // A non-type template argument is a constant-evaluated context. + EnterExpressionEvaluationContext Evaluated(S, Sema::ConstantEvaluated); + if (Arg.getKind() == TemplateArgument::Declaration) { + if (Decl *D = Arg.getAsDecl()) + S.MarkAnyDeclReferenced(Loc, D, true); + } else if (Arg.getKind() == TemplateArgument::Expression) { + S.MarkDeclarationsReferencedInExpr(Arg.getAsExpr(), false); + } } return Inherited::TraverseTemplateArgument(Arg); } -bool MarkReferencedDecls::TraverseRecordType(RecordType *T) { - if (ClassTemplateSpecializationDecl *Spec - = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) { - const TemplateArgumentList &Args = Spec->getTemplateArgs(); - return TraverseTemplateArguments(Args.data(), Args.size()); - } - - return true; -} - void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) { MarkReferencedDecls Marker(*this, Loc); - Marker.TraverseType(Context.getCanonicalType(T)); + Marker.TraverseType(T); } namespace { @@ -14479,6 +14502,7 @@ bool Sema::DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement, const PartialDiagnostic &PD) { switch (ExprEvalContexts.back().Context) { case Unevaluated: + case UnevaluatedList: case UnevaluatedAbstract: case DiscardedStatement: // The argument will never be evaluated, so don't complain. diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index 806a3d813ee8..c9aa99ee383c 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -134,6 +134,7 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, assert(!AbstractInstanceResult); switch (SemaRef.ExprEvalContexts.back().Context) { case Sema::Unevaluated: + case Sema::UnevaluatedList: if (isField && SemaRef.getLangOpts().CPlusPlus11) AbstractInstanceResult = IMA_Field_Uneval_Context; break; diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index befee05713e0..45eff5ee6b62 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -6561,6 +6561,13 @@ InitializationSequence::Perform(Sema &S, break; } + // Promote from an unevaluated context to an unevaluated list context in + // C++11 list-initialization; we need to instantiate entities usable in + // constant expressions here in order to perform narrowing checks =( + EnterExpressionEvaluationContext Evaluated( + S, EnterExpressionEvaluationContext::InitList, + CurInit.get() && isa<InitListExpr>(CurInit.get())); + // C++ [class.abstract]p2: // no objects of an abstract class can be created except as subobjects // of a class derived from it diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 3bae69164ffd..a0d574915eba 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -1274,7 +1274,7 @@ static void addFunctionPointerConversion(Sema &S, ConvTy, ConvTSI, /*isInline=*/true, /*isExplicit=*/false, - /*isConstexpr=*/false, + /*isConstexpr=*/S.getLangOpts().CPlusPlus1z, CallOperator->getBody()->getLocEnd()); Conversion->setAccess(AS_public); Conversion->setImplicit(true); @@ -1565,6 +1565,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, // A lambda-expression shall not appear in an unevaluated operand // (Clause 5). case Unevaluated: + case UnevaluatedList: case UnevaluatedAbstract: // C++1y [expr.const]p2: // A conditional-expression e is a core constant expression unless the diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 38a7b8c127cc..883e2ae264e9 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -2960,6 +2960,7 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, if (CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(Cand->getUnderlyingDecl())) { if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) AddMethodCandidate(M, Cand, RD, ThisTy, Classification, + /*ThisArg=*/nullptr, llvm::makeArrayRef(&Arg, NumArgs), OCS, true); else if (CtorInfo) AddOverloadCandidate(CtorInfo.Constructor, CtorInfo.FoundDecl, @@ -2972,7 +2973,7 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) AddMethodTemplateCandidate( Tmpl, Cand, RD, nullptr, ThisTy, Classification, - llvm::makeArrayRef(&Arg, NumArgs), OCS, true); + /*ThisArg=*/nullptr, llvm::makeArrayRef(&Arg, NumArgs), OCS, true); else if (CtorInfo) AddTemplateOverloadCandidate( CtorInfo.ConstructorTmpl, CtorInfo.FoundDecl, nullptr, diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 33574b9aec35..41f4fa746fc6 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -29,6 +29,7 @@ #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" @@ -589,7 +590,6 @@ clang::MakeDeductionFailureInfo(ASTContext &Context, Result.Result = static_cast<unsigned>(TDK); Result.HasDiagnostic = false; switch (TDK) { - case Sema::TDK_Success: case Sema::TDK_Invalid: case Sema::TDK_InstantiationDepth: case Sema::TDK_TooManyArguments: @@ -645,6 +645,10 @@ clang::MakeDeductionFailureInfo(ASTContext &Context, Result.HasDiagnostic = true; } break; + + case Sema::TDK_Success: + case Sema::TDK_NonDependentConversionFailure: + llvm_unreachable("not a deduction failure"); } return Result; @@ -660,6 +664,7 @@ void DeductionFailureInfo::Destroy() { case Sema::TDK_TooFewArguments: case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_CUDATargetMismatch: + case Sema::TDK_NonDependentConversionFailure: break; case Sema::TDK_Inconsistent: @@ -704,6 +709,7 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() { case Sema::TDK_DeducedMismatchNested: case Sema::TDK_NonDeducedMismatch: case Sema::TDK_CUDATargetMismatch: + case Sema::TDK_NonDependentConversionFailure: return TemplateParameter(); case Sema::TDK_Incomplete: @@ -735,6 +741,7 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() { case Sema::TDK_Underqualified: case Sema::TDK_NonDeducedMismatch: case Sema::TDK_CUDATargetMismatch: + case Sema::TDK_NonDependentConversionFailure: return nullptr; case Sema::TDK_DeducedMismatch: @@ -763,6 +770,7 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() { case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_SubstitutionFailure: case Sema::TDK_CUDATargetMismatch: + case Sema::TDK_NonDependentConversionFailure: return nullptr; case Sema::TDK_Inconsistent: @@ -791,6 +799,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() { case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_SubstitutionFailure: case Sema::TDK_CUDATargetMismatch: + case Sema::TDK_NonDependentConversionFailure: return nullptr; case Sema::TDK_Inconsistent: @@ -821,8 +830,8 @@ llvm::Optional<unsigned> DeductionFailureInfo::getCallArgIndex() { void OverloadCandidateSet::destroyCandidates() { for (iterator i = begin(), e = end(); i != e; ++i) { - for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii) - i->Conversions[ii].~ImplicitConversionSequence(); + for (auto &C : i->Conversions) + C.~ImplicitConversionSequence(); if (!i->Viable && i->FailureKind == ovl_fail_bad_deduction) i->DeductionFailure.Destroy(); } @@ -830,12 +839,20 @@ void OverloadCandidateSet::destroyCandidates() { void OverloadCandidateSet::clear() { destroyCandidates(); - ConversionSequenceAllocator.Reset(); - NumInlineSequences = 0; + // DiagnoseIfAttrs are just pointers, so we don't need to destroy them. + SlabAllocator.Reset(); + NumInlineBytesUsed = 0; Candidates.clear(); Functions.clear(); } +DiagnoseIfAttr ** +OverloadCandidateSet::addDiagnoseIfComplaints(ArrayRef<DiagnoseIfAttr *> CA) { + auto *DIA = slabAllocate<DiagnoseIfAttr *>(CA.size()); + std::uninitialized_copy(CA.begin(), CA.end(), DIA); + return DIA; +} + namespace { class UnbridgedCastsSet { struct Entry { @@ -5814,6 +5831,28 @@ static bool IsAcceptableNonMemberOperatorCandidate(ASTContext &Context, return false; } +static void initDiagnoseIfComplaint(Sema &S, OverloadCandidateSet &CandidateSet, + OverloadCandidate &Candidate, + FunctionDecl *Function, + ArrayRef<Expr *> Args, + bool MissingImplicitThis = false, + Expr *ExplicitThis = nullptr) { + SmallVector<DiagnoseIfAttr *, 8> Results; + if (DiagnoseIfAttr *DIA = S.checkArgDependentDiagnoseIf( + Function, Args, Results, MissingImplicitThis, ExplicitThis)) { + Results.clear(); + Results.push_back(DIA); + } + + Candidate.NumTriggeredDiagnoseIfs = Results.size(); + if (Results.empty()) + Candidate.DiagnoseIfInfo = nullptr; + else if (Results.size() == 1) + Candidate.DiagnoseIfInfo = Results[0]; + else + Candidate.DiagnoseIfInfo = CandidateSet.addDiagnoseIfComplaints(Results); +} + /// AddOverloadCandidate - Adds the given function to the set of /// candidate functions, using the given function call arguments. If /// @p SuppressUserConversions, then don't allow user-defined @@ -5829,7 +5868,8 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, bool PartialOverloading, - bool AllowExplicit) { + bool AllowExplicit, + ConversionSequenceList EarlyConversions) { const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>()); assert(Proto && "Functions without a prototype cannot be overloaded"); @@ -5845,10 +5885,11 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // function, e.g., X::f(). We use an empty type for the implied // object argument (C++ [over.call.func]p3), and the acting context // is irrelevant. - AddMethodCandidate(Method, FoundDecl, Method->getParent(), - QualType(), Expr::Classification::makeSimpleLValue(), - Args, CandidateSet, SuppressUserConversions, - PartialOverloading); + AddMethodCandidate(Method, FoundDecl, Method->getParent(), QualType(), + Expr::Classification::makeSimpleLValue(), + /*ThisArg=*/nullptr, Args, CandidateSet, + SuppressUserConversions, PartialOverloading, + EarlyConversions); return; } // We treat a constructor like a non-member function, since its object @@ -5881,7 +5922,8 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); // Add this candidate - OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size()); + OverloadCandidate &Candidate = + CandidateSet.addCandidate(Args.size(), EarlyConversions); Candidate.FoundDecl = FoundDecl; Candidate.Function = Function; Candidate.Viable = true; @@ -5945,7 +5987,10 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // Determine the implicit conversion sequences for each of the // arguments. for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) { - if (ArgIdx < NumParams) { + if (Candidate.Conversions[ArgIdx].isInitialized()) { + // We already formed a conversion sequence for this parameter during + // template argument deduction. + } else if (ArgIdx < NumParams) { // (C++ 13.3.2p3): for F to be a viable function, there shall // exist for each argument an implicit conversion sequence // (13.3.3.1) that converts that argument to the corresponding @@ -5971,6 +6016,31 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, } } + // C++ [over.best.ics]p4+: (proposed DR resolution) + // If the target is the first parameter of an inherited constructor when + // constructing an object of type C with an argument list that has exactly + // one expression, an implicit conversion sequence cannot be formed if C is + // reference-related to the type that the argument would have after the + // application of the user-defined conversion (if any) and before the final + // standard conversion sequence. + auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(FoundDecl.getDecl()); + if (Shadow && Args.size() == 1 && !isa<InitListExpr>(Args.front())) { + bool DerivedToBase, ObjCConversion, ObjCLifetimeConversion; + QualType ConvertedArgumentType = Args.front()->getType(); + if (Candidate.Conversions[0].isUserDefined()) + ConvertedArgumentType = + Candidate.Conversions[0].UserDefined.After.getFromType(); + if (CompareReferenceRelationship(Args.front()->getLocStart(), + Context.getRecordType(Shadow->getParent()), + ConvertedArgumentType, DerivedToBase, + ObjCConversion, + ObjCLifetimeConversion) >= Ref_Related) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_inhctor_slice; + return; + } + } + if (EnableIfAttr *FailedAttr = CheckEnableIf(Function, Args)) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_enable_if; @@ -5983,6 +6053,8 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, Candidate.FailureKind = ovl_fail_ext_disabled; return; } + + initDiagnoseIfComplaint(*this, CandidateSet, Candidate, Function, Args); } ObjCMethodDecl * @@ -6095,66 +6167,87 @@ getOrderedEnableIfAttrs(const FunctionDecl *Function) { return Result; } -EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args, - bool MissingImplicitThis) { - auto EnableIfAttrs = getOrderedEnableIfAttrs(Function); - if (EnableIfAttrs.empty()) - return nullptr; - - SFINAETrap Trap(*this); - SmallVector<Expr *, 16> ConvertedArgs; - bool InitializationFailed = false; +static bool +convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg, + ArrayRef<Expr *> Args, Sema::SFINAETrap &Trap, + bool MissingImplicitThis, Expr *&ConvertedThis, + SmallVectorImpl<Expr *> &ConvertedArgs) { + if (ThisArg) { + CXXMethodDecl *Method = cast<CXXMethodDecl>(Function); + assert(!isa<CXXConstructorDecl>(Method) && + "Shouldn't have `this` for ctors!"); + assert(!Method->isStatic() && "Shouldn't have `this` for static methods!"); + ExprResult R = S.PerformObjectArgumentInitialization( + ThisArg, /*Qualifier=*/nullptr, Method, Method); + if (R.isInvalid()) + return false; + ConvertedThis = R.get(); + } else { + if (auto *MD = dyn_cast<CXXMethodDecl>(Function)) { + (void)MD; + assert((MissingImplicitThis || MD->isStatic() || + isa<CXXConstructorDecl>(MD)) && + "Expected `this` for non-ctor instance methods"); + } + ConvertedThis = nullptr; + } // Ignore any variadic arguments. Converting them is pointless, since the - // user can't refer to them in the enable_if condition. + // user can't refer to them in the function condition. unsigned ArgSizeNoVarargs = std::min(Function->param_size(), Args.size()); // Convert the arguments. for (unsigned I = 0; I != ArgSizeNoVarargs; ++I) { ExprResult R; - if (I == 0 && !MissingImplicitThis && isa<CXXMethodDecl>(Function) && - !cast<CXXMethodDecl>(Function)->isStatic() && - !isa<CXXConstructorDecl>(Function)) { - CXXMethodDecl *Method = cast<CXXMethodDecl>(Function); - R = PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/nullptr, - Method, Method); - } else { - R = PerformCopyInitialization(InitializedEntity::InitializeParameter( - Context, Function->getParamDecl(I)), + R = S.PerformCopyInitialization(InitializedEntity::InitializeParameter( + S.Context, Function->getParamDecl(I)), SourceLocation(), Args[I]); - } - if (R.isInvalid()) { - InitializationFailed = true; - break; - } + if (R.isInvalid()) + return false; ConvertedArgs.push_back(R.get()); } - if (InitializationFailed || Trap.hasErrorOccurred()) - return EnableIfAttrs[0]; + if (Trap.hasErrorOccurred()) + return false; // Push default arguments if needed. if (!Function->isVariadic() && Args.size() < Function->getNumParams()) { for (unsigned i = Args.size(), e = Function->getNumParams(); i != e; ++i) { ParmVarDecl *P = Function->getParamDecl(i); - ExprResult R = PerformCopyInitialization( - InitializedEntity::InitializeParameter(Context, + ExprResult R = S.PerformCopyInitialization( + InitializedEntity::InitializeParameter(S.Context, Function->getParamDecl(i)), SourceLocation(), P->hasUninstantiatedDefaultArg() ? P->getUninstantiatedDefaultArg() : P->getDefaultArg()); - if (R.isInvalid()) { - InitializationFailed = true; - break; - } + if (R.isInvalid()) + return false; ConvertedArgs.push_back(R.get()); } - if (InitializationFailed || Trap.hasErrorOccurred()) - return EnableIfAttrs[0]; + if (Trap.hasErrorOccurred()) + return false; } + return true; +} + +EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args, + bool MissingImplicitThis) { + SmallVector<EnableIfAttr *, 4> EnableIfAttrs = + getOrderedEnableIfAttrs(Function); + if (EnableIfAttrs.empty()) + return nullptr; + + SFINAETrap Trap(*this); + SmallVector<Expr *, 16> ConvertedArgs; + // FIXME: We should look into making enable_if late-parsed. + Expr *DiscardedThis; + if (!convertArgsForAvailabilityChecks( + *this, Function, /*ThisArg=*/nullptr, Args, Trap, + /*MissingImplicitThis=*/true, DiscardedThis, ConvertedArgs)) + return EnableIfAttrs[0]; for (auto *EIA : EnableIfAttrs) { APValue Result; @@ -6170,6 +6263,87 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args, return nullptr; } +static bool gatherDiagnoseIfAttrs(FunctionDecl *Function, bool ArgDependent, + SmallVectorImpl<DiagnoseIfAttr *> &Errors, + SmallVectorImpl<DiagnoseIfAttr *> &Nonfatal) { + for (auto *DIA : Function->specific_attrs<DiagnoseIfAttr>()) + if (ArgDependent == DIA->getArgDependent()) { + if (DIA->isError()) + Errors.push_back(DIA); + else + Nonfatal.push_back(DIA); + } + + return !Errors.empty() || !Nonfatal.empty(); +} + +template <typename CheckFn> +static DiagnoseIfAttr * +checkDiagnoseIfAttrsWith(const SmallVectorImpl<DiagnoseIfAttr *> &Errors, + SmallVectorImpl<DiagnoseIfAttr *> &Nonfatal, + CheckFn &&IsSuccessful) { + // Note that diagnose_if attributes are late-parsed, so they appear in the + // correct order (unlike enable_if attributes). + auto ErrAttr = llvm::find_if(Errors, IsSuccessful); + if (ErrAttr != Errors.end()) + return *ErrAttr; + + llvm::erase_if(Nonfatal, [&](DiagnoseIfAttr *A) { return !IsSuccessful(A); }); + return nullptr; +} + +DiagnoseIfAttr * +Sema::checkArgDependentDiagnoseIf(FunctionDecl *Function, ArrayRef<Expr *> Args, + SmallVectorImpl<DiagnoseIfAttr *> &Nonfatal, + bool MissingImplicitThis, + Expr *ThisArg) { + SmallVector<DiagnoseIfAttr *, 4> Errors; + if (!gatherDiagnoseIfAttrs(Function, /*ArgDependent=*/true, Errors, Nonfatal)) + return nullptr; + + SFINAETrap Trap(*this); + SmallVector<Expr *, 16> ConvertedArgs; + Expr *ConvertedThis; + if (!convertArgsForAvailabilityChecks(*this, Function, ThisArg, Args, Trap, + MissingImplicitThis, ConvertedThis, + ConvertedArgs)) + return nullptr; + + return checkDiagnoseIfAttrsWith(Errors, Nonfatal, [&](DiagnoseIfAttr *DIA) { + APValue Result; + // It's sane to use the same ConvertedArgs for any redecl of this function, + // since EvaluateWithSubstitution only cares about the position of each + // argument in the arg list, not the ParmVarDecl* it maps to. + if (!DIA->getCond()->EvaluateWithSubstitution( + Result, Context, DIA->getParent(), ConvertedArgs, ConvertedThis)) + return false; + return Result.isInt() && Result.getInt().getBoolValue(); + }); +} + +DiagnoseIfAttr *Sema::checkArgIndependentDiagnoseIf( + FunctionDecl *Function, SmallVectorImpl<DiagnoseIfAttr *> &Nonfatal) { + SmallVector<DiagnoseIfAttr *, 4> Errors; + if (!gatherDiagnoseIfAttrs(Function, /*ArgDependent=*/false, Errors, + Nonfatal)) + return nullptr; + + return checkDiagnoseIfAttrsWith(Errors, Nonfatal, [&](DiagnoseIfAttr *DIA) { + bool Result; + return DIA->getCond()->EvaluateAsBooleanCondition(Result, Context) && + Result; + }); +} + +void Sema::emitDiagnoseIfDiagnostic(SourceLocation Loc, + const DiagnoseIfAttr *DIA) { + auto Code = DIA->isError() ? diag::err_diagnose_if_succeeded + : diag::warn_diagnose_if_succeeded; + Diag(Loc, Code) << DIA->getMessage(); + Diag(DIA->getLocation(), diag::note_from_diagnose_if) + << DIA->getParent() << DIA->getCond()->getSourceRange(); +} + /// \brief Add all of the function declarations in the given function set to /// the overload candidate set. void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, @@ -6185,7 +6359,7 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(), cast<CXXMethodDecl>(FD)->getParent(), Args[0]->getType(), Args[0]->Classify(Context), - Args.slice(1), CandidateSet, + Args[0], Args.slice(1), CandidateSet, SuppressUserConversions, PartialOverloading); else AddOverloadCandidate(FD, F.getPair(), Args, CandidateSet, @@ -6194,13 +6368,12 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D); if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) && !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic()) - AddMethodTemplateCandidate(FunTmpl, F.getPair(), - cast<CXXRecordDecl>(FunTmpl->getDeclContext()), - ExplicitTemplateArgs, - Args[0]->getType(), - Args[0]->Classify(Context), Args.slice(1), - CandidateSet, SuppressUserConversions, - PartialOverloading); + AddMethodTemplateCandidate( + FunTmpl, F.getPair(), + cast<CXXRecordDecl>(FunTmpl->getDeclContext()), + ExplicitTemplateArgs, Args[0]->getType(), + Args[0]->Classify(Context), Args[0], Args.slice(1), CandidateSet, + SuppressUserConversions, PartialOverloading); else AddTemplateOverloadCandidate(FunTmpl, F.getPair(), ExplicitTemplateArgs, Args, @@ -6215,6 +6388,7 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType, Expr::Classification ObjectClassification, + Expr *ThisArg, ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions) { @@ -6230,12 +6404,12 @@ void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, AddMethodTemplateCandidate(TD, FoundDecl, ActingContext, /*ExplicitArgs*/ nullptr, ObjectType, ObjectClassification, - Args, CandidateSet, + ThisArg, Args, CandidateSet, SuppressUserConversions); } else { AddMethodCandidate(cast<CXXMethodDecl>(Decl), FoundDecl, ActingContext, ObjectType, ObjectClassification, - Args, + ThisArg, Args, CandidateSet, SuppressUserConversions); } } @@ -6251,10 +6425,11 @@ void Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, QualType ObjectType, Expr::Classification ObjectClassification, - ArrayRef<Expr *> Args, + Expr *ThisArg, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, - bool PartialOverloading) { + bool PartialOverloading, + ConversionSequenceList EarlyConversions) { const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>()); assert(Proto && "Methods without a prototype cannot be overloaded"); @@ -6275,7 +6450,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); // Add this candidate - OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size() + 1); + OverloadCandidate &Candidate = + CandidateSet.addCandidate(Args.size() + 1, EarlyConversions); Candidate.FoundDecl = FoundDecl; Candidate.Function = Method; Candidate.IsSurrogate = false; @@ -6337,7 +6513,10 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, // Determine the implicit conversion sequences for each of the // arguments. for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) { - if (ArgIdx < NumParams) { + if (Candidate.Conversions[ArgIdx + 1].isInitialized()) { + // We already formed a conversion sequence for this parameter during + // template argument deduction. + } else if (ArgIdx < NumParams) { // (C++ 13.3.2p3): for F to be a viable function, there shall // exist for each argument an implicit conversion sequence // (13.3.3.1) that converts that argument to the corresponding @@ -6368,6 +6547,9 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, Candidate.DeductionFailure.Data = FailedAttr; return; } + + initDiagnoseIfComplaint(*this, CandidateSet, Candidate, Method, Args, + /*MissingImplicitThis=*/!ThisArg, ThisArg); } /// \brief Add a C++ member function template as a candidate to the candidate @@ -6380,6 +6562,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, Expr::Classification ObjectClassification, + Expr *ThisArg, ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions, @@ -6398,19 +6581,30 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, // functions. TemplateDeductionInfo Info(CandidateSet.getLocation()); FunctionDecl *Specialization = nullptr; - if (TemplateDeductionResult Result - = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, Args, - Specialization, Info, PartialOverloading)) { - OverloadCandidate &Candidate = CandidateSet.addCandidate(); + ConversionSequenceList Conversions; + if (TemplateDeductionResult Result = DeduceTemplateArguments( + MethodTmpl, ExplicitTemplateArgs, Args, Specialization, Info, + PartialOverloading, [&](ArrayRef<QualType> ParamTypes) { + return CheckNonDependentConversions( + MethodTmpl, ParamTypes, Args, CandidateSet, Conversions, + SuppressUserConversions, ActingContext, ObjectType, + ObjectClassification); + })) { + OverloadCandidate &Candidate = + CandidateSet.addCandidate(Conversions.size(), Conversions); Candidate.FoundDecl = FoundDecl; Candidate.Function = MethodTmpl->getTemplatedDecl(); Candidate.Viable = false; - Candidate.FailureKind = ovl_fail_bad_deduction; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; Candidate.ExplicitCallArguments = Args.size(); - Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, - Info); + if (Result == TDK_NonDependentConversionFailure) + Candidate.FailureKind = ovl_fail_bad_conversion; + else { + Candidate.FailureKind = ovl_fail_bad_deduction; + Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, + Info); + } return; } @@ -6420,8 +6614,9 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, assert(isa<CXXMethodDecl>(Specialization) && "Specialization is not a member function?"); AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl, - ActingContext, ObjectType, ObjectClassification, Args, - CandidateSet, SuppressUserConversions, PartialOverloading); + ActingContext, ObjectType, ObjectClassification, + /*ThisArg=*/ThisArg, Args, CandidateSet, + SuppressUserConversions, PartialOverloading, Conversions); } /// \brief Add a C++ function template specialization as a candidate @@ -6449,19 +6644,29 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, // functions. TemplateDeductionInfo Info(CandidateSet.getLocation()); FunctionDecl *Specialization = nullptr; - if (TemplateDeductionResult Result - = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, Args, - Specialization, Info, PartialOverloading)) { - OverloadCandidate &Candidate = CandidateSet.addCandidate(); + ConversionSequenceList Conversions; + if (TemplateDeductionResult Result = DeduceTemplateArguments( + FunctionTemplate, ExplicitTemplateArgs, Args, Specialization, Info, + PartialOverloading, [&](ArrayRef<QualType> ParamTypes) { + return CheckNonDependentConversions(FunctionTemplate, ParamTypes, + Args, CandidateSet, Conversions, + SuppressUserConversions); + })) { + OverloadCandidate &Candidate = + CandidateSet.addCandidate(Conversions.size(), Conversions); Candidate.FoundDecl = FoundDecl; Candidate.Function = FunctionTemplate->getTemplatedDecl(); Candidate.Viable = false; - Candidate.FailureKind = ovl_fail_bad_deduction; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; Candidate.ExplicitCallArguments = Args.size(); - Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, - Info); + if (Result == TDK_NonDependentConversionFailure) + Candidate.FailureKind = ovl_fail_bad_conversion; + else { + Candidate.FailureKind = ovl_fail_bad_deduction; + Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, + Info); + } return; } @@ -6469,7 +6674,64 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, // deduction as a candidate. assert(Specialization && "Missing function template specialization?"); AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet, - SuppressUserConversions, PartialOverloading); + SuppressUserConversions, PartialOverloading, + /*AllowExplicit*/false, Conversions); +} + +/// Check that implicit conversion sequences can be formed for each argument +/// whose corresponding parameter has a non-dependent type, per DR1391's +/// [temp.deduct.call]p10. +bool Sema::CheckNonDependentConversions( + FunctionTemplateDecl *FunctionTemplate, ArrayRef<QualType> ParamTypes, + ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, + ConversionSequenceList &Conversions, bool SuppressUserConversions, + CXXRecordDecl *ActingContext, QualType ObjectType, + Expr::Classification ObjectClassification) { + // FIXME: The cases in which we allow explicit conversions for constructor + // arguments never consider calling a constructor template. It's not clear + // that is correct. + const bool AllowExplicit = false; + + auto *FD = FunctionTemplate->getTemplatedDecl(); + auto *Method = dyn_cast<CXXMethodDecl>(FD); + bool HasThisConversion = Method && !isa<CXXConstructorDecl>(Method); + unsigned ThisConversions = HasThisConversion ? 1 : 0; + + Conversions = + CandidateSet.allocateConversionSequences(ThisConversions + Args.size()); + + // Overload resolution is always an unevaluated context. + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); + + // For a method call, check the 'this' conversion here too. DR1391 doesn't + // require that, but this check should never result in a hard error, and + // overload resolution is permitted to sidestep instantiations. + if (HasThisConversion && !cast<CXXMethodDecl>(FD)->isStatic() && + !ObjectType.isNull()) { + Conversions[0] = TryObjectArgumentInitialization( + *this, CandidateSet.getLocation(), ObjectType, ObjectClassification, + Method, ActingContext); + if (Conversions[0].isBad()) + return true; + } + + for (unsigned I = 0, N = std::min(ParamTypes.size(), Args.size()); I != N; + ++I) { + QualType ParamType = ParamTypes[I]; + if (!ParamType->isDependentType()) { + Conversions[ThisConversions + I] + = TryCopyInitialization(*this, Args[I], ParamType, + SuppressUserConversions, + /*InOverloadResolution=*/true, + /*AllowObjCWritebackConversion=*/ + getLangOpts().ObjCAutoRefCount, + AllowExplicit); + if (Conversions[ThisConversions + I].isBad()) + return true; + } + } + + return false; } /// Determine whether this is an allowable conversion from the result @@ -6677,6 +6939,8 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, Candidate.DeductionFailure.Data = FailedAttr; return; } + + initDiagnoseIfComplaint(*this, CandidateSet, Candidate, Conversion, None, false, From); } /// \brief Adds a conversion function template specialization @@ -6829,6 +7093,8 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, Candidate.DeductionFailure.Data = FailedAttr; return; } + + initDiagnoseIfComplaint(*this, CandidateSet, Candidate, Conversion, None); } /// \brief Add overload candidates for overloaded operators that are @@ -6877,10 +7143,8 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, Oper != OperEnd; ++Oper) AddMethodCandidate(Oper.getPair(), Args[0]->getType(), - Args[0]->Classify(Context), - Args.slice(1), - CandidateSet, - /* SuppressUserConversions = */ false); + Args[0]->Classify(Context), Args[0], Args.slice(1), + CandidateSet, /*SuppressUserConversions=*/false); } } @@ -8708,8 +8972,8 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1, // Define functions that don't require ill-formed conversions for a given // argument to be better candidates than functions that do. - unsigned NumArgs = Cand1.NumConversions; - assert(Cand2.NumConversions == NumArgs && "Overload candidate mismatch"); + unsigned NumArgs = Cand1.Conversions.size(); + assert(Cand2.Conversions.size() == NumArgs && "Overload candidate mismatch"); bool HasBetterConversion = false; for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) { bool Cand1Bad = IsIllFormedConversion(Cand1.Conversions[ArgIdx]); @@ -8911,6 +9175,17 @@ void Sema::diagnoseEquivalentInternalLinkageDeclarations( } } +static bool isCandidateUnavailableDueToDiagnoseIf(const OverloadCandidate &OC) { + ArrayRef<DiagnoseIfAttr *> Info = OC.getDiagnoseIfInfo(); + if (!Info.empty() && Info[0]->isError()) + return true; + + assert(llvm::all_of(Info, + [](const DiagnoseIfAttr *A) { return !A->isError(); }) && + "DiagnoseIf info shouldn't have mixed warnings and errors."); + return false; +} + /// \brief Computes the best viable function (C++ 13.3.3) /// within an overload candidate set. /// @@ -8989,13 +9264,19 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, // Best is the best viable function. if (Best->Function && (Best->Function->isDeleted() || - S.isFunctionConsideredUnavailable(Best->Function))) + S.isFunctionConsideredUnavailable(Best->Function) || + isCandidateUnavailableDueToDiagnoseIf(*Best))) return OR_Deleted; if (!EquivalentCands.empty()) S.diagnoseEquivalentInternalLinkageDeclarations(Loc, Best->Function, EquivalentCands); + for (const auto *W : Best->getDiagnoseIfInfo()) { + assert(W->isWarning() && "Errors should've been caught earlier!"); + S.emitDiagnoseIfDiagnostic(Loc, W); + } + return OR_Success; } @@ -9836,7 +10117,7 @@ static void DiagnoseFailedEnableIfAttr(Sema &S, OverloadCandidate *Cand) { EnableIfAttr *Attr = static_cast<EnableIfAttr*>(Cand->DeductionFailure.Data); S.Diag(Callee->getLocation(), - diag::note_ovl_candidate_disabled_by_enable_if_attr) + diag::note_ovl_candidate_disabled_by_function_cond_attr) << Attr->getCond()->getSourceRange() << Attr->getMessage(); } @@ -9866,21 +10147,28 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, FunctionDecl *Fn = Cand->Function; // Note deleted candidates, but only if they're viable. - if (Cand->Viable && (Fn->isDeleted() || - S.isFunctionConsideredUnavailable(Fn))) { - std::string FnDesc; - OverloadCandidateKind FnKind = + if (Cand->Viable) { + if (Fn->isDeleted() || S.isFunctionConsideredUnavailable(Fn)) { + std::string FnDesc; + OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc); - S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted) - << FnKind << FnDesc - << (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0); - MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); - return; - } + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted) + << FnKind << FnDesc + << (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0); + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); + return; + } + if (isCandidateUnavailableDueToDiagnoseIf(*Cand)) { + auto *A = Cand->DiagnoseIfInfo.get<DiagnoseIfAttr *>(); + assert(A->isError() && "Non-error diagnose_if disables a candidate?"); + S.Diag(Cand->Function->getLocation(), + diag::note_ovl_candidate_disabled_by_function_cond_attr) + << A->getCond()->getSourceRange() << A->getMessage(); + return; + } - // We don't really have anything else to say about viable candidates. - if (Cand->Viable) { + // We don't really have anything else to say about viable candidates. S.NoteOverloadCandidate(Cand->FoundDecl, Fn); return; } @@ -9908,7 +10196,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, case ovl_fail_bad_conversion: { unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0); - for (unsigned N = Cand->NumConversions; I != N; ++I) + for (unsigned N = Cand->Conversions.size(); I != N; ++I) if (Cand->Conversions[I].isBad()) return DiagnoseBadConversion(S, Cand, I, TakingCandidateAddress); @@ -9927,6 +10215,12 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, case ovl_fail_ext_disabled: return DiagnoseOpenCLExtensionDisabled(S, Cand); + case ovl_fail_inhctor_slice: + S.Diag(Fn->getLocation(), + diag::note_ovl_candidate_inherited_constructor_slice); + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); + return; + case ovl_fail_addr_not_available: { bool Available = checkAddressOfCandidateIsAvailable(S, Cand->Function); (void)Available; @@ -9971,12 +10265,12 @@ static void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) { static void NoteBuiltinOperatorCandidate(Sema &S, StringRef Opc, SourceLocation OpLoc, OverloadCandidate *Cand) { - assert(Cand->NumConversions <= 2 && "builtin operator is not binary"); + assert(Cand->Conversions.size() <= 2 && "builtin operator is not binary"); std::string TypeStr("operator"); TypeStr += Opc; TypeStr += "("; TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString(); - if (Cand->NumConversions == 1) { + if (Cand->Conversions.size() == 1) { TypeStr += ")"; S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr; } else { @@ -9989,9 +10283,7 @@ static void NoteBuiltinOperatorCandidate(Sema &S, StringRef Opc, static void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc, OverloadCandidate *Cand) { - unsigned NoOperands = Cand->NumConversions; - for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) { - const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx]; + for (const ImplicitConversionSequence &ICS : Cand->Conversions) { if (ICS.isBad()) break; // all meaningless after first invalid if (!ICS.isAmbiguous()) continue; @@ -10011,7 +10303,8 @@ static SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) { static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) { switch ((Sema::TemplateDeductionResult)DFI.Result) { case Sema::TDK_Success: - llvm_unreachable("TDK_success while diagnosing bad deduction"); + case Sema::TDK_NonDependentConversionFailure: + llvm_unreachable("non-deduction failure while diagnosing bad deduction"); case Sema::TDK_Invalid: case Sema::TDK_Incomplete: @@ -10114,11 +10407,11 @@ struct CompareOverloadCandidatesForDisplay { // If there's any ordering between the defined conversions... // FIXME: this might not be transitive. - assert(L->NumConversions == R->NumConversions); + assert(L->Conversions.size() == R->Conversions.size()); int leftBetter = 0; unsigned I = (L->IgnoreObjectArgument || R->IgnoreObjectArgument); - for (unsigned E = L->NumConversions; I != E; ++I) { + for (unsigned E = L->Conversions.size(); I != E; ++I) { switch (CompareImplicitConversionSequences(S, Loc, L->Conversions[I], R->Conversions[I])) { @@ -10167,7 +10460,8 @@ struct CompareOverloadCandidatesForDisplay { } /// CompleteNonViableCandidate - Normally, overload resolution only -/// computes up to the first. Produces the FixIt set if possible. +/// computes up to the first bad conversion. Produces the FixIt set if +/// possible. static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, ArrayRef<Expr *> Args) { assert(!Cand->Viable); @@ -10180,30 +10474,24 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, // Use a implicit copy initialization to check conversion fixes. Cand->Fix.setConversionChecker(TryCopyInitialization); - // Skip forward to the first bad conversion. - unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0); - unsigned ConvCount = Cand->NumConversions; - while (true) { + // Attempt to fix the bad conversion. + unsigned ConvCount = Cand->Conversions.size(); + for (unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0); /**/; + ++ConvIdx) { assert(ConvIdx != ConvCount && "no bad conversion in candidate"); - ConvIdx++; - if (Cand->Conversions[ConvIdx - 1].isBad()) { - Unfixable = !Cand->TryToFixBadConversion(ConvIdx - 1, S); + if (Cand->Conversions[ConvIdx].isInitialized() && + Cand->Conversions[ConvIdx].isBad()) { + Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S); break; } } - if (ConvIdx == ConvCount) - return; - - assert(!Cand->Conversions[ConvIdx].isInitialized() && - "remaining conversion is initialized?"); - // FIXME: this should probably be preserved from the overload // operation somehow. bool SuppressUserConversions = false; - const FunctionProtoType* Proto; - unsigned ArgIdx = ConvIdx; + const FunctionProtoType *Proto; + unsigned ArgIdx = 0; if (Cand->IsSurrogate) { QualType ConvType @@ -10211,40 +10499,56 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>()) ConvType = ConvPtrType->getPointeeType(); Proto = ConvType->getAs<FunctionProtoType>(); - ArgIdx--; + ArgIdx = 1; } else if (Cand->Function) { Proto = Cand->Function->getType()->getAs<FunctionProtoType>(); if (isa<CXXMethodDecl>(Cand->Function) && !isa<CXXConstructorDecl>(Cand->Function)) - ArgIdx--; + ArgIdx = 1; } else { // Builtin binary operator with a bad first conversion. assert(ConvCount <= 3); - for (; ConvIdx != ConvCount; ++ConvIdx) - Cand->Conversions[ConvIdx] - = TryCopyInitialization(S, Args[ConvIdx], - Cand->BuiltinTypes.ParamTypes[ConvIdx], - SuppressUserConversions, - /*InOverloadResolution*/ true, - /*AllowObjCWritebackConversion=*/ - S.getLangOpts().ObjCAutoRefCount); + for (unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0); + ConvIdx != ConvCount; ++ConvIdx) { + if (Cand->Conversions[ConvIdx].isInitialized()) + continue; + if (Cand->BuiltinTypes.ParamTypes[ConvIdx]->isDependentType()) + Cand->Conversions[ConvIdx].setAsIdentityConversion( + Args[ConvIdx]->getType()); + else + Cand->Conversions[ConvIdx] = TryCopyInitialization( + S, Args[ConvIdx], Cand->BuiltinTypes.ParamTypes[ConvIdx], + SuppressUserConversions, + /*InOverloadResolution*/ true, + /*AllowObjCWritebackConversion=*/ + S.getLangOpts().ObjCAutoRefCount); + // FIXME: If the conversion is bad, try to fix it. + } return; } // Fill in the rest of the conversions. unsigned NumParams = Proto->getNumParams(); - for (; ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) { - if (ArgIdx < NumParams) { - Cand->Conversions[ConvIdx] = TryCopyInitialization( - S, Args[ArgIdx], Proto->getParamType(ArgIdx), SuppressUserConversions, - /*InOverloadResolution=*/true, - /*AllowObjCWritebackConversion=*/ - S.getLangOpts().ObjCAutoRefCount); - // Store the FixIt in the candidate if it exists. - if (!Unfixable && Cand->Conversions[ConvIdx].isBad()) - Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S); - } - else + for (unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0); + ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) { + if (Cand->Conversions[ConvIdx].isInitialized()) { + // Found the bad conversion. + } else if (ArgIdx < NumParams) { + if (Proto->getParamType(ArgIdx)->isDependentType()) + Cand->Conversions[ConvIdx].setAsIdentityConversion( + Args[ArgIdx]->getType()); + else { + Cand->Conversions[ConvIdx] = + TryCopyInitialization(S, Args[ArgIdx], Proto->getParamType(ArgIdx), + SuppressUserConversions, + /*InOverloadResolution=*/true, + /*AllowObjCWritebackConversion=*/ + S.getLangOpts().ObjCAutoRefCount); + // Store the FixIt in the candidate if it exists. + if (!Unfixable && Cand->Conversions[ConvIdx].isBad()) + Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S); + } + } else Cand->Conversions[ConvIdx].setEllipsis(); } } @@ -12429,6 +12733,16 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, TemplateArgs = &TemplateArgsBuffer; } + // Poor-programmer's Lazy<Expr *>; isImplicitAccess requires stripping + // parens/casts, which would be nice to avoid potentially doing multiple + // times. + llvm::Optional<Expr *> UnresolvedBase; + auto GetUnresolvedBase = [&] { + if (!UnresolvedBase.hasValue()) + UnresolvedBase = + UnresExpr->isImplicitAccess() ? nullptr : UnresExpr->getBase(); + return *UnresolvedBase; + }; for (UnresolvedMemberExpr::decls_iterator I = UnresExpr->decls_begin(), E = UnresExpr->decls_end(); I != E; ++I) { @@ -12449,14 +12763,15 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, continue; AddMethodCandidate(Method, I.getPair(), ActingDC, ObjectType, - ObjectClassification, Args, CandidateSet, + ObjectClassification, + /*ThisArg=*/GetUnresolvedBase(), Args, CandidateSet, /*SuppressUserConversions=*/false); } else { - AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func), - I.getPair(), ActingDC, TemplateArgs, - ObjectType, ObjectClassification, - Args, CandidateSet, - /*SuppressUsedConversions=*/false); + AddMethodTemplateCandidate( + cast<FunctionTemplateDecl>(Func), I.getPair(), ActingDC, + TemplateArgs, ObjectType, ObjectClassification, + /*ThisArg=*/GetUnresolvedBase(), Args, CandidateSet, + /*SuppressUsedConversions=*/false); } } @@ -12569,10 +12884,20 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, diag::err_ovl_no_viable_member_function_in_call) << Method << Method->getSourceRange(); Diag(Method->getLocation(), - diag::note_ovl_candidate_disabled_by_enable_if_attr) + diag::note_ovl_candidate_disabled_by_function_cond_attr) << Attr->getCond()->getSourceRange() << Attr->getMessage(); return ExprError(); } + + SmallVector<DiagnoseIfAttr *, 4> Nonfatal; + if (const DiagnoseIfAttr *Attr = checkArgDependentDiagnoseIf( + Method, Args, Nonfatal, false, MemE->getBase())) { + emitDiagnoseIfDiagnostic(MemE->getMemberLoc(), Attr); + return ExprError(); + } + + for (const auto *Attr : Nonfatal) + emitDiagnoseIfDiagnostic(MemE->getMemberLoc(), Attr); } if ((isa<CXXConstructorDecl>(CurContext) || @@ -12652,7 +12977,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, Oper != OperEnd; ++Oper) { AddMethodCandidate(Oper.getPair(), Object.get()->getType(), Object.get()->Classify(Context), - Args, CandidateSet, + Object.get(), Args, CandidateSet, /*SuppressUserConversions=*/ false); } @@ -12928,7 +13253,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end(); Oper != OperEnd; ++Oper) { AddMethodCandidate(Oper.getPair(), Base->getType(), Base->Classify(Context), - None, CandidateSet, /*SuppressUserConversions=*/false); + Base, None, CandidateSet, + /*SuppressUserConversions=*/false); } bool HadMultipleCandidates = (CandidateSet.size() > 1); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 66a10ef7993e..795e6025d96f 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -5158,6 +5158,11 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return Arg; } + // The initialization of the parameter from the argument is + // a constant-evaluated context. + EnterExpressionEvaluationContext ConstantEvaluated(*this, + Sema::ConstantEvaluated); + if (getLangOpts().CPlusPlus1z) { // C++1z [temp.arg.nontype]p1: // A template-argument for a non-type template parameter shall be diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index b79904c0a703..93e796ee9668 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -669,6 +669,19 @@ public: Info.PendingDeducedPacks[Pack.Index] = Pack.Outer; } + /// Determine whether this pack has already been partially expanded into a + /// sequence of (prior) function parameters / template arguments. + bool isPartiallyExpanded() { + if (Packs.size() != 1 || !S.CurrentInstantiationScope) + return false; + + auto *PartiallySubstitutedPack = + S.CurrentInstantiationScope->getPartiallySubstitutedPack(); + return PartiallySubstitutedPack && + getDepthAndIndex(PartiallySubstitutedPack) == + std::make_pair(Info.getDeducedDepth(), Packs.front().Index); + } + /// Move to deducing the next element in each pack that is being deduced. void nextPackElement() { // Capture the deduced template arguments for each parameter pack expanded @@ -2552,6 +2565,12 @@ static bool isSimpleTemplateIdType(QualType T) { return false; } +static void +MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, + bool OnlyDeduced, + unsigned Level, + llvm::SmallBitVector &Deduced); + /// \brief Substitute the explicitly-provided template arguments into the /// given function template according to C++ [temp.arg.explicit]. /// @@ -2613,7 +2632,7 @@ Sema::SubstituteExplicitTemplateArguments( // Enter a new template instantiation context where we check the // explicitly-specified template arguments against this function template, // and then substitute them into the function parameter types. - SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end()); + SmallVector<TemplateArgument, 4> DeducedArgs; InstantiatingTemplate Inst(*this, Info.getLocation(), FunctionTemplate, DeducedArgs, ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution, @@ -2893,14 +2912,13 @@ static unsigned getPackIndexForParam(Sema &S, /// /// \param OriginalCallArgs If non-NULL, the original call arguments against /// which the deduced argument types should be compared. -Sema::TemplateDeductionResult -Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, - SmallVectorImpl<DeducedTemplateArgument> &Deduced, - unsigned NumExplicitlySpecified, - FunctionDecl *&Specialization, - TemplateDeductionInfo &Info, - SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs, - bool PartialOverloading) { +Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( + FunctionTemplateDecl *FunctionTemplate, + SmallVectorImpl<DeducedTemplateArgument> &Deduced, + unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, + TemplateDeductionInfo &Info, + SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs, + bool PartialOverloading, llvm::function_ref<bool()> CheckNonDependent) { // Unevaluated SFINAE context. EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); SFINAETrap Trap(*this); @@ -2927,6 +2945,18 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, PartialOverloading)) return Result; + // C++ [temp.deduct.call]p10: [DR1391] + // If deduction succeeds for all parameters that contain + // template-parameters that participate in template argument deduction, + // and all template arguments are explicitly specified, deduced, or + // obtained from default template arguments, remaining parameters are then + // compared with the corresponding arguments. For each remaining parameter + // P with a type that was non-dependent before substitution of any + // explicitly-specified template arguments, if the corresponding argument + // A cannot be implicitly converted to P, deduction fails. + if (CheckNonDependent()) + return TDK_NonDependentConversionFailure; + // Form the template argument list from the deduced template arguments. TemplateArgumentList *DeducedArgumentList = TemplateArgumentList::CreateCopy(Context, Builder); @@ -3373,12 +3403,19 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( /// \param Info the argument will be updated to provide additional information /// about template argument deduction. /// +/// \param CheckNonDependent A callback to invoke to check conversions for +/// non-dependent parameters, between deduction and substitution, per DR1391. +/// If this returns true, substitution will be skipped and we return +/// TDK_NonDependentConversionFailure. The callback is passed the parameter +/// types (after substituting explicit template arguments). +/// /// \returns the result of template argument deduction. Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, FunctionDecl *&Specialization, TemplateDeductionInfo &Info, - bool PartialOverloading) { + bool PartialOverloading, + llvm::function_ref<bool(ArrayRef<QualType>)> CheckNonDependent) { if (FunctionTemplate->isInvalidDecl()) return TDK_Invalid; @@ -3389,7 +3426,6 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // Template argument deduction is done by comparing each function template // parameter type (call it P) with the type of the corresponding argument // of the call (call it A) as described below. - unsigned CheckArgs = Args.size(); if (Args.size() < Function->getMinRequiredArguments() && !PartialOverloading) return TDK_TooFewArguments; else if (TooManyArguments(NumParams, Args.size(), PartialOverloading)) { @@ -3397,9 +3433,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( = Function->getType()->getAs<FunctionProtoType>(); if (Proto->isTemplateVariadic()) /* Do nothing */; - else if (Proto->isVariadic()) - CheckArgs = NumParams; - else + else if (!Proto->isVariadic()) return TDK_TooManyArguments; } @@ -3409,7 +3443,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); SmallVector<DeducedTemplateArgument, 4> Deduced; - SmallVector<QualType, 4> ParamTypes; + SmallVector<QualType, 8> ParamTypes; unsigned NumExplicitlySpecified = 0; if (ExplicitTemplateArgs) { TemplateDeductionResult Result = @@ -3429,7 +3463,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( ParamTypes.push_back(Function->getParamDecl(I)->getType()); } - SmallVector<OriginalCallArg, 4> OriginalCallArgs; + SmallVector<OriginalCallArg, 8> OriginalCallArgs; // Deduce an argument of type ParamType from an expression with index ArgIdx. auto DeduceCallArgument = [&](QualType ParamType, unsigned ArgIdx) { @@ -3448,6 +3482,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // Deduce template arguments from the function parameters. Deduced.resize(TemplateParams->size()); + SmallVector<QualType, 8> ParamTypesForArgChecking; for (unsigned ParamIdx = 0, NumParamTypes = ParamTypes.size(), ArgIdx = 0; ParamIdx != NumParamTypes; ++ParamIdx) { QualType ParamType = ParamTypes[ParamIdx]; @@ -3456,51 +3491,68 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( dyn_cast<PackExpansionType>(ParamType); if (!ParamExpansion) { // Simple case: matching a function parameter to a function argument. - if (ArgIdx >= CheckArgs) + if (ArgIdx >= Args.size()) break; + ParamTypesForArgChecking.push_back(ParamType); if (auto Result = DeduceCallArgument(ParamType, ArgIdx++)) return Result; continue; } + QualType ParamPattern = ParamExpansion->getPattern(); + PackDeductionScope PackScope(*this, TemplateParams, Deduced, Info, + ParamPattern); + // C++0x [temp.deduct.call]p1: // For a function parameter pack that occurs at the end of the // parameter-declaration-list, the type A of each remaining argument of // the call is compared with the type P of the declarator-id of the // function parameter pack. Each comparison deduces template arguments // for subsequent positions in the template parameter packs expanded by - // the function parameter pack. For a function parameter pack that does - // not occur at the end of the parameter-declaration-list, the type of - // the parameter pack is a non-deduced context. - // FIXME: This does not say that subsequent parameters are also non-deduced. - // See also DR1388 / DR1399, which effectively says we should keep deducing - // after the pack. - if (ParamIdx + 1 < NumParamTypes) - break; - - QualType ParamPattern = ParamExpansion->getPattern(); - PackDeductionScope PackScope(*this, TemplateParams, Deduced, Info, - ParamPattern); - - for (; ArgIdx < Args.size(); PackScope.nextPackElement(), ++ArgIdx) - if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx)) - return Result; + // the function parameter pack. When a function parameter pack appears + // in a non-deduced context [not at the end of the list], the type of + // that parameter pack is never deduced. + // + // FIXME: The above rule allows the size of the parameter pack to change + // after we skip it (in the non-deduced case). That makes no sense, so + // we instead notionally deduce the pack against N arguments, where N is + // the length of the explicitly-specified pack if it's expanded by the + // parameter pack and 0 otherwise, and we treat each deduction as a + // non-deduced context. + if (ParamIdx + 1 == NumParamTypes) { + for (; ArgIdx < Args.size(); PackScope.nextPackElement(), ++ArgIdx) { + ParamTypesForArgChecking.push_back(ParamPattern); + if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx)) + return Result; + } + } else { + // If the parameter type contains an explicitly-specified pack that we + // could not expand, skip the number of parameters notionally created + // by the expansion. + Optional<unsigned> NumExpansions = ParamExpansion->getNumExpansions(); + if (NumExpansions && !PackScope.isPartiallyExpanded()) { + for (unsigned I = 0; I != *NumExpansions && ArgIdx < Args.size(); + ++I, ++ArgIdx) { + ParamTypesForArgChecking.push_back(ParamPattern); + // FIXME: Should we add OriginalCallArgs for these? What if the + // corresponding argument is a list? + PackScope.nextPackElement(); + } + } + } // Build argument packs for each of the parameter packs expanded by this // pack expansion. if (auto Result = PackScope.finish()) return Result; - - // After we've matching against a parameter pack, we're done. - break; } - return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, - NumExplicitlySpecified, Specialization, - Info, &OriginalCallArgs, - PartialOverloading); + return FinishTemplateArgumentDeduction( + FunctionTemplate, Deduced, NumExplicitlySpecified, Specialization, Info, + &OriginalCallArgs, PartialOverloading, + [&]() { return CheckNonDependent(ParamTypesForArgChecking); }); } QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType, @@ -4230,12 +4282,6 @@ bool Sema::DeduceReturnType(FunctionDecl *FD, SourceLocation Loc, return StillUndeduced; } -static void -MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, - bool OnlyDeduced, - unsigned Level, - llvm::SmallBitVector &Deduced); - /// \brief If this is a non-static member function, static void AddImplicitObjectParameterType(ASTContext &Context, diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 160c9f090788..ba4a5b7bc0d7 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -2280,16 +2280,18 @@ namespace { }; } -bool Sema::InstantiateClassTemplateSpecialization( - SourceLocation PointOfInstantiation, +/// Get the instantiation pattern to use to instantiate the definition of a +/// given ClassTemplateSpecializationDecl (either the pattern of the primary +/// template or of a partial specialization). +static CXXRecordDecl * +getPatternForClassTemplateSpecialization( + Sema &S, SourceLocation PointOfInstantiation, ClassTemplateSpecializationDecl *ClassTemplateSpec, TemplateSpecializationKind TSK, bool Complain) { - // Perform the actual instantiation on the canonical declaration. - ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>( - ClassTemplateSpec->getCanonicalDecl()); - if (ClassTemplateSpec->isInvalidDecl()) - return true; - + Sema::InstantiatingTemplate Inst(S, PointOfInstantiation, ClassTemplateSpec); + if (Inst.isInvalid() || Inst.isAlreadyInstantiating()) + return nullptr; + ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate(); CXXRecordDecl *Pattern = nullptr; @@ -2309,15 +2311,13 @@ bool Sema::InstantiateClassTemplateSpecialization( for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) { ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I]; TemplateDeductionInfo Info(FailedCandidates.getLocation()); - if (TemplateDeductionResult Result - = DeduceTemplateArguments(Partial, - ClassTemplateSpec->getTemplateArgs(), - Info)) { + if (Sema::TemplateDeductionResult Result = S.DeduceTemplateArguments( + Partial, ClassTemplateSpec->getTemplateArgs(), Info)) { // Store the failed-deduction information for use in diagnostics, later. // TODO: Actually use the failed-deduction info? FailedCandidates.addCandidate().set( DeclAccessPair::make(Template, AS_public), Partial, - MakeDeductionFailureInfo(Context, Result, Info)); + MakeDeductionFailureInfo(S.Context, Result, Info)); (void)Result; } else { Matched.push_back(PartialSpecMatchResult()); @@ -2347,9 +2347,8 @@ bool Sema::InstantiateClassTemplateSpecialization( for (SmallVectorImpl<MatchResult>::iterator P = Best + 1, PEnd = Matched.end(); P != PEnd; ++P) { - if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial, - PointOfInstantiation) - == P->Partial) + if (S.getMoreSpecializedPartialSpecialization( + P->Partial, Best->Partial, PointOfInstantiation) == P->Partial) Best = P; } @@ -2360,9 +2359,9 @@ bool Sema::InstantiateClassTemplateSpecialization( PEnd = Matched.end(); P != PEnd; ++P) { if (P != Best && - getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial, - PointOfInstantiation) - != Best->Partial) { + S.getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial, + PointOfInstantiation) != + Best->Partial) { Ambiguous = true; break; } @@ -2370,20 +2369,20 @@ bool Sema::InstantiateClassTemplateSpecialization( if (Ambiguous) { // Partial ordering did not produce a clear winner. Complain. + Inst.Clear(); ClassTemplateSpec->setInvalidDecl(); - Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous) + S.Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous) << ClassTemplateSpec; // Print the matching partial specializations. for (SmallVectorImpl<MatchResult>::iterator P = Matched.begin(), PEnd = Matched.end(); P != PEnd; ++P) - Diag(P->Partial->getLocation(), diag::note_partial_spec_match) - << getTemplateArgumentBindingsText( - P->Partial->getTemplateParameters(), - *P->Args); + S.Diag(P->Partial->getLocation(), diag::note_partial_spec_match) + << S.getTemplateArgumentBindingsText( + P->Partial->getTemplateParameters(), *P->Args); - return true; + return nullptr; } } @@ -2416,13 +2415,27 @@ bool Sema::InstantiateClassTemplateSpecialization( Pattern = OrigTemplate->getTemplatedDecl(); } - bool Result = InstantiateClass(PointOfInstantiation, ClassTemplateSpec, - Pattern, - getTemplateInstantiationArgs(ClassTemplateSpec), - TSK, - Complain); + return Pattern; +} - return Result; +bool Sema::InstantiateClassTemplateSpecialization( + SourceLocation PointOfInstantiation, + ClassTemplateSpecializationDecl *ClassTemplateSpec, + TemplateSpecializationKind TSK, bool Complain) { + // Perform the actual instantiation on the canonical declaration. + ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>( + ClassTemplateSpec->getCanonicalDecl()); + if (ClassTemplateSpec->isInvalidDecl()) + return true; + + CXXRecordDecl *Pattern = getPatternForClassTemplateSpecialization( + *this, PointOfInstantiation, ClassTemplateSpec, TSK, Complain); + if (!Pattern) + return true; + + return InstantiateClass(PointOfInstantiation, ClassTemplateSpec, Pattern, + getTemplateInstantiationArgs(ClassTemplateSpec), TSK, + Complain); } /// \brief Instantiates the definitions of all of the member diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index f4013b820641..d2a5e5cb5312 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -168,39 +168,59 @@ static void instantiateDependentAlignValueAttr( Aligned->getSpellingListIndex()); } -static void instantiateDependentEnableIfAttr( +static Expr *instantiateDependentFunctionAttrCondition( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const EnableIfAttr *A, const Decl *Tmpl, Decl *New) { + const Attr *A, Expr *OldCond, const Decl *Tmpl, FunctionDecl *New) { Expr *Cond = nullptr; { - EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated); - ExprResult Result = S.SubstExpr(A->getCond(), TemplateArgs); + Sema::ContextRAII SwitchContext(S, New); + EnterExpressionEvaluationContext Unevaluated(S, Sema::ConstantEvaluated); + ExprResult Result = S.SubstExpr(OldCond, TemplateArgs); if (Result.isInvalid()) - return; + return nullptr; Cond = Result.getAs<Expr>(); } if (!Cond->isTypeDependent()) { ExprResult Converted = S.PerformContextuallyConvertToBool(Cond); if (Converted.isInvalid()) - return; + return nullptr; Cond = Converted.get(); } SmallVector<PartialDiagnosticAt, 8> Diags; - if (A->getCond()->isValueDependent() && !Cond->isValueDependent() && - !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(New), - Diags)) { - S.Diag(A->getLocation(), diag::err_enable_if_never_constant_expr); - for (int I = 0, N = Diags.size(); I != N; ++I) - S.Diag(Diags[I].first, Diags[I].second); - return; + if (OldCond->isValueDependent() && !Cond->isValueDependent() && + !Expr::isPotentialConstantExprUnevaluated(Cond, New, Diags)) { + S.Diag(A->getLocation(), diag::err_attr_cond_never_constant_expr) << A; + for (const auto &P : Diags) + S.Diag(P.first, P.second); + return nullptr; } + return Cond; +} - EnableIfAttr *EIA = new (S.getASTContext()) - EnableIfAttr(A->getLocation(), S.getASTContext(), Cond, - A->getMessage(), - A->getSpellingListIndex()); - New->addAttr(EIA); +static void instantiateDependentEnableIfAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const EnableIfAttr *EIA, const Decl *Tmpl, FunctionDecl *New) { + Expr *Cond = instantiateDependentFunctionAttrCondition( + S, TemplateArgs, EIA, EIA->getCond(), Tmpl, New); + + if (Cond) + New->addAttr(new (S.getASTContext()) EnableIfAttr( + EIA->getLocation(), S.getASTContext(), Cond, EIA->getMessage(), + EIA->getSpellingListIndex())); +} + +static void instantiateDependentDiagnoseIfAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const DiagnoseIfAttr *DIA, const Decl *Tmpl, FunctionDecl *New) { + Expr *Cond = instantiateDependentFunctionAttrCondition( + S, TemplateArgs, DIA, DIA->getCond(), Tmpl, New); + + if (Cond) + New->addAttr(new (S.getASTContext()) DiagnoseIfAttr( + DIA->getLocation(), S.getASTContext(), Cond, DIA->getMessage(), + DIA->getDiagnosticType(), DIA->getArgDependent(), New, + DIA->getSpellingListIndex())); } // Constructs and adds to New a new instance of CUDALaunchBoundsAttr using @@ -334,7 +354,13 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, if (const auto *EnableIf = dyn_cast<EnableIfAttr>(TmplAttr)) { instantiateDependentEnableIfAttr(*this, TemplateArgs, EnableIf, Tmpl, - New); + cast<FunctionDecl>(New)); + continue; + } + + if (const auto *DiagnoseIf = dyn_cast<DiagnoseIfAttr>(TmplAttr)) { + instantiateDependentDiagnoseIfAttr(*this, TemplateArgs, DiagnoseIf, Tmpl, + cast<FunctionDecl>(New)); continue; } |