r181212 - Fix representation of compound literals for C++ objects with destructors.
Jordan Rose
jordan_rose at apple.com
Mon May 6 09:48:12 PDT 2013
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}}
+ }
+}
More information about the cfe-commits
mailing list