r181212 - Fix representation of compound literals for C++ objects with destructors.

Richard Smith richard at metafoo.co.uk
Mon May 6 10:35:29 PDT 2013


CodeGen has a hack to deal with the possibility of multiple
CXXBindTemporaryExprs binding to the same temporary. Do we still need that
with this fix in place, or do we have the same issue elsewhere?

On Mon, May 6, 2013 at 9:48 AM, Jordan Rose <jordan_rose at apple.com> wrote:

> Author: jrose
> Date: Mon May  6 11:48:12 2013
> New Revision: 181212
>
> URL: http://llvm.org/viewvc/llvm-project?rev=181212&view=rev
> Log:
> Fix representation of compound literals for C++ objects with destructors.
>
> Previously, this compound literal expression (a GNU extension in C++):
>
>   (AggregateWithDtor){1, 2}
>
> resulted in this AST:
>
>  `-CXXBindTemporaryExpr [...] 'struct Point' (CXXTemporary [...])
>    `-CompoundLiteralExpr [...] 'struct AggregateWithDtor'
>      `-CXXBindTemporaryExpr [...] 'struct AggregateWithDtor' (CXXTemporary
> [...])
>        `-InitListExpr [...] 'struct AggregateWithDtor'
>          |-IntegerLiteral [...] 'int' 1
>          `-IntegerLiteral [...] 'int' 2
>
> Note the two CXXBindTemporaryExprs. The InitListExpr is really part of the
> CompoundLiteralExpr, not an object in its own right. By introducing a new
> entity initialization kind in Sema specifically for compound literals, we
> avoid the treatment of the inner InitListExpr as a temporary.
>
>  `-CXXBindTemporaryExpr [...] 'struct Point' (CXXTemporary [...])
>    `-CompoundLiteralExpr [...] 'struct AggregateWithDtor'
>      `-InitListExpr [...] 'struct AggregateWithDtor'
>        |-IntegerLiteral [...] 'int' 1
>        `-IntegerLiteral [...] 'int' 2
>
> Modified:
>     cfe/trunk/include/clang/Sema/Initialization.h
>     cfe/trunk/lib/Sema/SemaExpr.cpp
>     cfe/trunk/lib/Sema/SemaInit.cpp
>     cfe/trunk/test/SemaCXX/compound-literal.cpp
>
> Modified: cfe/trunk/include/clang/Sema/Initialization.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=181212&r1=181211&r2=181212&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Initialization.h (original)
> +++ cfe/trunk/include/clang/Sema/Initialization.h Mon May  6 11:48:12 2013
> @@ -75,7 +75,10 @@ public:
>      EK_ComplexElement,
>      /// \brief The entity being initialized is the field that captures a
>      /// variable in a lambda.
> -    EK_LambdaCapture
> +    EK_LambdaCapture,
> +    /// \brief The entity being initialized is the initializer for a
> compound
> +    /// literal.
> +    EK_CompoundLiteralInit
>    };
>
>  private:
> @@ -118,8 +121,8 @@ private:
>      /// low bit indicating whether the parameter is "consumed".
>      uintptr_t Parameter;
>
> -    /// \brief When Kind == EK_Temporary, the type source information for
> -    /// the temporary.
> +    /// \brief When Kind == EK_Temporary or EK_CompoundLiteralInit, the
> type
> +    /// source information for the temporary.
>      TypeSourceInfo *TypeInfo;
>
>      struct LN LocAndNRVO;
> @@ -287,7 +290,16 @@ public:
>                                                     SourceLocation Loc) {
>      return InitializedEntity(Var, Field, Loc);
>    }
> -
> +
> +  /// \brief Create the entity for a compound literal initializer.
> +  static InitializedEntity InitializeCompoundLiteralInit(TypeSourceInfo
> *TSI) {
> +    InitializedEntity Result(EK_CompoundLiteralInit, SourceLocation(),
> +                             TSI->getType());
> +    Result.TypeInfo = TSI;
> +    return Result;
> +  }
> +
> +
>    /// \brief Determine the kind of initialization.
>    EntityKind getKind() const { return Kind; }
>
> @@ -302,7 +314,7 @@ public:
>    /// \brief Retrieve complete type-source information for the object
> being
>    /// constructed, if known.
>    TypeSourceInfo *getTypeSourceInfo() const {
> -    if (Kind == EK_Temporary)
> +    if (Kind == EK_Temporary || Kind == EK_CompoundLiteralInit)
>        return TypeInfo;
>
>      return 0;
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=181212&r1=181211&r2=181212&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon May  6 11:48:12 2013
> @@ -4509,7 +4509,7 @@ Sema::BuildCompoundLiteralExpr(SourceLoc
>      return ExprError();
>
>    InitializedEntity Entity
> -    = InitializedEntity::InitializeTemporary(literalType);
> +    = InitializedEntity::InitializeCompoundLiteralInit(TInfo);
>    InitializationKind Kind
>      = InitializationKind::CreateCStyleCast(LParenLoc,
>                                             SourceRange(LParenLoc,
> RParenLoc),
>
> Modified: cfe/trunk/lib/Sema/SemaInit.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=181212&r1=181211&r2=181212&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaInit.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaInit.cpp Mon May  6 11:48:12 2013
> @@ -2394,6 +2394,7 @@ DeclarationName InitializedEntity::getNa
>    case EK_VectorElement:
>    case EK_ComplexElement:
>    case EK_BlockElement:
> +  case EK_CompoundLiteralInit:
>      return DeclarationName();
>    }
>
> @@ -2420,6 +2421,7 @@ DeclaratorDecl *InitializedEntity::getDe
>    case EK_ComplexElement:
>    case EK_BlockElement:
>    case EK_LambdaCapture:
> +  case EK_CompoundLiteralInit:
>      return 0;
>    }
>
> @@ -2437,6 +2439,7 @@ bool InitializedEntity::allowsNRVO() con
>    case EK_Member:
>    case EK_New:
>    case EK_Temporary:
> +  case EK_CompoundLiteralInit:
>    case EK_Base:
>    case EK_Delegating:
>    case EK_ArrayElement:
> @@ -4468,6 +4471,7 @@ getAssignmentAction(const InitializedEnt
>    case InitializedEntity::EK_ComplexElement:
>    case InitializedEntity::EK_BlockElement:
>    case InitializedEntity::EK_LambdaCapture:
> +  case InitializedEntity::EK_CompoundLiteralInit:
>      return Sema::AA_Initializing;
>    }
>
> @@ -4490,6 +4494,7 @@ static bool shouldBindAsTemporary(const
>    case InitializedEntity::EK_Exception:
>    case InitializedEntity::EK_BlockElement:
>    case InitializedEntity::EK_LambdaCapture:
> +  case InitializedEntity::EK_CompoundLiteralInit:
>      return false;
>
>    case InitializedEntity::EK_Parameter:
> @@ -4520,6 +4525,7 @@ static bool shouldDestroyTemporary(const
>      case InitializedEntity::EK_Temporary:
>      case InitializedEntity::EK_ArrayElement:
>      case InitializedEntity::EK_Exception:
> +    case InitializedEntity::EK_CompoundLiteralInit:
>        return true;
>    }
>
> @@ -4601,6 +4607,7 @@ static SourceLocation getInitializationL
>    case InitializedEntity::EK_VectorElement:
>    case InitializedEntity::EK_ComplexElement:
>    case InitializedEntity::EK_BlockElement:
> +  case InitializedEntity::EK_CompoundLiteralInit:
>      return Initializer->getLocStart();
>    }
>    llvm_unreachable("missed an InitializedEntity kind?");
> @@ -4828,6 +4835,31 @@ static bool isReferenceBinding(const Ini
>           s.Kind == InitializationSequence::SK_BindReferenceToTemporary;
>  }
>
> +/// Returns true if the parameters describe a constructor initialization
> of
> +/// an explicit temporary object, e.g. "Point(x, y)".
> +static bool isExplicitTemporary(const InitializedEntity &Entity,
> +                                const InitializationKind &Kind,
> +                                unsigned NumArgs) {
> +  switch (Entity.getKind()) {
> +  case InitializedEntity::EK_Temporary:
> +  case InitializedEntity::EK_CompoundLiteralInit:
> +    break;
> +  default:
> +    return false;
> +  }
> +
> +  switch (Kind.getKind()) {
> +  case InitializationKind::IK_DirectList:
> +    return true;
> +  // FIXME: Hack to work around cast weirdness.
> +  case InitializationKind::IK_Direct:
> +  case InitializationKind::IK_Value:
> +    return NumArgs != 1;
> +  default:
> +    return false;
> +  }
> +}
> +
>  static ExprResult
>  PerformConstructorInitialization(Sema &S,
>                                   const InitializedEntity &Entity,
> @@ -4878,11 +4910,7 @@ PerformConstructorInitialization(Sema &S
>      return ExprError();
>
>
> -  if (Entity.getKind() == InitializedEntity::EK_Temporary &&
> -      (Kind.getKind() == InitializationKind::IK_DirectList ||
> -       (NumArgs != 1 && // FIXME: Hack to work around cast weirdness
> -        (Kind.getKind() == InitializationKind::IK_Direct ||
> -         Kind.getKind() == InitializationKind::IK_Value)))) {
> +  if (isExplicitTemporary(Entity, Kind, NumArgs)) {
>      // An explicitly-constructed temporary, e.g., X(1, 2).
>      S.MarkFunctionReferenced(Loc, Constructor);
>      if (S.DiagnoseUseOfDecl(Constructor, Loc))
> @@ -4984,6 +5012,7 @@ InitializedEntityOutlivesFullExpression(
>    case InitializedEntity::EK_Parameter:
>    case InitializedEntity::EK_Temporary:
>    case InitializedEntity::EK_LambdaCapture:
> +  case InitializedEntity::EK_CompoundLiteralInit:
>      // The entity being initialized might not outlive the full-expression.
>      return false;
>    }
>
> Modified: cfe/trunk/test/SemaCXX/compound-literal.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/compound-literal.cpp?rev=181212&r1=181211&r2=181212&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/compound-literal.cpp (original)
> +++ cfe/trunk/test/SemaCXX/compound-literal.cpp Mon May  6 11:48:12 2013
> @@ -1,4 +1,8 @@
> -// RUN: %clang_cc1 -fsyntax-only -verify %s
> +// RUN: %clang_cc1 -fsyntax-only -std=c++03 -verify -ast-dump %s > %t-03
> +// RUN: FileCheck --input-file=%t-03 %s
> +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -ast-dump %s > %t-11
> +// RUN: FileCheck --input-file=%t-11 %s
> +// RUN: FileCheck --input-file=%t-11 %s --check-prefix=CHECK-CXX11
>
>  // http://llvm.org/PR7905
>  namespace PR7905 {
> @@ -12,3 +16,63 @@ void foo2() {
>    (void)(M<short> []) {{3}};
>  }
>  }
> +
> +// Check compound literals mixed with C++11 list-initialization.
> +namespace brace_initializers {
> +  struct POD {
> +    int x, y;
> +  };
> +  struct HasCtor {
> +    HasCtor(int x, int y);
> +  };
> +  struct HasDtor {
> +    int x, y;
> +    ~HasDtor();
> +  };
> +  struct HasCtorDtor {
> +    HasCtorDtor(int x, int y);
> +    ~HasCtorDtor();
> +  };
> +
> +  void test() {
> +    (void)(POD){1, 2};
> +    // CHECK-NOT: CXXBindTemporaryExpr {{.*}} 'struct
> brace_initializers::POD'
> +    // CHECK: CompoundLiteralExpr {{.*}} 'struct brace_initializers::POD'
> +    // CHECK-NEXT: InitListExpr {{.*}} 'struct brace_initializers::POD'
> +    // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}
> +    // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}}
> +
> +    (void)(HasDtor){1, 2};
> +    // CHECK: CXXBindTemporaryExpr {{.*}} 'struct
> brace_initializers::HasDtor'
> +    // CHECK-NEXT: CompoundLiteralExpr {{.*}} 'struct
> brace_initializers::HasDtor'
> +    // CHECK-NEXT: InitListExpr {{.*}} 'struct
> brace_initializers::HasDtor'
> +    // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}
> +    // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}}
> +
> +#if __cplusplus >= 201103L
> +    (void)(HasCtor){1, 2};
> +    // CHECK-CXX11-NOT: CXXBindTemporaryExpr {{.*}} 'struct
> brace_initializers::HasCtor'
> +    // CHECK-CXX11: CompoundLiteralExpr {{.*}} 'struct
> brace_initializers::HasCtor'
> +    // CHECK-CXX11-NEXT: CXXTemporaryObjectExpr {{.*}} 'struct
> brace_initializers::HasCtor'
> +    // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 1{{$}}
> +    // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 2{{$}}
> +
> +    (void)(HasCtorDtor){1, 2};
> +    // CHECK-CXX11: CXXBindTemporaryExpr {{.*}} 'struct
> brace_initializers::HasCtorDtor'
> +    // CHECK-CXX11-NEXT: CompoundLiteralExpr {{.*}} 'struct
> brace_initializers::HasCtorDtor'
> +    // CHECK-CXX11-NEXT: CXXTemporaryObjectExpr {{.*}} 'struct
> brace_initializers::HasCtorDtor'
> +    // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 1{{$}}
> +    // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 2{{$}}
> +#endif
> +  }
> +
> +  struct PrivateDtor {
> +    int x, y;
> +  private:
> +    ~PrivateDtor(); // expected-note {{declared private here}}
> +  };
> +
> +  void testPrivateDtor() {
> +    (void)(PrivateDtor){1, 2}; // expected-error {{temporary of type
> 'brace_initializers::PrivateDtor' has private destructor}}
> +  }
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130506/b13ca712/attachment.html>


More information about the cfe-commits mailing list