summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp596
1 files changed, 417 insertions, 179 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
index 2ad6754..610e0a9 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
@@ -150,7 +150,7 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
Sema &S) {
// Get the length of the string as parsed.
auto *ConstantArrayTy =
- cast<ConstantArrayType>(Str->getType()->getUnqualifiedDesugaredType());
+ cast<ConstantArrayType>(Str->getType()->getAsArrayTypeUnsafe());
uint64_t StrLength = ConstantArrayTy->getSize().getZExtValue();
if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
@@ -640,6 +640,9 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
InitListExpr *IL, QualType &T,
bool VerifyOnly)
: SemaRef(S), VerifyOnly(VerifyOnly) {
+ // FIXME: Check that IL isn't already the semantic form of some other
+ // InitListExpr. If it is, we'd create a broken AST.
+
hadError = false;
FullyStructuredList =
@@ -751,6 +754,68 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
}
}
+/// Warn that \p Entity was of scalar type and was initialized by a
+/// single-element braced initializer list.
+static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity,
+ SourceRange Braces) {
+ // Don't warn during template instantiation. If the initialization was
+ // non-dependent, we warned during the initial parse; otherwise, the
+ // type might not be scalar in some uses of the template.
+ if (!S.ActiveTemplateInstantiations.empty())
+ return;
+
+ unsigned DiagID = 0;
+
+ switch (Entity.getKind()) {
+ case InitializedEntity::EK_VectorElement:
+ case InitializedEntity::EK_ComplexElement:
+ case InitializedEntity::EK_ArrayElement:
+ case InitializedEntity::EK_Parameter:
+ case InitializedEntity::EK_Parameter_CF_Audited:
+ case InitializedEntity::EK_Result:
+ // Extra braces here are suspicious.
+ DiagID = diag::warn_braces_around_scalar_init;
+ break;
+
+ case InitializedEntity::EK_Member:
+ // Warn on aggregate initialization but not on ctor init list or
+ // default member initializer.
+ if (Entity.getParent())
+ DiagID = diag::warn_braces_around_scalar_init;
+ break;
+
+ case InitializedEntity::EK_Variable:
+ case InitializedEntity::EK_LambdaCapture:
+ // No warning, might be direct-list-initialization.
+ // FIXME: Should we warn for copy-list-initialization in these cases?
+ break;
+
+ case InitializedEntity::EK_New:
+ case InitializedEntity::EK_Temporary:
+ case InitializedEntity::EK_CompoundLiteralInit:
+ // No warning, braces are part of the syntax of the underlying construct.
+ break;
+
+ case InitializedEntity::EK_RelatedResult:
+ // No warning, we already warned when initializing the result.
+ break;
+
+ case InitializedEntity::EK_Exception:
+ case InitializedEntity::EK_Base:
+ case InitializedEntity::EK_Delegating:
+ case InitializedEntity::EK_BlockElement:
+ llvm_unreachable("unexpected braced scalar init");
+ }
+
+ if (DiagID) {
+ S.Diag(Braces.getBegin(), DiagID)
+ << Braces
+ << FixItHint::CreateRemoval(Braces.getBegin())
+ << FixItHint::CreateRemoval(Braces.getEnd());
+ }
+}
+
+
/// Check whether the initializer \p IList (that was written with explicit
/// braces) can be used to initialize an object of type \p T.
///
@@ -826,12 +891,9 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
}
}
- if (!VerifyOnly && T->isScalarType() && IList->getNumInits() == 1 &&
- !TopLevelObject)
- SemaRef.Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init)
- << IList->getSourceRange()
- << FixItHint::CreateRemoval(IList->getLocStart())
- << FixItHint::CreateRemoval(IList->getLocEnd());
+ if (!VerifyOnly && T->isScalarType() &&
+ IList->getNumInits() == 1 && !isa<InitListExpr>(IList->getInit(0)))
+ warnBracedScalarInit(SemaRef, Entity, IList->getSourceRange());
}
void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
@@ -904,7 +966,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
StructuredList, StructuredIndex);
if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
- if (!ElemType->isRecordType() || ElemType->isAggregateType()) {
+ if (!SemaRef.getLangOpts().CPlusPlus) {
InitListExpr *InnerStructuredList
= getStructuredSubobjectInit(IList, Index, ElemType,
StructuredList, StructuredIndex,
@@ -915,8 +977,6 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
++Index;
return;
}
- assert(SemaRef.getLangOpts().CPlusPlus &&
- "non-aggregate records are only possible in C++");
// C++ initialization is handled later.
} else if (isa<ImplicitValueInitExpr>(expr)) {
// This happens during template instantiation when we see an InitListExpr
@@ -929,43 +989,24 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
return;
}
- // FIXME: Need to handle atomic aggregate types with implicit init lists.
- if (ElemType->isScalarType() || ElemType->isAtomicType())
- return CheckScalarType(Entity, IList, ElemType, Index,
- StructuredList, StructuredIndex);
-
- assert((ElemType->isRecordType() || ElemType->isVectorType() ||
- ElemType->isArrayType()) && "Unexpected type");
-
- if (const ArrayType *arrayType = SemaRef.Context.getAsArrayType(ElemType)) {
- // arrayType can be incomplete if we're initializing a flexible
- // array member. There's nothing we can do with the completed
- // type here, though.
-
- if (IsStringInit(expr, arrayType, SemaRef.Context) == SIF_None) {
- if (!VerifyOnly) {
- CheckStringInit(expr, ElemType, arrayType, SemaRef);
- UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
- }
- ++Index;
- return;
- }
-
- // Fall through for subaggregate initialization.
-
- } else if (SemaRef.getLangOpts().CPlusPlus) {
- // C++ [dcl.init.aggr]p12:
- // All implicit type conversions (clause 4) are considered when
- // initializing the aggregate member with an initializer from
- // an initializer-list. If the initializer can initialize a
- // member, the member is initialized. [...]
+ if (SemaRef.getLangOpts().CPlusPlus) {
+ // C++ [dcl.init.aggr]p2:
+ // Each member is copy-initialized from the corresponding
+ // initializer-clause.
// FIXME: Better EqualLoc?
InitializationKind Kind =
InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation());
- InitializationSequence Seq(SemaRef, Entity, Kind, expr);
+ InitializationSequence Seq(SemaRef, Entity, Kind, expr,
+ /*TopLevelOfInitList*/ true);
- if (Seq) {
+ // C++14 [dcl.init.aggr]p13:
+ // If the assignment-expression can initialize a member, the member is
+ // initialized. Otherwise [...] brace elision is assumed
+ //
+ // Brace elision is never performed if the element is not an
+ // assignment-expression.
+ if (Seq || isa<InitListExpr>(expr)) {
if (!VerifyOnly) {
ExprResult Result =
Seq.Perform(SemaRef, Entity, Kind, expr);
@@ -974,13 +1015,38 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
UpdateStructuredListElement(StructuredList, StructuredIndex,
Result.getAs<Expr>());
- }
+ } else if (!Seq)
+ hadError = true;
++Index;
return;
}
// Fall through for subaggregate initialization
+ } else if (ElemType->isScalarType() || ElemType->isAtomicType()) {
+ // FIXME: Need to handle atomic aggregate types with implicit init lists.
+ return CheckScalarType(Entity, IList, ElemType, Index,
+ StructuredList, StructuredIndex);
+ } else if (const ArrayType *arrayType =
+ SemaRef.Context.getAsArrayType(ElemType)) {
+ // arrayType can be incomplete if we're initializing a flexible
+ // array member. There's nothing we can do with the completed
+ // type here, though.
+
+ if (IsStringInit(expr, arrayType, SemaRef.Context) == SIF_None) {
+ if (!VerifyOnly) {
+ CheckStringInit(expr, ElemType, arrayType, SemaRef);
+ UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
+ }
+ ++Index;
+ return;
+ }
+
+ // Fall through for subaggregate initialization.
+
} else {
+ assert((ElemType->isRecordType() || ElemType->isVectorType()) &&
+ "Unexpected type");
+
// C99 6.7.8p13:
//
// The initializer for a structure or union object that has
@@ -990,10 +1056,8 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
// initial value of the object, including unnamed members, is
// that of the expression.
ExprResult ExprRes = expr;
- if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
- SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes,
- !VerifyOnly)
- != Sema::Incompatible) {
+ if (SemaRef.CheckSingleAssignmentConstraints(
+ ElemType, ExprRes, !VerifyOnly) != Sema::Incompatible) {
if (ExprRes.isInvalid())
hadError = true;
else {
@@ -3037,6 +3101,28 @@ void InitializationSequence::SetOverloadFailure(FailureKind Failure,
// Attempt initialization
//===----------------------------------------------------------------------===//
+/// Tries to add a zero initializer. Returns true if that worked.
+static bool
+maybeRecoverWithZeroInitialization(Sema &S, InitializationSequence &Sequence,
+ const InitializedEntity &Entity) {
+ if (Entity.getKind() != InitializedEntity::EK_Variable)
+ return false;
+
+ VarDecl *VD = cast<VarDecl>(Entity.getDecl());
+ if (VD->getInit() || VD->getLocEnd().isMacroID())
+ return false;
+
+ QualType VariableTy = VD->getType().getCanonicalType();
+ SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd());
+ std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc);
+ if (!Init.empty()) {
+ Sequence.AddZeroInitializationStep(Entity.getType());
+ Sequence.SetZeroInitializationFixit(Init, Loc);
+ return true;
+ }
+ return false;
+}
+
static void MaybeProduceObjCObject(Sema &S,
InitializationSequence &Sequence,
const InitializedEntity &Entity) {
@@ -3107,15 +3193,13 @@ static OverloadingResult
ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
MultiExprArg Args,
OverloadCandidateSet &CandidateSet,
- ArrayRef<NamedDecl *> Ctors,
+ DeclContext::lookup_result Ctors,
OverloadCandidateSet::iterator &Best,
bool CopyInitializing, bool AllowExplicit,
- bool OnlyListConstructors, bool InitListSyntax) {
+ bool OnlyListConstructors, bool IsListInit) {
CandidateSet.clear();
- for (ArrayRef<NamedDecl *>::iterator
- Con = Ctors.begin(), ConEnd = Ctors.end(); Con != ConEnd; ++Con) {
- NamedDecl *D = *Con;
+ for (NamedDecl *D : Ctors) {
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
bool SuppressUserConversions = false;
@@ -3129,19 +3213,21 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
Constructor = cast<CXXConstructorDecl>(D);
// C++11 [over.best.ics]p4:
- // However, when considering the argument of a constructor or
- // user-defined conversion function that is a candidate:
- // -- by 13.3.1.3 when invoked for the copying/moving of a temporary
- // in the second step of a class copy-initialization,
- // -- by 13.3.1.7 when passing the initializer list as a single
- // argument or when the initializer list has exactly one elementand
- // a conversion to some class X or reference to (possibly
- // cv-qualified) X is considered for the first parameter of a
- // constructor of X, or
- // -- by 13.3.1.4, 13.3.1.5, or 13.3.1.6 in all cases,
- // only standard conversion sequences and ellipsis conversion sequences
- // are considered.
- if ((CopyInitializing || (InitListSyntax && Args.size() == 1)) &&
+ // ... and the constructor or user-defined conversion function is a
+ // candidate by
+ // - 13.3.1.3, when the argument is the temporary in the second step
+ // of a class copy-initialization, or
+ // - 13.3.1.4, 13.3.1.5, or 13.3.1.6 (in all cases),
+ // user-defined conversion sequences are not considered.
+ // FIXME: This breaks backward compatibility, e.g. PR12117. As a
+ // temporary fix, let's re-instate the third bullet above until
+ // there is a resolution in the standard, i.e.,
+ // - 13.3.1.7 when the initializer list has exactly one element that is
+ // itself an initializer list and a conversion to some class X or
+ // reference to (possibly cv-qualified) X is considered for the first
+ // parameter of a constructor of X.
+ if ((CopyInitializing ||
+ (IsListInit && Args.size() == 1 && isa<InitListExpr>(Args[0]))) &&
Constructor->isCopyOrMoveConstructor())
SuppressUserConversions = true;
}
@@ -3178,16 +3264,19 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
/// \brief Attempt initialization by constructor (C++ [dcl.init]), which
/// enumerates the constructors of the initialized entity and performs overload
/// resolution to select the best.
-/// If InitListSyntax is true, this is list-initialization of a non-aggregate
-/// class type.
+/// \param IsListInit Is this list-initialization?
+/// \param IsInitListCopy Is this non-list-initialization resulting from a
+/// list-initialization from {x} where x is the same
+/// type as the entity?
static void TryConstructorInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
MultiExprArg Args, QualType DestType,
InitializationSequence &Sequence,
- bool InitListSyntax = false) {
- assert((!InitListSyntax || (Args.size() == 1 && isa<InitListExpr>(Args[0]))) &&
- "InitListSyntax must come with a single initializer list argument.");
+ bool IsListInit = false,
+ bool IsInitListCopy = false) {
+ assert((!IsListInit || (Args.size() == 1 && isa<InitListExpr>(Args[0]))) &&
+ "IsListInit must come with a single initializer list argument.");
// The type we're constructing needs to be complete.
if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
@@ -3206,29 +3295,28 @@ static void TryConstructorInitialization(Sema &S,
// Determine whether we are allowed to call explicit constructors or
// explicit conversion operators.
- bool AllowExplicit = Kind.AllowExplicit() || InitListSyntax;
+ bool AllowExplicit = Kind.AllowExplicit() || IsListInit;
bool CopyInitialization = Kind.getKind() == InitializationKind::IK_Copy;
// - Otherwise, if T is a class type, constructors are considered. The
// applicable constructors are enumerated, and the best one is chosen
// through overload resolution.
- DeclContext::lookup_result R = S.LookupConstructors(DestRecordDecl);
- // The container holding the constructors can under certain conditions
- // be changed while iterating (e.g. because of deserialization).
- // To be safe we copy the lookup results to a new container.
- SmallVector<NamedDecl*, 16> Ctors(R.begin(), R.end());
+ DeclContext::lookup_result Ctors = S.LookupConstructors(DestRecordDecl);
OverloadingResult Result = OR_No_Viable_Function;
OverloadCandidateSet::iterator Best;
bool AsInitializerList = false;
- // C++11 [over.match.list]p1:
- // When objects of non-aggregate type T are list-initialized, overload
- // resolution selects the constructor in two phases:
+ // C++11 [over.match.list]p1, per DR1467:
+ // When objects of non-aggregate type T are list-initialized, such that
+ // 8.5.4 [dcl.init.list] specifies that overload resolution is performed
+ // according to the rules in this section, overload resolution selects
+ // the constructor in two phases:
+ //
// - Initially, the candidate functions are the initializer-list
// constructors of the class T and the argument list consists of the
// initializer list as a single argument.
- if (InitListSyntax) {
+ if (IsListInit) {
InitListExpr *ILE = cast<InitListExpr>(Args[0]);
AsInitializerList = true;
@@ -3239,7 +3327,7 @@ static void TryConstructorInitialization(Sema &S,
CandidateSet, Ctors, Best,
CopyInitialization, AllowExplicit,
/*OnlyListConstructor=*/true,
- InitListSyntax);
+ IsListInit);
// Time to unwrap the init list.
Args = MultiExprArg(ILE->getInits(), ILE->getNumInits());
@@ -3256,10 +3344,10 @@ static void TryConstructorInitialization(Sema &S,
CandidateSet, Ctors, Best,
CopyInitialization, AllowExplicit,
/*OnlyListConstructors=*/false,
- InitListSyntax);
+ IsListInit);
}
if (Result) {
- Sequence.SetOverloadFailure(InitListSyntax ?
+ Sequence.SetOverloadFailure(IsListInit ?
InitializationSequence::FK_ListConstructorOverloadFailed :
InitializationSequence::FK_ConstructorOverloadFailed,
Result);
@@ -3273,7 +3361,8 @@ static void TryConstructorInitialization(Sema &S,
if (Kind.getKind() == InitializationKind::IK_Default &&
Entity.getType().isConstQualified() &&
!cast<CXXConstructorDecl>(Best->Function)->isUserProvided()) {
- Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+ if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity))
+ Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
return;
}
@@ -3281,7 +3370,7 @@ static void TryConstructorInitialization(Sema &S,
// In copy-list-initialization, if an explicit constructor is chosen, the
// initializer is ill-formed.
CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
- if (InitListSyntax && !Kind.AllowExplicit() && CtorDecl->isExplicit()) {
+ if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) {
Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor);
return;
}
@@ -3289,10 +3378,9 @@ static void TryConstructorInitialization(Sema &S,
// Add the constructor initialization step. Any cv-qualification conversion is
// subsumed by the initialization.
bool HadMultipleCandidates = (CandidateSet.size() > 1);
- Sequence.AddConstructorInitializationStep(CtorDecl,
- Best->FoundDecl.getAccess(),
- DestType, HadMultipleCandidates,
- InitListSyntax, AsInitializerList);
+ Sequence.AddConstructorInitializationStep(
+ CtorDecl, Best->FoundDecl.getAccess(), DestType, HadMultipleCandidates,
+ IsListInit | IsInitListCopy, AsInitializerList);
}
static bool
@@ -3350,6 +3438,11 @@ static void TryReferenceListInitialization(Sema &S,
Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
return;
}
+ // Can't reference initialize a compound literal.
+ if (Entity.getKind() == InitializedEntity::EK_CompoundLiteralInit) {
+ Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
+ return;
+ }
QualType DestType = Entity.getType();
QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
@@ -3425,48 +3518,97 @@ static void TryListInitialization(Sema &S,
TryReferenceListInitialization(S, Entity, Kind, InitList, Sequence);
return;
}
- if (DestType->isRecordType()) {
- if (S.RequireCompleteType(InitList->getLocStart(), DestType, 0)) {
- Sequence.setIncompleteTypeFailure(DestType);
- return;
- }
- // C++11 [dcl.init.list]p3:
- // - If T is an aggregate, aggregate initialization is performed.
- if (!DestType->isAggregateType()) {
- if (S.getLangOpts().CPlusPlus11) {
- // - Otherwise, if the initializer list has no elements and T is a
- // class type with a default constructor, the object is
- // value-initialized.
- if (InitList->getNumInits() == 0) {
- CXXRecordDecl *RD = DestType->getAsCXXRecordDecl();
- if (RD->hasDefaultConstructor()) {
- TryValueInitialization(S, Entity, Kind, Sequence, InitList);
- return;
- }
+ if (DestType->isRecordType() &&
+ S.RequireCompleteType(InitList->getLocStart(), DestType, 0)) {
+ Sequence.setIncompleteTypeFailure(DestType);
+ return;
+ }
+
+ // C++11 [dcl.init.list]p3, per DR1467:
+ // - If T is a class type and the initializer list has a single element of
+ // type cv U, where U is T or a class derived from T, the object is
+ // initialized from that element (by copy-initialization for
+ // copy-list-initialization, or by direct-initialization for
+ // direct-list-initialization).
+ // - Otherwise, if T is a character array and the initializer list has a
+ // single element that is an appropriately-typed string literal
+ // (8.5.2 [dcl.init.string]), initialization is performed as described
+ // in that section.
+ // - Otherwise, if T is an aggregate, [...] (continue below).
+ if (S.getLangOpts().CPlusPlus11 && InitList->getNumInits() == 1) {
+ if (DestType->isRecordType()) {
+ QualType InitType = InitList->getInit(0)->getType();
+ if (S.Context.hasSameUnqualifiedType(InitType, DestType) ||
+ S.IsDerivedFrom(InitType, DestType)) {
+ Expr *InitAsExpr = InitList->getInit(0);
+ TryConstructorInitialization(S, Entity, Kind, InitAsExpr, DestType,
+ Sequence, /*InitListSyntax*/ false,
+ /*IsInitListCopy*/ true);
+ return;
+ }
+ }
+ if (const ArrayType *DestAT = S.Context.getAsArrayType(DestType)) {
+ Expr *SubInit[1] = {InitList->getInit(0)};
+ if (!isa<VariableArrayType>(DestAT) &&
+ IsStringInit(SubInit[0], DestAT, S.Context) == SIF_None) {
+ InitializationKind SubKind =
+ Kind.getKind() == InitializationKind::IK_DirectList
+ ? InitializationKind::CreateDirect(Kind.getLocation(),
+ InitList->getLBraceLoc(),
+ InitList->getRBraceLoc())
+ : Kind;
+ Sequence.InitializeFrom(S, Entity, SubKind, SubInit,
+ /*TopLevelOfInitList*/ true);
+
+ // TryStringLiteralInitialization() (in InitializeFrom()) will fail if
+ // the element is not an appropriately-typed string literal, in which
+ // case we should proceed as in C++11 (below).
+ if (Sequence) {
+ Sequence.RewrapReferenceInitList(Entity.getType(), InitList);
+ return;
}
+ }
+ }
+ }
- // - Otherwise, if T is a specialization of std::initializer_list<E>,
- // an initializer_list object constructed [...]
- if (TryInitializerListConstruction(S, InitList, DestType, Sequence))
+ // C++11 [dcl.init.list]p3:
+ // - If T is an aggregate, aggregate initialization is performed.
+ if (DestType->isRecordType() && !DestType->isAggregateType()) {
+ if (S.getLangOpts().CPlusPlus11) {
+ // - Otherwise, if the initializer list has no elements and T is a
+ // class type with a default constructor, the object is
+ // value-initialized.
+ if (InitList->getNumInits() == 0) {
+ CXXRecordDecl *RD = DestType->getAsCXXRecordDecl();
+ if (RD->hasDefaultConstructor()) {
+ TryValueInitialization(S, Entity, Kind, Sequence, InitList);
return;
+ }
+ }
- // - Otherwise, if T is a class type, constructors are considered.
- Expr *InitListAsExpr = InitList;
- TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType,
- Sequence, /*InitListSyntax*/true);
- } else
- Sequence.SetFailed(
- InitializationSequence::FK_InitListBadDestinationType);
- return;
- }
+ // - Otherwise, if T is a specialization of std::initializer_list<E>,
+ // an initializer_list object constructed [...]
+ if (TryInitializerListConstruction(S, InitList, DestType, Sequence))
+ return;
+
+ // - Otherwise, if T is a class type, constructors are considered.
+ Expr *InitListAsExpr = InitList;
+ TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType,
+ Sequence, /*InitListSyntax*/ true);
+ } else
+ Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
+ return;
}
+
if (S.getLangOpts().CPlusPlus && !DestType->isAggregateType() &&
InitList->getNumInits() == 1 &&
InitList->getInit(0)->getType()->isRecordType()) {
// - Otherwise, if the initializer list has a single element of type E
// [...references are handled above...], the object or reference is
- // initialized from that element; if a narrowing conversion is required
+ // initialized from that element (by copy-initialization for
+ // copy-list-initialization, or by direct-initialization for
+ // direct-list-initialization); if a narrowing conversion is required
// to convert the element to T, the program is ill-formed.
//
// Per core-24034, this is direct-initialization if we were performing
@@ -3543,14 +3685,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
// to see if there is a suitable conversion.
CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
- DeclContext::lookup_result R = S.LookupConstructors(T1RecordDecl);
- // The container holding the constructors can under certain conditions
- // be changed while iterating (e.g. because of deserialization).
- // To be safe we copy the lookup results to a new container.
- SmallVector<NamedDecl*, 16> Ctors(R.begin(), R.end());
- for (SmallVectorImpl<NamedDecl *>::iterator
- CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) {
- NamedDecl *D = *CI;
+ for (NamedDecl *D : S.LookupConstructors(T1RecordDecl)) {
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
// Find the constructor (which may be a template).
@@ -3586,11 +3721,8 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
// functions.
CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl());
- std::pair<CXXRecordDecl::conversion_iterator,
- CXXRecordDecl::conversion_iterator>
- Conversions = T2RecordDecl->getVisibleConversionFunctions();
- for (CXXRecordDecl::conversion_iterator
- I = Conversions.first, E = Conversions.second; I != E; ++I) {
+ const auto &Conversions = T2RecordDecl->getVisibleConversionFunctions();
+ for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
NamedDecl *D = *I;
CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
@@ -4127,7 +4259,8 @@ static void TryDefaultInitialization(Sema &S,
// a const-qualified type T, T shall be a class type with a user-provided
// default constructor.
if (DestType.isConstQualified() && S.getLangOpts().CPlusPlus) {
- Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+ if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity))
+ Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
return;
}
@@ -4218,11 +4351,9 @@ static void TryUserDefinedConversion(Sema &S,
CXXRecordDecl *SourceRecordDecl
= cast<CXXRecordDecl>(SourceRecordType->getDecl());
- std::pair<CXXRecordDecl::conversion_iterator,
- CXXRecordDecl::conversion_iterator>
- Conversions = SourceRecordDecl->getVisibleConversionFunctions();
- for (CXXRecordDecl::conversion_iterator
- I = Conversions.first, E = Conversions.second; I != E; ++I) {
+ const auto &Conversions =
+ SourceRecordDecl->getVisibleConversionFunctions();
+ for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
NamedDecl *D = *I;
CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
@@ -4408,8 +4539,7 @@ static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) {
/// \brief Determine whether we have compatible array types for the
/// purposes of GNU by-copy array initialization.
-static bool hasCompatibleArrayTypes(ASTContext &Context,
- const ArrayType *Dest,
+static bool hasCompatibleArrayTypes(ASTContext &Context, const ArrayType *Dest,
const ArrayType *Source) {
// If the source and destination array types are equivalent, we're
// done.
@@ -4668,7 +4798,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
return;
}
- // Determine whether we should consider writeback conversions for
+ // Determine whether we should consider writeback conversions for
// Objective-C ARC.
bool allowObjCWritebackConversion = S.getLangOpts().ObjCAutoRefCount &&
Entity.isParameterKind();
@@ -5022,6 +5152,8 @@ static ExprResult CopyObject(Sema &S,
const InitializedEntity &Entity,
ExprResult CurInit,
bool IsExtraneousCopy) {
+ if (CurInit.isInvalid())
+ return CurInit;
// Determine which class type we're copying to.
Expr *CurInitExpr = (Expr *)CurInit.get();
CXXRecordDecl *Class = nullptr;
@@ -5636,6 +5768,115 @@ static void DiagnoseNarrowingInInitList(Sema &S,
QualType EntityType,
const Expr *PostInit);
+/// Provide warnings when std::move is used on construction.
+static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr,
+ bool IsReturnStmt) {
+ if (!InitExpr)
+ return;
+
+ QualType DestType = InitExpr->getType();
+ if (!DestType->isRecordType())
+ return;
+
+ unsigned DiagID = 0;
+ if (IsReturnStmt) {
+ const CXXConstructExpr *CCE =
+ dyn_cast<CXXConstructExpr>(InitExpr->IgnoreParens());
+ if (!CCE || CCE->getNumArgs() != 1)
+ return;
+
+ if (!CCE->getConstructor()->isCopyOrMoveConstructor())
+ return;
+
+ InitExpr = CCE->getArg(0)->IgnoreImpCasts();
+
+ // Remove implicit temporary and constructor nodes.
+ if (const MaterializeTemporaryExpr *MTE =
+ dyn_cast<MaterializeTemporaryExpr>(InitExpr)) {
+ InitExpr = MTE->GetTemporaryExpr()->IgnoreImpCasts();
+ while (const CXXConstructExpr *CCE =
+ dyn_cast<CXXConstructExpr>(InitExpr)) {
+ if (isa<CXXTemporaryObjectExpr>(CCE))
+ return;
+ if (CCE->getNumArgs() == 0)
+ return;
+ if (CCE->getNumArgs() > 1 && !isa<CXXDefaultArgExpr>(CCE->getArg(1)))
+ return;
+ InitExpr = CCE->getArg(0);
+ }
+ InitExpr = InitExpr->IgnoreImpCasts();
+ DiagID = diag::warn_redundant_move_on_return;
+ }
+ }
+
+ // Find the std::move call and get the argument.
+ const CallExpr *CE = dyn_cast<CallExpr>(InitExpr->IgnoreParens());
+ if (!CE || CE->getNumArgs() != 1)
+ return;
+
+ const FunctionDecl *MoveFunction = CE->getDirectCallee();
+ if (!MoveFunction || !MoveFunction->isInStdNamespace() ||
+ !MoveFunction->getIdentifier() ||
+ !MoveFunction->getIdentifier()->isStr("move"))
+ return;
+
+ const Expr *Arg = CE->getArg(0)->IgnoreImplicit();
+
+ if (IsReturnStmt) {
+ const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg->IgnoreParenImpCasts());
+ if (!DRE || DRE->refersToEnclosingVariableOrCapture())
+ return;
+
+ const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
+ if (!VD || !VD->hasLocalStorage())
+ return;
+
+ if (!VD->getType()->isRecordType())
+ return;
+
+ if (DiagID == 0) {
+ DiagID = S.Context.hasSameUnqualifiedType(DestType, VD->getType())
+ ? diag::warn_pessimizing_move_on_return
+ : diag::warn_redundant_move_on_return;
+ }
+ } else {
+ DiagID = diag::warn_pessimizing_move_on_initialization;
+ const Expr *ArgStripped = Arg->IgnoreImplicit()->IgnoreParens();
+ if (!ArgStripped->isRValue() || !ArgStripped->getType()->isRecordType())
+ return;
+ }
+
+ S.Diag(CE->getLocStart(), DiagID);
+
+ // Get all the locations for a fix-it. Don't emit the fix-it if any location
+ // is within a macro.
+ SourceLocation CallBegin = CE->getCallee()->getLocStart();
+ if (CallBegin.isMacroID())
+ return;
+ SourceLocation RParen = CE->getRParenLoc();
+ if (RParen.isMacroID())
+ return;
+ SourceLocation LParen;
+ SourceLocation ArgLoc = Arg->getLocStart();
+
+ // Special testing for the argument location. Since the fix-it needs the
+ // location right before the argument, the argument location can be in a
+ // macro only if it is at the beginning of the macro.
+ while (ArgLoc.isMacroID() &&
+ S.getSourceManager().isAtStartOfImmediateMacroExpansion(ArgLoc)) {
+ ArgLoc = S.getSourceManager().getImmediateExpansionRange(ArgLoc).first;
+ }
+
+ if (LParen.isMacroID())
+ return;
+
+ LParen = ArgLoc.getLocWithOffset(-1);
+
+ S.Diag(CE->getLocStart(), diag::note_remove_move)
+ << FixItHint::CreateRemoval(SourceRange(CallBegin, LParen))
+ << FixItHint::CreateRemoval(SourceRange(RParen, RParen));
+}
+
ExprResult
InitializationSequence::Perform(Sema &S,
const InitializedEntity &Entity,
@@ -5646,6 +5887,21 @@ InitializationSequence::Perform(Sema &S,
Diagnose(S, Entity, Kind, Args);
return ExprError();
}
+ if (!ZeroInitializationFixit.empty()) {
+ unsigned DiagID = diag::err_default_init_const;
+ if (Decl *D = Entity.getDecl())
+ if (S.getLangOpts().MSVCCompat && D->hasAttr<SelectAnyAttr>())
+ DiagID = diag::ext_default_init_const;
+
+ // The initialization would have succeeded with this fixit. Since the fixit
+ // is on the error, we need to build a valid AST in this case, so this isn't
+ // handled in the Failed() branch above.
+ QualType DestType = Entity.getType();
+ S.Diag(Kind.getLocation(), DiagID)
+ << DestType << (bool)DestType->getAs<RecordType>()
+ << FixItHint::CreateInsertion(ZeroInitializationFixitLoc,
+ ZeroInitializationFixit);
+ }
if (getKind() == DependentSequence) {
// If the declaration is a non-dependent, incomplete array type
@@ -5820,15 +6076,6 @@ InitializationSequence::Perform(Sema &S,
&BasePath, IgnoreBaseAccess))
return ExprError();
- if (S.BasePathInvolvesVirtualBase(BasePath)) {
- QualType T = SourceType;
- if (const PointerType *Pointer = T->getAs<PointerType>())
- T = Pointer->getPointeeType();
- if (const RecordType *RecordTy = T->getAs<RecordType>())
- S.MarkVTableUsed(CurInit.get()->getLocStart(),
- cast<CXXRecordDecl>(RecordTy->getDecl()));
- }
-
ExprValueKind VK =
Step->Kind == SK_CastDerivedToBaseLValue ?
VK_LValue :
@@ -6359,6 +6606,12 @@ InitializationSequence::Perform(Sema &S,
cast<FieldDecl>(Entity.getDecl()),
CurInit.get());
+ // Check for std::move on construction.
+ if (const Expr *E = CurInit.get()) {
+ CheckMoveOnConstruction(S, E,
+ Entity.getKind() == InitializedEntity::EK_Result);
+ }
+
return CurInit;
}
@@ -6455,26 +6708,6 @@ static void diagnoseListInit(Sema &S, const InitializedEntity &Entity,
"Inconsistent init list check result.");
}
-/// Prints a fixit for adding a null initializer for |Entity|. Call this only
-/// right after emitting a diagnostic.
-static void maybeEmitZeroInitializationFixit(Sema &S,
- InitializationSequence &Sequence,
- const InitializedEntity &Entity) {
- if (Entity.getKind() != InitializedEntity::EK_Variable)
- return;
-
- VarDecl *VD = cast<VarDecl>(Entity.getDecl());
- if (VD->getInit() || VD->getLocEnd().isMacroID())
- return;
-
- QualType VariableTy = VD->getType().getCanonicalType();
- SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd());
- std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc);
-
- S.Diag(Loc, diag::note_add_initializer)
- << VD << FixItHint::CreateInsertion(Loc, Init);
-}
-
bool InitializationSequence::Diagnose(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -6622,12 +6855,19 @@ bool InitializationSequence::Diagnose(Sema &S,
<< Args[0]->getSourceRange();
break;
- case FK_ReferenceInitDropsQualifiers:
+ case FK_ReferenceInitDropsQualifiers: {
+ QualType SourceType = Args[0]->getType();
+ QualType NonRefType = DestType.getNonReferenceType();
+ Qualifiers DroppedQualifiers =
+ SourceType.getQualifiers() - NonRefType.getQualifiers();
+
S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
- << DestType.getNonReferenceType()
- << Args[0]->getType()
+ << SourceType
+ << NonRefType
+ << DroppedQualifiers.getCVRQualifiers()
<< Args[0]->getSourceRange();
break;
+ }
case FK_ReferenceInitFailed:
S.Diag(Kind.getLocation(), diag::err_reference_bind_failed)
@@ -6659,9 +6899,9 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_TooManyInitsForScalar: {
SourceRange R;
- if (InitListExpr *InitList = dyn_cast<InitListExpr>(Args[0]))
- R = SourceRange(InitList->getInit(0)->getLocEnd(),
- InitList->getLocEnd());
+ auto *InitList = dyn_cast<InitListExpr>(Args[0]);
+ if (InitList && InitList->getNumInits() == 1)
+ R = SourceRange(InitList->getInit(0)->getLocEnd(), InitList->getLocEnd());
else
R = SourceRange(Args.front()->getLocEnd(), Args.back()->getLocEnd());
@@ -6806,7 +7046,6 @@ bool InitializationSequence::Diagnose(Sema &S,
} else {
S.Diag(Kind.getLocation(), diag::err_default_init_const)
<< DestType << (bool)DestType->getAs<RecordType>();
- maybeEmitZeroInitializationFixit(S, *this, Entity);
}
break;
@@ -7262,7 +7501,6 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity,
EqualLoc,
AllowExplicit);
InitializationSequence Seq(*this, Entity, Kind, InitE, TopLevelOfInitList);
- Init.get();
ExprResult Result = Seq.Perform(*this, Entity, Kind, InitE);
OpenPOWER on IntegriCloud