aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp225
1 files changed, 147 insertions, 78 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 22bf35dbd0cb..8bfaa46162bc 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -655,7 +655,8 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
// contain the constexpr specifier.
if (New->getConstexprKind() != Old->getConstexprKind()) {
Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch)
- << New << New->getConstexprKind() << Old->getConstexprKind();
+ << New << static_cast<int>(New->getConstexprKind())
+ << static_cast<int>(Old->getConstexprKind());
Diag(Old->getLocation(), diag::note_previous_declaration);
Invalid = true;
} else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() &&
@@ -694,6 +695,17 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
Invalid = true;
}
+ // C++11 [temp.friend]p4 (DR329):
+ // When a function is defined in a friend function declaration in a class
+ // template, the function is instantiated when the function is odr-used.
+ // The same restrictions on multiple declarations and definitions that
+ // apply to non-template function declarations and definitions also apply
+ // to these implicit definitions.
+ const FunctionDecl *OldDefinition = nullptr;
+ if (New->isThisDeclarationInstantiatedFromAFriendDefinition() &&
+ Old->isDefined(OldDefinition, true))
+ CheckForFunctionRedefinition(New, OldDefinition);
+
return Invalid;
}
@@ -723,7 +735,7 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
Diag(Decomp.getLSquareLoc(),
!getLangOpts().CPlusPlus17
? diag::ext_decomp_decl
- : D.getContext() == DeclaratorContext::ConditionContext
+ : D.getContext() == DeclaratorContext::Condition
? diag::ext_decomp_decl_cond
: diag::warn_cxx14_compat_decomp_decl)
<< Decomp.getSourceRange();
@@ -890,7 +902,8 @@ static bool checkSimpleDecomposition(
llvm::function_ref<ExprResult(SourceLocation, Expr *, unsigned)> GetInit) {
if ((int64_t)Bindings.size() != NumElems) {
S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
- << DecompType << (unsigned)Bindings.size() << NumElems.toString(10)
+ << DecompType << (unsigned)Bindings.size()
+ << (unsigned)NumElems.getLimitedValue(UINT_MAX) << NumElems.toString(10)
<< (NumElems < Bindings.size());
return true;
}
@@ -1066,8 +1079,9 @@ static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T,
TemplateArgumentListInfo &Args;
ICEDiagnoser(LookupResult &R, TemplateArgumentListInfo &Args)
: R(R), Args(Args) {}
- void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override {
- S.Diag(Loc, diag::err_decomp_decl_std_tuple_size_not_constant)
+ Sema::SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
+ SourceLocation Loc) override {
+ return S.Diag(Loc, diag::err_decomp_decl_std_tuple_size_not_constant)
<< printTemplateArgs(S.Context.getPrintingPolicy(), Args);
}
} Diagnoser(R, Args);
@@ -1077,7 +1091,7 @@ static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T,
if (E.isInvalid())
return IsTupleLike::Error;
- E = S.VerifyIntegerConstantExpression(E.get(), &Size, Diagnoser, false);
+ E = S.VerifyIntegerConstantExpression(E.get(), &Size, Diagnoser);
if (E.isInvalid())
return IsTupleLike::Error;
@@ -1135,8 +1149,9 @@ static bool checkTupleLikeDecomposition(Sema &S,
const llvm::APSInt &TupleSize) {
if ((int64_t)Bindings.size() != TupleSize) {
S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
- << DecompType << (unsigned)Bindings.size() << TupleSize.toString(10)
- << (TupleSize < Bindings.size());
+ << DecompType << (unsigned)Bindings.size()
+ << (unsigned)TupleSize.getLimitedValue(UINT_MAX)
+ << TupleSize.toString(10) << (TupleSize < Bindings.size());
return true;
}
@@ -1184,7 +1199,8 @@ static bool checkTupleLikeDecomposition(Sema &S,
// an xvalue otherwise
if (!Src->getType()->isLValueReferenceType())
E = ImplicitCastExpr::Create(S.Context, E.get()->getType(), CK_NoOp,
- E.get(), nullptr, VK_XValue);
+ E.get(), nullptr, VK_XValue,
+ FPOptionsOverride());
TemplateArgumentListInfo Args(Loc, Loc);
Args.addArgument(
@@ -1248,8 +1264,7 @@ static bool checkTupleLikeDecomposition(Sema &S,
if (E.isInvalid())
return true;
RefVD->setInit(E.get());
- if (!E.get()->isValueDependent())
- RefVD->checkInitIsICE();
+ S.CheckCompleteVariableDeclaration(RefVD);
E = S.BuildDeclarationNameExpr(CXXScopeSpec(),
DeclarationNameInfo(B->getDeclName(), Loc),
@@ -1360,7 +1375,7 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
[](FieldDecl *FD) { return !FD->isUnnamedBitfield(); });
assert(Bindings.size() != NumFields);
S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
- << DecompType << (unsigned)Bindings.size() << NumFields
+ << DecompType << (unsigned)Bindings.size() << NumFields << NumFields
<< (NumFields < Bindings.size());
return true;
};
@@ -1373,11 +1388,23 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
if (FD->isUnnamedBitfield())
continue;
- if (FD->isAnonymousStructOrUnion()) {
- S.Diag(Src->getLocation(), diag::err_decomp_decl_anon_union_member)
- << DecompType << FD->getType()->isUnionType();
- S.Diag(FD->getLocation(), diag::note_declared_at);
- return true;
+ // All the non-static data members are required to be nameable, so they
+ // must all have names.
+ if (!FD->getDeclName()) {
+ if (RD->isLambda()) {
+ S.Diag(Src->getLocation(), diag::err_decomp_decl_lambda);
+ S.Diag(RD->getLocation(), diag::note_lambda_decl);
+ return true;
+ }
+
+ if (FD->isAnonymousStructOrUnion()) {
+ S.Diag(Src->getLocation(), diag::err_decomp_decl_anon_union_member)
+ << DecompType << FD->getType()->isUnionType();
+ S.Diag(FD->getLocation(), diag::note_declared_at);
+ return true;
+ }
+
+ // FIXME: Are there any other ways we could have an anonymous member?
}
// We have a real field to bind.
@@ -1618,7 +1645,7 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
if (Kind == Sema::CheckConstexprKind::Diagnose) {
SemaRef.Diag(DD->getLocation(), diag::err_constexpr_dtor_subobject)
- << DD->getConstexprKind() << !FD
+ << static_cast<int>(DD->getConstexprKind()) << !FD
<< (FD ? FD->getDeclName() : DeclarationName()) << T;
SemaRef.Diag(Loc, diag::note_constexpr_dtor_subobject)
<< !FD << (FD ? FD->getDeclName() : DeclarationName()) << T;
@@ -2588,7 +2615,7 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
Diag(AL.getLoc(), AL.getKind() == ParsedAttr::UnknownAttribute
? (unsigned)diag::warn_unknown_attribute_ignored
: (unsigned)diag::err_base_specifier_attribute)
- << AL;
+ << AL << AL.getRange();
}
TypeSourceInfo *TInfo = nullptr;
@@ -3577,8 +3604,10 @@ namespace {
Base = SubME->getBase();
}
- if (!isa<CXXThisExpr>(Base->IgnoreParenImpCasts()))
+ if (!isa<CXXThisExpr>(Base->IgnoreParenImpCasts())) {
+ Visit(Base);
return;
+ }
if (AddressOf && AllPODFields)
return;
@@ -3905,9 +3934,22 @@ void Sema::ActOnStartTrailingRequiresClause(Scope *S, Declarator &D) {
}
ExprResult Sema::ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr) {
+ return ActOnRequiresClause(ConstraintExpr);
+}
+
+ExprResult Sema::ActOnRequiresClause(ExprResult ConstraintExpr) {
+ if (ConstraintExpr.isInvalid())
+ return ExprError();
+
+ ConstraintExpr = CorrectDelayedTyposInExpr(ConstraintExpr);
if (ConstraintExpr.isInvalid())
return ExprError();
- return CorrectDelayedTyposInExpr(ConstraintExpr);
+
+ if (DiagnoseUnexpandedParameterPack(ConstraintExpr.get(),
+ UPPC_RequiresClause))
+ return ExprError();
+
+ return ConstraintExpr;
}
/// This is invoked after parsing an in-class initializer for a
@@ -5478,8 +5520,9 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
// Bases.
for (const auto &Base : ClassDecl->bases()) {
- // Bases are always records in a well-formed non-dependent class.
const RecordType *RT = Base.getType()->getAs<RecordType>();
+ if (!RT)
+ continue;
// Remember direct virtual bases.
if (Base.isVirtual()) {
@@ -5869,13 +5912,22 @@ static void ReferenceDllExportedMembers(Sema &S, CXXRecordDecl *Class) {
// The function will be passed to the consumer when its definition is
// encountered.
- } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() ||
+ } else if (MD->isExplicitlyDefaulted()) {
+ // Synthesize and instantiate explicitly defaulted methods.
+ S.MarkFunctionReferenced(Class->getLocation(), MD);
+
+ if (TSK != TSK_ExplicitInstantiationDefinition) {
+ // Except for explicit instantiation defs, we will not see the
+ // definition again later, so pass it to the consumer now.
+ S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD));
+ }
+ } else if (!MD->isTrivial() ||
MD->isCopyAssignmentOperator() ||
MD->isMoveAssignmentOperator()) {
- // Synthesize and instantiate non-trivial implicit methods, explicitly
- // defaulted methods, and the copy and move assignment operators. The
- // latter are exported even if they are trivial, because the address of
- // an operator can be taken and should compare equal across libraries.
+ // Synthesize and instantiate non-trivial implicit methods, and the copy
+ // and move assignment operators. The latter are exported even if they
+ // are trivial, because the address of an operator can be taken and
+ // should compare equal across libraries.
S.MarkFunctionReferenced(Class->getLocation(), MD);
// There is no later point when we will see the definition of this
@@ -6056,7 +6108,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
Attr *ClassAttr = getDLLAttr(Class);
// MSVC inherits DLL attributes to partial class template specializations.
- if (Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) {
+ if (Context.getTargetInfo().shouldDLLImportComdatSymbols() && !ClassAttr) {
if (auto *Spec = dyn_cast<ClassTemplatePartialSpecializationDecl>(Class)) {
if (Attr *TemplateAttr =
getDLLAttr(Spec->getSpecializedTemplate()->getTemplatedDecl())) {
@@ -6076,7 +6128,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
return;
}
- if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ if (Context.getTargetInfo().shouldDLLImportComdatSymbols() &&
!ClassAttr->isInherited()) {
// Diagnose dll attributes on members of class with dll attribute.
for (Decl *Member : Class->decls()) {
@@ -6141,8 +6193,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
if (MD->isInlined()) {
// MinGW does not import or export inline methods. But do it for
// template instantiations.
- if (!Context.getTargetInfo().getCXXABI().isMicrosoft() &&
- !Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment() &&
+ if (!Context.getTargetInfo().shouldDLLImportComdatSymbols() &&
TSK != TSK_ExplicitInstantiationDeclaration &&
TSK != TSK_ExplicitInstantiationDefinition)
continue;
@@ -7331,9 +7382,10 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
// If a function is explicitly defaulted on its first declaration, it is
// implicitly considered to be constexpr if the implicit declaration
// would be.
- MD->setConstexprKind(
- Constexpr ? (MD->isConsteval() ? CSK_consteval : CSK_constexpr)
- : CSK_unspecified);
+ MD->setConstexprKind(Constexpr ? (MD->isConsteval()
+ ? ConstexprSpecKind::Consteval
+ : ConstexprSpecKind::Constexpr)
+ : ConstexprSpecKind::Unspecified);
if (!Type->hasExceptionSpec()) {
// C++2a [except.spec]p3:
@@ -8022,10 +8074,10 @@ private:
if (ReturnFalse.isInvalid())
return StmtError();
- return S.ActOnIfStmt(Loc, false, nullptr,
+ return S.ActOnIfStmt(Loc, false, Loc, nullptr,
S.ActOnCondition(nullptr, Loc, NotCond.get(),
Sema::ConditionKind::Boolean),
- ReturnFalse.get(), SourceLocation(), nullptr);
+ Loc, ReturnFalse.get(), SourceLocation(), nullptr);
}
StmtResult visitSubobjectArray(QualType Type, llvm::APInt Size,
@@ -8177,9 +8229,9 @@ private:
return StmtError();
// if (...)
- return S.ActOnIfStmt(Loc, /*IsConstexpr=*/false, InitStmt, Cond,
- ReturnStmt.get(), /*ElseLoc=*/SourceLocation(),
- /*Else=*/nullptr);
+ return S.ActOnIfStmt(Loc, /*IsConstexpr=*/false, Loc, InitStmt, Cond, Loc,
+ ReturnStmt.get(),
+ /*ElseLoc=*/SourceLocation(), /*Else=*/nullptr);
}
case DefaultedComparisonKind::NotEqual:
@@ -8212,7 +8264,7 @@ static void lookupOperatorsForDefaultedComparison(Sema &Self, Scope *S,
UnresolvedSetImpl &Operators,
OverloadedOperatorKind Op) {
auto Lookup = [&](OverloadedOperatorKind OO) {
- Self.LookupOverloadedOperatorName(OO, S, QualType(), QualType(), Operators);
+ Self.LookupOverloadedOperatorName(OO, S, Operators);
};
// Every defaulted operator looks up itself.
@@ -8425,7 +8477,7 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
// FIXME: Only applying this to the first declaration seems problematic, as
// simple reorderings can affect the meaning of the program.
if (First && !FD->isConstexpr() && Info.Constexpr)
- FD->setConstexprKind(CSK_constexpr);
+ FD->setConstexprKind(ConstexprSpecKind::Constexpr);
// C++2a [except.spec]p3:
// If a declaration of a function does not have a noexcept-specifier
@@ -9399,7 +9451,8 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
// brace-or-equal-initializer
if (CSM == Sema::CXXDefaultConstructor && FI->hasInClassInitializer()) {
if (Diagnose)
- S.Diag(FI->getLocation(), diag::note_nontrivial_in_class_init) << FI;
+ S.Diag(FI->getLocation(), diag::note_nontrivial_default_member_init)
+ << FI;
return false;
}
@@ -11106,8 +11159,8 @@ QualType Sema::CheckComparisonCategoryType(ComparisonCategoryType Kind,
// Attempt to diagnose reasons why the STL definition of this type
// might be foobar, including it failing to be a constant expression.
// TODO Handle more ways the lookup or result can be invalid.
- if (!VD->isStaticDataMember() || !VD->isConstexpr() || !VD->hasInit() ||
- !VD->checkInitIsICE())
+ if (!VD->isStaticDataMember() ||
+ !VD->isUsableInConstantExpressions(Context))
return UnsupportedSTLError(USS_InvalidMember, MemName, VD);
// Attempt to evaluate the var decl as a constant expression and extract
@@ -12936,7 +12989,8 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
Context, ClassDecl, ClassLoc, NameInfo, /*Type*/ QualType(),
/*TInfo=*/nullptr, ExplicitSpecifier(),
/*isInline=*/true, /*isImplicitlyDeclared=*/true,
- Constexpr ? CSK_constexpr : CSK_unspecified);
+ Constexpr ? ConstexprSpecKind::Constexpr
+ : ConstexprSpecKind::Unspecified);
DefaultCon->setAccess(AS_public);
DefaultCon->setDefaulted();
@@ -13057,7 +13111,7 @@ Sema::findInheritingConstructor(SourceLocation Loc,
Context, Derived, UsingLoc, NameInfo, TInfo->getType(), TInfo,
BaseCtor->getExplicitSpecifier(), /*isInline=*/true,
/*isImplicitlyDeclared=*/true,
- Constexpr ? BaseCtor->getConstexprKind() : CSK_unspecified,
+ Constexpr ? BaseCtor->getConstexprKind() : ConstexprSpecKind::Unspecified,
InheritedConstructor(Shadow, BaseCtor),
BaseCtor->getTrailingRequiresClause());
if (Shadow->isInvalidDecl())
@@ -13214,7 +13268,8 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,
QualType(), nullptr, /*isInline=*/true,
/*isImplicitlyDeclared=*/true,
- Constexpr ? CSK_constexpr : CSK_unspecified);
+ Constexpr ? ConstexprSpecKind::Constexpr
+ : ConstexprSpecKind::Unspecified);
Destructor->setAccess(AS_public);
Destructor->setDefaulted();
@@ -13849,7 +13904,8 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
CXXMethodDecl *CopyAssignment = CXXMethodDecl::Create(
Context, ClassDecl, ClassLoc, NameInfo, QualType(),
/*TInfo=*/nullptr, /*StorageClass=*/SC_None,
- /*isInline=*/true, Constexpr ? CSK_constexpr : CSK_unspecified,
+ /*isInline=*/true,
+ Constexpr ? ConstexprSpecKind::Constexpr : ConstexprSpecKind::Unspecified,
SourceLocation());
CopyAssignment->setAccess(AS_public);
CopyAssignment->setDefaulted();
@@ -14174,7 +14230,8 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
CXXMethodDecl *MoveAssignment = CXXMethodDecl::Create(
Context, ClassDecl, ClassLoc, NameInfo, QualType(),
/*TInfo=*/nullptr, /*StorageClass=*/SC_None,
- /*isInline=*/true, Constexpr ? CSK_constexpr : CSK_unspecified,
+ /*isInline=*/true,
+ Constexpr ? ConstexprSpecKind::Constexpr : ConstexprSpecKind::Unspecified,
SourceLocation());
MoveAssignment->setAccess(AS_public);
MoveAssignment->setDefaulted();
@@ -14558,7 +14615,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
ExplicitSpecifier(),
/*isInline=*/true,
/*isImplicitlyDeclared=*/true,
- Constexpr ? CSK_constexpr : CSK_unspecified);
+ Constexpr ? ConstexprSpecKind::Constexpr
+ : ConstexprSpecKind::Unspecified);
CopyConstructor->setAccess(AS_public);
CopyConstructor->setDefaulted();
@@ -14691,7 +14749,8 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
ExplicitSpecifier(),
/*isInline=*/true,
/*isImplicitlyDeclared=*/true,
- Constexpr ? CSK_constexpr : CSK_unspecified);
+ Constexpr ? ConstexprSpecKind::Constexpr
+ : ConstexprSpecKind::Unspecified);
MoveConstructor->setAccess(AS_public);
MoveConstructor->setDefaulted();
@@ -14793,9 +14852,13 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
SynthesizedFunctionScope Scope(*this, Conv);
assert(!Conv->getReturnType()->isUndeducedType());
+ QualType ConvRT = Conv->getType()->getAs<FunctionType>()->getReturnType();
+ CallingConv CC =
+ ConvRT->getPointeeType()->getAs<FunctionType>()->getCallConv();
+
CXXRecordDecl *Lambda = Conv->getParent();
FunctionDecl *CallOp = Lambda->getLambdaCallOperator();
- FunctionDecl *Invoker = Lambda->getLambdaStaticInvoker();
+ FunctionDecl *Invoker = Lambda->getLambdaStaticInvoker(CC);
if (auto *TemplateArgs = Conv->getTemplateSpecializationArgs()) {
CallOp = InstantiateFunctionDeclaration(
@@ -14866,9 +14929,9 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
// (since it's unusable otherwise); in the case where we inline the
// block literal, it has block literal lifetime semantics.
if (!BuildBlock.isInvalid() && !getLangOpts().ObjCAutoRefCount)
- BuildBlock = ImplicitCastExpr::Create(Context, BuildBlock.get()->getType(),
- CK_CopyAndAutoreleaseBlockObject,
- BuildBlock.get(), nullptr, VK_RValue);
+ BuildBlock = ImplicitCastExpr::Create(
+ Context, BuildBlock.get()->getType(), CK_CopyAndAutoreleaseBlockObject,
+ BuildBlock.get(), nullptr, VK_RValue, FPOptionsOverride());
if (BuildBlock.isInvalid()) {
Diag(CurrentLocation, diag::note_lambda_to_block_conv);
@@ -15032,24 +15095,14 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
DeclContext::lookup_result Lookup =
ClassPattern->lookup(Field->getDeclName());
- // Lookup can return at most two results: the pattern for the field, or the
- // injected class name of the parent record. No other member can have the
- // same name as the field.
- // In modules mode, lookup can return multiple results (coming from
- // different modules).
- assert((getLangOpts().Modules || (!Lookup.empty() && Lookup.size() <= 2)) &&
- "more than two lookup results for field name");
- FieldDecl *Pattern = dyn_cast<FieldDecl>(Lookup[0]);
- if (!Pattern) {
- assert(isa<CXXRecordDecl>(Lookup[0]) &&
- "cannot have other non-field member with same name");
- for (auto L : Lookup)
- if (isa<FieldDecl>(L)) {
- Pattern = cast<FieldDecl>(L);
- break;
- }
- assert(Pattern && "We must have set the Pattern!");
+ FieldDecl *Pattern = nullptr;
+ for (auto L : Lookup) {
+ if (isa<FieldDecl>(L)) {
+ Pattern = cast<FieldDecl>(L);
+ break;
+ }
}
+ assert(Pattern && "We must have set the Pattern!");
if (!Pattern->hasInClassInitializer() ||
InstantiateInClassInitializer(Loc, Field, Pattern,
@@ -15076,9 +15129,10 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
// constructor before the initializer is lexically complete will ultimately
// come here at which point we can diagnose it.
RecordDecl *OutermostClass = ParentRD->getOuterLexicalRecordContext();
- Diag(Loc, diag::err_in_class_initializer_not_yet_parsed)
+ Diag(Loc, diag::err_default_member_initializer_not_yet_parsed)
<< OutermostClass << Field;
- Diag(Field->getEndLoc(), diag::note_in_class_initializer_not_yet_parsed);
+ Diag(Field->getEndLoc(),
+ diag::note_default_member_initializer_not_yet_parsed);
// Recover by marking the field invalid, unless we're in a SFINAE context.
if (!isSFINAEContext())
Field->setInvalidDecl();
@@ -15503,6 +15557,18 @@ checkLiteralOperatorTemplateParameterList(Sema &SemaRef,
SemaRef.Context.hasSameType(PmDecl->getType(), SemaRef.Context.CharTy))
return false;
+ // C++20 [over.literal]p5:
+ // A string literal operator template is a literal operator template
+ // whose template-parameter-list comprises a single non-type
+ // template-parameter of class type.
+ //
+ // As a DR resolution, we also allow placeholders for deduced class
+ // template specializations.
+ if (SemaRef.getLangOpts().CPlusPlus20 &&
+ !PmDecl->isTemplateParameterPack() &&
+ (PmDecl->getType()->isRecordType() ||
+ PmDecl->getType()->getAs<DeducedTemplateSpecializationType>()))
+ return false;
} else if (TemplateParams->size() == 2) {
TemplateTypeParmDecl *PmType =
dyn_cast<TemplateTypeParmDecl>(TemplateParams->getParam(0));
@@ -15559,6 +15625,8 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
// template <char...> type operator "" name() and
// template <class T, T...> type operator "" name() are the only valid
// template signatures, and the only valid signatures with no parameters.
+ //
+ // C++20 also allows template <SomeClass T> type operator "" name().
if (TpDecl) {
if (FnDecl->param_size() != 0) {
Diag(FnDecl->getLocation(),
@@ -15988,9 +16056,10 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
AssertExpr = FullAssertExpr.get();
llvm::APSInt Cond;
- if (!Failed && VerifyIntegerConstantExpression(AssertExpr, &Cond,
- diag::err_static_assert_expression_is_not_constant,
- /*AllowFold=*/false).isInvalid())
+ if (!Failed && VerifyIntegerConstantExpression(
+ AssertExpr, &Cond,
+ diag::err_static_assert_expression_is_not_constant)
+ .isInvalid())
Failed = true;
if (!Failed && !Cond) {
@@ -16282,7 +16351,7 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
// Try to convert the decl specifier to a type. This works for
// friend templates because ActOnTag never produces a ClassTemplateDecl
// for a TUK_Friend.
- Declarator TheDeclarator(DS, DeclaratorContext::MemberContext);
+ Declarator TheDeclarator(DS, DeclaratorContext::Member);
TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S);
QualType T = TSI->getType();
if (TheDeclarator.isInvalidType())