summaryrefslogtreecommitdiff
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.cpp571
1 files changed, 370 insertions, 201 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
index c3a89463dc69..060ee3eef212 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
@@ -26,6 +26,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
+
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -204,6 +205,8 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
// Semantic checking for initializer lists.
//===----------------------------------------------------------------------===//
+namespace {
+
/// @brief Semantic checking for initializer lists.
///
/// The InitListChecker class contains a set of routines that each
@@ -231,11 +234,11 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
/// point. CheckDesignatedInitializer() recursively steps into the
/// designated subobject and manages backing out the recursion to
/// initialize the subobjects after the one designated.
-namespace {
class InitListChecker {
Sema &SemaRef;
bool hadError;
bool VerifyOnly; // no diagnostics, no structure building
+ bool TreatUnavailableAsInvalid; // Used only in VerifyOnly mode.
llvm::DenseMap<InitListExpr *, InitListExpr *> SyntacticToSemantic;
InitListExpr *FullyStructuredList;
@@ -280,6 +283,7 @@ class InitListChecker {
unsigned &StructuredIndex);
void CheckStructUnionTypes(const InitializedEntity &Entity,
InitListExpr *IList, QualType DeclType,
+ CXXRecordDecl::base_class_range Bases,
RecordDecl::field_iterator Field,
bool SubobjectIsDesignatorContext, unsigned &Index,
InitListExpr *StructuredList,
@@ -317,7 +321,8 @@ class InitListChecker {
static ExprResult PerformEmptyInit(Sema &SemaRef,
SourceLocation Loc,
const InitializedEntity &Entity,
- bool VerifyOnly);
+ bool VerifyOnly,
+ bool TreatUnavailableAsInvalid);
// Explanation on the "FillWithNoInit" mode:
//
@@ -338,6 +343,10 @@ class InitListChecker {
// in the InitListExpr, the "holes" in Case#1 are filled not with empty
// initializers but with special "NoInitExpr" place holders, which tells the
// CodeGen not to generate any initializers for these parts.
+ void FillInEmptyInitForBase(unsigned Init, const CXXBaseSpecifier &Base,
+ const InitializedEntity &ParentEntity,
+ InitListExpr *ILE, bool &RequiresSecondPass,
+ bool FillWithNoInit);
void FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
const InitializedEntity &ParentEntity,
InitListExpr *ILE, bool &RequiresSecondPass,
@@ -353,19 +362,22 @@ class InitListChecker {
public:
InitListChecker(Sema &S, const InitializedEntity &Entity,
- InitListExpr *IL, QualType &T, bool VerifyOnly);
+ InitListExpr *IL, QualType &T, bool VerifyOnly,
+ bool TreatUnavailableAsInvalid);
bool HadError() { return hadError; }
// @brief Retrieves the fully-structured initializer list used for
// semantic analysis and code generation.
InitListExpr *getFullyStructuredList() const { return FullyStructuredList; }
};
+
} // end anonymous namespace
ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef,
SourceLocation Loc,
const InitializedEntity &Entity,
- bool VerifyOnly) {
+ bool VerifyOnly,
+ bool TreatUnavailableAsInvalid) {
InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
true);
MultiExprArg SubInit;
@@ -419,8 +431,6 @@ ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef,
if (CtorDecl->getMinRequiredArguments() == 0 &&
CtorDecl->isExplicit() && R->getDeclName() &&
SemaRef.SourceMgr.isInSystemHeader(CtorDecl->getLocation())) {
-
-
bool IsInStd = false;
for (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(R->getDeclContext());
ND && !IsInStd; ND = dyn_cast<NamespaceDecl>(ND->getParent())) {
@@ -437,7 +447,8 @@ ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef,
InitSeq.InitializeFrom(
SemaRef, Entity,
InitializationKind::CreateValue(Loc, Loc, Loc, true),
- MultiExprArg(), /*TopLevelOfInitList=*/false);
+ MultiExprArg(), /*TopLevelOfInitList=*/false,
+ TreatUnavailableAsInvalid);
// Emit a warning for this. System header warnings aren't shown
// by default, but people working on system headers should see it.
if (!VerifyOnly) {
@@ -474,10 +485,43 @@ void InitListChecker::CheckEmptyInitializable(const InitializedEntity &Entity,
SourceLocation Loc) {
assert(VerifyOnly &&
"CheckEmptyInitializable is only inteded for verification mode.");
- if (PerformEmptyInit(SemaRef, Loc, Entity, /*VerifyOnly*/true).isInvalid())
+ if (PerformEmptyInit(SemaRef, Loc, Entity, /*VerifyOnly*/true,
+ TreatUnavailableAsInvalid).isInvalid())
hadError = true;
}
+void InitListChecker::FillInEmptyInitForBase(
+ unsigned Init, const CXXBaseSpecifier &Base,
+ const InitializedEntity &ParentEntity, InitListExpr *ILE,
+ bool &RequiresSecondPass, bool FillWithNoInit) {
+ assert(Init < ILE->getNumInits() && "should have been expanded");
+
+ InitializedEntity BaseEntity = InitializedEntity::InitializeBase(
+ SemaRef.Context, &Base, false, &ParentEntity);
+
+ if (!ILE->getInit(Init)) {
+ ExprResult BaseInit =
+ FillWithNoInit ? new (SemaRef.Context) NoInitExpr(Base.getType())
+ : PerformEmptyInit(SemaRef, ILE->getLocEnd(), BaseEntity,
+ /*VerifyOnly*/ false,
+ TreatUnavailableAsInvalid);
+ if (BaseInit.isInvalid()) {
+ hadError = true;
+ return;
+ }
+
+ ILE->setInit(Init, BaseInit.getAs<Expr>());
+ } else if (InitListExpr *InnerILE =
+ dyn_cast<InitListExpr>(ILE->getInit(Init))) {
+ FillInEmptyInitializations(BaseEntity, InnerILE,
+ RequiresSecondPass, FillWithNoInit);
+ } else if (DesignatedInitUpdateExpr *InnerDIUE =
+ dyn_cast<DesignatedInitUpdateExpr>(ILE->getInit(Init))) {
+ FillInEmptyInitializations(BaseEntity, InnerDIUE->getUpdater(),
+ RequiresSecondPass, /*FillWithNoInit =*/true);
+ }
+}
+
void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
const InitializedEntity &ParentEntity,
InitListExpr *ILE,
@@ -535,7 +579,8 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
}
ExprResult MemberInit = PerformEmptyInit(SemaRef, Loc, MemberEntity,
- /*VerifyOnly*/false);
+ /*VerifyOnly*/false,
+ TreatUnavailableAsInvalid);
if (MemberInit.isInvalid()) {
hadError = true;
return;
@@ -592,14 +637,25 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
// The fields beyond ILE->getNumInits() are default initialized, so in
// order to leave them uninitialized, the ILE is expanded and the extra
// fields are then filled with NoInitExpr.
- unsigned NumFields = 0;
- for (auto *Field : RDecl->fields())
- if (!Field->isUnnamedBitfield())
- ++NumFields;
- if (ILE->getNumInits() < NumFields)
- ILE->resizeInits(SemaRef.Context, NumFields);
+ unsigned NumElems = numStructUnionElements(ILE->getType());
+ if (RDecl->hasFlexibleArrayMember())
+ ++NumElems;
+ if (ILE->getNumInits() < NumElems)
+ ILE->resizeInits(SemaRef.Context, NumElems);
unsigned Init = 0;
+
+ if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RDecl)) {
+ for (auto &Base : CXXRD->bases()) {
+ if (hadError)
+ return;
+
+ FillInEmptyInitForBase(Init, Base, Entity, ILE, RequiresSecondPass,
+ FillWithNoInit);
+ ++Init;
+ }
+ }
+
for (auto *Field : RDecl->fields()) {
if (Field->isUnnamedBitfield())
continue;
@@ -661,7 +717,8 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
else {
ExprResult ElementInit = PerformEmptyInit(SemaRef, ILE->getLocEnd(),
ElementEntity,
- /*VerifyOnly*/false);
+ /*VerifyOnly*/false,
+ TreatUnavailableAsInvalid);
if (ElementInit.isInvalid()) {
hadError = true;
return;
@@ -707,11 +764,12 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
}
}
-
InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
InitListExpr *IL, QualType &T,
- bool VerifyOnly)
- : SemaRef(S), VerifyOnly(VerifyOnly) {
+ bool VerifyOnly,
+ bool TreatUnavailableAsInvalid)
+ : SemaRef(S), VerifyOnly(VerifyOnly),
+ TreatUnavailableAsInvalid(TreatUnavailableAsInvalid) {
// FIXME: Check that IL isn't already the semantic form of some other
// InitListExpr. If it is, we'd create a broken AST.
@@ -744,6 +802,8 @@ int InitListChecker::numArrayElements(QualType DeclType) {
int InitListChecker::numStructUnionElements(QualType DeclType) {
RecordDecl *structDecl = DeclType->getAs<RecordType>()->getDecl();
int InitializableMembers = 0;
+ if (auto *CXXRD = dyn_cast<CXXRecordDecl>(structDecl))
+ InitializableMembers += CXXRD->getNumBases();
for (const auto *Field : structDecl->fields())
if (!Field->isUnnamedBitfield())
++InitializableMembers;
@@ -888,7 +948,6 @@ static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity,
}
}
-
/// Check whether the initializer \p IList (that was written with explicit
/// braces) can be used to initialize an object of type \p T.
///
@@ -992,10 +1051,14 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
assert(DeclType->isAggregateType() &&
"non-aggregate records should be handed in CheckSubElementType");
RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
- CheckStructUnionTypes(Entity, IList, DeclType, RD->field_begin(),
- SubobjectIsDesignatorContext, Index,
- StructuredList, StructuredIndex,
- TopLevelObject);
+ auto Bases =
+ CXXRecordDecl::base_class_range(CXXRecordDecl::base_class_iterator(),
+ CXXRecordDecl::base_class_iterator());
+ if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
+ Bases = CXXRD->bases();
+ CheckStructUnionTypes(Entity, IList, DeclType, Bases, RD->field_begin(),
+ SubobjectIsDesignatorContext, Index, StructuredList,
+ StructuredIndex, TopLevelObject);
} else if (DeclType->isArrayType()) {
llvm::APSInt Zero(
SemaRef.Context.getTypeSize(SemaRef.Context.getSizeType()),
@@ -1130,8 +1193,8 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
// Fall through for subaggregate initialization.
} else {
- assert((ElemType->isRecordType() || ElemType->isVectorType()) &&
- "Unexpected type");
+ assert((ElemType->isRecordType() || ElemType->isVectorType() ||
+ ElemType->isClkEventT()) && "Unexpected type");
// C99 6.7.8p13:
//
@@ -1220,7 +1283,6 @@ void InitListChecker::CheckComplexType(const InitializedEntity &Entity,
}
}
-
void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
InitListExpr *IList, QualType DeclType,
unsigned &Index,
@@ -1672,16 +1734,13 @@ bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity,
return FlexArrayDiag != diag::ext_flexible_array_init;
}
-void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
- InitListExpr *IList,
- QualType DeclType,
- RecordDecl::field_iterator Field,
- bool SubobjectIsDesignatorContext,
- unsigned &Index,
- InitListExpr *StructuredList,
- unsigned &StructuredIndex,
- bool TopLevelObject) {
- RecordDecl* structDecl = DeclType->getAs<RecordType>()->getDecl();
+void InitListChecker::CheckStructUnionTypes(
+ const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType,
+ CXXRecordDecl::base_class_range Bases, RecordDecl::field_iterator Field,
+ bool SubobjectIsDesignatorContext, unsigned &Index,
+ InitListExpr *StructuredList, unsigned &StructuredIndex,
+ bool TopLevelObject) {
+ RecordDecl *structDecl = DeclType->getAs<RecordType>()->getDecl();
// If the record is invalid, some of it's members are invalid. To avoid
// confusion, we forgo checking the intializer for the entire record.
@@ -1726,13 +1785,35 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
return;
}
+ bool InitializedSomething = false;
+
+ // If we have any base classes, they are initialized prior to the fields.
+ for (auto &Base : Bases) {
+ Expr *Init = Index < IList->getNumInits() ? IList->getInit(Index) : nullptr;
+ SourceLocation InitLoc = Init ? Init->getLocStart() : IList->getLocEnd();
+
+ // Designated inits always initialize fields, so if we see one, all
+ // remaining base classes have no explicit initializer.
+ if (Init && isa<DesignatedInitExpr>(Init))
+ Init = nullptr;
+
+ InitializedEntity BaseEntity = InitializedEntity::InitializeBase(
+ SemaRef.Context, &Base, false, &Entity);
+ if (Init) {
+ CheckSubElementType(BaseEntity, IList, Base.getType(), Index,
+ StructuredList, StructuredIndex);
+ InitializedSomething = true;
+ } else if (VerifyOnly) {
+ CheckEmptyInitializable(BaseEntity, InitLoc);
+ }
+ }
+
// If structDecl is a forward declaration, this loop won't do
// anything except look at designated initializers; That's okay,
// because an error should get printed out elsewhere. It might be
// worthwhile to skip over the rest of the initializer, though.
RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
RecordDecl::field_iterator FieldEnd = RD->field_end();
- bool InitializedSomething = false;
bool CheckForMissingFields = true;
while (Index < IList->getNumInits()) {
Expr *Init = IList->getInit(Index);
@@ -1782,7 +1863,7 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
// Make sure we can use this declaration.
bool InvalidUse;
if (VerifyOnly)
- InvalidUse = !SemaRef.CanUseDecl(*Field);
+ InvalidUse = !SemaRef.CanUseDecl(*Field, TreatUnavailableAsInvalid);
else
InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field,
IList->getInit(Index)->getLocStart());
@@ -1895,8 +1976,8 @@ static DesignatedInitExpr *CloneDesignatedInitExpr(Sema &SemaRef,
SmallVector<Expr*, 4> IndexExprs(NumIndexExprs);
for (unsigned I = 0; I < NumIndexExprs; ++I)
IndexExprs[I] = DIE->getSubExpr(I + 1);
- return DesignatedInitExpr::Create(SemaRef.Context, DIE->designators_begin(),
- DIE->size(), IndexExprs,
+ return DesignatedInitExpr::Create(SemaRef.Context, DIE->designators(),
+ IndexExprs,
DIE->getEqualOrColonLoc(),
DIE->usesGNUSyntax(), DIE->getInit());
}
@@ -1919,7 +2000,7 @@ class FieldInitializerValidatorCCC : public CorrectionCandidateCallback {
RecordDecl *Record;
};
-}
+} // end anonymous namespace
/// @brief Check the well-formedness of a C99 designated initializer.
///
@@ -2146,8 +2227,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
for (auto *FI : RT->getDecl()->fields()) {
if (FI->isUnnamedBitfield())
continue;
- if (KnownField == FI)
+ if (declaresSameEntity(KnownField, FI)) {
+ KnownField = FI;
break;
+ }
++FieldIndex;
}
@@ -2160,11 +2243,11 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
FieldIndex = 0;
if (!VerifyOnly) {
FieldDecl *CurrentField = StructuredList->getInitializedFieldInUnion();
- if (CurrentField && CurrentField != *Field) {
+ if (CurrentField && !declaresSameEntity(CurrentField, *Field)) {
assert(StructuredList->getNumInits() == 1
&& "A union should never have more than one initializer!");
- // we're about to throw away an initializer, emit warning
+ // We're about to throw away an initializer, emit warning.
SemaRef.Diag(D->getFieldLoc(),
diag::warn_initializer_overrides)
<< D->getSourceRange();
@@ -2186,7 +2269,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// Make sure we can use this declaration.
bool InvalidUse;
if (VerifyOnly)
- InvalidUse = !SemaRef.CanUseDecl(*Field);
+ InvalidUse = !SemaRef.CanUseDecl(*Field, TreatUnavailableAsInvalid);
else
InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field, D->getFieldLoc());
if (InvalidUse) {
@@ -2276,7 +2359,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
if (CheckDesignatedInitializer(MemberEntity, IList, DIE, DesigIdx + 1,
FieldType, nullptr, nullptr, Index,
StructuredList, newStructuredIndex,
- true, false))
+ FinishSubobjectInit, false))
return true;
}
@@ -2304,8 +2387,11 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// Check the remaining fields within this class/struct/union subobject.
bool prevHadError = hadError;
- CheckStructUnionTypes(Entity, IList, CurrentObjectType, Field, false, Index,
- StructuredList, FieldIndex);
+ auto NoBases =
+ CXXRecordDecl::base_class_range(CXXRecordDecl::base_class_iterator(),
+ CXXRecordDecl::base_class_iterator());
+ CheckStructUnionTypes(Entity, IList, CurrentObjectType, NoBases, Field,
+ false, Index, StructuredList, FieldIndex);
return hadError && !prevHadError;
}
@@ -2467,11 +2553,11 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
Index = OldIndex;
ElementEntity.setElementIndex(ElementIndex);
- if (CheckDesignatedInitializer(ElementEntity, IList, DIE, DesigIdx + 1,
- ElementType, nullptr, nullptr, Index,
- StructuredList, ElementIndex,
- (DesignatedStartIndex == DesignatedEndIndex),
- false))
+ if (CheckDesignatedInitializer(
+ ElementEntity, IList, DIE, DesigIdx + 1, ElementType, nullptr,
+ nullptr, Index, StructuredList, ElementIndex,
+ FinishSubobjectInit && (DesignatedStartIndex == DesignatedEndIndex),
+ false))
return true;
// Move to the next index in the array that we'll be initializing.
@@ -2751,7 +2837,7 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
DesignatedInitExpr *DIE
= DesignatedInitExpr::Create(Context,
- Designators.data(), Designators.size(),
+ Designators,
InitExpressions, Loc, GNUSyntax,
Init.getAs<Expr>());
@@ -2787,10 +2873,11 @@ InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index,
InitializedEntity
InitializedEntity::InitializeBase(ASTContext &Context,
const CXXBaseSpecifier *Base,
- bool IsInheritedVirtualBase) {
+ bool IsInheritedVirtualBase,
+ const InitializedEntity *Parent) {
InitializedEntity Result;
Result.Kind = EK_Base;
- Result.Parent = nullptr;
+ Result.Parent = Parent;
Result.Base = reinterpret_cast<uintptr_t>(Base);
if (IsInheritedVirtualBase)
Result.Base |= 0x01;
@@ -2928,7 +3015,7 @@ unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const {
return Depth + 1;
}
-void InitializedEntity::dump() const {
+LLVM_DUMP_METHOD void InitializedEntity::dump() const {
dumpImpl(llvm::errs());
}
@@ -3137,13 +3224,9 @@ void InitializationSequence::AddListInitializationStep(QualType T) {
Steps.push_back(S);
}
-void
-InitializationSequence
-::AddConstructorInitializationStep(CXXConstructorDecl *Constructor,
- AccessSpecifier Access,
- QualType T,
- bool HadMultipleCandidates,
- bool FromInitList, bool AsInitList) {
+void InitializationSequence::AddConstructorInitializationStep(
+ DeclAccessPair FoundDecl, CXXConstructorDecl *Constructor, QualType T,
+ bool HadMultipleCandidates, bool FromInitList, bool AsInitList) {
Step S;
S.Kind = FromInitList ? AsInitList ? SK_StdInitializerListConstructorCall
: SK_ConstructorInitializationFromList
@@ -3151,7 +3234,7 @@ InitializationSequence
S.Type = T;
S.Function.HadMultipleCandidates = HadMultipleCandidates;
S.Function.Function = Constructor;
- S.Function.FoundDecl = DeclAccessPair::make(Constructor, Access);
+ S.Function.FoundDecl = FoundDecl;
Steps.push_back(S);
}
@@ -3313,7 +3396,8 @@ static void TryListInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
InitListExpr *InitList,
- InitializationSequence &Sequence);
+ InitializationSequence &Sequence,
+ bool TreatUnavailableAsInvalid);
/// \brief When initializing from init list via constructor, handle
/// initialization of an object of type std::initializer_list<T>.
@@ -3323,7 +3407,8 @@ static void TryListInitialization(Sema &S,
static bool TryInitializerListConstruction(Sema &S,
InitListExpr *List,
QualType DestType,
- InitializationSequence &Sequence) {
+ InitializationSequence &Sequence,
+ bool TreatUnavailableAsInvalid) {
QualType E;
if (!S.isStdInitializerList(DestType, &E))
return false;
@@ -3342,7 +3427,8 @@ static bool TryInitializerListConstruction(Sema &S,
InitializedEntity::InitializeTemporary(ArrayType);
InitializationKind Kind =
InitializationKind::CreateDirectList(List->getExprLoc());
- TryListInitialization(S, HiddenArray, Kind, List, Sequence);
+ TryListInitialization(S, HiddenArray, Kind, List, Sequence,
+ TreatUnavailableAsInvalid);
if (Sequence)
Sequence.AddStdInitializerListConstructionStep(DestType);
return true;
@@ -3359,18 +3445,13 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
CandidateSet.clear();
for (NamedDecl *D : Ctors) {
- DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
- bool SuppressUserConversions = false;
+ auto Info = getConstructorInfo(D);
+ if (!Info.Constructor)
+ continue;
- // Find the constructor (which may be a template).
- CXXConstructorDecl *Constructor = nullptr;
- FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
- if (ConstructorTmpl)
- Constructor = cast<CXXConstructorDecl>(
- ConstructorTmpl->getTemplatedDecl());
- else {
- Constructor = cast<CXXConstructorDecl>(D);
+ bool SuppressUserConversions = false;
+ if (!Info.ConstructorTmpl) {
// C++11 [over.best.ics]p4:
// ... and the constructor or user-defined conversion function is a
// candidate by
@@ -3387,15 +3468,15 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
// parameter of a constructor of X.
if ((CopyInitializing ||
(IsListInit && Args.size() == 1 && isa<InitListExpr>(Args[0]))) &&
- Constructor->isCopyOrMoveConstructor())
+ Info.Constructor->isCopyOrMoveConstructor())
SuppressUserConversions = true;
}
- if (!Constructor->isInvalidDecl() &&
- (AllowExplicit || !Constructor->isExplicit()) &&
- (!OnlyListConstructors || S.isInitListConstructor(Constructor))) {
- if (ConstructorTmpl)
- S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+ if (!Info.Constructor->isInvalidDecl() &&
+ (AllowExplicit || !Info.Constructor->isExplicit()) &&
+ (!OnlyListConstructors || S.isInitListConstructor(Info.Constructor))) {
+ if (Info.ConstructorTmpl)
+ S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
/*ExplicitArgs*/ nullptr, Args,
CandidateSet, SuppressUserConversions);
else {
@@ -3407,9 +3488,9 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
// are also considered.
bool AllowExplicitConv = AllowExplicit && !CopyInitializing &&
Args.size() == 1 &&
- Constructor->isCopyOrMoveConstructor();
- S.AddOverloadCandidate(Constructor, FoundDecl, Args, CandidateSet,
- SuppressUserConversions,
+ Info.Constructor->isCopyOrMoveConstructor();
+ S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args,
+ CandidateSet, SuppressUserConversions,
/*PartialOverloading=*/false,
/*AllowExplicit=*/AllowExplicitConv);
}
@@ -3517,18 +3598,23 @@ static void TryConstructorInitialization(Sema &S,
// If a program calls for the default initialization of an object
// of a const-qualified type T, T shall be a class type with a
// user-provided default constructor.
+ // C++ core issue 253 proposal:
+ // If the implicit default constructor initializes all subobjects, no
+ // initializer should be required.
+ // The 253 proposal is for example needed to process libstdc++ headers in 5.x.
+ CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
if (Kind.getKind() == InitializationKind::IK_Default &&
- Entity.getType().isConstQualified() &&
- !cast<CXXConstructorDecl>(Best->Function)->isUserProvided()) {
- if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity))
- Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
- return;
+ Entity.getType().isConstQualified()) {
+ if (!CtorDecl->getParent()->allowConstDefaultInit()) {
+ if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity))
+ Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+ return;
+ }
}
// C++11 [over.match.list]p1:
// In copy-list-initialization, if an explicit constructor is chosen, the
// initializer is ill-formed.
- CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) {
Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor);
return;
@@ -3538,7 +3624,7 @@ static void TryConstructorInitialization(Sema &S,
// subsumed by the initialization.
bool HadMultipleCandidates = (CandidateSet.size() > 1);
Sequence.AddConstructorInitializationStep(
- CtorDecl, Best->FoundDecl.getAccess(), DestType, HadMultipleCandidates,
+ Best->FoundDecl, CtorDecl, DestType, HadMultipleCandidates,
IsListInit | IsInitListCopy, AsInitializerList);
}
@@ -3591,7 +3677,8 @@ static void TryReferenceListInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
InitListExpr *InitList,
- InitializationSequence &Sequence) {
+ InitializationSequence &Sequence,
+ bool TreatUnavailableAsInvalid) {
// First, catch C++03 where this isn't possible.
if (!S.getLangOpts().CPlusPlus11) {
Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
@@ -3647,7 +3734,8 @@ static void TryReferenceListInitialization(Sema &S,
// Not reference-related. Create a temporary and bind to that.
InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1);
- TryListInitialization(S, TempEntity, Kind, InitList, Sequence);
+ TryListInitialization(S, TempEntity, Kind, InitList, Sequence,
+ TreatUnavailableAsInvalid);
if (Sequence) {
if (DestType->isRValueReferenceType() ||
(T1Quals.hasConst() && !T1Quals.hasVolatile()))
@@ -3663,7 +3751,8 @@ static void TryListInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
InitListExpr *InitList,
- InitializationSequence &Sequence) {
+ InitializationSequence &Sequence,
+ bool TreatUnavailableAsInvalid) {
QualType DestType = Entity.getType();
// C++ doesn't allow scalar initialization with more than one argument.
@@ -3674,7 +3763,8 @@ static void TryListInitialization(Sema &S,
return;
}
if (DestType->isReferenceType()) {
- TryReferenceListInitialization(S, Entity, Kind, InitList, Sequence);
+ TryReferenceListInitialization(S, Entity, Kind, InitList, Sequence,
+ TreatUnavailableAsInvalid);
return;
}
@@ -3718,7 +3808,8 @@ static void TryListInitialization(Sema &S,
InitList->getRBraceLoc())
: Kind;
Sequence.InitializeFrom(S, Entity, SubKind, SubInit,
- /*TopLevelOfInitList*/ true);
+ /*TopLevelOfInitList*/ true,
+ TreatUnavailableAsInvalid);
// TryStringLiteralInitialization() (in InitializeFrom()) will fail if
// the element is not an appropriately-typed string literal, in which
@@ -3750,7 +3841,8 @@ static void TryListInitialization(Sema &S,
// - Otherwise, if T is a specialization of std::initializer_list<E>,
// an initializer_list object constructed [...]
- if (TryInitializerListConstruction(S, InitList, DestType, Sequence))
+ if (TryInitializerListConstruction(S, InitList, DestType, Sequence,
+ TreatUnavailableAsInvalid))
return;
// - Otherwise, if T is a class type, constructors are considered.
@@ -3763,8 +3855,48 @@ static void TryListInitialization(Sema &S,
}
if (S.getLangOpts().CPlusPlus && !DestType->isAggregateType() &&
- InitList->getNumInits() == 1 &&
- InitList->getInit(0)->getType()->isRecordType()) {
+ InitList->getNumInits() == 1) {
+ Expr *E = InitList->getInit(0);
+
+ // - Otherwise, if T is an enumeration with a fixed underlying type,
+ // the initializer-list has a single element v, and the initialization
+ // is direct-list-initialization, the object is initialized with the
+ // value T(v); if a narrowing conversion is required to convert v to
+ // the underlying type of T, the program is ill-formed.
+ auto *ET = DestType->getAs<EnumType>();
+ if (S.getLangOpts().CPlusPlus1z &&
+ Kind.getKind() == InitializationKind::IK_DirectList &&
+ ET && ET->getDecl()->isFixed() &&
+ !S.Context.hasSameUnqualifiedType(E->getType(), DestType) &&
+ (E->getType()->isIntegralOrEnumerationType() ||
+ E->getType()->isFloatingType())) {
+ // There are two ways that T(v) can work when T is an enumeration type.
+ // If there is either an implicit conversion sequence from v to T or
+ // a conversion function that can convert from v to T, then we use that.
+ // Otherwise, if v is of integral, enumeration, or floating-point type,
+ // it is converted to the enumeration type via its underlying type.
+ // There is no overlap possible between these two cases (except when the
+ // source value is already of the destination type), and the first
+ // case is handled by the general case for single-element lists below.
+ ImplicitConversionSequence ICS;
+ ICS.setStandard();
+ ICS.Standard.setAsIdentityConversion();
+ // If E is of a floating-point type, then the conversion is ill-formed
+ // due to narrowing, but go through the motions in order to produce the
+ // right diagnostic.
+ ICS.Standard.Second = E->getType()->isFloatingType()
+ ? ICK_Floating_Integral
+ : ICK_Integral_Conversion;
+ ICS.Standard.setFromType(E->getType());
+ ICS.Standard.setToType(0, E->getType());
+ ICS.Standard.setToType(1, DestType);
+ ICS.Standard.setToType(2, DestType);
+ Sequence.AddConversionSequenceStep(ICS, ICS.Standard.getToType(2),
+ /*TopLevelOfInitList*/true);
+ Sequence.RewrapReferenceInitList(Entity.getType(), InitList);
+ return;
+ }
+
// - 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 (by copy-initialization for
@@ -3778,22 +3910,25 @@ static void TryListInitialization(Sema &S,
// copy-initialization. This only matters if we might use an 'explicit'
// conversion operator, so we only need to handle the cases where the source
// is of record type.
- InitializationKind SubKind =
- Kind.getKind() == InitializationKind::IK_DirectList
- ? InitializationKind::CreateDirect(Kind.getLocation(),
- InitList->getLBraceLoc(),
- InitList->getRBraceLoc())
- : Kind;
- Expr *SubInit[1] = { InitList->getInit(0) };
- Sequence.InitializeFrom(S, Entity, SubKind, SubInit,
- /*TopLevelOfInitList*/true);
- if (Sequence)
- Sequence.RewrapReferenceInitList(Entity.getType(), InitList);
- return;
+ if (InitList->getInit(0)->getType()->isRecordType()) {
+ InitializationKind SubKind =
+ Kind.getKind() == InitializationKind::IK_DirectList
+ ? InitializationKind::CreateDirect(Kind.getLocation(),
+ InitList->getLBraceLoc(),
+ InitList->getRBraceLoc())
+ : Kind;
+ Expr *SubInit[1] = { InitList->getInit(0) };
+ Sequence.InitializeFrom(S, Entity, SubKind, SubInit,
+ /*TopLevelOfInitList*/true,
+ TreatUnavailableAsInvalid);
+ if (Sequence)
+ Sequence.RewrapReferenceInitList(Entity.getType(), InitList);
+ return;
+ }
}
InitListChecker CheckInitList(S, Entity, InitList,
- DestType, /*VerifyOnly=*/true);
+ DestType, /*VerifyOnly=*/true, TreatUnavailableAsInvalid);
if (CheckInitList.HadError()) {
Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed);
return;
@@ -3847,26 +3982,19 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
for (NamedDecl *D : S.LookupConstructors(T1RecordDecl)) {
- DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
-
- // Find the constructor (which may be a template).
- CXXConstructorDecl *Constructor = nullptr;
- FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
- if (ConstructorTmpl)
- Constructor = cast<CXXConstructorDecl>(
- ConstructorTmpl->getTemplatedDecl());
- else
- Constructor = cast<CXXConstructorDecl>(D);
+ auto Info = getConstructorInfo(D);
+ if (!Info.Constructor)
+ continue;
- if (!Constructor->isInvalidDecl() &&
- Constructor->isConvertingConstructor(AllowExplicit)) {
- if (ConstructorTmpl)
- S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+ if (!Info.Constructor->isInvalidDecl() &&
+ Info.Constructor->isConvertingConstructor(AllowExplicit)) {
+ if (Info.ConstructorTmpl)
+ S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
/*ExplicitArgs*/ nullptr,
Initializer, CandidateSet,
/*SuppressUserConversions=*/true);
else
- S.AddOverloadCandidate(Constructor, FoundDecl,
+ S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl,
Initializer, CandidateSet,
/*SuppressUserConversions=*/true);
}
@@ -4068,7 +4196,6 @@ convertQualifiersAndValueKindIfNecessary(Sema &S,
return Initializer->getValueKind();
}
-
/// \brief Reference initialization without resolving overloaded functions.
static void TryReferenceInitializationCore(Sema &S,
const InitializedEntity &Entity,
@@ -4303,7 +4430,6 @@ static void TryReferenceInitializationCore(Sema &S,
}
Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
- return;
}
/// \brief Attempt character array initialization from a string literal
@@ -4472,27 +4598,19 @@ static void TryUserDefinedConversion(Sema &S,
Con = CopyOfCon.begin(), ConEnd = CopyOfCon.end();
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
- DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
-
- // Find the constructor (which may be a template).
- CXXConstructorDecl *Constructor = nullptr;
- FunctionTemplateDecl *ConstructorTmpl
- = dyn_cast<FunctionTemplateDecl>(D);
- if (ConstructorTmpl)
- Constructor = cast<CXXConstructorDecl>(
- ConstructorTmpl->getTemplatedDecl());
- else
- Constructor = cast<CXXConstructorDecl>(D);
+ auto Info = getConstructorInfo(D);
+ if (!Info.Constructor)
+ continue;
- if (!Constructor->isInvalidDecl() &&
- Constructor->isConvertingConstructor(AllowExplicit)) {
- if (ConstructorTmpl)
- S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+ if (!Info.Constructor->isInvalidDecl() &&
+ Info.Constructor->isConvertingConstructor(AllowExplicit)) {
+ if (Info.ConstructorTmpl)
+ S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
/*ExplicitArgs*/ nullptr,
Initializer, CandidateSet,
/*SuppressUserConversions=*/true);
else
- S.AddOverloadCandidate(Constructor, FoundDecl,
+ S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl,
Initializer, CandidateSet,
/*SuppressUserConversions=*/true);
}
@@ -4689,8 +4807,8 @@ static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) {
// If isWeakAccess to true, there will be an implicit
// load which requires a cleanup.
if (S.getLangOpts().ObjCAutoRefCount && isWeakAccess)
- S.ExprNeedsCleanups = true;
-
+ S.Cleanup.setExprNeedsCleanups(true);
+
if (iik == IIK_okay) return;
S.Diag(src->getExprLoc(), diag::err_arc_nonlocal_writeback)
@@ -4800,9 +4918,11 @@ InitializationSequence::InitializationSequence(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
MultiExprArg Args,
- bool TopLevelOfInitList)
+ bool TopLevelOfInitList,
+ bool TreatUnavailableAsInvalid)
: FailedCandidateSet(Kind.getLocation(), OverloadCandidateSet::CSK_Normal) {
- InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList);
+ InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList,
+ TreatUnavailableAsInvalid);
}
/// Tries to get a FunctionDecl out of `E`. If it succeeds and we can take the
@@ -4820,7 +4940,8 @@ void InitializationSequence::InitializeFrom(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
MultiExprArg Args,
- bool TopLevelOfInitList) {
+ bool TopLevelOfInitList,
+ bool TreatUnavailableAsInvalid) {
ASTContext &Context = S.Context;
// Eliminate non-overload placeholder types in the arguments. We
@@ -4874,7 +4995,8 @@ void InitializationSequence::InitializeFrom(Sema &S,
// object is list-initialized (8.5.4).
if (Kind.getKind() != InitializationKind::IK_Direct) {
if (InitListExpr *InitList = dyn_cast_or_null<InitListExpr>(Initializer)) {
- TryListInitialization(S, Entity, Kind, InitList, *this);
+ TryListInitialization(S, Entity, Kind, InitList, *this,
+ TreatUnavailableAsInvalid);
return;
}
}
@@ -4958,7 +5080,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
Entity.getKind() == InitializedEntity::EK_Member &&
Initializer && isa<InitListExpr>(Initializer)) {
TryListInitialization(S, Entity, Kind, cast<InitListExpr>(Initializer),
- *this);
+ *this, TreatUnavailableAsInvalid);
AddParenthesizedArrayInitStep(DestType);
} else if (DestAT->getElementType()->isCharType())
SetFailed(FK_ArrayNeedsInitListOrStringLiteral);
@@ -5232,38 +5354,33 @@ static void LookupCopyAndMoveConstructors(Sema &S,
for (SmallVectorImpl<NamedDecl *>::iterator
CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) {
NamedDecl *D = *CI;
- CXXConstructorDecl *Constructor = nullptr;
+ auto Info = getConstructorInfo(D);
+ if (!Info.Constructor)
+ continue;
- if ((Constructor = dyn_cast<CXXConstructorDecl>(D))) {
- // Handle copy/moveconstructors, only.
- if (!Constructor || Constructor->isInvalidDecl() ||
- !Constructor->isCopyOrMoveConstructor() ||
- !Constructor->isConvertingConstructor(/*AllowExplicit=*/true))
+ if (!Info.ConstructorTmpl) {
+ // Handle copy/move constructors, only.
+ if (Info.Constructor->isInvalidDecl() ||
+ !Info.Constructor->isCopyOrMoveConstructor() ||
+ !Info.Constructor->isConvertingConstructor(/*AllowExplicit=*/true))
continue;
- DeclAccessPair FoundDecl
- = DeclAccessPair::make(Constructor, Constructor->getAccess());
- S.AddOverloadCandidate(Constructor, FoundDecl,
+ S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl,
CurInitExpr, CandidateSet);
continue;
}
// Handle constructor templates.
- FunctionTemplateDecl *ConstructorTmpl = cast<FunctionTemplateDecl>(D);
- if (ConstructorTmpl->isInvalidDecl())
+ if (Info.ConstructorTmpl->isInvalidDecl())
continue;
- Constructor = cast<CXXConstructorDecl>(
- ConstructorTmpl->getTemplatedDecl());
- if (!Constructor->isConvertingConstructor(/*AllowExplicit=*/true))
+ if (!Info.Constructor->isConvertingConstructor(/*AllowExplicit=*/true))
continue;
// FIXME: Do we need to limit this to copy-constructor-like
// candidates?
- DeclAccessPair FoundDecl
- = DeclAccessPair::make(ConstructorTmpl, ConstructorTmpl->getAccess());
- S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, nullptr,
- CurInitExpr, CandidateSet, true);
+ S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
+ nullptr, CurInitExpr, CandidateSet, true);
}
}
@@ -5402,8 +5519,8 @@ static ExprResult CopyObject(Sema &S,
SmallVector<Expr*, 8> ConstructorArgs;
CurInit.get(); // Ownership transferred into MultiExprArg, below.
- S.CheckConstructorAccess(Loc, Constructor, Entity,
- Best->FoundDecl.getAccess(), IsExtraneousCopy);
+ S.CheckConstructorAccess(Loc, Constructor, Best->FoundDecl, Entity,
+ IsExtraneousCopy);
if (IsExtraneousCopy) {
// If this is a totally extraneous copy for C++03 reference
@@ -5438,7 +5555,8 @@ static ExprResult CopyObject(Sema &S,
return ExprError();
// Actually perform the constructor call.
- CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable,
+ CurInit = S.BuildCXXConstructExpr(Loc, T, Best->FoundDecl, Constructor,
+ Elidable,
ConstructorArgs,
HadMultipleCandidates,
/*ListInit*/ false,
@@ -5485,7 +5603,7 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S,
switch (OR) {
case OR_Success:
S.CheckConstructorAccess(Loc, cast<CXXConstructorDecl>(Best->Function),
- Entity, Best->FoundDecl.getAccess(), Diag);
+ Best->FoundDecl, Entity, Diag);
// FIXME: Check default arguments as far as that's possible.
break;
@@ -5611,7 +5729,6 @@ PerformConstructorInitialization(Sema &S,
if (isExplicitTemporary(Entity, Kind, NumArgs)) {
// An explicitly-constructed temporary, e.g., X(1, 2).
- S.MarkFunctionReferenced(Loc, Constructor);
if (S.DiagnoseUseOfDecl(Constructor, Loc))
return ExprError();
@@ -5623,10 +5740,19 @@ PerformConstructorInitialization(Sema &S,
? SourceRange(LBraceLoc, RBraceLoc)
: Kind.getParenRange();
+ if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(
+ Step.Function.FoundDecl.getDecl())) {
+ Constructor = S.findInheritingConstructor(Loc, Constructor, Shadow);
+ if (S.DiagnoseUseOfDecl(Constructor, Loc))
+ return ExprError();
+ }
+ S.MarkFunctionReferenced(Loc, Constructor);
+
CurInit = new (S.Context) CXXTemporaryObjectExpr(
- S.Context, Constructor, TSInfo, ConstructorArgs, ParenOrBraceRange,
- HadMultipleCandidates, IsListInitialization,
- IsStdInitListInitialization, ConstructorInitRequiresZeroInit);
+ S.Context, Constructor, TSInfo,
+ ConstructorArgs, ParenOrBraceRange, HadMultipleCandidates,
+ IsListInitialization, IsStdInitListInitialization,
+ ConstructorInitRequiresZeroInit);
} else {
CXXConstructExpr::ConstructionKind ConstructKind =
CXXConstructExpr::CK_Complete;
@@ -5651,6 +5777,7 @@ PerformConstructorInitialization(Sema &S,
// unconditionally.
if (Entity.allowsNRVO())
CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
+ Step.Function.FoundDecl,
Constructor, /*Elidable=*/true,
ConstructorArgs,
HadMultipleCandidates,
@@ -5661,6 +5788,7 @@ PerformConstructorInitialization(Sema &S,
ParenOrBraceRange);
else
CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
+ Step.Function.FoundDecl,
Constructor,
ConstructorArgs,
HadMultipleCandidates,
@@ -5674,8 +5802,7 @@ PerformConstructorInitialization(Sema &S,
return ExprError();
// Only check access if all of that succeeded.
- S.CheckConstructorAccess(Loc, Constructor, Entity,
- Step.Function.FoundDecl.getAccess());
+ S.CheckConstructorAccess(Loc, Constructor, Step.Function.FoundDecl, Entity);
if (S.DiagnoseUseOfDecl(Step.Function.FoundDecl, Loc))
return ExprError();
@@ -5777,6 +5904,11 @@ static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
FallbackDecl);
case InitializedEntity::EK_Base:
+ // For subobjects, we look at the complete object.
+ if (Entity->getParent())
+ return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
+ Entity);
+ // Fall through.
case InitializedEntity::EK_Delegating:
// We can reach this case for aggregate initialization in a constructor:
// struct A { int &&r; };
@@ -6042,6 +6174,36 @@ static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr,
<< FixItHint::CreateRemoval(SourceRange(RParen, RParen));
}
+static void CheckForNullPointerDereference(Sema &S, const Expr *E) {
+ // Check to see if we are dereferencing a null pointer. If so, this is
+ // undefined behavior, so warn about it. This only handles the pattern
+ // "*null", which is a very syntactic check.
+ if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E->IgnoreParenCasts()))
+ if (UO->getOpcode() == UO_Deref &&
+ UO->getSubExpr()->IgnoreParenCasts()->
+ isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull)) {
+ S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
+ S.PDiag(diag::warn_binding_null_to_reference)
+ << UO->getSubExpr()->getSourceRange());
+ }
+}
+
+MaterializeTemporaryExpr *
+Sema::CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary,
+ bool BoundToLvalueReference) {
+ auto MTE = new (Context)
+ MaterializeTemporaryExpr(T, Temporary, BoundToLvalueReference);
+
+ // Order an ExprWithCleanups for lifetime marks.
+ //
+ // TODO: It'll be good to have a single place to check the access of the
+ // destructor and generate ExprWithCleanups for various uses. Currently these
+ // are done in both CreateMaterializeTemporaryExpr and MaybeBindToTemporary,
+ // but there may be a chance to merge them.
+ Cleanup.setExprNeedsCleanups(false);
+ return MTE;
+}
+
ExprResult
InitializationSequence::Perform(Sema &S,
const InitializedEntity &Entity,
@@ -6294,6 +6456,7 @@ InitializationSequence::Perform(Sema &S,
/*IsInitializerList=*/false,
ExtendingEntity->getDecl());
+ CheckForNullPointerDereference(S, CurInit.get());
break;
case SK_BindReferenceToTemporary: {
@@ -6305,7 +6468,7 @@ InitializationSequence::Perform(Sema &S,
return ExprError();
// Materialize the temporary into memory.
- MaterializeTemporaryExpr *MTE = new (S.Context) MaterializeTemporaryExpr(
+ MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr(
Entity.getType().getNonReferenceType(), CurInit.get(),
Entity.getType()->isLValueReferenceType());
@@ -6325,7 +6488,7 @@ InitializationSequence::Perform(Sema &S,
MTE->getType()->isObjCLifetimeType()) ||
(MTE->getStorageDuration() == SD_Automatic &&
MTE->getType().isDestructedType()))
- S.ExprNeedsCleanups = true;
+ S.Cleanup.setExprNeedsCleanups(true);
CurInit = MTE;
break;
@@ -6360,7 +6523,8 @@ InitializationSequence::Perform(Sema &S,
return ExprError();
// Build an expression that constructs a temporary.
- CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor,
+ CurInit = S.BuildCXXConstructExpr(Loc, Step->Type,
+ FoundFn, Constructor,
ConstructorArgs,
HadMultipleCandidates,
/*ListInit*/ false,
@@ -6371,8 +6535,8 @@ InitializationSequence::Perform(Sema &S,
if (CurInit.isInvalid())
return ExprError();
- S.CheckConstructorAccess(Kind.getLocation(), Constructor, Entity,
- FoundFn.getAccess());
+ S.CheckConstructorAccess(Kind.getLocation(), Constructor, FoundFn,
+ Entity);
if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()))
return ExprError();
@@ -6499,7 +6663,8 @@ InitializationSequence::Perform(Sema &S,
InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(Ty);
InitializedEntity InitEntity = IsTemporary ? TempEntity : Entity;
InitListChecker PerformInitList(S, InitEntity,
- InitList, Ty, /*VerifyOnly=*/false);
+ InitList, Ty, /*VerifyOnly=*/false,
+ /*TreatUnavailableAsInvalid=*/false);
if (PerformInitList.HadError())
return ExprError();
@@ -6715,9 +6880,9 @@ InitializationSequence::Perform(Sema &S,
<< CurInit.get()->getSourceRange();
// Materialize the temporary into memory.
- MaterializeTemporaryExpr *MTE = new (S.Context)
- MaterializeTemporaryExpr(CurInit.get()->getType(), CurInit.get(),
- /*BoundToLvalueReference=*/false);
+ MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr(
+ CurInit.get()->getType(), CurInit.get(),
+ /*BoundToLvalueReference=*/false);
// Maybe lifetime-extend the array temporary's subobjects to match the
// entity's lifetime.
@@ -6870,7 +7035,8 @@ static void diagnoseListInit(Sema &S, const InitializedEntity &Entity,
}
InitListChecker DiagnoseInitList(S, Entity, InitList, DestType,
- /*VerifyOnly=*/false);
+ /*VerifyOnly=*/false,
+ /*TreatUnavailableAsInvalid=*/false);
assert(DiagnoseInitList.HadError() &&
"Inconsistent init list check result.");
}
@@ -7132,17 +7298,20 @@ bool InitializationSequence::Diagnose(Sema &S,
isa<CXXConstructorDecl>(S.CurContext)) {
// This is implicit default initialization of a member or
// base within a constructor. If no viable function was
- // found, notify the user that she needs to explicitly
+ // found, notify the user that they need to explicitly
// initialize this base/member.
CXXConstructorDecl *Constructor
= cast<CXXConstructorDecl>(S.CurContext);
+ const CXXRecordDecl *InheritedFrom = nullptr;
+ if (auto Inherited = Constructor->getInheritedConstructor())
+ InheritedFrom = Inherited.getShadowDecl()->getNominatedBaseClass();
if (Entity.getKind() == InitializedEntity::EK_Base) {
S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
- << (Constructor->getInheritedConstructor() ? 2 :
- Constructor->isImplicit() ? 1 : 0)
+ << (InheritedFrom ? 2 : Constructor->isImplicit() ? 1 : 0)
<< S.Context.getTypeDeclType(Constructor->getParent())
<< /*base=*/0
- << Entity.getType();
+ << Entity.getType()
+ << InheritedFrom;
RecordDecl *BaseDecl
= Entity.getBaseSpecifier()->getType()->getAs<RecordType>()
@@ -7151,11 +7320,11 @@ bool InitializationSequence::Diagnose(Sema &S,
<< S.Context.getTagDeclType(BaseDecl);
} else {
S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
- << (Constructor->getInheritedConstructor() ? 2 :
- Constructor->isImplicit() ? 1 : 0)
+ << (InheritedFrom ? 2 : Constructor->isImplicit() ? 1 : 0)
<< S.Context.getTypeDeclType(Constructor->getParent())
<< /*member=*/1
- << Entity.getName();
+ << Entity.getName()
+ << InheritedFrom;
S.Diag(Entity.getDecl()->getLocation(),
diag::note_member_declared_at);