[cfe-commits] r140457 - in /cfe/trunk: include/clang/Sema/Initialization.h include/clang/Sema/Overload.h include/clang/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaOverload.cpp
Douglas Gregor
dgregor at apple.com
Mon Sep 26 07:58:29 PDT 2011
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
More information about the cfe-commits
mailing list