[cfe-commits] r91050 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaInit.h test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp

Douglas Gregor dgregor at apple.com
Thu Dec 10 09:56:55 PST 2009


Author: dgregor
Date: Thu Dec 10 11:56:55 2009
New Revision: 91050

URL: http://llvm.org/viewvc/llvm-project?rev=91050&view=rev
Log:
Move initialization via initializer list over to InitializationSequences.

Added:
    cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp   (with props)
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/lib/Sema/SemaInit.h

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=91050&r1=91049&r2=91050&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Dec 10 11:56:55 2009
@@ -542,7 +542,11 @@
 def err_reference_bind_failed : Error<
   "reference to type %0 could not bind to an %select{rvalue|lvalue}1 of type "
   "%2">;
-
+def err_reference_bind_init_list : Error<
+  "reference to type %0 cannot bind to an initializer list">;
+def err_init_list_bad_dest_type : Error<
+  "%select{|non-aggregate }0type %1 cannot be initialized with an initializer "
+  "list">;
 
 // FIXME: passing in an English string as %1!
 def err_reference_init_drops_quals : Error<

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=91050&r1=91049&r2=91050&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Dec 10 11:56:55 2009
@@ -3499,7 +3499,8 @@
       Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
       VDecl->setInvalidDecl();
     } else if (!VDecl->isInvalidDecl()) {
-      if (VDecl->getType()->isReferenceType()) {
+      if (VDecl->getType()->isReferenceType()
+          || isa<InitListExpr>(Init)) {
         InitializedEntity Entity
           = InitializedEntity::InitializeVariable(VDecl);
 
@@ -3513,7 +3514,8 @@
         InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
         if (InitSeq) {
           OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
-                                      MultiExprArg(*this, (void**)&Init, 1));
+                                           MultiExprArg(*this, (void**)&Init, 1),
+                                                    &DclT);
           if (Result.isInvalid()) {
             VDecl->setInvalidDecl();
             return;
@@ -3524,8 +3526,7 @@
           InitSeq.Diagnose(*this, Entity, Kind, &Init, 1);
           VDecl->setInvalidDecl();
           return;
-        }
-        
+        }    
       } else if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
                                        VDecl->getDeclName(), DirectInit))
         VDecl->setInvalidDecl();

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=91050&r1=91049&r2=91050&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Dec 10 11:56:55 2009
@@ -1968,6 +1968,7 @@
   case SK_UserConversion:
   case SK_QualificationConversionRValue:
   case SK_QualificationConversionLValue:
+  case SK_ListInitialization:
     break;
     
   case SK_ConversionSequence:
@@ -2027,6 +2028,13 @@
   Steps.push_back(S);
 }
 
+void InitializationSequence::AddListInitializationStep(QualType T) {
+  Step S;
+  S.Kind = SK_ListInitialization;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
 void InitializationSequence::SetOverloadFailure(FailureKind Failure, 
                                                 OverloadingResult Result) {
   SequenceKind = FailedSequence;
@@ -2039,16 +2047,51 @@
 //===----------------------------------------------------------------------===//
 
 /// \brief Attempt list initialization (C++0x [dcl.init.list]) 
-static bool TryListInitialization(Sema &S, 
+static void TryListInitialization(Sema &S, 
                                   const InitializedEntity &Entity,
                                   const InitializationKind &Kind,
                                   InitListExpr *InitList,
                                   InitializationSequence &Sequence) {
-  // FIXME: For now, it is safe to assume that list initialization always
-  // works. When we actually perform list initialization, we'll do all of the
-  // necessary checking.
-  // C++0x initializer lists will force us to perform more checking here.
-  return true;
+  // FIXME: We only perform rudimentary checking of list
+  // initializations at this point, then assume that any list
+  // initialization of an array, aggregate, or scalar will be
+  // well-formed. We we actually "perform" list initialization, we'll
+  // do all of the necessary checking.  C++0x initializer lists will
+  // force us to perform more checking here.
+  Sequence.setSequenceKind(InitializationSequence::ListInitialization);
+
+  QualType DestType = Entity.getType().getType();
+
+  // C++ [dcl.init]p13:
+  //   If T is a scalar type, then a declaration of the form 
+  //
+  //     T x = { a };
+  //
+  //   is equivalent to
+  //
+  //     T x = a;
+  if (DestType->isScalarType()) {
+    if (InitList->getNumInits() > 1 && S.getLangOptions().CPlusPlus) {
+      Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForScalar);
+      return;
+    }
+
+    // Assume scalar initialization from a single value works.
+  } else if (DestType->isAggregateType()) {
+    // Assume aggregate initialization works.
+  } else if (DestType->isVectorType()) {
+    // Assume vector initialization works.
+  } else if (DestType->isReferenceType()) {
+    // FIXME: C++0x defines behavior for this.
+    Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
+    return;
+  } else if (DestType->isRecordType()) {
+    // FIXME: C++0x defines behavior for this
+    Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
+  }
+
+  // Add a general "list initialization" step.
+  Sequence.AddListInitializationStep(DestType);
 }
 
 /// \brief Try a reference initialization that involves calling a conversion
@@ -2485,6 +2528,7 @@
   //       list-initialized (8.5.4).
   if (InitListExpr *InitList = dyn_cast_or_null<InitListExpr>(Initializer)) {
     TryListInitialization(S, Entity, Kind, InitList, *this);
+    return;
   }
   
   //     - If the destination type is a reference type, see 8.5.3.
@@ -2578,7 +2622,8 @@
 InitializationSequence::Perform(Sema &S,
                                 const InitializedEntity &Entity,
                                 const InitializationKind &Kind,
-                                Action::MultiExprArg Args) {
+                                Action::MultiExprArg Args,
+                                QualType *ResultType) {
   if (SequenceKind == FailedSequence) {
     unsigned NumArgs = Args.size();
     Diagnose(S, Entity, Kind, (Expr **)Args.release(), NumArgs);
@@ -2586,6 +2631,41 @@
   }
   
   if (SequenceKind == DependentSequence) {
+    // If the declaration is a non-dependent, incomplete array type
+    // that has an initializer, then its type will be completed once
+    // the initializer is instantiated.
+    if (ResultType && !Entity.getType().getType()->isDependentType() &&
+        Args.size() == 1) {
+      QualType DeclType = Entity.getType().getType();
+      if (const IncompleteArrayType *ArrayT
+                           = S.Context.getAsIncompleteArrayType(DeclType)) {
+        // FIXME: We don't currently have the ability to accurately
+        // compute the length of an initializer list without
+        // performing full type-checking of the initializer list
+        // (since we have to determine where braces are implicitly
+        // introduced and such).  So, we fall back to making the array
+        // type a dependently-sized array type with no specified
+        // bound.
+        if (isa<InitListExpr>((Expr *)Args.get()[0])) {
+          SourceRange Brackets;
+          // Scavange the location of the brackets from the entity, if we can.
+          if (isa<IncompleteArrayTypeLoc>(Entity.getType())) {
+            IncompleteArrayTypeLoc ArrayLoc
+              = cast<IncompleteArrayTypeLoc>(Entity.getType());
+            Brackets = ArrayLoc.getBracketsRange();
+          }
+
+          *ResultType
+            = S.Context.getDependentSizedArrayType(ArrayT->getElementType(),
+                                                   /*NumElts=*/0,
+                                                   ArrayT->getSizeModifier(),
+                                       ArrayT->getIndexTypeCVRQualifiers(),
+                                                   Brackets);
+        }
+
+      }
+    }
+
     if (Kind.getKind() == InitializationKind::IK_Copy)
       return Sema::OwningExprResult(S, Args.release()[0]);
 
@@ -2598,6 +2678,8 @@
   }
 
   QualType DestType = Entity.getType().getType().getNonReferenceType();
+  if (ResultType)
+    *ResultType = Entity.getType().getType();
 
   Sema::OwningExprResult CurInit(S);
   // For copy initialization and any other initialization forms that
@@ -2754,6 +2836,17 @@
       CurInit.release();
       CurInit = S.Owned(CurInitExpr);        
       break;
+
+    case SK_ListInitialization: {
+      InitListExpr *InitList = cast<InitListExpr>(CurInitExpr);
+      QualType Ty = Step->Type;
+      if (S.CheckInitList(InitList, ResultType? *ResultType : Ty))
+        return S.ExprError();
+
+      CurInit.release();
+      CurInit = S.Owned(InitList);
+      break;
+    }
     }
   }
   
@@ -2865,7 +2958,27 @@
       << (Args[0]->isLvalue(S.Context) == Expr::LV_Valid)
       << Args[0]->getType()
       << Args[0]->getSourceRange();
-      break;
+    break;
+
+  case FK_TooManyInitsForScalar: {
+    InitListExpr *InitList = cast<InitListExpr>(Args[0]);
+
+    S.Diag(Kind.getLocation(), diag::err_excess_initializers)
+      << /*scalar=*/2 
+      << SourceRange(InitList->getInit(1)->getLocStart(),
+                     InitList->getLocEnd());
+    break;
+  }
+
+  case FK_ReferenceBindingToInitList:
+    S.Diag(Kind.getLocation(), diag::err_reference_bind_init_list)
+      << DestType.getNonReferenceType() << Args[0]->getSourceRange();
+    break;
+
+  case FK_InitListBadDestinationType:
+    S.Diag(Kind.getLocation(), diag::err_init_list_bad_dest_type)
+      << (DestType->isRecordType()) << DestType << Args[0]->getSourceRange();
+    break;
   }
   
   return true;

Modified: cfe/trunk/lib/Sema/SemaInit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.h?rev=91050&r1=91049&r2=91050&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.h (original)
+++ cfe/trunk/lib/Sema/SemaInit.h Thu Dec 10 11:56:55 2009
@@ -1,4 +1,4 @@
-//===--- SemaInit.h - Semantic Analysis for Initializers ------------------===//
+//===--- SemaInit.h - Semantic Analysis for Initializers --------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -304,7 +304,10 @@
     DependentSequence,
 
     /// \brief A reference binding.
-    ReferenceBinding
+    ReferenceBinding,
+
+    /// \brief List initialization
+    ListInitialization
   };
   
   /// \brief Describes the kind of a particular step in an initialization
@@ -329,7 +332,9 @@
     /// \brief Perform a qualification conversion, producing an lvalue.
     SK_QualificationConversionLValue,
     /// \brief Perform an implicit conversion sequence.
-    SK_ConversionSequence
+    SK_ConversionSequence,
+    /// \brief Perform list-initialization
+    SK_ListInitialization
   };
   
   /// \brief A single step in the initialization sequence.
@@ -388,7 +393,14 @@
     /// \brief Reference binding failed.
     FK_ReferenceInitFailed,
     /// \brief Implicit conversion failed.
-    FK_ConversionFailed
+    FK_ConversionFailed,
+    /// \brief Too many initializers for scalar
+    FK_TooManyInitsForScalar,
+    /// \brief Reference initialization from an initializer list
+    FK_ReferenceBindingToInitList,
+    /// \brief Initialization of some unused destination type with an
+    /// initializer list.
+    FK_InitListBadDestinationType
   };
   
 private:
@@ -437,13 +449,20 @@
   /// \param Args the argument(s) provided for initialization, ownership of
   /// which is transfered into the routine.
   ///
+  /// \param ResultType if non-NULL, will be set to the type of the
+  /// initialized object, which is the type of the declaration in most
+  /// cases. However, when the initialized object is a variable of
+  /// incomplete array type and the initializer is an initializer
+  /// list, this type will be set to the completed array type.
+  ///
   /// \returns an expression that performs the actual object initialization, if
   /// the initialization is well-formed. Otherwise, emits diagnostics
   /// and returns an invalid expression.
   Action::OwningExprResult Perform(Sema &S,
                                    const InitializedEntity &Entity,
                                    const InitializationKind &Kind,
-                                   Action::MultiExprArg Args);
+                                   Action::MultiExprArg Args,
+                                   QualType *ResultType = 0);
   
   /// \brief Diagnose an potentially-invalid initialization sequence.
   ///
@@ -501,7 +520,10 @@
   /// \brief Add a new step that applies an implicit conversion sequence.
   void AddConversionSequenceStep(const ImplicitConversionSequence &ICS,
                                  QualType T);
-  
+
+  /// \brief Add a list-initialiation step  
+  void AddListInitializationStep(QualType T);
+
   /// \brief Note that this initialization sequence failed.
   void SetFailed(FailureKind Failure) {
     SequenceKind = FailedSequence;

Added: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp?rev=91050&view=auto

==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp (added)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp Thu Dec 10 11:56:55 2009
@@ -0,0 +1,5 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+void f0() {
+  int &ir = { 17 }; // expected-error{{reference to type 'int' cannot bind to an initializer list}}
+}

Propchange: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp

------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp

------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list