diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaAttr.cpp | 30 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 25 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 43 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 39 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 18 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 13 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 224 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 20 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 48 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 116 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 41 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 22 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 2 |
14 files changed, 377 insertions, 265 deletions
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index 76ca65373dda..8c13ead64457 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -126,6 +126,36 @@ void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, PackStack.Act(PragmaLoc, Action, StringRef(), Alignment); } +void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, PragmaClangSectionAction Action, + PragmaClangSectionKind SecKind, StringRef SecName) { + PragmaClangSection *CSec; + switch (SecKind) { + case PragmaClangSectionKind::PCSK_BSS: + CSec = &PragmaClangBSSSection; + break; + case PragmaClangSectionKind::PCSK_Data: + CSec = &PragmaClangDataSection; + break; + case PragmaClangSectionKind::PCSK_Rodata: + CSec = &PragmaClangRodataSection; + break; + case PragmaClangSectionKind::PCSK_Text: + CSec = &PragmaClangTextSection; + break; + default: + llvm_unreachable("invalid clang section kind"); + } + + if (Action == PragmaClangSectionAction::PCSA_Clear) { + CSec->Valid = false; + return; + } + + CSec->Valid = true; + CSec->SectionName = SecName; + CSec->PragmaLocation = PragmaLoc; +} + void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action, StringRef SlotLabel, Expr *alignment) { Expr *Alignment = static_cast<Expr *>(alignment); diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 224d9e9a0ee2..b9349dc06bff 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -1860,6 +1860,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts()); } + LLVM_FALLTHROUGH; // Fall through (for statement expressions). case Sema::PCC_ForInit: diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index ef6dfaa2f28c..cba220daf774 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -8651,6 +8651,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD->setInvalidDecl(); } + // Apply an implicit SectionAttr if '#pragma clang section text' is active + if (PragmaClangTextSection.Valid && D.isFunctionDefinition() && + !NewFD->hasAttr<SectionAttr>()) { + NewFD->addAttr(PragmaClangTextSectionAttr::CreateImplicit(Context, + PragmaClangTextSection.SectionName, + PragmaClangTextSection.PragmaLocation)); + } + // Apply an implicit SectionAttr if #pragma code_seg is active. if (CodeSegStack.CurrentValue && D.isFunctionDefinition() && !NewFD->hasAttr<SectionAttr>()) { @@ -11175,6 +11183,23 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) { if (!VD) return; + // Apply an implicit SectionAttr if '#pragma clang section bss|data|rodata' is active + if (VD->hasGlobalStorage() && VD->isThisDeclarationADefinition() && + !inTemplateInstantiation() && !VD->hasAttr<SectionAttr>()) { + if (PragmaClangBSSSection.Valid) + VD->addAttr(PragmaClangBSSSectionAttr::CreateImplicit(Context, + PragmaClangBSSSection.SectionName, + PragmaClangBSSSection.PragmaLocation)); + if (PragmaClangDataSection.Valid) + VD->addAttr(PragmaClangDataSectionAttr::CreateImplicit(Context, + PragmaClangDataSection.SectionName, + PragmaClangDataSection.PragmaLocation)); + if (PragmaClangRodataSection.Valid) + VD->addAttr(PragmaClangRodataSectionAttr::CreateImplicit(Context, + PragmaClangRodataSection.SectionName, + PragmaClangRodataSection.PragmaLocation)); + } + if (auto *DD = dyn_cast<DecompositionDecl>(ThisDecl)) { for (auto *BD : DD->bindings()) { FinalizeDeclaration(BD); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index acacdc263c08..844299bb87cf 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -547,17 +547,23 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Diag(OldParam->getLocation(), diag::note_previous_definition) << OldParam->getDefaultArgRange(); } else if (OldParamHasDfl) { - // Merge the old default argument into the new parameter. - // It's important to use getInit() here; getDefaultArg() - // strips off any top-level ExprWithCleanups. - NewParam->setHasInheritedDefaultArg(); - if (OldParam->hasUnparsedDefaultArg()) - NewParam->setUnparsedDefaultArg(); - else if (OldParam->hasUninstantiatedDefaultArg()) - NewParam->setUninstantiatedDefaultArg( - OldParam->getUninstantiatedDefaultArg()); - else - NewParam->setDefaultArg(OldParam->getInit()); + // Merge the old default argument into the new parameter unless the new + // function is a friend declaration in a template class. In the latter + // case the default arguments will be inherited when the friend + // declaration will be instantiated. + if (New->getFriendObjectKind() == Decl::FOK_None || + !New->getLexicalDeclContext()->isDependentContext()) { + // It's important to use getInit() here; getDefaultArg() + // strips off any top-level ExprWithCleanups. + NewParam->setHasInheritedDefaultArg(); + if (OldParam->hasUnparsedDefaultArg()) + NewParam->setUnparsedDefaultArg(); + else if (OldParam->hasUninstantiatedDefaultArg()) + NewParam->setUninstantiatedDefaultArg( + OldParam->getUninstantiatedDefaultArg()); + else + NewParam->setDefaultArg(OldParam->getInit()); + } } else if (NewParamHasDfl) { if (New->getDescribedFunctionTemplate()) { // Paragraph 4, quoted above, only applies to non-template functions. @@ -638,7 +644,12 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Diag(Old->getLocation(), diag::note_previous_declaration); Invalid = true; } else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() && - Old->isDefined(Def)) { + Old->isDefined(Def) && + // If a friend function is inlined but does not have 'inline' + // specifier, it is a definition. Do not report attribute conflict + // in this case, redefinition will be diagnosed later. + (New->isInlineSpecified() || + New->getFriendObjectKind() == Decl::FOK_None)) { // C++11 [dcl.fcn.spec]p4: // If the definition of a function appears in a translation unit before its // first declaration as inline, the program is ill-formed. @@ -13232,6 +13243,14 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc, } } + ExprResult FullAssertExpr = ActOnFinishFullExpr(AssertExpr, StaticAssertLoc, + /*DiscardedValue*/false, + /*IsConstexpr*/true); + if (FullAssertExpr.isInvalid()) + Failed = true; + else + AssertExpr = FullAssertExpr.get(); + Decl *Decl = StaticAssertDecl::Create(Context, CurContext, StaticAssertLoc, AssertExpr, AssertMessage, RParenLoc, Failed); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 4e7fb19b282b..0f8f5c253ac6 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -11828,6 +11828,28 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, RHSExpr->getType()->isOverloadableType()) return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); } + + // If we're instantiating "a.x < b" or "A::x < b" and 'x' names a function + // template, diagnose the missing 'template' keyword instead of diagnosing + // an invalid use of a bound member function. + // + // Note that "A::x < b" might be valid if 'b' has an overloadable type due + // to C++1z [over.over]/1.4, but we already checked for that case above. + if (Opc == BO_LT && inTemplateInstantiation() && + (pty->getKind() == BuiltinType::BoundMember || + pty->getKind() == BuiltinType::Overload)) { + auto *OE = dyn_cast<OverloadExpr>(LHSExpr); + if (OE && !OE->hasTemplateKeyword() && !OE->hasExplicitTemplateArgs() && + std::any_of(OE->decls_begin(), OE->decls_end(), [](NamedDecl *ND) { + return isa<FunctionTemplateDecl>(ND); + })) { + Diag(OE->getQualifier() ? OE->getQualifierLoc().getBeginLoc() + : OE->getNameLoc(), + diag::err_template_kw_missing) + << OE->getName().getAsString() << ""; + return ExprError(); + } + } ExprResult LHS = CheckPlaceholderExpr(LHSExpr); if (LHS.isInvalid()) return ExprError(); @@ -11953,16 +11975,13 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, << resultType << Input.get()->getSourceRange(); else if (resultType->hasIntegerRepresentation()) break; - else if (resultType->isExtVectorType()) { - if (Context.getLangOpts().OpenCL) { - // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate - // on vector float types. - QualType T = resultType->getAs<ExtVectorType>()->getElementType(); - if (!T->isIntegerType()) - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } - break; + else if (resultType->isExtVectorType() && Context.getLangOpts().OpenCL) { + // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate + // on vector float types. + QualType T = resultType->getAs<ExtVectorType>()->getElementType(); + if (!T->isIntegerType()) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); } else { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index a05f7a7e406b..00a4b39f1423 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2658,6 +2658,8 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, Context, GlobalCtx, SourceLocation(), SourceLocation(), Name, FnType, /*TInfo=*/nullptr, SC_None, false, true); Alloc->setImplicit(); + // Global allocation functions should always be visible. + Alloc->setHidden(false); // Implicit sized deallocation functions always have default visibility. Alloc->addAttr( @@ -5104,7 +5106,9 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS, return QualType(); // Cast LHS to type of use. - QualType UseType = isIndirect ? Context.getPointerType(Class) : Class; + QualType UseType = Context.getQualifiedType(Class, LHSType.getQualifiers()); + if (isIndirect) + UseType = Context.getPointerType(UseType); ExprValueKind VK = isIndirect ? VK_RValue : LHS.get()->getValueKind(); LHS = ImpCastExprToType(LHS.get(), UseType, CK_DerivedToBase, VK, &BasePath); @@ -5281,16 +5285,16 @@ static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS switch (CandidateSet.BestViableFunction(Self, QuestionLoc, Best)) { case OR_Success: { // We found a match. Perform the conversions on the arguments and move on. - ExprResult LHSRes = - Self.PerformImplicitConversion(LHS.get(), Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], Sema::AA_Converting); + ExprResult LHSRes = Self.PerformImplicitConversion( + LHS.get(), Best->BuiltinParamTypes[0], Best->Conversions[0], + Sema::AA_Converting); if (LHSRes.isInvalid()) break; LHS = LHSRes; - ExprResult RHSRes = - Self.PerformImplicitConversion(RHS.get(), Best->BuiltinTypes.ParamTypes[1], - Best->Conversions[1], Sema::AA_Converting); + ExprResult RHSRes = Self.PerformImplicitConversion( + RHS.get(), Best->BuiltinParamTypes[1], Best->Conversions[1], + Sema::AA_Converting); if (RHSRes.isInvalid()) break; RHS = RHSRes; diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 1d32e5796812..1fb25f4e0e7c 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -3747,20 +3747,19 @@ static void LookupPotentialTypoResult(Sema &SemaRef, bool FindHidden); /// \brief Check whether the declarations found for a typo correction are -/// visible, and if none of them are, convert the correction to an 'import -/// a module' correction. +/// visible. Set the correction's RequiresImport flag to true if none of the +/// declarations are visible, false otherwise. static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) { - if (TC.begin() == TC.end()) - return; - TypoCorrection::decl_iterator DI = TC.begin(), DE = TC.end(); for (/**/; DI != DE; ++DI) if (!LookupResult::isVisible(SemaRef, *DI)) break; - // Nothing to do if all decls are visible. - if (DI == DE) + // No filtering needed if all decls are visible. + if (DI == DE) { + TC.setRequiresImport(false); return; + } llvm::SmallVector<NamedDecl*, 4> NewDecls(TC.begin(), DI); bool AnyVisibleDecls = !NewDecls.empty(); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 7bdd8872456a..5cc13f391d11 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -7136,8 +7136,7 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, /// operator. NumContextualBoolArguments is the number of arguments /// (at the beginning of the argument list) that will be contextually /// converted to bool. -void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, - ArrayRef<Expr *> Args, +void Sema::AddBuiltinCandidate(QualType *ParamTys, ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool IsAssignmentOperator, unsigned NumContextualBoolArguments) { @@ -7151,9 +7150,7 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, Candidate.Function = nullptr; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; - Candidate.BuiltinTypes.ResultTy = ResultTy; - for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) - Candidate.BuiltinTypes.ParamTypes[ArgIdx] = ParamTys[ArgIdx]; + std::copy(ParamTys, ParamTys + Args.size(), Candidate.BuiltinParamTypes); // Determine the implicit conversion sequences for each of the // arguments. @@ -7492,7 +7489,7 @@ static void AddBuiltinAssignmentOperatorCandidates(Sema &S, // T& operator=(T&, T) ParamTypes[0] = S.Context.getLValueReferenceType(T); ParamTypes[1] = T; - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssignmentOperator=*/true); if (!S.Context.getCanonicalType(T).isVolatileQualified()) { @@ -7500,7 +7497,7 @@ static void AddBuiltinAssignmentOperatorCandidates(Sema &S, ParamTypes[0] = S.Context.getLValueReferenceType(S.Context.getVolatileType(T)); ParamTypes[1] = T; - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssignmentOperator=*/true); } } @@ -7620,64 +7617,6 @@ class BuiltinOperatorOverloadBuilder { return S.Context.*ArithmeticTypes[index]; } - /// \brief Gets the canonical type resulting from the usual arithemetic - /// converions for the given arithmetic types. - CanQualType getUsualArithmeticConversions(unsigned L, unsigned R) { - // Accelerator table for performing the usual arithmetic conversions. - // The rules are basically: - // - if either is floating-point, use the wider floating-point - // - if same signedness, use the higher rank - // - if same size, use unsigned of the higher rank - // - use the larger type - // These rules, together with the axiom that higher ranks are - // never smaller, are sufficient to precompute all of these results - // *except* when dealing with signed types of higher rank. - // (we could precompute SLL x UI for all known platforms, but it's - // better not to make any assumptions). - // We assume that int128 has a higher rank than long long on all platforms. - enum PromotedType : int8_t { - Dep=-1, - Flt, Dbl, LDbl, SI, SL, SLL, S128, UI, UL, ULL, U128 - }; - static const PromotedType ConversionsTable[LastPromotedArithmeticType] - [LastPromotedArithmeticType] = { -/* Flt*/ { Flt, Dbl, LDbl, Flt, Flt, Flt, Flt, Flt, Flt, Flt, Flt }, -/* Dbl*/ { Dbl, Dbl, LDbl, Dbl, Dbl, Dbl, Dbl, Dbl, Dbl, Dbl, Dbl }, -/*LDbl*/ { LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl }, -/* SI*/ { Flt, Dbl, LDbl, SI, SL, SLL, S128, UI, UL, ULL, U128 }, -/* SL*/ { Flt, Dbl, LDbl, SL, SL, SLL, S128, Dep, UL, ULL, U128 }, -/* SLL*/ { Flt, Dbl, LDbl, SLL, SLL, SLL, S128, Dep, Dep, ULL, U128 }, -/*S128*/ { Flt, Dbl, LDbl, S128, S128, S128, S128, S128, S128, S128, U128 }, -/* UI*/ { Flt, Dbl, LDbl, UI, Dep, Dep, S128, UI, UL, ULL, U128 }, -/* UL*/ { Flt, Dbl, LDbl, UL, UL, Dep, S128, UL, UL, ULL, U128 }, -/* ULL*/ { Flt, Dbl, LDbl, ULL, ULL, ULL, S128, ULL, ULL, ULL, U128 }, -/*U128*/ { Flt, Dbl, LDbl, U128, U128, U128, U128, U128, U128, U128, U128 }, - }; - - assert(L < LastPromotedArithmeticType); - assert(R < LastPromotedArithmeticType); - int Idx = ConversionsTable[L][R]; - - // Fast path: the table gives us a concrete answer. - if (Idx != Dep) return getArithmeticType(Idx); - - // Slow path: we need to compare widths. - // An invariant is that the signed type has higher rank. - CanQualType LT = getArithmeticType(L), - RT = getArithmeticType(R); - unsigned LW = S.Context.getIntWidth(LT), - RW = S.Context.getIntWidth(RT); - - // If they're different widths, use the signed type. - if (LW > RW) return LT; - else if (LW < RW) return RT; - - // Otherwise, use the unsigned type of the signed type's rank. - if (L == SL || R == SL) return S.Context.UnsignedLongTy; - assert(L == SLL || R == SLL); - return S.Context.UnsignedLongLongTy; - } - /// \brief Helper method to factor out the common pattern of adding overloads /// for '++' and '--' builtin operators. void addPlusPlusMinusMinusStyleOverloads(QualType CandidateTy, @@ -7689,10 +7628,7 @@ class BuiltinOperatorOverloadBuilder { }; // Non-volatile version. - if (Args.size() == 1) - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet); - else - S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); // Use a heuristic to reduce number of builtin candidates in the set: // add volatile version only if there are conversions to a volatile type. @@ -7700,10 +7636,7 @@ class BuiltinOperatorOverloadBuilder { ParamTypes[0] = S.Context.getLValueReferenceType( S.Context.getVolatileType(CandidateTy)); - if (Args.size() == 1) - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet); - else - S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } // Add restrict version only if there are conversions to a restrict type @@ -7713,10 +7646,7 @@ class BuiltinOperatorOverloadBuilder { ParamTypes[0] = S.Context.getLValueReferenceType( S.Context.getCVRQualifiedType(CandidateTy, Qualifiers::Restrict)); - if (Args.size() == 1) - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet); - else - S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); if (HasVolatile) { ParamTypes[0] @@ -7724,10 +7654,7 @@ class BuiltinOperatorOverloadBuilder { S.Context.getCVRQualifiedType(CandidateTy, (Qualifiers::Volatile | Qualifiers::Restrict))); - if (Args.size() == 1) - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet); - else - S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } @@ -7841,8 +7768,7 @@ public: if (Proto->getTypeQuals() || Proto->getRefQualifier()) continue; - S.AddBuiltinCandidate(S.Context.getLValueReferenceType(PointeeTy), - &ParamTy, Args, CandidateSet); + S.AddBuiltinCandidate(&ParamTy, Args, CandidateSet); } } @@ -7859,7 +7785,7 @@ public: for (unsigned Arith = FirstPromotedArithmeticType; Arith < LastPromotedArithmeticType; ++Arith) { QualType ArithTy = getArithmeticType(Arith); - S.AddBuiltinCandidate(ArithTy, &ArithTy, Args, CandidateSet); + S.AddBuiltinCandidate(&ArithTy, Args, CandidateSet); } // Extension: We also add these operators for vector types. @@ -7868,7 +7794,7 @@ public: VecEnd = CandidateTypes[0].vector_end(); Vec != VecEnd; ++Vec) { QualType VecTy = *Vec; - S.AddBuiltinCandidate(VecTy, &VecTy, Args, CandidateSet); + S.AddBuiltinCandidate(&VecTy, Args, CandidateSet); } } @@ -7883,7 +7809,7 @@ public: PtrEnd = CandidateTypes[0].pointer_end(); Ptr != PtrEnd; ++Ptr) { QualType ParamTy = *Ptr; - S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, CandidateSet); + S.AddBuiltinCandidate(&ParamTy, Args, CandidateSet); } } @@ -7899,7 +7825,7 @@ public: for (unsigned Int = FirstPromotedIntegralType; Int < LastPromotedIntegralType; ++Int) { QualType IntTy = getArithmeticType(Int); - S.AddBuiltinCandidate(IntTy, &IntTy, Args, CandidateSet); + S.AddBuiltinCandidate(&IntTy, Args, CandidateSet); } // Extension: We also add this operator for vector types. @@ -7908,7 +7834,7 @@ public: VecEnd = CandidateTypes[0].vector_end(); Vec != VecEnd; ++Vec) { QualType VecTy = *Vec; - S.AddBuiltinCandidate(VecTy, &VecTy, Args, CandidateSet); + S.AddBuiltinCandidate(&VecTy, Args, CandidateSet); } } @@ -7933,15 +7859,14 @@ public: continue; QualType ParamTypes[2] = { *MemPtr, *MemPtr }; - S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } if (CandidateTypes[ArgIdx].hasNullPtrType()) { CanQualType NullPtrTy = S.Context.getCanonicalType(S.Context.NullPtrTy); if (AddedTypes.insert(NullPtrTy).second) { QualType ParamTypes[2] = { NullPtrTy, NullPtrTy }; - S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, - CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } } @@ -8017,7 +7942,7 @@ public: continue; QualType ParamTypes[2] = { *Ptr, *Ptr }; - S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } for (BuiltinCandidateTypeSet::iterator Enum = CandidateTypes[ArgIdx].enumeration_begin(), @@ -8033,7 +7958,7 @@ public: continue; QualType ParamTypes[2] = { *Enum, *Enum }; - S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } } @@ -8076,7 +8001,7 @@ public: if (Arg == 0 || Op == OO_Plus) { // operator+(T*, ptrdiff_t) or operator-(T*, ptrdiff_t) // T* operator+(ptrdiff_t, T*); - S.AddBuiltinCandidate(*Ptr, AsymmetricParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(AsymmetricParamTypes, Args, CandidateSet); } if (Op == OO_Minus) { // ptrdiff_t operator-(T, T); @@ -8084,8 +8009,7 @@ public: continue; QualType ParamTypes[2] = { *Ptr, *Ptr }; - S.AddBuiltinCandidate(S.Context.getPointerDiffType(), ParamTypes, - Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } } @@ -8120,7 +8044,7 @@ public: // where LR is the result of the usual arithmetic conversions // between types L and R. // Our candidates ignore the first parameter. - void addGenericBinaryArithmeticOverloads(bool isComparison) { + void addGenericBinaryArithmeticOverloads() { if (!HasArithmeticOrEnumeralCandidateType) return; @@ -8130,10 +8054,7 @@ public: Right < LastPromotedArithmeticType; ++Right) { QualType LandR[2] = { getArithmeticType(Left), getArithmeticType(Right) }; - QualType Result = - isComparison ? S.Context.BoolTy - : getUsualArithmeticConversions(Left, Right); - S.AddBuiltinCandidate(Result, LandR, Args, CandidateSet); + S.AddBuiltinCandidate(LandR, Args, CandidateSet); } } @@ -8148,15 +8069,7 @@ public: Vec2End = CandidateTypes[1].vector_end(); Vec2 != Vec2End; ++Vec2) { QualType LandR[2] = { *Vec1, *Vec2 }; - QualType Result = S.Context.BoolTy; - if (!isComparison) { - if ((*Vec1)->isExtVectorType() || !(*Vec2)->isExtVectorType()) - Result = *Vec1; - else - Result = *Vec2; - } - - S.AddBuiltinCandidate(Result, LandR, Args, CandidateSet); + S.AddBuiltinCandidate(LandR, Args, CandidateSet); } } } @@ -8185,10 +8098,7 @@ public: Right < LastPromotedIntegralType; ++Right) { QualType LandR[2] = { getArithmeticType(Left), getArithmeticType(Right) }; - QualType Result = (Op == OO_LessLess || Op == OO_GreaterGreater) - ? LandR[0] - : getUsualArithmeticConversions(Left, Right); - S.AddBuiltinCandidate(Result, LandR, Args, CandidateSet); + S.AddBuiltinCandidate(LandR, Args, CandidateSet); } } } @@ -8262,7 +8172,7 @@ public: S.Context.getLValueReferenceType(*Ptr), isEqualOp ? *Ptr : S.Context.getPointerDiffType(), }; - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/ isEqualOp); bool NeedVolatile = !(*Ptr).isVolatileQualified() && @@ -8271,7 +8181,7 @@ public: // volatile version ParamTypes[0] = S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr)); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/isEqualOp); } @@ -8280,7 +8190,7 @@ public: // restrict version ParamTypes[0] = S.Context.getLValueReferenceType(S.Context.getRestrictType(*Ptr)); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/isEqualOp); if (NeedVolatile) { @@ -8290,7 +8200,7 @@ public: S.Context.getCVRQualifiedType(*Ptr, (Qualifiers::Volatile | Qualifiers::Restrict))); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/isEqualOp); } } @@ -8311,7 +8221,7 @@ public: }; // non-volatile version - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/true); bool NeedVolatile = !(*Ptr).isVolatileQualified() && @@ -8320,7 +8230,7 @@ public: // volatile version ParamTypes[0] = S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr)); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/true); } @@ -8329,7 +8239,7 @@ public: // restrict version ParamTypes[0] = S.Context.getLValueReferenceType(S.Context.getRestrictType(*Ptr)); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/true); if (NeedVolatile) { @@ -8339,7 +8249,7 @@ public: S.Context.getCVRQualifiedType(*Ptr, (Qualifiers::Volatile | Qualifiers::Restrict))); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/true); } } @@ -8372,7 +8282,7 @@ public: // Add this built-in operator as a candidate (VQ is empty). ParamTypes[0] = S.Context.getLValueReferenceType(getArithmeticType(Left)); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/isEqualOp); // Add this built-in operator as a candidate (VQ is 'volatile'). @@ -8380,7 +8290,7 @@ public: ParamTypes[0] = S.Context.getVolatileType(getArithmeticType(Left)); ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/isEqualOp); } } @@ -8399,14 +8309,14 @@ public: ParamTypes[1] = *Vec2; // Add this built-in operator as a candidate (VQ is empty). ParamTypes[0] = S.Context.getLValueReferenceType(*Vec1); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/isEqualOp); // Add this built-in operator as a candidate (VQ is 'volatile'). if (VisibleTypeConversionsQuals.hasVolatile()) { ParamTypes[0] = S.Context.getVolatileType(*Vec1); ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/isEqualOp); } } @@ -8438,13 +8348,13 @@ public: // Add this built-in operator as a candidate (VQ is empty). ParamTypes[0] = S.Context.getLValueReferenceType(getArithmeticType(Left)); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); if (VisibleTypeConversionsQuals.hasVolatile()) { // Add this built-in operator as a candidate (VQ is 'volatile'). ParamTypes[0] = getArithmeticType(Left); ParamTypes[0] = S.Context.getVolatileType(ParamTypes[0]); ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]); - S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } } @@ -8459,13 +8369,13 @@ public: // bool operator||(bool, bool); void addExclaimOverload() { QualType ParamTy = S.Context.BoolTy; - S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, CandidateSet, + S.AddBuiltinCandidate(&ParamTy, Args, CandidateSet, /*IsAssignmentOperator=*/false, /*NumContextualBoolArguments=*/1); } void addAmpAmpOrPipePipeOverload() { QualType ParamTypes[2] = { S.Context.BoolTy, S.Context.BoolTy }; - S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, CandidateSet, + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, /*IsAssignmentOperator=*/false, /*NumContextualBoolArguments=*/2); } @@ -8490,10 +8400,8 @@ public: if (!PointeeType->isObjectType()) continue; - QualType ResultTy = S.Context.getLValueReferenceType(PointeeType); - // T& operator[](T*, ptrdiff_t) - S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } for (BuiltinCandidateTypeSet::iterator @@ -8505,10 +8413,8 @@ public: if (!PointeeType->isObjectType()) continue; - QualType ResultTy = S.Context.getLValueReferenceType(PointeeType); - // T& operator[](ptrdiff_t, T*) - S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } @@ -8558,8 +8464,7 @@ public: T.isRestrictQualified()) continue; T = Q1.apply(S.Context, T); - QualType ResultTy = S.Context.getLValueReferenceType(T); - S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } } @@ -8587,7 +8492,7 @@ public: continue; QualType ParamTypes[2] = { *Ptr, *Ptr }; - S.AddBuiltinCandidate(*Ptr, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } for (BuiltinCandidateTypeSet::iterator @@ -8598,7 +8503,7 @@ public: continue; QualType ParamTypes[2] = { *MemPtr, *MemPtr }; - S.AddBuiltinCandidate(*MemPtr, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } if (S.getLangOpts().CPlusPlus11) { @@ -8613,7 +8518,7 @@ public: continue; QualType ParamTypes[2] = { *Enum, *Enum }; - S.AddBuiltinCandidate(*Enum, ParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } } @@ -8707,7 +8612,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, OpBuilder.addUnaryPlusOrMinusArithmeticOverloads(); } else { OpBuilder.addBinaryPlusOrMinusPointerOverloads(Op); - OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + OpBuilder.addGenericBinaryArithmeticOverloads(); } break; @@ -8715,11 +8620,11 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, if (Args.size() == 1) OpBuilder.addUnaryStarPointerOverloads(); else - OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + OpBuilder.addGenericBinaryArithmeticOverloads(); break; case OO_Slash: - OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + OpBuilder.addGenericBinaryArithmeticOverloads(); break; case OO_PlusPlus: @@ -8738,7 +8643,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, case OO_LessEqual: case OO_GreaterEqual: OpBuilder.addRelationalPointerOrEnumeralOverloads(); - OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/true); + OpBuilder.addGenericBinaryArithmeticOverloads(); break; case OO_Percent: @@ -8805,7 +8710,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, case OO_Conditional: OpBuilder.addConditionalOperatorOverloads(); - OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + OpBuilder.addGenericBinaryArithmeticOverloads(); break; } } @@ -10237,13 +10142,13 @@ static void NoteBuiltinOperatorCandidate(Sema &S, StringRef Opc, std::string TypeStr("operator"); TypeStr += Opc; TypeStr += "("; - TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString(); + TypeStr += Cand->BuiltinParamTypes[0].getAsString(); if (Cand->Conversions.size() == 1) { TypeStr += ")"; S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr; } else { TypeStr += ", "; - TypeStr += Cand->BuiltinTypes.ParamTypes[1].getAsString(); + TypeStr += Cand->BuiltinParamTypes[1].getAsString(); TypeStr += ")"; S.Diag(OpLoc, diag::note_ovl_builtin_binary_candidate) << TypeStr; } @@ -10480,7 +10385,7 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, } else { // Builtin operator. assert(ConvCount <= 3); - ParamTypes = Cand->BuiltinTypes.ParamTypes; + ParamTypes = Cand->BuiltinParamTypes; } // Fill in the rest of the conversions. @@ -12086,9 +11991,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in // operator node. - ExprResult InputRes = - PerformImplicitConversion(Input, Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], AA_Passing); + ExprResult InputRes = PerformImplicitConversion( + Input, Best->BuiltinParamTypes[0], Best->Conversions[0], AA_Passing); if (InputRes.isInvalid()) return ExprError(); Input = InputRes.get(); @@ -12332,15 +12236,15 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // break out so that we will build the appropriate built-in // operator node. ExprResult ArgsRes0 = - PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], AA_Passing); + PerformImplicitConversion(Args[0], Best->BuiltinParamTypes[0], + Best->Conversions[0], AA_Passing); if (ArgsRes0.isInvalid()) return ExprError(); Args[0] = ArgsRes0.get(); ExprResult ArgsRes1 = - PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1], - Best->Conversions[1], AA_Passing); + PerformImplicitConversion(Args[1], Best->BuiltinParamTypes[1], + Best->Conversions[1], AA_Passing); if (ArgsRes1.isInvalid()) return ExprError(); Args[1] = ArgsRes1.get(); @@ -12543,15 +12447,15 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // break out so that we will build the appropriate built-in // operator node. ExprResult ArgsRes0 = - PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], AA_Passing); + PerformImplicitConversion(Args[0], Best->BuiltinParamTypes[0], + Best->Conversions[0], AA_Passing); if (ArgsRes0.isInvalid()) return ExprError(); Args[0] = ArgsRes0.get(); ExprResult ArgsRes1 = - PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1], - Best->Conversions[1], AA_Passing); + PerformImplicitConversion(Args[1], Best->BuiltinParamTypes[1], + Best->Conversions[1], AA_Passing); if (ArgsRes1.isInvalid()) return ExprError(); Args[1] = ArgsRes1.get(); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index dcb2c11c73c7..151b89ab8d2a 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -3956,8 +3956,9 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, DeclContext *DC = CapturedDecl::castToDeclContext(CD); IdentifierInfo *ParamName = &Context.Idents.get("__context"); QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD)); - ImplicitParamDecl *Param - = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType); + auto *Param = + ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType, + ImplicitParamDecl::CapturedContext); DC->addDecl(Param); CD->setContextParam(0, Param); @@ -3992,15 +3993,17 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, "null type has been found already for '__context' parameter"); IdentifierInfo *ParamName = &Context.Idents.get("__context"); QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD)); - ImplicitParamDecl *Param - = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType); + auto *Param = + ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType, + ImplicitParamDecl::CapturedContext); DC->addDecl(Param); CD->setContextParam(ParamNum, Param); ContextIsFound = true; } else { IdentifierInfo *ParamName = &Context.Idents.get(I->first); - ImplicitParamDecl *Param - = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, I->second); + auto *Param = + ImplicitParamDecl::Create(Context, DC, Loc, ParamName, I->second, + ImplicitParamDecl::CapturedContext); DC->addDecl(Param); CD->setParam(ParamNum, Param); } @@ -4010,8 +4013,9 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, // Add __context implicitly if it is not specified. IdentifierInfo *ParamName = &Context.Idents.get("__context"); QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD)); - ImplicitParamDecl *Param = - ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType); + auto *Param = + ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType, + ImplicitParamDecl::CapturedContext); DC->addDecl(Param); CD->setContextParam(ParamNum, Param); } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 8cd7efbb1dba..1eea151a4ec8 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -4020,6 +4020,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, } } // fallthrough + LLVM_FALLTHROUGH; } default: { // We have a template type parameter but the template argument @@ -7594,6 +7595,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, return false; } // Fall through + LLVM_FALLTHROUGH; case TSK_ExplicitInstantiationDeclaration: case TSK_ExplicitInstantiationDefinition: @@ -7620,6 +7622,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, return true; } + llvm_unreachable("The switch over PrevTSK must be exhaustive."); case TSK_ExplicitInstantiationDeclaration: switch (PrevTSK) { @@ -8955,7 +8958,8 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // A member function [...] of a class template can be explicitly // instantiated from the member definition associated with its class // template. - UnresolvedSet<8> Matches; + UnresolvedSet<8> TemplateMatches; + FunctionDecl *NonTemplateMatch = nullptr; AttributeList *Attr = D.getDeclSpec().getAttributes().getList(); TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc()); for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); @@ -8966,11 +8970,13 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, QualType Adjusted = adjustCCAndNoReturn(R, Method->getType(), /*AdjustExceptionSpec*/true); if (Context.hasSameUnqualifiedType(Method->getType(), Adjusted)) { - Matches.clear(); - - Matches.addDecl(Method, P.getAccess()); - if (Method->getTemplateSpecializationKind() == TSK_Undeclared) - break; + if (Method->getPrimaryTemplate()) { + TemplateMatches.addDecl(Method, P.getAccess()); + } else { + // FIXME: Can this assert ever happen? Needs a test. + assert(!NonTemplateMatch && "Multiple NonTemplateMatches"); + NonTemplateMatch = Method; + } } } } @@ -9009,22 +9015,25 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, continue; } - Matches.addDecl(Specialization, P.getAccess()); + TemplateMatches.addDecl(Specialization, P.getAccess()); } - // Find the most specialized function template specialization. - UnresolvedSetIterator Result = getMostSpecialized( - Matches.begin(), Matches.end(), FailedCandidates, - D.getIdentifierLoc(), - PDiag(diag::err_explicit_instantiation_not_known) << Name, - PDiag(diag::err_explicit_instantiation_ambiguous) << Name, - PDiag(diag::note_explicit_instantiation_candidate)); - - if (Result == Matches.end()) - return true; + FunctionDecl *Specialization = NonTemplateMatch; + if (!Specialization) { + // Find the most specialized function template specialization. + UnresolvedSetIterator Result = getMostSpecialized( + TemplateMatches.begin(), TemplateMatches.end(), FailedCandidates, + D.getIdentifierLoc(), + PDiag(diag::err_explicit_instantiation_not_known) << Name, + PDiag(diag::err_explicit_instantiation_ambiguous) << Name, + PDiag(diag::note_explicit_instantiation_candidate)); + + if (Result == TemplateMatches.end()) + return true; - // Ignore access control bits, we don't need them for redeclaration checking. - FunctionDecl *Specialization = cast<FunctionDecl>(*Result); + // Ignore access control bits, we don't need them for redeclaration checking. + Specialization = cast<FunctionDecl>(*Result); + } // C++11 [except.spec]p4 // In an explicit instantiation an exception-specification may be specified, @@ -9379,6 +9388,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, } // Fall through to create a dependent typename type, from which we can recover // better. + LLVM_FALLTHROUGH; case LookupResult::NotFoundInCurrentInstantiation: // Okay, it's a member of an unknown instantiation. diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 75b69ae04f56..983b1ea795dd 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -56,8 +56,12 @@ namespace clang { TDF_TopLevelParameterTypeList = 0x10, /// \brief Within template argument deduction from overload resolution per /// C++ [over.over] allow matching function types that are compatible in - /// terms of noreturn and default calling convention adjustments. - TDF_InOverloadResolution = 0x20 + /// terms of noreturn and default calling convention adjustments, or + /// similarly matching a declared template specialization against a + /// possible template, per C++ [temp.deduct.decl]. In either case, permit + /// deduction where the parameter is a function type that can be converted + /// to the argument type. + TDF_AllowCompatibleFunctionType = 0x20, }; } @@ -1306,9 +1310,10 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, // If the parameter type is not dependent, there is nothing to deduce. if (!Param->isDependentType()) { if (!(TDF & TDF_SkipNonDependent)) { - bool NonDeduced = (TDF & TDF_InOverloadResolution)? - !S.isSameOrCompatibleFunctionType(CanParam, CanArg) : - Param != Arg; + bool NonDeduced = + (TDF & TDF_AllowCompatibleFunctionType) + ? !S.isSameOrCompatibleFunctionType(CanParam, CanArg) + : Param != Arg; if (NonDeduced) { return Sema::TDK_NonDeducedMismatch; } @@ -1318,10 +1323,10 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, } else if (!Param->isDependentType()) { CanQualType ParamUnqualType = CanParam.getUnqualifiedType(), ArgUnqualType = CanArg.getUnqualifiedType(); - bool Success = (TDF & TDF_InOverloadResolution)? - S.isSameOrCompatibleFunctionType(ParamUnqualType, - ArgUnqualType) : - ParamUnqualType == ArgUnqualType; + bool Success = + (TDF & TDF_AllowCompatibleFunctionType) + ? S.isSameOrCompatibleFunctionType(ParamUnqualType, ArgUnqualType) + : ParamUnqualType == ArgUnqualType; if (Success) return Sema::TDK_Success; } @@ -1524,17 +1529,56 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, return Sema::TDK_NonDeducedMismatch; // Check return types. - if (Sema::TemplateDeductionResult Result = - DeduceTemplateArgumentsByTypeMatch( - S, TemplateParams, FunctionProtoParam->getReturnType(), - FunctionProtoArg->getReturnType(), Info, Deduced, 0)) + if (auto Result = DeduceTemplateArgumentsByTypeMatch( + S, TemplateParams, FunctionProtoParam->getReturnType(), + FunctionProtoArg->getReturnType(), Info, Deduced, 0)) return Result; - return DeduceTemplateArguments( - S, TemplateParams, FunctionProtoParam->param_type_begin(), - FunctionProtoParam->getNumParams(), - FunctionProtoArg->param_type_begin(), - FunctionProtoArg->getNumParams(), Info, Deduced, SubTDF); + // Check parameter types. + if (auto Result = DeduceTemplateArguments( + S, TemplateParams, FunctionProtoParam->param_type_begin(), + FunctionProtoParam->getNumParams(), + FunctionProtoArg->param_type_begin(), + FunctionProtoArg->getNumParams(), Info, Deduced, SubTDF)) + return Result; + + if (TDF & TDF_AllowCompatibleFunctionType) + return Sema::TDK_Success; + + // FIXME: Per core-2016/10/1019 (no corresponding core issue yet), permit + // deducing through the noexcept-specifier if it's part of the canonical + // type. libstdc++ relies on this. + Expr *NoexceptExpr = FunctionProtoParam->getNoexceptExpr(); + if (NonTypeTemplateParmDecl *NTTP = + NoexceptExpr ? getDeducedParameterFromExpr(Info, NoexceptExpr) + : nullptr) { + assert(NTTP->getDepth() == Info.getDeducedDepth() && + "saw non-type template parameter with wrong depth"); + + llvm::APSInt Noexcept(1); + switch (FunctionProtoArg->canThrow(S.Context)) { + case CT_Cannot: + Noexcept = 1; + LLVM_FALLTHROUGH; + + case CT_Can: + // We give E in noexcept(E) the "deduced from array bound" treatment. + // FIXME: Should we? + return DeduceNonTypeTemplateArgument( + S, TemplateParams, NTTP, Noexcept, S.Context.BoolTy, + /*ArrayBound*/true, Info, Deduced); + + case CT_Dependent: + if (Expr *ArgNoexceptExpr = FunctionProtoArg->getNoexceptExpr()) + return DeduceNonTypeTemplateArgument( + S, TemplateParams, NTTP, ArgNoexceptExpr, Info, Deduced); + // Can't deduce anything from throw(T...). + break; + } + } + // FIXME: Detect non-deduced exception specification mismatches? + + return Sema::TDK_Success; } case Type::InjectedClassName: { @@ -1544,7 +1588,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, ->getInjectedSpecializationType(); assert(isa<TemplateSpecializationType>(Param) && "injected class name is not a template specialization type"); - // fall through + LLVM_FALLTHROUGH; } // template-name<T> (where template-name refers to a class template) @@ -2820,6 +2864,17 @@ Sema::SubstituteExplicitTemplateArguments( if (FunctionType) { auto EPI = Proto->getExtProtoInfo(); EPI.ExtParameterInfos = ExtParamInfos.getPointerOrNull(ParamTypes.size()); + + // In C++1z onwards, exception specifications are part of the function type, + // so substitution into the type must also substitute into the exception + // specification. + SmallVector<QualType, 4> ExceptionStorage; + if (getLangOpts().CPlusPlus1z && + SubstExceptionSpec( + Function->getLocation(), EPI.ExceptionSpec, ExceptionStorage, + MultiLevelTemplateArgumentList(*ExplicitArgumentList))) + return TDK_SubstitutionFailure; + *FunctionType = BuildFunctionType(ResultType, ParamTypes, Function->getLocation(), Function->getDeclName(), @@ -3714,13 +3769,6 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( = FunctionTemplate->getTemplateParameters(); QualType FunctionType = Function->getType(); - // When taking the address of a function, we require convertibility of - // the resulting function type. Otherwise, we allow arbitrary mismatches - // of calling convention, noreturn, and noexcept. - if (!IsAddressOfFunction) - ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, FunctionType, - /*AdjustExceptionSpec*/true); - // Substitute any explicit template arguments. LocalInstantiationScope InstScope(*this); SmallVector<DeducedTemplateArgument, 4> Deduced; @@ -3737,6 +3785,13 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( NumExplicitlySpecified = Deduced.size(); } + // When taking the address of a function, we require convertibility of + // the resulting function type. Otherwise, we allow arbitrary mismatches + // of calling convention and noreturn. + if (!IsAddressOfFunction) + ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, FunctionType, + /*AdjustExceptionSpec*/false); + // Unevaluated SFINAE context. EnterExpressionEvaluationContext Unevaluated( *this, Sema::ExpressionEvaluationContext::Unevaluated); @@ -3756,9 +3811,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( } if (!ArgFunctionType.isNull()) { - unsigned TDF = TDF_TopLevelParameterTypeList; - if (IsAddressOfFunction) - TDF |= TDF_InOverloadResolution; + unsigned TDF = + TDF_TopLevelParameterTypeList | TDF_AllowCompatibleFunctionType; // Deduce template arguments from the function type. if (TemplateDeductionResult Result = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, @@ -3789,7 +3843,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( !ResolveExceptionSpec(Info.getLocation(), SpecializationFPT)) return TDK_MiscellaneousDeductionFailure; - // Adjust the exception specification of the argument again to match the + // Adjust the exception specification of the argument to match the // substituted and resolved type we just formed. (Calling convention and // noreturn can't be dependent, so we don't actually need this for them // right now.) @@ -5127,6 +5181,8 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, for (unsigned I = 0, N = Proto->getNumParams(); I != N; ++I) MarkUsedTemplateParameters(Ctx, Proto->getParamType(I), OnlyDeduced, Depth, Used); + if (auto *E = Proto->getNoexceptExpr()) + MarkUsedTemplateParameters(Ctx, E, OnlyDeduced, Depth, Used); break; } diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index a654ca800b05..fe92dd8ac653 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -1692,20 +1692,26 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, return TLB.getTypeSourceInfo(Context, Result); } +bool Sema::SubstExceptionSpec(SourceLocation Loc, + FunctionProtoType::ExceptionSpecInfo &ESI, + SmallVectorImpl<QualType> &ExceptionStorage, + const MultiLevelTemplateArgumentList &Args) { + assert(ESI.Type != EST_Uninstantiated); + + bool Changed = false; + TemplateInstantiator Instantiator(*this, Args, Loc, DeclarationName()); + return Instantiator.TransformExceptionSpec(Loc, ESI, ExceptionStorage, + Changed); +} + void Sema::SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto, const MultiLevelTemplateArgumentList &Args) { FunctionProtoType::ExceptionSpecInfo ESI = Proto->getExtProtoInfo().ExceptionSpec; - assert(ESI.Type != EST_Uninstantiated); - - TemplateInstantiator Instantiator(*this, Args, New->getLocation(), - New->getDeclName()); SmallVector<QualType, 4> ExceptionStorage; - bool Changed = false; - if (Instantiator.TransformExceptionSpec( - New->getTypeSourceInfo()->getTypeLoc().getLocEnd(), ESI, - ExceptionStorage, Changed)) + if (SubstExceptionSpec(New->getTypeSourceInfo()->getTypeLoc().getLocEnd(), + ESI, ExceptionStorage, Args)) // On error, recover by dropping the exception specification. ESI.Type = EST_None; @@ -2350,6 +2356,25 @@ namespace { }; } +bool Sema::usesPartialOrExplicitSpecialization( + SourceLocation Loc, ClassTemplateSpecializationDecl *ClassTemplateSpec) { + if (ClassTemplateSpec->getTemplateSpecializationKind() == + TSK_ExplicitSpecialization) + return true; + + SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs; + ClassTemplateSpec->getSpecializedTemplate() + ->getPartialSpecializations(PartialSpecs); + for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) { + TemplateDeductionInfo Info(Loc); + if (!DeduceTemplateArguments(PartialSpecs[I], + ClassTemplateSpec->getTemplateArgs(), Info)) + return true; + } + + return false; +} + /// 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). diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index e7523ce2836d..148ce24293a0 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4807,7 +4807,7 @@ static NamedDecl *findInstantiationOf(ASTContext &Ctx, DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC, const MultiLevelTemplateArgumentList &TemplateArgs) { if (NamedDecl *D = dyn_cast<NamedDecl>(DC)) { - Decl* ID = FindInstantiatedDecl(Loc, D, TemplateArgs); + Decl* ID = FindInstantiatedDecl(Loc, D, TemplateArgs, true); return cast_or_null<DeclContext>(ID); } else return DC; } @@ -4839,7 +4839,8 @@ DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC, /// (<tt>X<int>::<Kind>::KnownValue</tt>). \p FindInstantiatedDecl performs /// this mapping from within the instantiation of <tt>X<int></tt>. NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, - const MultiLevelTemplateArgumentList &TemplateArgs) { + const MultiLevelTemplateArgumentList &TemplateArgs, + bool FindingInstantiatedContext) { DeclContext *ParentDC = D->getDeclContext(); // FIXME: Parmeters of pointer to functions (y below) that are themselves // parameters (p below) can have their ParentDC set to the translation-unit @@ -5000,7 +5001,22 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, QualType T = CheckTemplateIdType(TemplateName(TD), Loc, Args); if (T.isNull()) return nullptr; - DC = T->getAsCXXRecordDecl(); + auto *SubstRecord = T->getAsCXXRecordDecl(); + assert(SubstRecord && "class template id not a class type?"); + // Check that this template-id names the primary template and not a + // partial or explicit specialization. (In the latter cases, it's + // meaningless to attempt to find an instantiation of D within the + // specialization.) + // FIXME: The standard doesn't say what should happen here. + if (FindingInstantiatedContext && + usesPartialOrExplicitSpecialization( + Loc, cast<ClassTemplateSpecializationDecl>(SubstRecord))) { + Diag(Loc, diag::err_specialization_not_primary_template) + << T << (SubstRecord->getTemplateSpecializationKind() == + TSK_ExplicitSpecialization); + return nullptr; + } + DC = SubstRecord; continue; } } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index c189112e3455..8c8402e75e37 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -3367,7 +3367,7 @@ classifyPointerDeclarator(Sema &S, QualType type, Declarator &declarator, if (auto objcClass = type->getAs<ObjCInterfaceType>()) { if (objcClass->getInterface()->getIdentifier() == S.getNSErrorIdent()) { if (numNormalPointers == 2 && numTypeSpecifierPointers < 2) - return PointerDeclaratorKind::NSErrorPointerPointer;; + return PointerDeclaratorKind::NSErrorPointerPointer; } break; |