diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 28 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCodeComplete.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 59 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 91 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 171 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 53 |
10 files changed, 287 insertions, 161 deletions
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 8c09947ad7b..08c3b0ff327 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -445,7 +445,7 @@ unsigned DeclSpec::getParsedSpecifiers() const { if (hasTypeSpecifier()) Res |= PQ_TypeSpecifier; - if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified || + if (FS_inline_specified || FS_virtual_specified || hasExplicitSpecifier() || FS_noreturn_specified || FS_forceinline_specified) Res |= PQ_FunctionSpecifier; return Res; @@ -959,17 +959,24 @@ bool DeclSpec::setFunctionSpecVirtual(SourceLocation Loc, } bool DeclSpec::setFunctionSpecExplicit(SourceLocation Loc, - const char *&PrevSpec, - unsigned &DiagID) { + const char *&PrevSpec, unsigned &DiagID, + ExplicitSpecifier ExplicitSpec, + SourceLocation CloseParenLoc) { + assert((ExplicitSpec.getKind() == ExplicitSpecKind::ResolvedTrue || + ExplicitSpec.getExpr()) && + "invalid ExplicitSpecifier"); // 'explicit explicit' is ok, but warn as this is likely not what the user // intended. - if (FS_explicit_specified) { - DiagID = diag::warn_duplicate_declspec; + if (hasExplicitSpecifier()) { + DiagID = (ExplicitSpec.getExpr() || FS_explicit_specifier.getExpr()) + ? diag::err_duplicate_declspec + : diag::ext_warn_duplicate_declspec; PrevSpec = "explicit"; return true; } - FS_explicit_specified = true; + FS_explicit_specifier = ExplicitSpec; FS_explicitLoc = Loc; + FS_explicitCloseParenLoc = CloseParenLoc; return false; } @@ -1311,23 +1318,26 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { // The explicit specifier shall be used only in the declaration of // a constructor or conversion function within its class // definition; - if (isFriendSpecified() && (isVirtualSpecified() || isExplicitSpecified())) { + if (isFriendSpecified() && (isVirtualSpecified() || hasExplicitSpecifier())) { StringRef Keyword; + FixItHint Hint; SourceLocation SCLoc; if (isVirtualSpecified()) { Keyword = "virtual"; SCLoc = getVirtualSpecLoc(); + Hint = FixItHint::CreateRemoval(SCLoc); } else { Keyword = "explicit"; SCLoc = getExplicitSpecLoc(); + Hint = FixItHint::CreateRemoval(getExplicitSpecRange()); } - FixItHint Hint = FixItHint::CreateRemoval(SCLoc); S.Diag(SCLoc, diag::err_friend_decl_spec) << Keyword << Hint; - FS_virtual_specified = FS_explicit_specified = false; + FS_virtual_specified = false; + FS_explicit_specifier = ExplicitSpecifier(); FS_virtualLoc = FS_explicitLoc = SourceLocation(); } diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 4d23bf6b752..2a62eca11b6 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -4970,7 +4970,8 @@ QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type, AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args, CandidateSet, /*SuppressUsedConversions=*/false, - /*PartialOverloading=*/true); + /*PartialOverloading=*/true, + /*AllowExplicit*/ true); } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) { AddTemplateOverloadCandidate( FTD, DeclAccessPair::make(FTD, C->getAccess()), diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index ea6675f15bd..5b7a0d2cc32 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5725,7 +5725,7 @@ void Sema::DiagnoseFunctionSpecifiers(const DeclSpec &DS) { Diag(DS.getVirtualSpecLoc(), diag::err_virtual_non_function); - if (DS.isExplicitSpecified()) + if (DS.hasExplicitSpecifier()) Diag(DS.getExplicitSpecLoc(), diag::err_explicit_non_function); @@ -7989,7 +7989,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, return NewFD; } - bool isExplicit = D.getDeclSpec().isExplicitSpecified(); + ExplicitSpecifier ExplicitSpecifier = D.getDeclSpec().getExplicitSpecifier(); bool isConstexpr = D.getDeclSpec().isConstexprSpecified(); // Check that the return type is not an abstract class type. @@ -8009,7 +8009,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, R = SemaRef.CheckConstructorDeclarator(D, R, SC); return CXXConstructorDecl::Create( SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R, - TInfo, isExplicit, isInline, + TInfo, ExplicitSpecifier, isInline, /*isImplicitlyDeclared=*/false, isConstexpr); } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) { @@ -8054,13 +8054,13 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, IsVirtualOkay = true; return CXXConversionDecl::Create( SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R, - TInfo, isInline, isExplicit, isConstexpr, SourceLocation()); + TInfo, isInline, ExplicitSpecifier, isConstexpr, SourceLocation()); } else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) { SemaRef.CheckDeductionGuideDeclarator(D, R, SC); return CXXDeductionGuideDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), - isExplicit, NameInfo, R, TInfo, + ExplicitSpecifier, NameInfo, R, TInfo, D.getEndLoc()); } else if (DC->isRecord()) { // If the name of the function is the same as the name of the record, @@ -8421,7 +8421,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (getLangOpts().CPlusPlus) { bool isInline = D.getDeclSpec().isInlineSpecified(); bool isVirtual = D.getDeclSpec().isVirtualSpecified(); - bool isExplicit = D.getDeclSpec().isExplicitSpecified(); + bool hasExplicit = D.getDeclSpec().hasExplicitSpecifier(); bool isConstexpr = D.getDeclSpec().isConstexprSpecified(); isFriend = D.getDeclSpec().isFriendSpecified(); if (isFriend && !isInline && D.isFunctionDefinition()) { @@ -8604,20 +8604,20 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // The explicit specifier shall be used only in the declaration of a // constructor or conversion function within its class definition; // see 12.3.1 and 12.3.2. - if (isExplicit && !NewFD->isInvalidDecl() && + if (hasExplicit && !NewFD->isInvalidDecl() && !isa<CXXDeductionGuideDecl>(NewFD)) { if (!CurContext->isRecord()) { // 'explicit' was specified outside of the class. Diag(D.getDeclSpec().getExplicitSpecLoc(), diag::err_explicit_out_of_class) - << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc()); + << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecRange()); } else if (!isa<CXXConstructorDecl>(NewFD) && !isa<CXXConversionDecl>(NewFD)) { // 'explicit' was specified on a function that wasn't a constructor // or conversion function. Diag(D.getDeclSpec().getExplicitSpecLoc(), diag::err_explicit_non_ctor_or_conv_function) - << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc()); + << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecRange()); } } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 04192e3566c..fac7d418d40 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -657,14 +657,13 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Invalid = true; } - // FIXME: It's not clear what should happen if multiple declarations of a - // deduction guide have different explicitness. For now at least we simply - // reject any case where the explicitness changes. - auto *NewGuide = dyn_cast<CXXDeductionGuideDecl>(New); - if (NewGuide && NewGuide->isExplicitSpecified() != - cast<CXXDeductionGuideDecl>(Old)->isExplicitSpecified()) { - Diag(New->getLocation(), diag::err_deduction_guide_explicit_mismatch) - << NewGuide->isExplicitSpecified(); + // C++17 [temp.deduct.guide]p3: + // Two deduction guide declarations in the same translation unit + // for the same class template shall not have equivalent + // parameter-declaration-clauses. + if (isa<CXXDeductionGuideDecl>(New) && + !New->isFunctionTemplateSpecialization()) { + Diag(New->getLocation(), diag::err_deduction_guide_redeclared); Diag(Old->getLocation(), diag::note_previous_declaration); } @@ -8594,12 +8593,12 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, R = Context.getFunctionType(ConvType, None, Proto->getExtProtoInfo()); // C++0x explicit conversion operators. - if (DS.isExplicitSpecified()) + if (DS.hasExplicitSpecifier() && !getLangOpts().CPlusPlus2a) Diag(DS.getExplicitSpecLoc(), getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_explicit_conversion_functions : diag::ext_explicit_conversion_functions) - << SourceRange(DS.getExplicitSpecLoc()); + << SourceRange(DS.getExplicitSpecRange()); } /// ActOnConversionDeclarator - Called by ActOnDeclarator to complete @@ -10822,6 +10821,28 @@ struct ComputingExceptionSpec { }; } +bool Sema::tryResolveExplicitSpecifier(ExplicitSpecifier &ExplicitSpec) { + llvm::APSInt Result; + ExprResult Converted = CheckConvertedConstantExpression( + ExplicitSpec.getExpr(), Context.BoolTy, Result, CCEK_ExplicitBool); + ExplicitSpec.setExpr(Converted.get()); + if (Converted.isUsable() && !Converted.get()->isValueDependent()) { + ExplicitSpec.setKind(Result.getBoolValue() + ? ExplicitSpecKind::ResolvedTrue + : ExplicitSpecKind::ResolvedFalse); + return true; + } + ExplicitSpec.setKind(ExplicitSpecKind::Unresolved); + return false; +} + +ExplicitSpecifier Sema::ActOnExplicitBoolSpecifier(Expr *ExplicitExpr) { + ExplicitSpecifier ES(ExplicitExpr, ExplicitSpecKind::Unresolved); + if (!ExplicitExpr->isTypeDependent()) + tryResolveExplicitSpecifier(ES); + return ES; +} + static Sema::ImplicitExceptionSpecification ComputeDefaultedSpecialMemberExceptionSpec( Sema &S, SourceLocation Loc, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM, @@ -10970,9 +10991,9 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( = Context.DeclarationNames.getCXXConstructorName(ClassType); DeclarationNameInfo NameInfo(Name, ClassLoc); CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create( - Context, ClassDecl, ClassLoc, NameInfo, /*Type*/QualType(), - /*TInfo=*/nullptr, /*isExplicit=*/false, /*isInline=*/true, - /*isImplicitlyDeclared=*/true, Constexpr); + Context, ClassDecl, ClassLoc, NameInfo, /*Type*/ QualType(), + /*TInfo=*/nullptr, ExplicitSpecifier(), + /*isInline=*/true, /*isImplicitlyDeclared=*/true, Constexpr); DefaultCon->setAccess(AS_public); DefaultCon->setDefaulted(); @@ -11091,7 +11112,7 @@ Sema::findInheritingConstructor(SourceLocation Loc, CXXConstructorDecl *DerivedCtor = CXXConstructorDecl::Create( Context, Derived, UsingLoc, NameInfo, TInfo->getType(), TInfo, - BaseCtor->isExplicit(), /*Inline=*/true, + BaseCtor->getExplicitSpecifier(), /*Inline=*/true, /*ImplicitlyDeclared=*/true, Constexpr, InheritedConstructor(Shadow, BaseCtor)); if (Shadow->isInvalidDecl()) @@ -12543,8 +12564,9 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( // member of its class. CXXConstructorDecl *CopyConstructor = CXXConstructorDecl::Create( Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, - /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true, - Constexpr); + ExplicitSpecifier(), + /*isInline=*/true, + /*isImplicitlyDeclared=*/true, Constexpr); CopyConstructor->setAccess(AS_public); CopyConstructor->setDefaulted(); @@ -12673,8 +12695,9 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( // member of its class. CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create( Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, - /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true, - Constexpr); + ExplicitSpecifier(), + /*isInline=*/true, + /*isImplicitlyDeclared=*/true, Constexpr); MoveConstructor->setAccess(AS_public); MoveConstructor->setDefaulted(); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index e8a8887736e..8bcce39c5ef 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3763,9 +3763,10 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, hasCopyOrMoveCtorParam(S.Context, Info)); if (Info.ConstructorTmpl) - S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, - /*ExplicitArgs*/ nullptr, Args, - CandidateSet, SuppressUserConversions); + S.AddTemplateOverloadCandidate( + Info.ConstructorTmpl, Info.FoundDecl, + /*ExplicitArgs*/ nullptr, Args, CandidateSet, SuppressUserConversions, + /*PartialOverloading=*/false, AllowExplicit); else { // C++ [over.match.copy]p1: // - When initializing a temporary to be bound to the first parameter @@ -3779,8 +3780,8 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, hasCopyOrMoveCtorParam(S.Context, Info); S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args, CandidateSet, SuppressUserConversions, - /*PartialOverloading=*/false, - /*AllowExplicit=*/AllowExplicitConv); + /*PartialOverloading=*/false, AllowExplicit, + AllowExplicitConv); } } @@ -3813,16 +3814,17 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, else Conv = cast<CXXConversionDecl>(D); - if ((AllowExplicit && !CopyInitializing) || !Conv->isExplicit()) { + if (AllowExplicit || !Conv->isExplicit()) { if (ConvTemplate) - S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), - ActingDC, Initializer, DestType, - CandidateSet, AllowExplicit, - /*AllowResultConversion*/false); + S.AddTemplateConversionCandidate( + ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, + CandidateSet, AllowExplicit, AllowExplicit, + /*AllowResultConversion*/ false); else S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer, DestType, CandidateSet, AllowExplicit, - /*AllowResultConversion*/false); + AllowExplicit, + /*AllowResultConversion*/ false); } } } @@ -4368,14 +4370,16 @@ static OverloadingResult TryRefInitWithConversionFunction( if (!Info.Constructor->isInvalidDecl() && Info.Constructor->isConvertingConstructor(AllowExplicitCtors)) { if (Info.ConstructorTmpl) - S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, - /*ExplicitArgs*/ nullptr, - Initializer, CandidateSet, - /*SuppressUserConversions=*/true); + S.AddTemplateOverloadCandidate( + Info.ConstructorTmpl, Info.FoundDecl, + /*ExplicitArgs*/ nullptr, Initializer, CandidateSet, + /*SuppressUserConversions=*/true, + /*PartialOverloading*/ false, AllowExplicitCtors); else - S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, - Initializer, CandidateSet, - /*SuppressUserConversions=*/true); + S.AddOverloadCandidate( + Info.Constructor, Info.FoundDecl, Initializer, CandidateSet, + /*SuppressUserConversions=*/true, + /*PartialOverloading*/ false, AllowExplicitCtors); } } } @@ -4410,17 +4414,17 @@ static OverloadingResult TryRefInitWithConversionFunction( // candidates with reference-compatible results? That might be needed to // break recursion. if ((AllowExplicitConvs || !Conv->isExplicit()) && - (AllowRValues || Conv->getConversionType()->isLValueReferenceType())){ + (AllowRValues || + Conv->getConversionType()->isLValueReferenceType())) { if (ConvTemplate) - S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), - ActingDC, Initializer, - DestType, CandidateSet, - /*AllowObjCConversionOnExplicit=*/ - false); + S.AddTemplateConversionCandidate( + ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, + CandidateSet, + /*AllowObjCConversionOnExplicit=*/false, AllowExplicitConvs); else - S.AddConversionCandidate(Conv, I.getPair(), ActingDC, - Initializer, DestType, CandidateSet, - /*AllowObjCConversionOnExplicit=*/false); + S.AddConversionCandidate( + Conv, I.getPair(), ActingDC, Initializer, DestType, CandidateSet, + /*AllowObjCConversionOnExplicit=*/false, AllowExplicitConvs); } } } @@ -4996,14 +5000,16 @@ static void TryUserDefinedConversion(Sema &S, if (!Info.Constructor->isInvalidDecl() && Info.Constructor->isConvertingConstructor(AllowExplicit)) { if (Info.ConstructorTmpl) - S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, - /*ExplicitArgs*/ nullptr, - Initializer, CandidateSet, - /*SuppressUserConversions=*/true); + S.AddTemplateOverloadCandidate( + Info.ConstructorTmpl, Info.FoundDecl, + /*ExplicitArgs*/ nullptr, Initializer, CandidateSet, + /*SuppressUserConversions=*/true, + /*PartialOverloading*/ false, AllowExplicit); else S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Initializer, CandidateSet, - /*SuppressUserConversions=*/true); + /*SuppressUserConversions=*/true, + /*PartialOverloading*/ false, AllowExplicit); } } } @@ -5038,12 +5044,12 @@ static void TryUserDefinedConversion(Sema &S, if (AllowExplicit || !Conv->isExplicit()) { if (ConvTemplate) - S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), - ActingDC, Initializer, DestType, - CandidateSet, AllowExplicit); + S.AddTemplateConversionCandidate( + ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, + CandidateSet, AllowExplicit, AllowExplicit); else - S.AddConversionCandidate(Conv, I.getPair(), ActingDC, - Initializer, DestType, CandidateSet, + S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer, + DestType, CandidateSet, AllowExplicit, AllowExplicit); } } @@ -9336,6 +9342,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( OverloadCandidateSet::iterator Best; bool HasAnyDeductionGuide = false; + bool AllowExplicit = !Kind.isCopyInit() || ListInit; auto tryToResolveOverload = [&](bool OnlyListConstructors) -> OverloadingResult { @@ -9361,7 +9368,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( // converting constructors (12.3.1) of that class. // C++ [over.match.copy]p1: (non-list copy-initialization from class) // The converting constructors of T are candidate functions. - if (Kind.isCopyInit() && !ListInit) { + if (!AllowExplicit) { // Only consider converting constructors. if (GD->isExplicit()) continue; @@ -9396,11 +9403,13 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( if (TD) AddTemplateOverloadCandidate(TD, I.getPair(), /*ExplicitArgs*/ nullptr, - Inits, Candidates, - SuppressUserConversions); + Inits, Candidates, SuppressUserConversions, + /*PartialOverloading*/ false, + AllowExplicit); else AddOverloadCandidate(GD, I.getPair(), Inits, Candidates, - SuppressUserConversions); + SuppressUserConversions, + /*PartialOverloading*/ false, AllowExplicit); } return Candidates.BestViableFunction(*this, Kind.getLocation(), Best); }; diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index b686681f04f..1966e9e0803 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1325,7 +1325,7 @@ static void addFunctionPointerConversion(Sema &S, CXXConversionDecl *Conversion = CXXConversionDecl::Create( S.Context, Class, Loc, DeclarationNameInfo(ConversionName, Loc, ConvNameLoc), ConvTy, ConvTSI, - /*isInline=*/true, /*isExplicit=*/false, + /*isInline=*/true, ExplicitSpecifier(), /*isConstexpr=*/S.getLangOpts().CPlusPlus17, CallOperator->getBody()->getEndLoc()); Conversion->setAccess(AS_public); @@ -1412,7 +1412,7 @@ static void addBlockPointerConversion(Sema &S, CXXConversionDecl *Conversion = CXXConversionDecl::Create( S.Context, Class, Loc, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy, S.Context.getTrivialTypeSourceInfo(ConvTy, Loc), - /*isInline=*/true, /*isExplicit=*/false, + /*isInline=*/true, ExplicitSpecifier(), /*isConstexpr=*/false, CallOperator->getBody()->getEndLoc()); Conversion->setAccess(AS_public); Conversion->setImplicit(true); diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 001a06f0bdf..f1d2a052404 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -3041,10 +3041,11 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, llvm::makeArrayRef(&Arg, NumArgs), OCS, true); else if (CtorInfo) AddOverloadCandidate(CtorInfo.Constructor, CtorInfo.FoundDecl, - llvm::makeArrayRef(&Arg, NumArgs), OCS, true); + llvm::makeArrayRef(&Arg, NumArgs), OCS, + /*SuppressUserConversions*/ true); else AddOverloadCandidate(M, Cand, llvm::makeArrayRef(&Arg, NumArgs), OCS, - true); + /*SuppressUserConversions*/ true); } else if (FunctionTemplateDecl *Tmpl = dyn_cast<FunctionTemplateDecl>(Cand->getUnderlyingDecl())) { if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 19ac2bf33aa..74283a067cf 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -3242,10 +3242,13 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType, if (Info.ConstructorTmpl) S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, /*ExplicitArgs*/ nullptr, From, - CandidateSet, SuppressUserConversions); + CandidateSet, SuppressUserConversions, + /*PartialOverloading*/ false, + AllowExplicit); else S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, From, - CandidateSet, SuppressUserConversions); + CandidateSet, SuppressUserConversions, + /*PartialOverloading*/ false, AllowExplicit); } } @@ -3372,13 +3375,15 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, S.AddTemplateOverloadCandidate( Info.ConstructorTmpl, Info.FoundDecl, /*ExplicitArgs*/ nullptr, llvm::makeArrayRef(Args, NumArgs), - CandidateSet, SuppressUserConversions); + CandidateSet, SuppressUserConversions, + /*PartialOverloading*/ false, AllowExplicit); else // Allow one user-defined conversion when user specifies a // From->ToType conversion via an static cast (c-style, etc). S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, llvm::makeArrayRef(Args, NumArgs), - CandidateSet, SuppressUserConversions); + CandidateSet, SuppressUserConversions, + /*PartialOverloading*/ false, AllowExplicit); } } } @@ -3410,14 +3415,13 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, if (AllowExplicit || !Conv->isExplicit()) { if (ConvTemplate) - S.AddTemplateConversionCandidate(ConvTemplate, FoundDecl, - ActingContext, From, ToType, - CandidateSet, - AllowObjCConversionOnExplicit); + S.AddTemplateConversionCandidate( + ConvTemplate, FoundDecl, ActingContext, From, ToType, + CandidateSet, AllowObjCConversionOnExplicit, AllowExplicit); else - S.AddConversionCandidate(Conv, FoundDecl, ActingContext, - From, ToType, CandidateSet, - AllowObjCConversionOnExplicit); + S.AddConversionCandidate( + Conv, FoundDecl, ActingContext, From, ToType, CandidateSet, + AllowObjCConversionOnExplicit, AllowExplicit); } } } @@ -4445,13 +4449,13 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, } if (ConvTemplate) - S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, - Init, DeclType, CandidateSet, - /*AllowObjCConversionOnExplicit=*/false); + S.AddTemplateConversionCandidate( + ConvTemplate, I.getPair(), ActingDC, Init, DeclType, CandidateSet, + /*AllowObjCConversionOnExplicit=*/false, AllowExplicit); else - S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init, - DeclType, CandidateSet, - /*AllowObjCConversionOnExplicit=*/false); + S.AddConversionCandidate( + Conv, I.getPair(), ActingDC, Init, DeclType, CandidateSet, + /*AllowObjCConversionOnExplicit=*/false, AllowExplicit); } bool HadMultipleCandidates = (CandidateSet.size() > 1); @@ -5414,7 +5418,7 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, // condition shall be a contextually converted constant expression of type // bool. ImplicitConversionSequence ICS = - CCE == Sema::CCEK_ConstexprIf + CCE == Sema::CCEK_ConstexprIf || CCE == Sema::CCEK_ExplicitBool ? TryContextuallyConvertToBool(S, From) : TryCopyInitialization(S, From, T, /*SuppressUserConversions=*/false, @@ -5730,12 +5734,13 @@ collectViableConversionCandidates(Sema &SemaRef, Expr *From, QualType ToType, if (ConvTemplate) SemaRef.AddTemplateConversionCandidate( - ConvTemplate, FoundDecl, ActingContext, From, ToType, CandidateSet, - /*AllowObjCConversionOnExplicit=*/false); + ConvTemplate, FoundDecl, ActingContext, From, ToType, CandidateSet, + /*AllowObjCConversionOnExplicit=*/false, /*AllowExplicit*/ true); else SemaRef.AddConversionCandidate(Conv, FoundDecl, ActingContext, From, ToType, CandidateSet, - /*AllowObjCConversionOnExplicit=*/false); + /*AllowObjCConversionOnExplicit=*/false, + /*AllowExplicit*/ true); } } @@ -5987,13 +5992,11 @@ static bool IsAcceptableNonMemberOperatorCandidate(ASTContext &Context, /// \param PartialOverloading true if we are performing "partial" overloading /// based on an incomplete set of function arguments. This feature is used by /// code completion. -void Sema::AddOverloadCandidate(FunctionDecl *Function, - DeclAccessPair FoundDecl, ArrayRef<Expr *> Args, - OverloadCandidateSet &CandidateSet, - bool SuppressUserConversions, - bool PartialOverloading, bool AllowExplicit, - ADLCallKind IsADLCandidate, - ConversionSequenceList EarlyConversions) { +void Sema::AddOverloadCandidate( + FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef<Expr *> Args, + OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, + bool PartialOverloading, bool AllowExplicit, bool AllowExplicitConversions, + ADLCallKind IsADLCandidate, ConversionSequenceList EarlyConversions) { const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>()); assert(Proto && "Functions without a prototype cannot be overloaded"); @@ -6150,13 +6153,11 @@ void Sema::AddOverloadCandidate(FunctionDecl *Function, // (13.3.3.1) that converts that argument to the corresponding // parameter of F. QualType ParamType = Proto->getParamType(ArgIdx); - Candidate.Conversions[ArgIdx] - = TryCopyInitialization(*this, Args[ArgIdx], ParamType, - SuppressUserConversions, - /*InOverloadResolution=*/true, - /*AllowObjCWritebackConversion=*/ - getLangOpts().ObjCAutoRefCount, - AllowExplicit); + Candidate.Conversions[ArgIdx] = TryCopyInitialization( + *this, Args[ArgIdx], ParamType, SuppressUserConversions, + /*InOverloadResolution=*/true, + /*AllowObjCWritebackConversion=*/ + getLangOpts().ObjCAutoRefCount, AllowExplicitConversions); if (Candidate.Conversions[ArgIdx].isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; @@ -6170,6 +6171,15 @@ void Sema::AddOverloadCandidate(FunctionDecl *Function, } } + if (!AllowExplicit) { + ExplicitSpecifier ES = ExplicitSpecifier::getFromDecl(Function); + if (ES.getKind() != ExplicitSpecKind::ResolvedFalse) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_explicit_resolved; + return; + } + } + if (EnableIfAttr *FailedAttr = CheckEnableIf(Function, Args)) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_enable_if; @@ -6759,7 +6769,7 @@ void Sema::AddTemplateOverloadCandidate( FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, - bool PartialOverloading, ADLCallKind IsADLCandidate) { + bool PartialOverloading, bool AllowExplicit, ADLCallKind IsADLCandidate) { if (!CandidateSet.isNewCandidate(FunctionTemplate)) return; @@ -6808,9 +6818,10 @@ void Sema::AddTemplateOverloadCandidate( // Add the function template specialization produced by template argument // deduction as a candidate. assert(Specialization && "Missing function template specialization?"); - AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet, - SuppressUserConversions, PartialOverloading, - /*AllowExplicit*/ false, IsADLCandidate, Conversions); + AddOverloadCandidate( + Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions, + PartialOverloading, AllowExplicit, + /*AllowExplicitConversions*/ false, IsADLCandidate, Conversions); } /// Check that implicit conversion sequences can be formed for each argument @@ -6915,14 +6926,11 @@ static bool isAllowableExplicitConversion(Sema &S, /// and ToType is the type that we're eventually trying to convert to /// (which may or may not be the same type as the type that the /// conversion function produces). -void -Sema::AddConversionCandidate(CXXConversionDecl *Conversion, - DeclAccessPair FoundDecl, - CXXRecordDecl *ActingContext, - Expr *From, QualType ToType, - OverloadCandidateSet& CandidateSet, - bool AllowObjCConversionOnExplicit, - bool AllowResultConversion) { +void Sema::AddConversionCandidate( + CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, Expr *From, QualType ToType, + OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, + bool AllowExplicit, bool AllowResultConversion) { assert(!Conversion->getDescribedFunctionTemplate() && "Conversion function templates use AddTemplateConversionCandidate"); QualType ConvType = Conversion->getConversionType().getNonReferenceType(); @@ -7081,6 +7089,13 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, "Can only end up with a standard conversion sequence or failure"); } + if (!AllowExplicit && Conversion->getExplicitSpecifier().getKind() != + ExplicitSpecKind::ResolvedFalse) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_explicit_resolved; + return; + } + if (EnableIfAttr *FailedAttr = CheckEnableIf(Conversion, None)) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_enable_if; @@ -7100,14 +7115,11 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, /// to deduce the template arguments of the conversion function /// template from the type that we are converting to (C++ /// [temp.deduct.conv]). -void -Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, - DeclAccessPair FoundDecl, - CXXRecordDecl *ActingDC, - Expr *From, QualType ToType, - OverloadCandidateSet &CandidateSet, - bool AllowObjCConversionOnExplicit, - bool AllowResultConversion) { +void Sema::AddTemplateConversionCandidate( + FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, + CXXRecordDecl *ActingDC, Expr *From, QualType ToType, + OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, + bool AllowExplicit, bool AllowResultConversion) { assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) && "Only conversion function templates permitted here"); @@ -7137,7 +7149,7 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, assert(Specialization && "Missing function template specialization?"); AddConversionCandidate(Specialization, FoundDecl, ActingDC, From, ToType, CandidateSet, AllowObjCConversionOnExplicit, - AllowResultConversion); + AllowExplicit, AllowResultConversion); } /// AddSurrogateCandidate - Adds a "surrogate" candidate function that @@ -8991,12 +9003,14 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, AddOverloadCandidate(FD, FoundDecl, Args, CandidateSet, /*SupressUserConversions=*/false, PartialOverloading, - /*AllowExplicit=*/false, ADLCallKind::UsesADL); + /*AllowExplicitConversions*/ false, + /*AllowExplicit*/ true, ADLCallKind::UsesADL); } else { - AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I), FoundDecl, - ExplicitTemplateArgs, Args, CandidateSet, - /*SupressUserConversions=*/false, - PartialOverloading, ADLCallKind::UsesADL); + AddTemplateOverloadCandidate( + cast<FunctionTemplateDecl>(*I), FoundDecl, ExplicitTemplateArgs, Args, + CandidateSet, + /*SuppressUserConversions=*/false, PartialOverloading, + /*AllowExplicit*/true, ADLCallKind::UsesADL); } } } @@ -10327,6 +10341,33 @@ static void DiagnoseFailedEnableIfAttr(Sema &S, OverloadCandidate *Cand) { << Attr->getCond()->getSourceRange() << Attr->getMessage(); } +static void DiagnoseFailedExplicitSpec(Sema &S, OverloadCandidate *Cand) { + ExplicitSpecifier ES; + const char *DeclName; + switch (Cand->Function->getDeclKind()) { + case Decl::Kind::CXXConstructor: + ES = cast<CXXConstructorDecl>(Cand->Function)->getExplicitSpecifier(); + DeclName = "constructor"; + break; + case Decl::Kind::CXXConversion: + ES = cast<CXXConversionDecl>(Cand->Function)->getExplicitSpecifier(); + DeclName = "conversion operator"; + break; + case Decl::Kind::CXXDeductionGuide: + ES = cast<CXXDeductionGuideDecl>(Cand->Function)->getExplicitSpecifier(); + DeclName = "deductiong guide"; + break; + default: + llvm_unreachable("invalid Decl"); + } + assert(ES.getExpr() && "null expression should be handled before"); + S.Diag(Cand->Function->getLocation(), + diag::note_ovl_candidate_explicit_forbidden) + << DeclName; + S.Diag(ES.getExpr()->getBeginLoc(), + diag::note_explicit_bool_resolved_to_true); +} + static void DiagnoseOpenCLExtensionDisabled(Sema &S, OverloadCandidate *Cand) { FunctionDecl *Callee = Cand->Function; @@ -10411,6 +10452,9 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, case ovl_fail_enable_if: return DiagnoseFailedEnableIfAttr(S, Cand); + case ovl_fail_explicit_resolved: + return DiagnoseFailedExplicitSpec(S, Cand); + case ovl_fail_ext_disabled: return DiagnoseOpenCLExtensionDisabled(S, Cand); @@ -12981,8 +13025,9 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // Microsoft supports direct constructor calls. if (getLangOpts().MicrosoftExt && isa<CXXConstructorDecl>(Func)) { - AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(), - Args, CandidateSet); + AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(), Args, + CandidateSet, + /*SuppressUserConversions*/ false); } else if ((Method = dyn_cast<CXXMethodDecl>(Func))) { // If explicit template arguments were provided, we can't call a // non-template member function. diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index c58c446e52c..4b6ae96de40 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1156,7 +1156,7 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, if (DS.isVirtualSpecified()) EmitDiag(DS.getVirtualSpecLoc()); - if (DS.isExplicitSpecified()) + if (DS.hasExplicitSpecifier()) EmitDiag(DS.getExplicitSpecLoc()); if (DS.isNoreturnSpecified()) @@ -1836,8 +1836,8 @@ struct ConvertConstructorToDeductionGuideTransform { return nullptr; TypeSourceInfo *NewTInfo = TLB.getTypeSourceInfo(SemaRef.Context, NewType); - return buildDeductionGuide(TemplateParams, CD->isExplicit(), NewTInfo, - CD->getBeginLoc(), CD->getLocation(), + return buildDeductionGuide(TemplateParams, CD->getExplicitSpecifier(), + NewTInfo, CD->getBeginLoc(), CD->getLocation(), CD->getEndLoc()); } @@ -1866,8 +1866,8 @@ struct ConvertConstructorToDeductionGuideTransform { Params.push_back(NewParam); } - return buildDeductionGuide(Template->getTemplateParameters(), false, TSI, - Loc, Loc, Loc); + return buildDeductionGuide(Template->getTemplateParameters(), + ExplicitSpecifier(), TSI, Loc, Loc, Loc); } private: @@ -2017,7 +2017,7 @@ private: } NamedDecl *buildDeductionGuide(TemplateParameterList *TemplateParams, - bool Explicit, TypeSourceInfo *TInfo, + ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart, SourceLocation Loc, SourceLocation LocEnd) { DeclarationNameInfo Name(DeductionGuideName, Loc); @@ -2026,8 +2026,8 @@ private: // Build the implicit deduction guide template. auto *Guide = - CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, Explicit, - Name, TInfo->getType(), TInfo, LocEnd); + CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name, + TInfo->getType(), TInfo, LocEnd); Guide->setImplicit(); Guide->setParams(Params); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 653eb693268..1c7341d3cf8 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -366,6 +366,29 @@ static void instantiateDependentAMDGPUFlatWorkGroupSizeAttr( Attr.getSpellingListIndex()); } +static ExplicitSpecifier +instantiateExplicitSpecifier(Sema &S, + const MultiLevelTemplateArgumentList &TemplateArgs, + ExplicitSpecifier ES, FunctionDecl *New) { + if (!ES.getExpr()) + return ES; + Expr *OldCond = ES.getExpr(); + Expr *Cond = nullptr; + { + EnterExpressionEvaluationContext Unevaluated( + S, Sema::ExpressionEvaluationContext::ConstantEvaluated); + ExprResult SubstResult = S.SubstExpr(OldCond, TemplateArgs); + if (SubstResult.isInvalid()) { + return ExplicitSpecifier::Invalid(); + } + Cond = SubstResult.get(); + } + ExplicitSpecifier Result(Cond, ES.getKind()); + if (!Cond->isTypeDependent()) + S.tryResolveExplicitSpecifier(Result); + return Result; +} + static void instantiateDependentAMDGPUWavesPerEUAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const AMDGPUWavesPerEUAttr &Attr, Decl *New) { @@ -1690,6 +1713,14 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod()); LocalInstantiationScope Scope(SemaRef, MergeWithParentScope); + ExplicitSpecifier InstantiatedExplicitSpecifier; + if (auto *DGuide = dyn_cast<CXXDeductionGuideDecl>(D)) { + InstantiatedExplicitSpecifier = instantiateExplicitSpecifier( + SemaRef, TemplateArgs, DGuide->getExplicitSpecifier(), DGuide); + if (InstantiatedExplicitSpecifier.isInvalid()) + return nullptr; + } + SmallVector<ParmVarDecl *, 4> Params; TypeSourceInfo *TInfo = SubstFunctionType(D, Params); if (!TInfo) @@ -1727,8 +1758,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, FunctionDecl *Function; if (auto *DGuide = dyn_cast<CXXDeductionGuideDecl>(D)) { Function = CXXDeductionGuideDecl::Create( - SemaRef.Context, DC, D->getInnerLocStart(), DGuide->isExplicit(), - NameInfo, T, TInfo, D->getSourceRange().getEnd()); + SemaRef.Context, DC, D->getInnerLocStart(), + InstantiatedExplicitSpecifier, NameInfo, T, TInfo, + D->getSourceRange().getEnd()); if (DGuide->isCopyDeductionCandidate()) cast<CXXDeductionGuideDecl>(Function)->setIsCopyDeductionCandidate(); Function->setAccess(D->getAccess()); @@ -1996,6 +2028,12 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( } } + ExplicitSpecifier InstantiatedExplicitSpecifier = + instantiateExplicitSpecifier(SemaRef, TemplateArgs, + ExplicitSpecifier::getFromDecl(D), D); + if (InstantiatedExplicitSpecifier.isInvalid()) + return nullptr; + SmallVector<ParmVarDecl *, 4> Params; TypeSourceInfo *TInfo = SubstFunctionType(D, Params); if (!TInfo) @@ -2035,11 +2073,10 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( DeclarationNameInfo NameInfo = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { - Method = CXXConstructorDecl::Create(SemaRef.Context, Record, - StartLoc, NameInfo, T, TInfo, - Constructor->isExplicit(), - Constructor->isInlineSpecified(), - false, Constructor->isConstexpr()); + Method = CXXConstructorDecl::Create( + SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, + InstantiatedExplicitSpecifier, Constructor->isInlineSpecified(), false, + Constructor->isConstexpr()); Method->setRangeEnd(Constructor->getEndLoc()); } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { Method = CXXDestructorDecl::Create(SemaRef.Context, Record, @@ -2050,7 +2087,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) { Method = CXXConversionDecl::Create( SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, - Conversion->isInlineSpecified(), Conversion->isExplicit(), + Conversion->isInlineSpecified(), InstantiatedExplicitSpecifier, Conversion->isConstexpr(), Conversion->getEndLoc()); } else { StorageClass SC = D->isStatic() ? SC_Static : SC_None; |