https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/216994
Reverts llvm/llvm-project#197005 There are several things unclear about this patch, it doesn't update the bytecode interpreter at all, uses the driver in the test, doesn't add documentation, etc. >From e08a592154584623995143c66ecff9a15f282174 Mon Sep 17 00:00:00 2001 From: Timm Baeder <[email protected]> Date: Tue, 18 Aug 2026 13:29:13 +0200 Subject: [PATCH] Revert "[clang] Allow C-style casts in constexpr in MS compatible mode (#197005)" This reverts commit 2336d2cec6b4845691251869ebc1442595008a60. --- clang/include/clang/AST/Expr.h | 11 +- .../include/clang/Basic/DiagnosticASTKinds.td | 14 -- clang/include/clang/Basic/DiagnosticGroups.td | 2 - clang/include/clang/Sema/Overload.h | 9 +- clang/lib/AST/ByteCode/State.cpp | 24 --- clang/lib/AST/ByteCode/State.h | 4 - clang/lib/AST/Decl.cpp | 12 +- clang/lib/AST/ExprConstant.cpp | 29 ++-- clang/lib/Sema/SemaExpr.cpp | 13 -- clang/lib/Sema/SemaOverload.cpp | 28 +--- .../SemaCXX/microsoft-constexpr-SFINAE.cpp | 20 --- .../SemaCXX/microsoft-constexpr-SFINAE2.cpp | 20 --- clang/test/SemaCXX/microsoft-constexpr.cpp | 141 ------------------ clang/test/SemaCXX/microsoft-constexpr2.cpp | 42 ------ clang/test/SemaCXX/microsoft-constexpr3.cpp | 18 --- 15 files changed, 27 insertions(+), 360 deletions(-) delete mode 100644 clang/test/SemaCXX/microsoft-constexpr-SFINAE.cpp delete mode 100644 clang/test/SemaCXX/microsoft-constexpr-SFINAE2.cpp delete mode 100644 clang/test/SemaCXX/microsoft-constexpr.cpp delete mode 100644 clang/test/SemaCXX/microsoft-constexpr2.cpp delete mode 100644 clang/test/SemaCXX/microsoft-constexpr3.cpp diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 112af378258fc..f95f87cc4e8e0 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -562,8 +562,7 @@ class Expr : public ValueStmt { /// Note: This does not perform the implicit conversions required by C++11 /// [expr.const]p5. std::optional<llvm::APSInt> - getIntegerConstantExpr(const ASTContext &Ctx, - bool AllowRelaxedEval = false) const; + getIntegerConstantExpr(const ASTContext &Ctx) const; bool isIntegerConstantExpr(const ASTContext &Ctx) const; /// isCXX98IntegralConstantExpr - Return true if this expression is an @@ -575,8 +574,8 @@ class Expr : public ValueStmt { /// /// Note: This does not perform the implicit conversions required by C++11 /// [expr.const]p5. - bool isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result = nullptr, - bool AllowRelaxedEval = false) const; + bool isCXX11ConstantExpr(const ASTContext &Ctx, + APValue *Result = nullptr) const; /// isPotentialConstantExpr - Return true if this function's definition /// might be usable in a constant expression in C++11, if it were marked @@ -640,10 +639,6 @@ class Expr : public ValueStmt { /// to a string representation). SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr; - /// Location where we spot ptr to int cast or null subobject while - /// evaluating constant expression in MS compatibility mode. - SmallVectorImpl<PartialDiagnosticAt> *ExtendedDiag = nullptr; - EvalStatus() = default; /// Return true if the evaluated expression has diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index 3c39ccf51ab67..c4582a3a9d641 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -16,11 +16,6 @@ def note_constexpr_invalid_cast : Note< "of a reinterpret_cast}1}|%CastFrom{cast from %1}}0" " is not allowed in a constant expression" "%select{| in C++ standards before C++20||}0">; -def note_constexpr_invalid_cast_ptrtoint : Note< - "%select{reinterpret_cast||" - "%select{this conversion|cast that performs the conversions of a reinterpret_cast}1|" - "}0 is not allowed in a constant expression">; -def note_constexpr_has_lvalue : Note<"converting the address of an object to an integer is not allowed">; def note_constexpr_invalid_void_star_cast : Note< "cast from %0 is not allowed in a constant expression " "%select{in C++ standards before C++2c|because the pointed object " @@ -1038,15 +1033,6 @@ def warn_npot_ms_struct : Warning< "ms_struct may not produce Microsoft-compatible layouts with fundamental " "data types with sizes that aren't a power of two">, DefaultError, InGroup<IncompatibleMSStruct>; -def warn_relaxed_constant_fold_cast : Extension< - "folding constant expression involving " - "cast that performs the conversions of a reinterpret_cast " - "is a Microsoft extension">, - InGroup<MicrosoftRelaxedConstantFold>; -def warn_relaxed_constant_fold_null : Extension< - "folding constant expression that takes field address of null pointer " - "is a Microsoft extension">, - InGroup<MicrosoftRelaxedConstantFold>; def err_itanium_layout_unimplemented : Error< "Itanium-compatible layout for the Microsoft C++ ABI is not yet supported">; diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 9ee0b61a96a32..da28678477dd6 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1687,8 +1687,6 @@ def MicrosoftStringLiteralFromPredefined : DiagGroup< "microsoft-string-literal-from-predefined">; def MicrosoftInlineOnNonFunction : DiagGroup< "microsoft-inline-on-non-function">; -def MicrosoftRelaxedConstantFold : - DiagGroup<"relaxed-constant-fold">; // Aliases. def : DiagGroup<"msvc-include", [MicrosoftInclude]>; diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index a3ec9ef3f3e6d..1e412ff6fc9e2 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -463,11 +463,10 @@ class Sema; } ImplicitConversionRank getRank() const; - NarrowingKind getNarrowingKind(ASTContext &Context, const Expr *Converted, - APValue &ConstantValue, - QualType &ConstantType, - bool IgnoreFloatToIntegralConversion = false, - bool AllowRelaxedEval = false) const; + NarrowingKind + getNarrowingKind(ASTContext &Context, const Expr *Converted, + APValue &ConstantValue, QualType &ConstantType, + bool IgnoreFloatToIntegralConversion = false) const; bool isPointerConversionToBool() const; bool isPointerConversionToVoidPointer(ASTContext& Context) const; void dump() const; diff --git a/clang/lib/AST/ByteCode/State.cpp b/clang/lib/AST/ByteCode/State.cpp index d1087f0da92d5..38384bae23f57 100644 --- a/clang/lib/AST/ByteCode/State.cpp +++ b/clang/lib/AST/ByteCode/State.cpp @@ -18,21 +18,6 @@ using namespace clang::interp; State::~State() {} -bool State::shouldRelaxDiag(const SourceLocation &Loc, diag::kind DiagId) { - if (!Ctx.getLangOpts().MSVCCompat || !EvalStatus.ExtendedDiag) - return false; - switch (DiagId) { - case diag::note_constexpr_invalid_cast_ptrtoint: - addExtendedDiag(Loc, diag::warn_relaxed_constant_fold_cast); - return true; - case diag::note_constexpr_null_subobject: - addExtendedDiag(Loc, diag::warn_relaxed_constant_fold_null); - return true; - default: - return false; - } -} - OptionalDiagnostic State::FFDiag(SourceLocation Loc, diag::kind DiagId, unsigned ExtraNotes) { return diag(Loc, DiagId, ExtraNotes, false); @@ -58,10 +43,6 @@ OptionalDiagnostic State::FFDiag(SourceInfo SI, diag::kind DiagId, OptionalDiagnostic State::CCEDiag(SourceLocation Loc, diag::kind DiagId, unsigned ExtraNotes) { - if (shouldRelaxDiag(Loc, DiagId)) { - setActiveDiagnostic(false); - return OptionalDiagnostic(); - } EvalStatus.DiagEmitted = true; // Don't override a previous diagnostic. Don't bother collecting // diagnostics if we're evaluating for overflow. @@ -110,11 +91,6 @@ PartialDiagnostic &State::addDiag(SourceLocation Loc, diag::kind DiagId) { return EvalStatus.Diag->back().second; } -void State::addExtendedDiag(SourceLocation Loc, diag::kind DiagId) { - PartialDiagnostic PD(DiagId, Ctx.getDiagAllocator()); - EvalStatus.ExtendedDiag->push_back(std::make_pair(Loc, PD)); -} - OptionalDiagnostic State::diag(SourceLocation Loc, diag::kind DiagId, unsigned ExtraNotes, bool IsCCEDiag) { if (EvalStatus.Diag) { diff --git a/clang/lib/AST/ByteCode/State.h b/clang/lib/AST/ByteCode/State.h index 97af0bf2b6866..df91132c48472 100644 --- a/clang/lib/AST/ByteCode/State.h +++ b/clang/lib/AST/ByteCode/State.h @@ -92,8 +92,6 @@ class State { ASTContext &getASTContext() const { return Ctx; } const LangOptions &getLangOpts() const { return Ctx.getLangOpts(); } - bool shouldRelaxDiag(const SourceLocation &Loc, diag::kind DiagId); - /// Note that we have had a side-effect, and determine whether we should /// keep evaluating. bool noteSideEffect() const { @@ -206,8 +204,6 @@ class State { PartialDiagnostic &addDiag(SourceLocation Loc, diag::kind DiagId); - void addExtendedDiag(SourceLocation Loc, diag::kind DiagId); - OptionalDiagnostic diag(SourceLocation Loc, diag::kind DiagId, unsigned ExtraNotes, bool IsCCEDiag); diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 55f34e27ae535..152c621bc1ef4 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2578,11 +2578,9 @@ VarDecl::evaluateValueImpl(SmallVectorImpl<PartialDiagnosticAt> *Notes, Eval->IsEvaluating = true; - SmallVector<PartialDiagnosticAt> MSWarning; ASTContext &Ctx = getASTContext(); Expr::EvalResult EStatus; EStatus.Diag = Notes; - EStatus.ExtendedDiag = &MSWarning; bool Result = Init->EvaluateAsInitializer(Ctx, this, EStatus, IsConstantInitialization); Eval->Evaluated = std::move(EStatus.Val); @@ -2602,14 +2600,8 @@ VarDecl::evaluateValueImpl(SmallVectorImpl<PartialDiagnosticAt> *Notes, // failed. if (!Result) Eval->Evaluated = APValue(); - else { - if (!MSWarning.empty()) - for (auto &Info : MSWarning) - getASTContext().getDiagnostics().Report(Info.first, - Info.second.getDiagID()); - if (Eval->Evaluated.needsCleanup()) - Ctx.addDestruction(&Eval->Evaluated); - } + else if (Eval->Evaluated.needsCleanup()) + Ctx.addDestruction(&Eval->Evaluated); Eval->IsEvaluating = false; Eval->WasEvaluated = true; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 05f981f671e62..480d5119a5363 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -8742,9 +8742,8 @@ class ExprEvaluatorBase } bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E) { - if (E->getCastKind() != CK_PointerToIntegral) - CCEDiag(E, diag::note_constexpr_invalid_cast) - << diag::ConstexprInvalidCastKind::Reinterpret; + CCEDiag(E, diag::note_constexpr_invalid_cast) + << diag::ConstexprInvalidCastKind::Reinterpret; return static_cast<Derived*>(this)->VisitCastExpr(E); } bool VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) { @@ -20054,7 +20053,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { } case CK_PointerToIntegral: { - CCEDiag(E, diag::note_constexpr_invalid_cast_ptrtoint) + CCEDiag(E, diag::note_constexpr_invalid_cast) << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret << Info.Ctx.getLangOpts().CPlusPlus << E->getSourceRange(); @@ -20063,7 +20062,6 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { return false; if (LV.getLValueBase()) { - CCEDiag(E, diag::note_constexpr_has_lvalue) << E->getSourceRange(); // Only allow based lvalue casts if they are lossless. // FIXME: Allow a larger integer size than the pointer size, and allow // narrowing back down to pointer width in subsequent integral casts. @@ -22046,6 +22044,7 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx, // destruction. return false; } + return true; } @@ -22728,15 +22727,14 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { } /// Evaluate an expression as a C++11 integral constant expression. -static bool -EvaluateCPlusPlus11IntegralConstantExpr(const ASTContext &Ctx, const Expr *E, - llvm::APSInt *Value, - bool AllowRelaxedEval = false) { +static bool EvaluateCPlusPlus11IntegralConstantExpr(const ASTContext &Ctx, + const Expr *E, + llvm::APSInt *Value) { if (!E->getType()->isIntegralOrUnscopedEnumerationType()) return false; APValue Result; - if (!E->isCXX11ConstantExpr(Ctx, &Result, AllowRelaxedEval)) + if (!E->isCXX11ConstantExpr(Ctx, &Result)) return false; if (!Result.isInt()) @@ -22762,8 +22760,7 @@ bool Expr::isIntegerConstantExpr(const ASTContext &Ctx) const { } std::optional<llvm::APSInt> -Expr::getIntegerConstantExpr(const ASTContext &Ctx, - bool AllowRelaxedEval) const { +Expr::getIntegerConstantExpr(const ASTContext &Ctx) const { if (isValueDependent()) { // Expression evaluator can't succeed on a dependent expression. return std::nullopt; @@ -22771,8 +22768,7 @@ Expr::getIntegerConstantExpr(const ASTContext &Ctx, if (Ctx.getLangOpts().CPlusPlus11) { APSInt Value; - if (EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value, - AllowRelaxedEval)) + if (EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value)) return Value; return std::nullopt; } @@ -22802,8 +22798,7 @@ bool Expr::isCXX98IntegralConstantExpr(const ASTContext &Ctx) const { return CheckICE(this, Ctx).Kind == IK_ICE; } -bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result, - bool AllowRelaxedEval) const { +bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result) const { assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); @@ -22822,8 +22817,6 @@ bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result, // Build evaluation settings. Expr::EvalStatus Status; EvalInfo Info(Ctx, Status, EvaluationMode::ConstantExpression); - SmallVector<PartialDiagnosticAt> MSRelaxedDiag; - Status.ExtendedDiag = AllowRelaxedEval ? &MSRelaxedDiag : nullptr; bool IsConstExpr = ::EvaluateAsRValue(Info, this, Result ? *Result : Scratch) && diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 0908841dca8bf..f25829ae676dc 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -18100,9 +18100,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, Expr::EvalResult EvalResult; SmallVector<PartialDiagnosticAt, 8> Notes; - SmallVector<PartialDiagnosticAt> MSWarning; EvalResult.Diag = &Notes; - EvalResult.ExtendedDiag = &MSWarning; // Try to evaluate the expression, and produce diagnostics explaining why it's // not a constant expression as a side-effect. @@ -18114,17 +18112,6 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, if (!isa<ConstantExpr>(E)) E = ConstantExpr::Create(Context, E, EvalResult.Val); - // For -fms-compatibility mode we relax some requirements - // for constant folding in non-SFINAE contexts - if (!MSWarning.empty()) { - if (isSFINAEContext()) { - Folded = false; - } else { - for (auto &Info : MSWarning) - Diag(Info.first, Info.second); - } - } - // In C++11, we can rely on diagnostics being produced for any expression // which is not a constant expression. If no diagnostics were produced, then // this is a constant expression. diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 81bc6c68f377d..c94b3d8f0d462 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -12,7 +12,6 @@ #include "CheckExprLifetime.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/ASTDiagnostic.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" @@ -367,12 +366,9 @@ static const Expr *IgnoreNarrowingConversion(ASTContext &Ctx, /// type of the expression prior to the narrowing conversion. /// \param IgnoreFloatToIntegralConversion If true type-narrowing conversions /// from floating point types to integral types should be ignored. -/// \param AllowRelaxedEval If true constant expression evaluation is relaxed -/// to conform MSVC compiler behavior. NarrowingKind StandardConversionSequence::getNarrowingKind( ASTContext &Ctx, const Expr *Converted, APValue &ConstantValue, - QualType &ConstantType, bool IgnoreFloatToIntegralConversion, - bool AllowRelaxedEval) const { + QualType &ConstantType, bool IgnoreFloatToIntegralConversion) const { assert((Ctx.getLangOpts().CPlusPlus || Ctx.getLangOpts().C23) && "narrowing check outside C++"); @@ -461,8 +457,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind( Expr::EvalResult R; if ((Ctx.getLangOpts().C23 && Initializer->EvaluateAsRValue(R, Ctx)) || ((Ctx.getLangOpts().CPlusPlus && - Initializer->isCXX11ConstantExpr(Ctx, &ConstantValue, - AllowRelaxedEval)))) { + Initializer->isCXX11ConstantExpr(Ctx, &ConstantValue)))) { // Constant! if (Ctx.getLangOpts().C23) ConstantValue = R.Val; @@ -552,7 +547,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind( return NK_Dependent_Narrowing; std::optional<llvm::APSInt> OptInitializerValue = - Initializer->getIntegerConstantExpr(Ctx, AllowRelaxedEval); + Initializer->getIntegerConstantExpr(Ctx); if (!OptInitializerValue) { // If the bit-field width was dependent, it might end up being small // enough to fit in the target type (unless the target type is unsigned @@ -6602,14 +6597,11 @@ static ExprResult BuildConvertedConstantExpression(Sema &S, Expr *From, if (Result.isInvalid()) return Result; - bool AllowRelaxedEval = S.getASTContext().getLangOpts().MSVCCompat; - // Check for a narrowing implicit conversion. bool ReturnPreNarrowingValue = false; QualType PreNarrowingType; - switch (SCS->getNarrowingKind( - S.Context, Result.get(), PreNarrowingValue, PreNarrowingType, - /*IgnoreFloatToIntegralConversion*/ false, AllowRelaxedEval)) { + switch (SCS->getNarrowingKind(S.Context, Result.get(), PreNarrowingValue, + PreNarrowingType)) { case NK_Variable_Narrowing: // Implicit conversion to a narrower type, and the value is not a constant // expression. We'll diagnose this in a moment. @@ -6714,10 +6706,8 @@ Sema::EvaluateConvertedConstantExpression(Expr *E, QualType T, APValue &Value, ExprResult Result = E; // Check the expression is a constant expression. SmallVector<PartialDiagnosticAt, 8> Notes; - SmallVector<PartialDiagnosticAt> MSWarning; Expr::EvalResult Eval; Eval.Diag = &Notes; - Eval.ExtendedDiag = &MSWarning; assert(CCE != CCEKind::TempArgStrict && "unnexpected CCE Kind"); @@ -6736,12 +6726,8 @@ Sema::EvaluateConvertedConstantExpression(Expr *E, QualType T, APValue &Value, Result = ExprError(); } else { Value = Eval.Val; - // For -fms-compatibility mode we relax some requirements - // for constant folding in non-SFINAE contexts - bool CantFold = isSFINAEContext() && !MSWarning.empty(); - if (Notes.empty() && !CantFold) { - for (auto &Info : MSWarning) - Diag(Info.first, Info.second); + + if (Notes.empty()) { // It's a constant expression. Expr *E = Result.get(); if (const auto *CE = dyn_cast<ConstantExpr>(E)) { diff --git a/clang/test/SemaCXX/microsoft-constexpr-SFINAE.cpp b/clang/test/SemaCXX/microsoft-constexpr-SFINAE.cpp deleted file mode 100644 index 271d1bcfad99e..0000000000000 --- a/clang/test/SemaCXX/microsoft-constexpr-SFINAE.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -fms-compatibility -triple x86_64-windows-msvc %s - -typedef long long LONG_PTR; -typedef long LONG; -#define FIELD_OFFSET(type, field) ((LONG_PTR)&(((type *)0)->field)) - -struct S { - int x; - int y; -}; - -template<class T, LONG_PTR = FIELD_OFFSET(S, y)> -char probe(int); - -template<class> -long probe(...); - -static_assert(sizeof(probe<int>(0)) == sizeof(char), ""); -// expected-error@-1 {{static assertion failed due to requirement 'sizeof (probe<int>(0)) == sizeof(char)'}} -// expected-note@-2 {{expression evaluates to '4 == 1'}} diff --git a/clang/test/SemaCXX/microsoft-constexpr-SFINAE2.cpp b/clang/test/SemaCXX/microsoft-constexpr-SFINAE2.cpp deleted file mode 100644 index b63ea73eaab28..0000000000000 --- a/clang/test/SemaCXX/microsoft-constexpr-SFINAE2.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -fms-compatibility -triple x86_64-windows-msvc -verify %s - -typedef long long LONG_PTR; -typedef long LONG; -#define FIELD_OFFSET(type, field) ((LONG_PTR)&(((type *)0)->field)) - -struct S { - int x; - int y; -}; - -template<class T, bool = __builtin_choose_expr(FIELD_OFFSET(T, y) > 0, true, false)> -char probe(int); - -template<class> -long probe(...); - -static_assert(sizeof(probe<S>(0)) == sizeof(char), ""); -// expected-error@-1 {{static assertion failed due to requirement 'sizeof (probe<S>(0)) == sizeof(char)'}} -// expected-note@-2 {{expression evaluates to '4 == 1'}} diff --git a/clang/test/SemaCXX/microsoft-constexpr.cpp b/clang/test/SemaCXX/microsoft-constexpr.cpp deleted file mode 100644 index a473e51a55f4c..0000000000000 --- a/clang/test/SemaCXX/microsoft-constexpr.cpp +++ /dev/null @@ -1,141 +0,0 @@ -// Some of this should fail in MSVC, but work in clang -// when -fms-compatibility is enabled. -// RUN: %clang -fsyntax-only -fms-compatibility -std=c++20 %s - -typedef long LONG; -typedef __int64 LONG_PTR, *PLONG_PTR; - -#define FIELD_OFFSET(type, field) ((LONG_PTR)&(((type *)0)->field)) - -struct S { - int x; - int y; -}; - -constexpr bool cb_eq = FIELD_OFFSET(S, y) == 4; -constexpr bool cb_ne = FIELD_OFFSET(S, y) != 0; -constexpr bool cb_lt = FIELD_OFFSET(S, y) < 8; -constexpr bool cb_le = FIELD_OFFSET(S, y) <= 4; -constexpr bool cb_gt = FIELD_OFFSET(S, y) > 0; -constexpr bool cb_ge = FIELD_OFFSET(S, y) >= 4; -constexpr bool cb_bool = FIELD_OFFSET(S, y); - -static_assert(FIELD_OFFSET(S, y) == 4); -static_assert(FIELD_OFFSET(S, y) != 0); -static_assert(FIELD_OFFSET(S, y) < 8); -static_assert(FIELD_OFFSET(S, y) <= 4); -static_assert(FIELD_OFFSET(S, y) > 0); -static_assert(FIELD_OFFSET(S, y) >= 4); -static_assert(FIELD_OFFSET(S, y)); - - -enum E { - enum_offset_y = FIELD_OFFSET(S, y), - enum_cmp_y = FIELD_OFFSET(S, y) == 4 -}; - -int arr_bound[FIELD_OFFSET(S, y)]; -int arr_bound_cmp[FIELD_OFFSET(S, y) == 4 ? 1 : -1]; - -struct BitField { - int bf1 : FIELD_OFFSET(S, y); - int bf2 : FIELD_OFFSET(S, y) == 4; -}; - -template<int N> -struct TplInt {}; - -template<bool B> -struct TplBool {}; - -TplInt<FIELD_OFFSET(S, y)> tpl_int; -TplBool<FIELD_OFFSET(S, y) == 4> tpl_bool; - -void f() noexcept(FIELD_OFFSET(S, y) == 4) {} - -template<class T> -void g() { - if constexpr (FIELD_OFFSET(S, y) == 4) { - } else { - } -} - -struct ExplicitCtor { - explicit(FIELD_OFFSET(S, y) == 4) ExplicitCtor(int) {} -}; - -alignas(FIELD_OFFSET(S,y)) int __g; - -constinit int constinit_offset = FIELD_OFFSET(S, y); -constinit bool constinit_bool = FIELD_OFFSET(S, y) == 4; - -constexpr int constexpr_offset = FIELD_OFFSET(S, y); -constexpr int constexpr_cmp_as_int = FIELD_OFFSET(S, y) == 4; -constexpr bool constexpr_bool = FIELD_OFFSET(S, y) == 4; - -int switch_test(int v) { - switch (v) { - case FIELD_OFFSET(S, y): - return 1; - case FIELD_OFFSET(S, x): - return 2; - default: - return 0; - } -} - -template<int N = FIELD_OFFSET(S, y)> -struct DefaultTplInt {}; - -template<bool B = FIELD_OFFSET(S, y) == 4> -struct DefaultTplBool {}; - -DefaultTplInt<> default_tpl_int; -DefaultTplBool<> default_tpl_bool; - -struct ArrayMember { - int a[FIELD_OFFSET(S, y)]; -}; - -union U { - char c; - int a[FIELD_OFFSET(S, y)]; -}; - -typedef char typedef_arr[FIELD_OFFSET(S, y)]; -using using_arr = char[FIELD_OFFSET(S, y)]; - -constexpr int ternary_offset = - FIELD_OFFSET(S, y) == 4 ? FIELD_OFFSET(S, y) : -1; - -constexpr bool logical_and = - FIELD_OFFSET(S, y) == 4 && FIELD_OFFSET(S, x) == 0; - -constexpr bool logical_or = - FIELD_OFFSET(S, y) == 4 || FIELD_OFFSET(S, x) == 123; - -constexpr bool logical_not = - !FIELD_OFFSET(S, x); - -constexpr int arithmetic_add = FIELD_OFFSET(S, y) + 1; -constexpr int arithmetic_sub = FIELD_OFFSET(S, y) - 1; -constexpr int arithmetic_mul = FIELD_OFFSET(S, y) * 2; -constexpr int arithmetic_div = FIELD_OFFSET(S, y) / 2; -constexpr int arithmetic_mod = FIELD_OFFSET(S, y) % 3; - -constexpr int bit_or = FIELD_OFFSET(S, y) | 1; -constexpr int bit_and = FIELD_OFFSET(S, y) & 7; -constexpr int bit_xor = FIELD_OFFSET(S, y) ^ 1; -constexpr int bit_shl = FIELD_OFFSET(S, y) << 1; -constexpr int bit_shr = FIELD_OFFSET(S, y) >> 1; - -constexpr int comma_expr = (0, FIELD_OFFSET(S, y)); - -constexpr int cast_int = (int)FIELD_OFFSET(S, y); -constexpr long cast_long = (long)FIELD_OFFSET(S, y); -constexpr bool cast_bool = (bool)FIELD_OFFSET(S, y); - -template<class T, int N> -struct DependentTpl {}; - -DependentTpl<S, FIELD_OFFSET(S, y)> dependent_tpl; diff --git a/clang/test/SemaCXX/microsoft-constexpr2.cpp b/clang/test/SemaCXX/microsoft-constexpr2.cpp deleted file mode 100644 index 2430f082909f1..0000000000000 --- a/clang/test/SemaCXX/microsoft-constexpr2.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -fms-compatibility -Wrelaxed-constant-fold %s - -typedef long long LONG_PTR; -typedef long LONG; -#define FIELD_OFFSET(type, field) ((LONG_PTR)&(((type *)0)->field)) -#define FIELD_OFFSET2(type, field) (reinterpret_cast<LONG_PTR>(&(((type *)0)->field))) - -struct S { - int x; - int y; -} ob; - - -template<bool B> -struct TplBool {}; - -template<int V> -struct TplInt {}; - -TplBool<FIELD_OFFSET(S, y)> tc; // expected-error {{non-type template argument evaluates to 4, which cannot be narrowed to type 'bool'}} - // expected-warning@-1 {{folding constant expression involving cast that performs the conversions of a reinterpret_cast is a Microsoft extension}} - // expected-warning@-2 {{folding constant expression that takes field address of null pointer is a Microsoft extension}} -TplInt<FIELD_OFFSET(S, y)> ti; // expected-warning {{folding constant expression involving cast that performs the conversions of a reinterpret_cast is a Microsoft extension}} - // expected-warning@-1 {{folding constant expression that takes field address of null pointer is a Microsoft extension}} -constexpr long b = FIELD_OFFSET(S, y); // expected-warning {{folding constant expression involving cast that performs the conversions of a reinterpret_cast is a Microsoft extension}} - // expected-warning@-1 {{folding constant expression that takes field address of null pointer is a Microsoft extension}} -constexpr long b2 = FIELD_OFFSET2(S, y); // expected-warning {{folding constant expression involving cast that performs the conversions of a reinterpret_cast is a Microsoft extension}} - // expected-warning@-1 {{folding constant expression that takes field address of null pointer is a Microsoft extension}} -constexpr LONG_PTR b3 = (LONG_PTR)&ob; // expected-error {{constexpr variable 'b3' must be initialized by a constant expression}} - // expected-note@-1 {{converting the address of an object to an integer is not allowed}} -constexpr int* b4 = reinterpret_cast<int*>(&ob); // expected-error {{constexpr variable 'b4' must be initialized by a constant expression}} - // expected-note@-1 {{reinterpret_cast is not allowed in a constant expression}} -constexpr LONG_PTR b5 = (42 - FIELD_OFFSET(S, y)) + // expected-error {{constexpr variable 'b5' must be initialized by a constant expression}} - (8 + reinterpret_cast<LONG_PTR>(&ob)); // expected-note {{converting the address of an object to an integer is not allowed}} -constexpr LONG_PTR b6 = -reinterpret_cast<LONG_PTR>(&ob); // expected-error {{constexpr variable 'b6' must be initialized by a constant expression}} - // expected-note@-1 {{converting the address of an object to an integer is not allowed}} -constexpr LONG_PTR b7[2] = { FIELD_OFFSET(S, y), (LONG_PTR)&ob }; // expected-error {{constexpr variable 'b7' must be initialized by a constant expression}} - // expected-note@-1 {{converting the address of an object to an integer is not allowed}} -constexpr LONG_PTR b8 = (LONG_PTR)((char*)1 + FIELD_OFFSET(S, y)); // expected-error {{constexpr variable 'b8' must be initialized by a constant expression}} - // expected-note@-1 {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}} -constexpr LONG_PTR b9 = (LONG_PTR)(FIELD_OFFSET(S, y) / 0); // expected-error {{constexpr variable 'b9' must be initialized by a constant expression}} - // expected-note@-1 {{division by zero}} diff --git a/clang/test/SemaCXX/microsoft-constexpr3.cpp b/clang/test/SemaCXX/microsoft-constexpr3.cpp deleted file mode 100644 index dd52bb8f81d32..0000000000000 --- a/clang/test/SemaCXX/microsoft-constexpr3.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Ignore dynamic_cast when relaxing constant expression with -fms-compatibility -// However using dynamic_cast is still possible in c++20 and higher -// RUN: not %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only %s -// RUN: %clang_cc1 -std=c++20 -fms-compatibility -fsyntax-only %s - -struct B { - virtual ~B() {} -}; - -struct D : B { - int x = 123; -}; - -#define IsD(x) (dynamic_cast<const D*>(x) != 0) - -static const D od; - -constexpr bool is_d = IsD(&od); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
