diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/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::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. diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/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 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()->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. diff --git a/clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp b/clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp --- a/clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp +++ b/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