diff options
Diffstat (limited to 'include/clang/Sema/Initialization.h')
-rw-r--r-- | include/clang/Sema/Initialization.h | 252 |
1 files changed, 181 insertions, 71 deletions
diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index e69bebd..4433843 100644 --- a/include/clang/Sema/Initialization.h +++ b/include/clang/Sema/Initialization.h @@ -1,4 +1,4 @@ -//===--- SemaInit.h - Semantic Analysis for Initializers --------*- C++ -*-===// +//===--- Initialization.h - Semantic Analysis for Initializers --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -70,7 +70,10 @@ public: EK_BlockElement, /// \brief The entity being initialized is the real or imaginary part of a /// complex number. - EK_ComplexElement + EK_ComplexElement, + /// \brief The entity being initialized is the field that captures a + /// variable in a lambda. + EK_LambdaCapture }; private: @@ -85,7 +88,7 @@ private: QualType Type; union { - /// \brief When Kind == EK_Variable or EK_Member, the VarDecl or + /// \brief When Kind == EK_Variable, or EK_Member, the VarDecl or /// FieldDecl, respectively. DeclaratorDecl *VariableOrMember; @@ -98,7 +101,7 @@ private: TypeSourceInfo *TypeInfo; struct { - /// \brief When Kind == EK_Result, EK_Exception, or EK_New, the + /// \brief When Kind == EK_Result, EK_Exception, EK_New, the /// location of the 'return', 'throw', or 'new' keyword, /// respectively. When Kind == EK_Temporary, the location where /// the temporary is being created. @@ -118,6 +121,14 @@ private: /// EK_ComplexElement, the index of the array or vector element being /// initialized. unsigned Index; + + struct { + /// \brief The variable being captured by an EK_LambdaCapture. + VarDecl *Var; + + /// \brief The source location at which the capture occurs. + unsigned Location; + } Capture; }; InitializedEntity() { } @@ -147,6 +158,14 @@ private: InitializedEntity(ASTContext &Context, unsigned Index, const InitializedEntity &Parent); + /// \brief Create the initialization entity for a lambda capture. + InitializedEntity(VarDecl *Var, FieldDecl *Field, SourceLocation Loc) + : Kind(EK_LambdaCapture), Parent(0), Type(Field->getType()) + { + Capture.Var = Var; + Capture.Location = Loc.getRawEncoding(); + } + public: /// \brief Create the initialization entity for a variable. static InitializedEntity InitializeVariable(VarDecl *Var) { @@ -156,7 +175,7 @@ public: /// \brief Create the initialization entity for a parameter. static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm) { - bool Consumed = (Context.getLangOptions().ObjCAutoRefCount && + bool Consumed = (Context.getLangOpts().ObjCAutoRefCount && Parm->hasAttr<NSConsumedAttr>()); InitializedEntity Entity; @@ -246,6 +265,13 @@ public: return InitializedEntity(Context, Index, Parent); } + /// \brief Create the initialization entity for a lambda capture. + static InitializedEntity InitializeLambdaCapture(VarDecl *Var, + FieldDecl *Field, + SourceLocation Loc) { + return InitializedEntity(Var, Field, Loc); + } + /// \brief Determine the kind of initialization. EntityKind getKind() const { return Kind; } @@ -314,9 +340,22 @@ public: /// element, sets the element index. void setElementIndex(unsigned Index) { assert(getKind() == EK_ArrayElement || getKind() == EK_VectorElement || - EK_ComplexElement); + getKind() == EK_ComplexElement); this->Index = Index; } + + /// \brief Retrieve the variable for a captured variable in a lambda. + VarDecl *getCapturedVar() const { + assert(getKind() == EK_LambdaCapture && "Not a lambda capture!"); + return Capture.Var; + } + + /// \brief Determine the location of the capture when initializing + /// field from a captured variable in a lambda. + SourceLocation getCaptureLoc() const { + assert(getKind() == EK_LambdaCapture && "Not a lambda capture!"); + return SourceLocation::getFromRawEncoding(Capture.Location); + } }; /// \brief Describes the kind of initialization being performed, along with @@ -326,36 +365,36 @@ class InitializationKind { public: /// \brief The kind of initialization being performed. enum InitKind { - IK_Direct, ///< Direct initialization - IK_Copy, ///< Copy initialization - IK_Default, ///< Default initialization - IK_Value ///< Value initialization + IK_Direct, ///< Direct initialization + IK_DirectList, ///< Direct list-initialization + IK_Copy, ///< Copy initialization + IK_Default, ///< Default initialization + IK_Value ///< Value initialization }; private: - /// \brief The kind of initialization that we're storing. - enum StoredInitKind { - SIK_Direct = IK_Direct, ///< Direct initialization - SIK_Copy = IK_Copy, ///< Copy initialization - SIK_Default = IK_Default, ///< Default initialization - SIK_Value = IK_Value, ///< Value initialization - SIK_ImplicitValue, ///< Implicit value initialization - SIK_DirectCast, ///< Direct initialization due to a cast - /// \brief Direct initialization due to a C-style cast. - SIK_DirectCStyleCast, - /// \brief Direct initialization due to a functional-style cast. - SIK_DirectFunctionalCast + /// \brief The context of the initialization. + enum InitContext { + IC_Normal, ///< Normal context + IC_ExplicitConvs, ///< Normal context, but allows explicit conversion funcs + IC_Implicit, ///< Implicit context (value initialization) + IC_StaticCast, ///< Static cast context + IC_CStyleCast, ///< C-style cast context + IC_FunctionalCast ///< Functional cast context }; /// \brief The kind of initialization being performed. - StoredInitKind Kind; + InitKind Kind : 8; + + /// \brief The context of the initialization. + InitContext Context : 8; /// \brief The source locations involved in the initialization. SourceLocation Locations[3]; - InitializationKind(StoredInitKind Kind, SourceLocation Loc1, + InitializationKind(InitKind Kind, InitContext Context, SourceLocation Loc1, SourceLocation Loc2, SourceLocation Loc3) - : Kind(Kind) + : Kind(Kind), Context(Context) { Locations[0] = Loc1; Locations[1] = Loc2; @@ -367,41 +406,53 @@ public: static InitializationKind CreateDirect(SourceLocation InitLoc, SourceLocation LParenLoc, SourceLocation RParenLoc) { - return InitializationKind(SIK_Direct, InitLoc, LParenLoc, RParenLoc); + return InitializationKind(IK_Direct, IC_Normal, + InitLoc, LParenLoc, RParenLoc); + } + + static InitializationKind CreateDirectList(SourceLocation InitLoc) { + return InitializationKind(IK_DirectList, IC_Normal, + InitLoc, InitLoc, InitLoc); } /// \brief Create a direct initialization due to a cast that isn't a C-style /// or functional cast. static InitializationKind CreateCast(SourceRange TypeRange) { - return InitializationKind(SIK_DirectCast, - TypeRange.getBegin(), TypeRange.getBegin(), - TypeRange.getEnd()); + return InitializationKind(IK_Direct, IC_StaticCast, TypeRange.getBegin(), + TypeRange.getBegin(), TypeRange.getEnd()); } /// \brief Create a direct initialization for a C-style cast. static InitializationKind CreateCStyleCast(SourceLocation StartLoc, - SourceRange TypeRange) { - return InitializationKind(SIK_DirectCStyleCast, - StartLoc, TypeRange.getBegin(), + SourceRange TypeRange, + bool InitList) { + // C++ cast syntax doesn't permit init lists, but C compound literals are + // exactly that. + return InitializationKind(InitList ? IK_DirectList : IK_Direct, + IC_CStyleCast, StartLoc, TypeRange.getBegin(), TypeRange.getEnd()); } /// \brief Create a direct initialization for a functional cast. - static InitializationKind CreateFunctionalCast(SourceRange TypeRange) { - return InitializationKind(SIK_DirectFunctionalCast, - TypeRange.getBegin(), TypeRange.getBegin(), - TypeRange.getEnd()); + static InitializationKind CreateFunctionalCast(SourceRange TypeRange, + bool InitList) { + return InitializationKind(InitList ? IK_DirectList : IK_Direct, + IC_FunctionalCast, TypeRange.getBegin(), + TypeRange.getBegin(), TypeRange.getEnd()); } /// \brief Create a copy initialization. static InitializationKind CreateCopy(SourceLocation InitLoc, - SourceLocation EqualLoc) { - return InitializationKind(SIK_Copy, InitLoc, EqualLoc, EqualLoc); + SourceLocation EqualLoc, + bool AllowExplicitConvs = false) { + return InitializationKind(IK_Copy, + AllowExplicitConvs? IC_ExplicitConvs : IC_Normal, + InitLoc, EqualLoc, EqualLoc); } /// \brief Create a default initialization. static InitializationKind CreateDefault(SourceLocation InitLoc) { - return InitializationKind(SIK_Default, InitLoc, InitLoc, InitLoc); + return InitializationKind(IK_Default, IC_Normal, InitLoc, InitLoc, InitLoc); } /// \brief Create a value initialization. @@ -409,46 +460,39 @@ public: SourceLocation LParenLoc, SourceLocation RParenLoc, bool isImplicit = false) { - return InitializationKind(isImplicit? SIK_ImplicitValue : SIK_Value, + return InitializationKind(IK_Value, isImplicit ? IC_Implicit : IC_Normal, InitLoc, LParenLoc, RParenLoc); } /// \brief Determine the initialization kind. InitKind getKind() const { - if (Kind > SIK_ImplicitValue) - return IK_Direct; - if (Kind == SIK_ImplicitValue) - return IK_Value; - - return (InitKind)Kind; + return Kind; } /// \brief Determine whether this initialization is an explicit cast. bool isExplicitCast() const { - return Kind == SIK_DirectCast || - Kind == SIK_DirectCStyleCast || - Kind == SIK_DirectFunctionalCast; + return Context >= IC_StaticCast; } /// \brief Determine whether this initialization is a C-style cast. bool isCStyleOrFunctionalCast() const { - return Kind == SIK_DirectCStyleCast || Kind == SIK_DirectFunctionalCast; + return Context >= IC_CStyleCast; } - /// brief Determine whether this is a C-style cast. + /// \brief Determine whether this is a C-style cast. bool isCStyleCast() const { - return Kind == SIK_DirectCStyleCast; + return Context == IC_CStyleCast; } - /// brief Determine whether this is a functional-style cast. + /// \brief Determine whether this is a functional-style cast. bool isFunctionalCast() const { - return Kind == SIK_DirectFunctionalCast; + return Context == IC_FunctionalCast; } /// \brief Determine whether this initialization is an implicit /// value-initialization, e.g., as occurs during aggregate /// initialization. - bool isImplicitValueInit() const { return Kind == SIK_ImplicitValue; } + bool isImplicitValueInit() const { return Context == IC_Implicit; } /// \brief Retrieve the location at which initialization is occurring. SourceLocation getLocation() const { return Locations[0]; } @@ -461,16 +505,26 @@ public: /// \brief Retrieve the location of the equal sign for copy initialization /// (if present). SourceLocation getEqualLoc() const { - assert(Kind == SIK_Copy && "Only copy initialization has an '='"); + assert(Kind == IK_Copy && "Only copy initialization has an '='"); return Locations[1]; } - - bool isCopyInit() const { return Kind == SIK_Copy; } + + bool isCopyInit() const { return Kind == IK_Copy; } + + /// \brief Retrieve whether this initialization allows the use of explicit + /// constructors. + bool AllowExplicit() const { return !isCopyInit(); } + + /// \brief Retrieve whether this initialization allows the use of explicit + /// conversion functions. + bool allowExplicitConversionFunctions() const { + return !isCopyInit() || Context == IC_ExplicitConvs; + } /// \brief Retrieve the source range containing the locations of the open /// and closing parentheses for value and direct initializations. SourceRange getParenRange() const { - assert((getKind() == IK_Direct || Kind == SIK_Value) && + assert((Kind == IK_Direct || Kind == IK_Value) && "Only direct- and value-initialization have parentheses"); return SourceRange(Locations[1], Locations[2]); } @@ -530,6 +584,10 @@ public: SK_ListInitialization, /// \brief Perform list-initialization with a constructor. SK_ListConstructorCall, + /// \brief Unwrap the single-element initializer list for a reference. + SK_UnwrapInitList, + /// \brief Rewrap the single-element initializer list for a reference. + SK_RewrapInitList, /// \brief Perform initialization via a constructor. SK_ConstructorInitialization, /// \brief Zero-initialize the object @@ -544,12 +602,17 @@ public: /// \brief Array initialization (from an array rvalue). /// This is a GNU C extension. SK_ArrayInit, + /// \brief Array initialization from a parenthesized initializer list. + /// This is a GNU C++ extension. + SK_ParenthesizedArrayInit, /// \brief Pass an object by indirect copy-and-restore. SK_PassByIndirectCopyRestore, /// \brief Pass an object by indirect restore. SK_PassByIndirectRestore, /// \brief Produce an Objective-C object pointer. - SK_ProduceObjCObject + SK_ProduceObjCObject, + /// \brief Construct a std::initializer_list from an initializer list. + SK_StdInitializerList }; /// \brief A single step in the initialization sequence. @@ -579,8 +642,12 @@ public: } Function; /// \brief When Kind = SK_ConversionSequence, the implicit conversion - /// sequence + /// sequence. ImplicitConversionSequence *ICS; + + /// \brief When Kind = SK_RewrapInitList, the syntactic form of the + /// wrapping list. + InitListExpr *WrappingSyntacticList; }; void Destroy(); @@ -635,14 +702,26 @@ public: FK_InitListBadDestinationType, /// \brief Overloading for a user-defined conversion failed. FK_UserConversionOverloadFailed, - /// \brief Overloaded for initialization by constructor failed. + /// \brief Overloading for initialization by constructor failed. FK_ConstructorOverloadFailed, + /// \brief Overloading for list-initialization by constructor failed. + FK_ListConstructorOverloadFailed, /// \brief Default-initialization of a 'const' object. FK_DefaultInitOfConst, /// \brief Initialization of an incomplete type. FK_Incomplete, + /// \brief Variable-length array must not have an initializer. + FK_VariableLengthArrayHasInitializer, /// \brief List initialization failed at some point. - FK_ListInitializationFailed + FK_ListInitializationFailed, + /// \brief Initializer has a placeholder type which cannot be + /// resolved by initialization. + FK_PlaceholderType, + /// \brief Failed to initialize a std::initializer_list because copy + /// construction of some element failed. + FK_InitListElementCopyFailure, + /// \brief List-copy-initialization chose an explicit constructor. + FK_ExplicitConstructor }; private: @@ -655,6 +734,9 @@ private: /// \brief The candidate set created when initialization failed. OverloadCandidateSet FailedCandidateSet; + /// \brief The incomplete type that caused a failure. + QualType FailedIncompleteType; + /// \brief Prints a follow-up note that highlights the location of /// the initialized entity, if it's remote. void PrintInitLocationNote(Sema &S, const InitializedEntity &Entity); @@ -763,8 +845,9 @@ public: /// \param Function the function to which the overloaded function reference /// resolves. void AddAddressOverloadResolutionStep(FunctionDecl *Function, - DeclAccessPair Found); - + DeclAccessPair Found, + bool HadMultipleCandidates); + /// \brief Add a new step in the initialization that performs a derived-to- /// base cast. /// @@ -801,8 +884,9 @@ public: /// a constructor or a conversion function. void AddUserConversionStep(FunctionDecl *Function, DeclAccessPair FoundDecl, - QualType T); - + QualType T, + bool HadMultipleCandidates); + /// \brief Add a new step that performs a qualification conversion to the /// given type. void AddQualificationConversionStep(QualType Ty, @@ -812,17 +896,23 @@ public: void AddConversionSequenceStep(const ImplicitConversionSequence &ICS, QualType T); - /// \brief Add a list-initialiation step. + /// \brief Add a list-initialization step. void AddListInitializationStep(QualType T); /// \brief Add a constructor-initialization step. + /// + /// \arg FromInitList The constructor call is syntactically an initializer + /// list. + /// \arg AsInitList The constructor is called as an init list constructor. void AddConstructorInitializationStep(CXXConstructorDecl *Constructor, AccessSpecifier Access, - QualType T); + QualType T, + bool HadMultipleCandidates, + bool FromInitList, bool AsInitList); /// \brief Add a zero-initialization step. void AddZeroInitializationStep(QualType T); - + /// \brief Add a C assignment step. // // FIXME: It isn't clear whether this should ever be needed; @@ -840,6 +930,9 @@ public: /// \brief Add an array initialization step. void AddArrayInitStep(QualType T); + /// \brief Add a parenthesized array initialization step. + void AddParenthesizedArrayInitStep(QualType T); + /// \brief Add a step to pass an object by indirect copy-restore. void AddPassByIndirectCopyRestoreStep(QualType T, bool shouldCopy); @@ -847,10 +940,20 @@ public: /// retaining it). void AddProduceObjCObjectStep(QualType T); + /// \brief Add a step to construct a std::initializer_list object from an + /// initializer list. + void AddStdInitializerListConstructionStep(QualType T); + + /// \brief Add steps to unwrap a initializer list for a reference around a + /// single element and rewrap it at the end. + void RewrapReferenceInitList(QualType T, InitListExpr *Syntactic); + /// \brief Note that this initialization sequence failed. void SetFailed(FailureKind Failure) { SequenceKind = FailedSequence; this->Failure = Failure; + assert((Failure != FK_Incomplete || !FailedIncompleteType.isNull()) && + "Incomplete type failure requires a type!"); } /// \brief Note that this initialization sequence failed due to failed @@ -863,12 +966,19 @@ public: return FailedCandidateSet; } - /// brief Get the overloading result, for when the initialization + /// \brief Get the overloading result, for when the initialization /// sequence failed due to a bad overload. OverloadingResult getFailedOverloadResult() const { return FailedOverloadResult; } + /// \brief Note that this initialization sequence failed due to an + /// incomplete type. + void setIncompleteTypeFailure(QualType IncompleteType) { + FailedIncompleteType = IncompleteType; + SetFailed(FK_Incomplete); + } + /// \brief Determine why initialization failed. FailureKind getFailureKind() const { assert(Failed() && "Not an initialization failure!"); |