summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/DeclSpec.cpp28
-rw-r--r--clang/lib/Sema/SemaCodeComplete.cpp3
-rw-r--r--clang/lib/Sema/SemaDecl.cpp18
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp59
-rw-r--r--clang/lib/Sema/SemaInit.cpp91
-rw-r--r--clang/lib/Sema/SemaLambda.cpp4
-rw-r--r--clang/lib/Sema/SemaLookup.cpp5
-rw-r--r--clang/lib/Sema/SemaOverload.cpp171
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp16
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp53
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;
OpenPOWER on IntegriCloud