lebedev.ri updated this revision to Diff 239180.
lebedev.ri added a comment.

Not only do we need to 'insert' size implicit argument,
but we may need to insert alignment implicit argument.
And while for size we can only insert `nullptr`,
for alignment we can actually insert the correct value.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73020/new/

https://reviews.llvm.org/D73020

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp

Index: clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp
===================================================================
--- clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp
+++ clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp
@@ -32,7 +32,7 @@
 
 void *ptr_variable(int align) { return new (std::align_val_t(align)) A; }
 void *ptr_align16() { return new (std::align_val_t(16)) A; }
-void *ptr_align15() { return new (std::align_val_t(15)) A; }
+void *ptr_align15() { return new (std::align_val_t(15)) A; } // expected-error {{requested alignment is not a power of 2}}
 
 struct alignas(128) S {
   S() {}
@@ -49,11 +49,9 @@
   return new (std::align_val_t(256)) S;
 }
 void *alloc_overaligned_struct_with_extra_255_alignment(int align) {
-  return new (std::align_val_t(255)) S;
+  return new (std::align_val_t(255)) S; // expected-error {{requested alignment is not a power of 2}}
 }
 
 std::align_val_t align_variable(int align) { return std::align_val_t(align); }
 std::align_val_t align_align16() { return std::align_val_t(16); }
 std::align_val_t align_align15() { return std::align_val_t(15); }
-
-// expected-no-diagnostics
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -2070,18 +2070,45 @@
     // arguments. Skip the first parameter because we don't have a corresponding
     // argument. Skip the second parameter too if we're passing in the
     // alignment; we've already filled it in.
+    unsigned NumImplicitArgs = PassAlignment ? 2 : 1;
     if (GatherArgumentsForCall(PlacementLParen, OperatorNew, Proto,
-                               PassAlignment ? 2 : 1, PlacementArgs,
-                               AllPlaceArgs, CallType))
+                               NumImplicitArgs, PlacementArgs, AllPlaceArgs,
+                               CallType))
       return ExprError();
 
     if (!AllPlaceArgs.empty())
       PlacementArgs = AllPlaceArgs;
 
-    // FIXME: This is wrong: PlacementArgs misses out the first (size) argument.
-    DiagnoseSentinelCalls(OperatorNew, PlacementLParen, PlacementArgs);
+    // We would like to perform some checking on the given `operator new` call,
+    // but the PlacementArgs does not contain the implicit arguments,
+    // namely allocation size and maybe allocation alignment, so we need to
+    // conjure them. For size, we can't do anything better than just passing a
+    // nullptr, but for alignment we can either also pass a nullptr, or actually
+    // materialize the alignment we'll pass into the call.
+    llvm::SmallVector<Expr *, 8> CallArgs;
+    CallArgs.reserve(NumImplicitArgs + PlacementArgs.size());
+    CallArgs.emplace_back(nullptr);
+    if (PassAlignment) {
+      // Let's actually synthesize the alignment argument.
+      QualType AlignValT = Context.getTypeDeclType(getStdAlignValT());
+      QualType SizeTy =
+          AlignValT->castAs<EnumType>()->getDecl()->getIntegerType();
+      auto *AlignmentLiteral = IntegerLiteral::Create(
+          Context,
+          llvm::APInt(Context.getTypeSize(SizeTy),
+                      Alignment / Context.getCharWidth()),
+          SizeTy, SourceLocation());
+      auto *DesiredAlignmnet = ImplicitCastExpr::Create(
+          Context, AlignValT, CK_IntegralCast, AlignmentLiteral,
+          /*BasePath=*/nullptr, VK_RValue);
+      CallArgs.emplace_back(DesiredAlignmnet);
+    }
+    CallArgs.insert(CallArgs.end(), PlacementArgs.begin(), PlacementArgs.end());
 
-    // FIXME: Missing call to CheckFunctionCall or equivalent
+    DiagnoseSentinelCalls(OperatorNew, PlacementLParen, CallArgs);
+
+    checkCall(OperatorNew, Proto, /*ThisArg=*/nullptr, CallArgs,
+              /*IsMemberFunction=*/false, StartLoc, Range, CallType);
 
     // Warn if the type is over-aligned and is being allocated by (unaligned)
     // global operator new.
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -14460,8 +14460,10 @@
                                                     const Expr *E,
                                                     llvm::APSInt *Value,
                                                     SourceLocation *Loc) {
-  if (!E->getType()->isIntegralOrUnscopedEnumerationType()) {
-    if (Loc) *Loc = E->getExprLoc();
+  if (!E->getType()->isIntegralOrUnscopedEnumerationType() &&
+      !E->getType()->isAlignValT()) {
+    if (Loc)
+      *Loc = E->getExprLoc();
     return false;
   }
 
@@ -14593,7 +14595,7 @@
   ArgVector ArgValues(Args.size());
   for (ArrayRef<const Expr*>::iterator I = Args.begin(), E = Args.end();
        I != E; ++I) {
-    if ((*I)->isValueDependent() ||
+    if (!*I || (*I)->isValueDependent() ||
         !Evaluate(ArgValues[I - Args.begin()], Info, *I) ||
         Info.EvalStatus.HasSideEffects)
       // If evaluation fails, throw away the argument entirely.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to