@@ -1277,7 +1277,7 @@ class OpenACCCreateClause final
12771277};
12781278
12791279// A structure to stand in for the recipe on a reduction. RecipeDecl is the
1280- // 'main' declaration used for initializaiton, which is fixed.
1280+ // 'main' declaration used for initializaiton, which is fixed.
12811281struct OpenACCReductionRecipe {
12821282 VarDecl *AllocaDecl;
12831283
@@ -1297,45 +1297,72 @@ struct OpenACCReductionRecipe {
12971297 // -For a struct without the operator, this will be 1 element per field, which
12981298 // should be the combiner for that element.
12991299 // -For an array of any of the above, it will be the above for the element.
1300- llvm::SmallVector<CombinerRecipe, 1 > CombinerRecipes;
1300+ // Note: These are necessarily stored in either Trailing Storage (when in the
1301+ // AST), or in a separate collection when being semantically analyzed.
1302+ llvm::ArrayRef<CombinerRecipe> CombinerRecipes;
13011303
13021304 OpenACCReductionRecipe (VarDecl *A, llvm::ArrayRef<CombinerRecipe> Combiners)
13031305 : AllocaDecl(A), CombinerRecipes(Combiners) {}
13041306
13051307 bool isSet () const { return AllocaDecl; }
1306- static OpenACCReductionRecipe Empty () {
1307- return OpenACCReductionRecipe (/* AllocaDecl=*/ nullptr , {});
1308+ };
1309+
1310+ // A version of the above that is used for semantic analysis, at a time before
1311+ // the OpenACCReductionClause node has been created. This one has storage for
1312+ // the CombinerRecipe, since Trailing storage for it doesn't exist yet.
1313+ struct OpenACCReductionRecipeWithStorage : OpenACCReductionRecipe {
1314+ llvm::SmallVector<CombinerRecipe, 1 > CombinerRecipeStorage;
1315+
1316+ OpenACCReductionRecipeWithStorage (VarDecl *A,
1317+ llvm::ArrayRef<CombinerRecipe> Combiners)
1318+ : OpenACCReductionRecipe(A, {}), CombinerRecipeStorage(Combiners) {
1319+ CombinerRecipes = CombinerRecipeStorage;
1320+ }
1321+ static OpenACCReductionRecipeWithStorage Empty () {
1322+ return OpenACCReductionRecipeWithStorage (/* AllocaDecl=*/ nullptr , {});
13081323 }
13091324};
13101325
13111326class OpenACCReductionClause final
13121327 : public OpenACCClauseWithVarList,
13131328 private llvm::TrailingObjects<OpenACCReductionClause, Expr *,
1314- OpenACCReductionRecipe> {
1329+ OpenACCReductionRecipe,
1330+ OpenACCReductionRecipe::CombinerRecipe> {
13151331 friend TrailingObjects;
13161332 OpenACCReductionOperator Op;
13171333
13181334 OpenACCReductionClause (SourceLocation BeginLoc, SourceLocation LParenLoc,
13191335 OpenACCReductionOperator Operator,
13201336 ArrayRef<Expr *> VarList,
1321- ArrayRef<OpenACCReductionRecipe > Recipes,
1337+ ArrayRef<OpenACCReductionRecipeWithStorage > Recipes,
13221338 SourceLocation EndLoc)
13231339 : OpenACCClauseWithVarList(OpenACCClauseKind::Reduction, BeginLoc,
13241340 LParenLoc, EndLoc),
13251341 Op (Operator) {
1326- assert (VarList.size () == Recipes.size ());
1342+ assert (VarList.size () == Recipes.size ());
13271343 setExprs (getTrailingObjects<Expr *>(VarList.size ()), VarList);
1328- llvm::uninitialized_copy (Recipes,
1329- getTrailingObjects<OpenACCReductionRecipe>());
1330- }
13311344
1332- public:
1333- ~OpenACCReductionClause () {
1334- for (unsigned I = 0 ; I < getExprs ().size (); ++I) {
1335- getTrailingObjects<OpenACCReductionRecipe>()[I].~OpenACCReductionRecipe ();
1345+ // Since we're using trailing storage on this node to store the 'combiner'
1346+ // recipes of the Reduction Recipes (which have a 1:M relationship), we need
1347+ // to ensure we get the ArrayRef of each of our combiner 'correct'.
1348+ OpenACCReductionRecipe::CombinerRecipe *CurCombinerLoc =
1349+ getTrailingObjects<OpenACCReductionRecipe::CombinerRecipe>();
1350+ for (const auto &[Idx, R] : llvm::enumerate (Recipes)) {
1351+
1352+ // ArrayRef to the 'correct' data location in trailing storage.
1353+ llvm::MutableArrayRef<OpenACCReductionRecipe::CombinerRecipe>
1354+ NewCombiners{CurCombinerLoc, R.CombinerRecipes .size ()};
1355+ CurCombinerLoc += R.CombinerRecipes .size ();
1356+
1357+ llvm::uninitialized_copy (R.CombinerRecipes , NewCombiners.begin ());
1358+
1359+ // Placement new into the correct location in trailng storage.
1360+ new (&getTrailingObjects<OpenACCReductionRecipe>()[Idx])
1361+ OpenACCReductionRecipe (R.AllocaDecl , NewCombiners);
13361362 }
13371363 }
13381364
1365+ public:
13391366 static bool classof (const OpenACCClause *C) {
13401367 return C->getClauseKind () == OpenACCClauseKind::Reduction;
13411368 }
@@ -1353,13 +1380,17 @@ class OpenACCReductionClause final
13531380 static OpenACCReductionClause *
13541381 Create (const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
13551382 OpenACCReductionOperator Operator, ArrayRef<Expr *> VarList,
1356- ArrayRef<OpenACCReductionRecipe> Recipes, SourceLocation EndLoc);
1383+ ArrayRef<OpenACCReductionRecipeWithStorage> Recipes,
1384+ SourceLocation EndLoc);
13571385
13581386 OpenACCReductionOperator getReductionOp () const { return Op; }
13591387
13601388 size_t numTrailingObjects (OverloadToken<Expr *>) const {
13611389 return getExprs ().size ();
13621390 }
1391+ size_t numTrailingObjects (OverloadToken<OpenACCReductionRecipe>) const {
1392+ return getExprs ().size ();
1393+ }
13631394};
13641395
13651396class OpenACCLinkClause final
0 commit comments