]> granicus.if.org Git - clang/commitdiff
Change the way we store initialization kinds so that all direct inits can distinguish...
authorSebastian Redl <sebastian.redl@getdesigned.at>
Sun, 12 Feb 2012 16:37:36 +0000 (16:37 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Sun, 12 Feb 2012 16:37:36 +0000 (16:37 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150343 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Initialization.h
lib/Sema/SemaCast.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaInit.cpp
test/SemaCXX/cxx0x-initializer-aggregates.cpp
test/SemaCXX/cxx0x-initializer-references.cpp
test/SemaCXX/cxx0x-initializer-scalars.cpp
test/SemaCXX/generalized-initializers.cpp [deleted file]

index dde46a2ff41553d7340c46f7bc03a6b7f8f04662..3d8dfa4d5fc70a1ee762596c21e38c386a4273f2 100644 (file)
@@ -334,30 +334,27 @@ public:
   };
   
 private:
-  /// \brief The kind of initialization that we're storing.
-  enum StoredInitKind {
-    SIK_Direct = IK_Direct,         ///< Direct initialization
-    SIK_DirectList = IK_DirectList, ///< Direct list-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_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;
@@ -369,45 +366,50 @@ 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(SIK_DirectList, InitLoc, InitLoc, 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);
+    return InitializationKind(IK_Copy, 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.
@@ -415,46 +417,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]; }
@@ -467,11 +462,11 @@ 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.
@@ -480,7 +475,7 @@ public:
   /// \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]);
   }
index 545305cfc42e5258dbc2def9445336d1938dbbf7..c74bb9a067d39757923565a900dbb38c64ae66d3 100644 (file)
@@ -320,11 +320,13 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
   if (!destType->isRecordType() && !srcType->isRecordType())
     return false;
 
+  bool initList = isa<InitListExpr>(src);
   InitializedEntity entity = InitializedEntity::InitializeTemporary(destType);
   InitializationKind initKind
     = (CT == CT_CStyle)? InitializationKind::CreateCStyleCast(range.getBegin(),
-                                                              range)
-    : (CT == CT_Functional)? InitializationKind::CreateFunctionalCast(range)
+                                                              range, initList)
+    : (CT == CT_Functional)? InitializationKind::CreateFunctionalCast(range,
+                                                                      initList)
     : InitializationKind::CreateCast(/*type range?*/ range);
   InitializationSequence sequence(S, entity, initKind, &src, 1);
 
@@ -1301,13 +1303,16 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
       return TC_Failed;
     }
   }
-  
+
+  // FIXME: doesn't correctly identify T({1})
+  bool InitList = isa<InitListExpr>(SrcExpr.get());
   InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType);
   InitializationKind InitKind
     = (CCK == Sema::CCK_CStyleCast)
-        ? InitializationKind::CreateCStyleCast(OpRange.getBegin(), OpRange)
+        ? InitializationKind::CreateCStyleCast(OpRange.getBegin(), OpRange,
+                                               InitList)
     : (CCK == Sema::CCK_FunctionalCast)
-        ? InitializationKind::CreateFunctionalCast(OpRange)
+        ? InitializationKind::CreateFunctionalCast(OpRange, InitList)
     : InitializationKind::CreateCast(OpRange);
   Expr *SrcExprRaw = SrcExpr.get();
   InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExprRaw, 1);
index 72a8de2b71e0a933bf49e8b2d52ea44498235554..467cf43797ed8093e49cb2dbf8f6880b4a1a0870 100644 (file)
@@ -2150,18 +2150,22 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
     // any of the arguments are type-dependent expressions.
     DiscardCleanupsInEvaluationContext();
   } else {
+    bool InitList = false;
+    if (isa<InitListExpr>(Init)) {
+      InitList = true;
+      Args = &Init;
+      NumArgs = 1;
+    }
+
     // Initialize the member.
     InitializedEntity MemberEntity =
       DirectMember ? InitializedEntity::InitializeMember(DirectMember, 0)
                    : InitializedEntity::InitializeMember(IndirectMember, 0);
     InitializationKind Kind =
-      InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(),
-                                       InitRange.getEnd());
+      InitList ? InitializationKind::CreateDirectList(IdLoc)
+               : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(),
+                                                  InitRange.getEnd());
 
-    if (isa<InitListExpr>(Init)) {
-      Args = &Init;
-      NumArgs = 1;
-    }
     InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs);
     ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind,
                                             MultiExprArg(*this, Args, NumArgs),
@@ -2214,20 +2218,23 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
       << TInfo->getTypeLoc().getLocalSourceRange();
   Diag(NameLoc, diag::warn_cxx98_compat_delegating_ctor);
 
-  SourceRange InitRange = Init->getSourceRange();
-  // Initialize the object.
-  InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation(
-                                     QualType(ClassDecl->getTypeForDecl(), 0));
-  InitializationKind Kind =
-    InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(),
-                                     InitRange.getEnd());
-
+  bool InitList = true;
   Expr **Args = &Init;
   unsigned NumArgs = 1;
   if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
+    InitList = false;
     Args = ParenList->getExprs();
     NumArgs = ParenList->getNumExprs();
   }
+
+  SourceRange InitRange = Init->getSourceRange();
+  // Initialize the object.
+  InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation(
+                                     QualType(ClassDecl->getTypeForDecl(), 0));
+  InitializationKind Kind =
+    InitList ? InitializationKind::CreateDirectList(NameLoc)
+             : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(),
+                                                InitRange.getEnd());
   InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args, NumArgs);
   ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind,
                                               MultiExprArg(*this, Args,NumArgs),
@@ -2341,18 +2348,21 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
     BaseSpec = const_cast<CXXBaseSpecifier *>(VirtualBaseSpec);
 
   // Initialize the base.
-  InitializedEntity BaseEntity =
-    InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec);
-  InitializationKind Kind = 
-    InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(),
-                                     InitRange.getEnd());
-
+  bool InitList = true;
   Expr **Args = &Init;
   unsigned NumArgs = 1;
   if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
+    InitList = false;
     Args = ParenList->getExprs();
     NumArgs = ParenList->getNumExprs();
   }
+
+  InitializedEntity BaseEntity =
+    InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec);
+  InitializationKind Kind =
+    InitList ? InitializationKind::CreateDirectList(BaseLoc)
+             : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(),
+                                                InitRange.getEnd());
   InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs);
   ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind,
                                           MultiExprArg(*this, Args, NumArgs),
index 946b2a07af54d9acabf030a7901a22eb298c77f4..ce5956ae2f8e6db26cb6f469fc16cfc8fd320d89 100644 (file)
@@ -3809,7 +3809,8 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
     = InitializedEntity::InitializeTemporary(literalType);
   InitializationKind Kind
     = InitializationKind::CreateCStyleCast(LParenLoc, 
-                                           SourceRange(LParenLoc, RParenLoc));
+                                           SourceRange(LParenLoc, RParenLoc),
+                                           /*InitList=*/true);
   InitializationSequence InitSeq(*this, Entity, Kind, &LiteralExpr, 1);
   ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
                                        MultiExprArg(*this, &LiteralExpr, 1),
index c5d491353966d510f830dc3264c5db77492d444a..8376c0d66b42528c8d4059e384cc9753f763cbf9 100644 (file)
@@ -3970,11 +3970,13 @@ InitializationSequence::InitializationSequence(Sema &S,
       SourceType = Initializer->getType();
   }
 
-  //     - If the initializer is a braced-init-list, the object is
-  //       list-initialized (8.5.4).
-  if (InitListExpr *InitList = dyn_cast_or_null<InitListExpr>(Initializer)) {
-    TryListInitialization(S, Entity, Kind, InitList, *this);
-    return;
+  //     - If the initializer is a (non-parenthesized) braced-init-list, the
+  //       object is list-initialized (8.5.4).
+  if (Kind.getKind() != InitializationKind::IK_Direct) {
+    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.
index d8b79deb62a9c83faeb033b95835eb74335e4819..b716d81834fd134393cb9095c3051efc2625c9cf 100644 (file)
@@ -56,4 +56,6 @@ namespace aggregate {
     // String is not default-constructible
     static_assert(sizeof(overloaded({1})) == sizeof(one), "bad overload");
   }
+
+  struct C { int a[2]; C():a({1, 2}) { } }; // expected-error {{array initializer must be an initializer list}}
 }
index f84f1be7d51c80f0ea25586a4d8e0cb98c8e5013..fb962641de82595fd59e05e55641bf2a251c8e6c 100644 (file)
@@ -71,4 +71,9 @@ namespace reference {
     static_assert(sizeof(h({1, 2})) == sizeof(two), "bad overload resolution");
   }
 
+  void edge_cases() {
+    // FIXME: very poor error message
+    int const &b({0}); // expected-error {{could not bind}}
+  }
+
 }
index e0843c2246d4b4d5205cd43e5071025dba2d6e3e..7d2b5b3ab9f51d30ca1886d8422f0d6ade642388 100644 (file)
@@ -55,4 +55,9 @@ namespace integral {
     emptylist({});
     emptylist({}, {}, {});
   }
+
+  void edge_cases() {
+    // FIXME: very poor error message
+    int a({0}); // expected-error {{cannot initialize}}
+  }
 }
diff --git a/test/SemaCXX/generalized-initializers.cpp b/test/SemaCXX/generalized-initializers.cpp
deleted file mode 100644 (file)
index 1228d30..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
-// XFAIL: *
-
-template <typename T, typename U>
-struct same_type { static const bool value = false; };
-template <typename T>
-struct same_type<T, T> { static const bool value = true; };
-
-namespace std {
-  typedef decltype(sizeof(int)) size_t;
-
-  // libc++'s implementation
-  template <class _E>
-  class initializer_list
-  {
-    const _E* __begin_;
-    size_t    __size_;
-
-    initializer_list(const _E* __b, size_t __s)
-      : __begin_(__b),
-        __size_(__s)
-    {}
-
-  public:
-    typedef _E        value_type;
-    typedef const _E& reference;
-    typedef const _E& const_reference;
-    typedef size_t    size_type;
-
-    typedef const _E* iterator;
-    typedef const _E* const_iterator;
-
-    initializer_list() : __begin_(nullptr), __size_(0) {}
-
-    size_t    size()  const {return __size_;}
-    const _E* begin() const {return __begin_;}
-    const _E* end()   const {return __begin_ + __size_;}
-  };
-}
-
-namespace litb {
-
-  // invalid
-  struct A { int a[2]; A():a({1, 2}) { } }; // expected-error {{}}
-
-  // invalid
-  int a({0}); // expected-error {{}}
-
-  // invalid
-  int const &b({0}); // expected-error {{}}
-
-}