[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