On Sep 24, 2011, at 10:48 AM, Sebastian Redl wrote: > Author: cornedbee > Date: Sat Sep 24 12:48:00 2011 > New Revision: 140457 > > URL: http://llvm.org/viewvc/llvm-project?rev=140457&view=rev > Log: > Give InitListChecker a verification-only mode, where it neither emits > diagnostics nor > builds a semantic (structured) initializer list, just reports on whether it > can match > the given list to the target type. > Use this mode for doing init list checking in the initial step of > initialization, which > will eventually allow us to do overload resolution based on the outcome.
Cool. Comments below. > Modified: > cfe/trunk/include/clang/Sema/Initialization.h > cfe/trunk/include/clang/Sema/Overload.h > cfe/trunk/include/clang/Sema/Sema.h > cfe/trunk/lib/Sema/SemaExpr.cpp > cfe/trunk/lib/Sema/SemaInit.cpp > cfe/trunk/lib/Sema/SemaOverload.cpp > > Modified: cfe/trunk/include/clang/Sema/Initialization.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=140457&r1=140456&r2=140457&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Sema/Initialization.h (original) > +++ cfe/trunk/include/clang/Sema/Initialization.h Sat Sep 24 12:48:00 2011 > @@ -810,7 +810,7 @@ > void AddConversionSequenceStep(const ImplicitConversionSequence &ICS, > QualType T); > > - /// \brief Add a list-initialiation step > + /// \brief Add a list-initialiation step. > void AddListInitializationStep(QualType T); > > /// \brief Add a constructor-initialization step. > > Modified: cfe/trunk/include/clang/Sema/Overload.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Overload.h?rev=140457&r1=140456&r2=140457&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Sema/Overload.h (original) > +++ cfe/trunk/include/clang/Sema/Overload.h Sat Sep 24 12:48:00 2011 > @@ -464,6 +464,7 @@ > bool isEllipsis() const { return getKind() == EllipsisConversion; } > bool isAmbiguous() const { return getKind() == AmbiguousConversion; } > bool isUserDefined() const { return getKind() == UserDefinedConversion; } > + bool isFailure() const { return isBad() || isAmbiguous(); } > > /// Determines whether this conversion sequence has been > /// initialized. Most operations should never need to query > > Modified: cfe/trunk/include/clang/Sema/Sema.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=140457&r1=140456&r2=140457&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Sema/Sema.h (original) > +++ cfe/trunk/include/clang/Sema/Sema.h Sat Sep 24 12:48:00 2011 > @@ -1383,7 +1383,7 @@ > QualType ResultType, > Expr *Value, > bool AllowNRVO = true); > - > + > bool CanPerformCopyInitialization(const InitializedEntity &Entity, > ExprResult Init); > ExprResult PerformCopyInitialization(const InitializedEntity &Entity, > @@ -2217,8 +2217,9 @@ > > //===--------------------------------------------------------------------===// > // Expression Parsing Callbacks: SemaExpr.cpp. > > - bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, > - const ObjCInterfaceDecl *UnknownObjCClass=0); > + bool CanUseDecl(NamedDecl *D); > + bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, > + const ObjCInterfaceDecl *UnknownObjCClass = 0); > std::string getDeletedOrUnavailableSuffix(const FunctionDecl *FD); > bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD, > ObjCMethodDecl *Getter, > @@ -5580,7 +5581,8 @@ > // CheckAssignmentOperands, and ActOnReturnStmt. Prior to type checking, > // this routine performs the default function/array converions. > AssignConvertType CheckSingleAssignmentConstraints(QualType LHSType, > - ExprResult &RHS); > + ExprResult &RHS, > + bool Diagnose = true); > > // \brief If the lhs type is a transparent union, check whether we > // can initialize the transparent union with the given expression. > @@ -5593,11 +5595,13 @@ > > ExprResult PerformImplicitConversion(Expr *From, QualType ToType, > AssignmentAction Action, > - bool AllowExplicit = false); > + bool AllowExplicit = false, > + bool Diagnose = true); > ExprResult PerformImplicitConversion(Expr *From, QualType ToType, > AssignmentAction Action, > bool AllowExplicit, > - ImplicitConversionSequence& ICS); > + ImplicitConversionSequence& ICS, > + bool Diagnose = true); > ExprResult PerformImplicitConversion(Expr *From, QualType ToType, > const ImplicitConversionSequence& ICS, > AssignmentAction Action, Why did you add the Diagnose flag to PerformImplicitConversion? It doesn't seem to be used at all, and probably shouldn't even be there: if the intent is to check whether a conversion would work, wouldn't it be better to make SemaOverload.cpp's TryImplicitConversion available? > Modified: cfe/trunk/lib/Sema/SemaExpr.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=140457&r1=140456&r2=140457&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) > +++ cfe/trunk/lib/Sema/SemaExpr.cpp Sat Sep 24 12:48:00 2011 > @@ -41,6 +41,20 @@ > using namespace clang; > using namespace sema; > > +/// \brief Determine whether the use of this declaration is valid, without > +/// emitting diagnostics. > +bool Sema::CanUseDecl(NamedDecl *D) { > + // See if this is an auto-typed variable whose initializer we are parsing. > + if (ParsingInitForAutoVars.count(D)) > + return false; > + > + // See if this is a deleted function. > + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { > + if (FD->isDeleted()) > + return false; > + } > + return true; > +} This should also check availability, and return false if the declaration is unavailable. > Modified: cfe/trunk/lib/Sema/SemaInit.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=140457&r1=140456&r2=140457&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaInit.cpp (original) > +++ cfe/trunk/lib/Sema/SemaInit.cpp Sat Sep 24 12:48:00 2011 > @@ -169,6 +169,7 @@ > class InitListChecker { > Sema &SemaRef; > bool hadError; > + bool VerifyOnly; // no diagnostics, no structure building > std::map<InitListExpr *, InitListExpr *> SyntacticToSemantic; > InitListExpr *FullyStructuredList; > > @@ -257,7 +258,7 @@ > bool TopLevelObject); > public: > InitListChecker(Sema &S, const InitializedEntity &Entity, > - InitListExpr *IL, QualType &T); > + InitListExpr *IL, QualType &T, bool VerifyOnly); > bool HadError() { return hadError; } > // @brief Retrieves the fully-structured initializer list used for > @@ -450,8 +451,9 @@ > > > InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity, > - InitListExpr *IL, QualType &T) > - : SemaRef(S) { > + InitListExpr *IL, QualType &T, > + bool VerifyOnly) > + : SemaRef(S), VerifyOnly(VerifyOnly) { > hadError = false; > > unsigned newIndex = 0; > @@ -462,7 +464,7 @@ > FullyStructuredList, newStructuredIndex, > /*TopLevelObject=*/true); > > - if (!hadError) { > + if (!hadError && !VerifyOnly) { > bool RequiresSecondPass = false; > FillInValueInitializations(Entity, FullyStructuredList, > RequiresSecondPass); It seems like we do still need to check the value initializations (to make sure there is a suitable default constructor for members that haven't been initialized), although we don't want to build anything. > +static DesignatedInitExpr *CloneDesignatedInitExpr(Sema &SemaRef, > + DesignatedInitExpr *DIE) { > + unsigned NumIndexExprs = DIE->getNumSubExprs() - 1; > + 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.data(), > + NumIndexExprs, DIE->getEqualOrColonLoc(), > + DIE->usesGNUSyntax(), DIE->getInit()); > +} > + > /// @brief Check the well-formedness of a C99 designated initializer. > /// > /// Determines whether the designated initializer @p DIE, which > @@ -1426,14 +1509,14 @@ > bool > InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, > InitListExpr *IList, > - DesignatedInitExpr *DIE, > - unsigned DesigIdx, > - QualType &CurrentObjectType, > - RecordDecl::field_iterator *NextField, > - llvm::APSInt *NextElementIndex, > - unsigned &Index, > - InitListExpr *StructuredList, > - unsigned &StructuredIndex, > + DesignatedInitExpr *DIE, > + unsigned DesigIdx, > + QualType &CurrentObjectType, > + RecordDecl::field_iterator > *NextField, > + llvm::APSInt *NextElementIndex, > + unsigned &Index, > + InitListExpr *StructuredList, > + unsigned &StructuredIndex, > bool FinishSubobjectInit, > bool TopLevelObject) { > if (DesigIdx == DIE->size()) { > @@ -1458,19 +1541,21 @@ > return hadError && !prevHadError; > } > > - bool IsFirstDesignator = (DesigIdx == 0); > - assert((IsFirstDesignator || StructuredList) && > - "Need a non-designated initializer list to start from"); > - > DesignatedInitExpr::Designator *D = DIE->getDesignator(DesigIdx); > - // Determine the structural initializer list that corresponds to the > - // current subobject. > - StructuredList = IsFirstDesignator? SyntacticToSemantic[IList] > - : getStructuredSubobjectInit(IList, Index, CurrentObjectType, > - StructuredList, StructuredIndex, > - SourceRange(D->getStartLocation(), > - > DIE->getSourceRange().getEnd())); > - assert(StructuredList && "Expected a structured initializer list"); > + bool IsFirstDesignator = (DesigIdx == 0); > + if (!VerifyOnly) { > + assert((IsFirstDesignator || StructuredList) && > + "Need a non-designated initializer list to start from"); > + > + // Determine the structural initializer list that corresponds to the > + // current subobject. > + StructuredList = IsFirstDesignator? SyntacticToSemantic[IList] > + : getStructuredSubobjectInit(IList, Index, CurrentObjectType, > + StructuredList, StructuredIndex, > + SourceRange(D->getStartLocation(), > + > DIE->getSourceRange().getEnd())); > + assert(StructuredList && "Expected a structured initializer list"); > + } > > if (D->isFieldDesignator()) { > // C99 6.7.8p7: > @@ -1487,8 +1572,9 @@ > SourceLocation Loc = D->getDotLoc(); > if (Loc.isInvalid()) > Loc = D->getFieldLoc(); > - SemaRef.Diag(Loc, diag::err_field_designator_non_aggr) > - << SemaRef.getLangOptions().CPlusPlus << CurrentObjectType; > + if (!VerifyOnly) > + SemaRef.Diag(Loc, diag::err_field_designator_non_aggr) > + << SemaRef.getLangOptions().CPlusPlus << CurrentObjectType; > ++Index; > return true; > } > @@ -1511,6 +1597,9 @@ > if (!KnownField && Field->isAnonymousStructOrUnion()) { > if (IndirectFieldDecl *IF = > FindIndirectFieldDesignator(*Field, FieldName)) { > + // In verify mode, don't modify the original. > + if (VerifyOnly) > + DIE = CloneDesignatedInitExpr(SemaRef, DIE); > ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, IF); It would be a little less wasteful, memory-wise, if we could do the expand + clone in one operation, so that we don't end up making a copy of the DesignatedInitExpr storage and then throwing that memory away when we reallocate. - Doug _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
