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
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181212 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 993e68b..de93adb 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -2394,6 +2394,7 @@
case EK_VectorElement:
case EK_ComplexElement:
case EK_BlockElement:
+ case EK_CompoundLiteralInit:
return DeclarationName();
}
@@ -2420,6 +2421,7 @@
case EK_ComplexElement:
case EK_BlockElement:
case EK_LambdaCapture:
+ case EK_CompoundLiteralInit:
return 0;
}
@@ -2437,6 +2439,7 @@
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 @@
case InitializedEntity::EK_ComplexElement:
case InitializedEntity::EK_BlockElement:
case InitializedEntity::EK_LambdaCapture:
+ case InitializedEntity::EK_CompoundLiteralInit:
return Sema::AA_Initializing;
}
@@ -4490,6 +4494,7 @@
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 @@
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_Exception:
+ case InitializedEntity::EK_CompoundLiteralInit:
return true;
}
@@ -4601,6 +4607,7 @@
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 @@
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 @@
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 @@
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;
}