[clang] [clang][Interp] Handle virtual calls with covariant return types (PR #101218)
https://github.com/tbaederr closed https://github.com/llvm/llvm-project/pull/101218 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Interp] Fix the location of uninitialized base warning (PR #100761)
https://github.com/tbaederr approved this pull request. https://github.com/llvm/llvm-project/pull/100761 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Handle virtual calls with covariant return types (PR #101218)
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/101218 >From 78961fbfbd791844b1622aa305664199e3451260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 30 Jul 2024 20:11:37 +0200 Subject: [PATCH] [clang][Interp] Handle virtual calls with covariant return types --- clang/lib/AST/Interp/Interp.h | 24 +++- clang/test/AST/Interp/cxx2a.cpp | 21 + 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index d128988a480e1..63e9966b831db 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -2628,7 +2628,29 @@ inline bool CallVirt(InterpState , CodePtr OpPC, const Function *Func, } } - return Call(S, OpPC, Func, VarArgSize); + if (!Call(S, OpPC, Func, VarArgSize)) +return false; + + // Covariant return types. The return type of Overrider is a pointer + // or reference to a class type. + if (Overrider != InitialFunction && + Overrider->getReturnType()->isPointerOrReferenceType() && + InitialFunction->getReturnType()->isPointerOrReferenceType()) { +QualType OverriderPointeeType = +Overrider->getReturnType()->getPointeeType(); +QualType InitialPointeeType = +InitialFunction->getReturnType()->getPointeeType(); +// We've called Overrider above, but calling code expects us to return what +// InitialFunction returned. According to the rules for covariant return +// types, what InitialFunction returns needs to be a base class of what +// Overrider returns. So, we need to do an upcast here. +unsigned Offset = S.getContext().collectBaseOffset( +InitialPointeeType->getAsRecordDecl(), +OverriderPointeeType->getAsRecordDecl()); +return GetPtrBasePop(S, OpPC, Offset); + } + + return true; } inline bool CallBI(InterpState , CodePtr , const Function *Func, diff --git a/clang/test/AST/Interp/cxx2a.cpp b/clang/test/AST/Interp/cxx2a.cpp index 27d1aa1a27f75..ad021b30cfd3c 100644 --- a/clang/test/AST/Interp/cxx2a.cpp +++ b/clang/test/AST/Interp/cxx2a.cpp @@ -13,3 +13,24 @@ consteval int aConstevalFunction() { // both-error {{consteval function never pr return 0; } /// We're NOT calling the above function. The diagnostics should appear anyway. + +namespace Covariant { + struct A { +virtual constexpr char f() const { return 'Z'; } +char a = f(); + }; + + struct D : A {}; + struct Covariant1 { +D d; +virtual const A *f() const; + }; + + struct Covariant3 : Covariant1 { +constexpr virtual const D *f() const { return >d; } + }; + + constexpr Covariant3 cb; + constexpr const Covariant1 *cb1 = + static_assert(cb1->f()->a == 'Z'); +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][NFC] Add Type::isPointerOrReferenceType() (PR #101206)
https://github.com/tbaederr closed https://github.com/llvm/llvm-project/pull/101206 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Handle virtual calls with covariant return types (PR #101218)
Timm =?utf-8?q?Bäder?= Message-ID: In-Reply-To: https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/101218 None >From 2f54449a650b094a47309e3230557df1f195d384 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 30 Jul 2024 19:10:41 +0200 Subject: [PATCH 1/2] [clang][NFC] Add Type::isPointerOrReferenceType() --- clang/include/clang/AST/Type.h| 5 + clang/include/clang/Sema/Overload.h | 2 +- clang/lib/AST/ExprCXX.cpp | 2 +- clang/lib/AST/Interp/Context.cpp | 2 +- clang/lib/AST/ItaniumMangle.cpp | 2 +- clang/lib/AST/Type.cpp| 2 +- clang/lib/Analysis/Consumed.cpp | 10 +++--- clang/lib/Analysis/ThreadSafetyCommon.cpp | 2 +- clang/lib/Sema/SemaDecl.cpp | 6 +++--- clang/lib/Sema/SemaDeclAttr.cpp | 2 +- clang/lib/Sema/SemaExprCXX.cpp| 2 +- clang/lib/Sema/SemaTemplate.cpp | 2 +- 12 files changed, 20 insertions(+), 19 deletions(-) diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 89a74ff1fb285..dec51e032158e 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2509,6 +2509,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { bool isFunctionNoProtoType() const { return getAs(); } bool isFunctionProtoType() const { return getAs(); } bool isPointerType() const; + bool isPointerOrReferenceType() const; bool isSignableType() const; bool isAnyPointerType() const; // Any C pointer or ObjC object pointer bool isCountAttributedType() const; @@ -7996,6 +7997,10 @@ inline bool Type::isPointerType() const { return isa(CanonicalType); } +inline bool Type::isPointerOrReferenceType() const { + return isPointerType() || isReferenceType(); +} + inline bool Type::isAnyPointerType() const { return isPointerType() || isObjCObjectPointerType(); } diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index 26ffe057c74a2..d6a6cee62a752 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -984,7 +984,7 @@ class Sema; unsigned getNumParams() const { if (IsSurrogate) { QualType STy = Surrogate->getConversionType(); -while (STy->isPointerType() || STy->isReferenceType()) +while (STy->isPointerOrReferenceType()) STy = STy->getPointeeType(); return STy->castAs()->getNumParams(); } diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index e2c9643151126..6212989e21737 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -152,7 +152,7 @@ bool CXXTypeidExpr::isMostDerived(ASTContext ) const { const Expr *E = getExprOperand()->IgnoreParenNoopCasts(Context); if (const auto *DRE = dyn_cast(E)) { QualType Ty = DRE->getDecl()->getType(); -if (!Ty->isPointerType() && !Ty->isReferenceType()) +if (!Ty->isPointerOrReferenceType()) return true; } diff --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp index b5e992c5a9ac1..fd66e6fe8dcbc 100644 --- a/clang/lib/AST/Interp/Context.cpp +++ b/clang/lib/AST/Interp/Context.cpp @@ -176,7 +176,7 @@ std::optional Context::classify(QualType T) const { T->isFunctionType()) return PT_FnPtr; - if (T->isReferenceType() || T->isPointerType() || + if (T->isPointerOrReferenceType() || T->isObjCObjectPointerType()) return PT_Ptr; diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index d46d621d4c7d4..ead5da4e90f2f 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -6484,7 +6484,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue , case APValue::LValue: { // Proposed in https://github.com/itanium-cxx-abi/cxx-abi/issues/47. -assert((T->isPointerType() || T->isReferenceType()) && +assert((T->isPointerOrReferenceType()) && "unexpected type for LValue template arg"); if (V.isNullPointer()) { diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index fdaab8e434593..0456b5f96b210 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -75,7 +75,7 @@ bool Qualifiers::isStrictSupersetOf(Qualifiers Other) const { const IdentifierInfo* QualType::getBaseTypeIdentifier() const { const Type* ty = getTypePtr(); NamedDecl *ND = nullptr; - if (ty->isPointerType() || ty->isReferenceType()) + if (ty->isPointerOrReferenceType()) return ty->getPointeeType().getBaseTypeIdentifier(); else if (ty->isRecordType()) ND = ty->castAs()->getDecl(); diff --git a/clang/lib/Analysis/Consumed.cpp b/clang/lib/Analysis/Consumed.cpp index d01c7f688e8b5..63c5943242944 100644 --- a/clang/lib/Analysis/Consumed.cpp +++ b/clang/lib/Analysis/Consumed.cpp @@ -141,7 +141,7 @@ static bool isCallableInState(const
[clang] [Clang][Interp] Fix the location of uninitialized base warning (PR #100761)
@@ -122,19 +124,18 @@ static bool CheckFieldsInitialized(InterpState , SourceLocation Loc, } // Check Fields in all bases - for (const Record::Base : R->bases()) { + for (auto [I, B] : llvm::enumerate(R->bases())) { tbaederr wrote: Does `auto &[I, B]` work here? What about `const auto &`? https://github.com/llvm/llvm-project/pull/100761 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][NFC] Add Type::isPointerOrReferenceType() (PR #101206)
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/101206 >From 22debffc8fd3e0e5120f4a968ff788a040955448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 30 Jul 2024 19:10:41 +0200 Subject: [PATCH] [clang][NFC] Add Type::isPointerOrReferenceType() --- clang/include/clang/AST/Type.h| 5 + clang/include/clang/Sema/Overload.h | 2 +- clang/lib/AST/ExprCXX.cpp | 2 +- clang/lib/AST/Interp/Context.cpp | 3 +-- clang/lib/AST/ItaniumMangle.cpp | 2 +- clang/lib/AST/Type.cpp| 2 +- clang/lib/Analysis/Consumed.cpp | 10 +++--- clang/lib/Analysis/ThreadSafetyCommon.cpp | 2 +- clang/lib/Sema/SemaDecl.cpp | 12 ++-- clang/lib/Sema/SemaDeclAttr.cpp | 2 +- clang/lib/Sema/SemaExprCXX.cpp| 2 +- clang/lib/Sema/SemaTemplate.cpp | 2 +- 12 files changed, 23 insertions(+), 23 deletions(-) diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 89a74ff1fb285..dec51e032158e 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2509,6 +2509,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { bool isFunctionNoProtoType() const { return getAs(); } bool isFunctionProtoType() const { return getAs(); } bool isPointerType() const; + bool isPointerOrReferenceType() const; bool isSignableType() const; bool isAnyPointerType() const; // Any C pointer or ObjC object pointer bool isCountAttributedType() const; @@ -7996,6 +7997,10 @@ inline bool Type::isPointerType() const { return isa(CanonicalType); } +inline bool Type::isPointerOrReferenceType() const { + return isPointerType() || isReferenceType(); +} + inline bool Type::isAnyPointerType() const { return isPointerType() || isObjCObjectPointerType(); } diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index 26ffe057c74a2..d6a6cee62a752 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -984,7 +984,7 @@ class Sema; unsigned getNumParams() const { if (IsSurrogate) { QualType STy = Surrogate->getConversionType(); -while (STy->isPointerType() || STy->isReferenceType()) +while (STy->isPointerOrReferenceType()) STy = STy->getPointeeType(); return STy->castAs()->getNumParams(); } diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index e2c9643151126..6212989e21737 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -152,7 +152,7 @@ bool CXXTypeidExpr::isMostDerived(ASTContext ) const { const Expr *E = getExprOperand()->IgnoreParenNoopCasts(Context); if (const auto *DRE = dyn_cast(E)) { QualType Ty = DRE->getDecl()->getType(); -if (!Ty->isPointerType() && !Ty->isReferenceType()) +if (!Ty->isPointerOrReferenceType()) return true; } diff --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp index b5e992c5a9ac1..b1e06cd4d8a4c 100644 --- a/clang/lib/AST/Interp/Context.cpp +++ b/clang/lib/AST/Interp/Context.cpp @@ -176,8 +176,7 @@ std::optional Context::classify(QualType T) const { T->isFunctionType()) return PT_FnPtr; - if (T->isReferenceType() || T->isPointerType() || - T->isObjCObjectPointerType()) + if (T->isPointerOrReferenceType() || T->isObjCObjectPointerType()) return PT_Ptr; if (const auto *AT = T->getAs()) diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index d46d621d4c7d4..ead5da4e90f2f 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -6484,7 +6484,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue , case APValue::LValue: { // Proposed in https://github.com/itanium-cxx-abi/cxx-abi/issues/47. -assert((T->isPointerType() || T->isReferenceType()) && +assert((T->isPointerOrReferenceType()) && "unexpected type for LValue template arg"); if (V.isNullPointer()) { diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index fdaab8e434593..0456b5f96b210 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -75,7 +75,7 @@ bool Qualifiers::isStrictSupersetOf(Qualifiers Other) const { const IdentifierInfo* QualType::getBaseTypeIdentifier() const { const Type* ty = getTypePtr(); NamedDecl *ND = nullptr; - if (ty->isPointerType() || ty->isReferenceType()) + if (ty->isPointerOrReferenceType()) return ty->getPointeeType().getBaseTypeIdentifier(); else if (ty->isRecordType()) ND = ty->castAs()->getDecl(); diff --git a/clang/lib/Analysis/Consumed.cpp b/clang/lib/Analysis/Consumed.cpp index d01c7f688e8b5..63c5943242944 100644 --- a/clang/lib/Analysis/Consumed.cpp +++ b/clang/lib/Analysis/Consumed.cpp @@ -141,7 +141,7 @@ static bool
[clang] [clang][NFC] Add Type::isPointerOrReferenceType() (PR #101206)
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/101206 Seems to be a common pattern. >From be90760736b0b72e96d0aee5af521207811aebfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 30 Jul 2024 19:10:41 +0200 Subject: [PATCH] [clang][NFC] Add Type::isPointerOrReferenceType() --- clang/include/clang/AST/Type.h| 5 + clang/include/clang/Sema/Overload.h | 2 +- clang/lib/AST/ExprCXX.cpp | 2 +- clang/lib/AST/Interp/Context.cpp | 3 +-- clang/lib/AST/ItaniumMangle.cpp | 2 +- clang/lib/AST/Type.cpp| 2 +- clang/lib/Analysis/Consumed.cpp | 10 +++--- clang/lib/Analysis/ThreadSafetyCommon.cpp | 2 +- clang/lib/Sema/SemaDecl.cpp | 12 ++-- clang/lib/Sema/SemaDeclAttr.cpp | 2 +- clang/lib/Sema/SemaExprCXX.cpp| 2 +- clang/lib/Sema/SemaTemplate.cpp | 2 +- 12 files changed, 23 insertions(+), 23 deletions(-) diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 89a74ff1fb285..dec51e032158e 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2509,6 +2509,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { bool isFunctionNoProtoType() const { return getAs(); } bool isFunctionProtoType() const { return getAs(); } bool isPointerType() const; + bool isPointerOrReferenceType() const; bool isSignableType() const; bool isAnyPointerType() const; // Any C pointer or ObjC object pointer bool isCountAttributedType() const; @@ -7996,6 +7997,10 @@ inline bool Type::isPointerType() const { return isa(CanonicalType); } +inline bool Type::isPointerOrReferenceType() const { + return isPointerType() || isReferenceType(); +} + inline bool Type::isAnyPointerType() const { return isPointerType() || isObjCObjectPointerType(); } diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index 26ffe057c74a2..d6a6cee62a752 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -984,7 +984,7 @@ class Sema; unsigned getNumParams() const { if (IsSurrogate) { QualType STy = Surrogate->getConversionType(); -while (STy->isPointerType() || STy->isReferenceType()) +while (STy->isPointerOrReferenceType()) STy = STy->getPointeeType(); return STy->castAs()->getNumParams(); } diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index e2c9643151126..6212989e21737 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -152,7 +152,7 @@ bool CXXTypeidExpr::isMostDerived(ASTContext ) const { const Expr *E = getExprOperand()->IgnoreParenNoopCasts(Context); if (const auto *DRE = dyn_cast(E)) { QualType Ty = DRE->getDecl()->getType(); -if (!Ty->isPointerType() && !Ty->isReferenceType()) +if (!Ty->isPointerOrReferenceType()) return true; } diff --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp index b5e992c5a9ac1..b1e06cd4d8a4c 100644 --- a/clang/lib/AST/Interp/Context.cpp +++ b/clang/lib/AST/Interp/Context.cpp @@ -176,8 +176,7 @@ std::optional Context::classify(QualType T) const { T->isFunctionType()) return PT_FnPtr; - if (T->isReferenceType() || T->isPointerType() || - T->isObjCObjectPointerType()) + if (T->isPointerOrReferenceType() || T->isObjCObjectPointerType()) return PT_Ptr; if (const auto *AT = T->getAs()) diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index d46d621d4c7d4..ead5da4e90f2f 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -6484,7 +6484,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue , case APValue::LValue: { // Proposed in https://github.com/itanium-cxx-abi/cxx-abi/issues/47. -assert((T->isPointerType() || T->isReferenceType()) && +assert((T->isPointerOrReferenceType()) && "unexpected type for LValue template arg"); if (V.isNullPointer()) { diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index fdaab8e434593..0456b5f96b210 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -75,7 +75,7 @@ bool Qualifiers::isStrictSupersetOf(Qualifiers Other) const { const IdentifierInfo* QualType::getBaseTypeIdentifier() const { const Type* ty = getTypePtr(); NamedDecl *ND = nullptr; - if (ty->isPointerType() || ty->isReferenceType()) + if (ty->isPointerOrReferenceType()) return ty->getPointeeType().getBaseTypeIdentifier(); else if (ty->isRecordType()) ND = ty->castAs()->getDecl(); diff --git a/clang/lib/Analysis/Consumed.cpp b/clang/lib/Analysis/Consumed.cpp index d01c7f688e8b5..63c5943242944 100644 --- a/clang/lib/Analysis/Consumed.cpp +++ b/clang/lib/Analysis/Consumed.cpp @@ -141,7 +141,7 @@
[clang] [Clang][Interp] Fix the location of uninitialized base warning (PR #100761)
@@ -122,19 +124,21 @@ static bool CheckFieldsInitialized(InterpState , SourceLocation Loc, } // Check Fields in all bases - for (const Record::Base : R->bases()) { + for (auto [I, B] : llvm::enumerate(R->bases())) { Pointer P = BasePtr.atField(B.Offset); if (!P.isInitialized()) { const Descriptor *Desc = BasePtr.getDeclDesc(); - if (Desc->asDecl()) -S.FFDiag(BasePtr.getDeclDesc()->asDecl()->getLocation(), - diag::note_constexpr_uninitialized_base) + if (const auto *CD = dyn_cast_or_null(R->getDecl())) { tbaederr wrote: ```suggestion if (const auto *CD = dyn_cast_if_present(R->getDecl())) { ``` https://github.com/llvm/llvm-project/pull/100761 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Interp] Fix the location of uninitialized base warning (PR #100761)
@@ -122,19 +124,21 @@ static bool CheckFieldsInitialized(InterpState , SourceLocation Loc, } // Check Fields in all bases - for (const Record::Base : R->bases()) { + for (auto [I, B] : llvm::enumerate(R->bases())) { Pointer P = BasePtr.atField(B.Offset); if (!P.isInitialized()) { const Descriptor *Desc = BasePtr.getDeclDesc(); - if (Desc->asDecl()) -S.FFDiag(BasePtr.getDeclDesc()->asDecl()->getLocation(), - diag::note_constexpr_uninitialized_base) + if (const auto *CD = dyn_cast_or_null(R->getDecl())) { +const auto = *std::next(CD->bases_begin(), I); +S.FFDiag(BS.getBaseTypeLoc(), diag::note_constexpr_uninitialized_base) +<< B.Desc->getType() << BS.getSourceRange(); + } else { +SourceLocation Loc = +Desc->asDecl() ? BasePtr.getDeclDesc()->asDecl()->getLocation() + : BasePtr.getDeclDesc()->asExpr()->getExprLoc(); +S.FFDiag(Loc, diag::note_constexpr_uninitialized_base) tbaederr wrote: ```suggestion S.FFDiag(Desc->getLocation(), diag::note_constexpr_uninitialized_base) ``` https://github.com/llvm/llvm-project/pull/100761 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libclang/python] Export all enums (PR #100941)
tbaederr wrote: > @tbaederr CI for this patch has failed due to unrelated failure that is > likely to be connected to your work: That should be fixed already, I assume this is using an old version of the test. https://github.com/llvm/llvm-project/pull/100941 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Interp] Fix the location of uninitialized base warning (PR #100761)
tbaederr wrote: CC @AaronBallman @Sirraide @shafik Since this adds new API to `CXXBaseSpecifier`. https://github.com/llvm/llvm-project/pull/100761 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Interp] Fix the location of uninitialized base warning (PR #100761)
https://github.com/tbaederr commented: ![Screenshot from 2024-07-27 07-04-02](https://github.com/user-attachments/assets/5a7c4b26-2c68-4bb1-8480-4b7ff9e4be87) The three regressions all have similar stack traces: ``` #5 0x0bba9f4c clang::Redeclarable::getFirstDecl() /home/fedora/interp-tests/llvm-project/clang/include/clang/AST/Redeclarable.h:216:38 #6 0x0bba9cd5 clang::Redeclarable::getMostRecentDecl() /home/fedora/interp-tests/llvm-project/clang/include/clang/AST/Redeclarable.h:227:12 #7 0x0bba9a69 clang::RecordDecl::getMostRecentDecl() /home/fedora/interp-tests/llvm-project/clang/include/clang/AST/Decl.h:4168:59 #8 0x0bba99b5 clang::CXXRecordDecl::getMostRecentDecl() /home/fedora/interp-tests/llvm-project/clang/include/clang/AST/DeclCXX.h:542:46 #9 0x0bba9995 clang::CXXRecordDecl::getMostRecentDecl() const /home/fedora/interp-tests/llvm-project/clang/include/clang/AST/DeclCXX.h:546:5 #10 0x0bba9969 clang::CXXRecordDecl::dataPtr() const /home/fedora/interp-tests/llvm-project/clang/include/clang/AST/DeclCXX.h:458:5 #11 0x0bba9885 clang::CXXRecordDecl::data() const /home/fedora/interp-tests/llvm-project/clang/include/clang/AST/DeclCXX.h:463:11 #12 0x0bc92be5 clang::CXXRecordDecl::bases_begin() const /home/fedora/interp-tests/llvm-project/clang/include/clang/AST/DeclCXX.h:627:58 #13 0x0bc7a6a9 clang::CXXRecordDecl::bases() const /home/fedora/interp-tests/llvm-project/clang/include/clang/AST/DeclCXX.h:623:35 #14 0x127e9d9f clang::interp::CheckFieldsInitialized(clang::interp::InterpState&, clang::SourceLocation, clang::interp::Pointer const&, clang::interp::Record const*) /home/fedora/interp-tests/llvm-project/clang/lib/AST/Interp/EvaluationResult.cpp:127:41 ``` So I think it's cases where the decl is no CXXRecordDecl. This patch also drops the handling where the pointer descriptor was created for an expression - this might be relevant for those tests or not. https://github.com/llvm/llvm-project/pull/100761 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Interp] Fix the location of uninitialized base warning (PR #100761)
@@ -14,33 +14,29 @@ struct DelBase { constexpr DelBase() = delete; // expected-note {{'DelBase' has been explicitly marked deleted here}} tbaederr wrote: The second bullet point of the comment at the top of the file is obsolete now. https://github.com/llvm/llvm-project/pull/100761 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Interp] Fix the location of uninitialized base warning (PR #100761)
@@ -122,22 +122,20 @@ static bool CheckFieldsInitialized(InterpState , SourceLocation Loc, } // Check Fields in all bases - for (const Record::Base : R->bases()) { + unsigned BaseIndex = 0; + const CXXRecordDecl *CD = dyn_cast(R->getDecl()); tbaederr wrote: ```suggestion const auto *CD = dyn_cast(R->getDecl()); ``` https://github.com/llvm/llvm-project/pull/100761 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Interp] Fix the location of uninitialized base warning (PR #100761)
@@ -122,22 +122,20 @@ static bool CheckFieldsInitialized(InterpState , SourceLocation Loc, } // Check Fields in all bases - for (const Record::Base : R->bases()) { + unsigned BaseIndex = 0; + const CXXRecordDecl *CD = dyn_cast(R->getDecl()); tbaederr wrote: This either needs to be a `cast<>` or a null check. And I think it should be a null check. https://github.com/llvm/llvm-project/pull/100761 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Interp] Fix the location of uninitialized base warning (PR #100761)
@@ -122,22 +122,20 @@ static bool CheckFieldsInitialized(InterpState , SourceLocation Loc, } // Check Fields in all bases - for (const Record::Base : R->bases()) { + unsigned BaseIndex = 0; + const CXXRecordDecl *CD = dyn_cast(R->getDecl()); + for (const CXXBaseSpecifier : CD->bases()) { +const Record::Base = *R->getBase(BaseIndex); Pointer P = BasePtr.atField(B.Offset); if (!P.isInitialized()) { - const Descriptor *Desc = BasePtr.getDeclDesc(); - if (Desc->asDecl()) -S.FFDiag(BasePtr.getDeclDesc()->asDecl()->getLocation(), - diag::note_constexpr_uninitialized_base) -<< B.Desc->getType(); - else -S.FFDiag(BasePtr.getDeclDesc()->asExpr()->getExprLoc(), - diag::note_constexpr_uninitialized_base) -<< B.Desc->getType(); - + SourceLocation TypeBeginLoc = BS.getBaseTypeLoc(); + SourceRange Range(TypeBeginLoc, BS.getEndLoc()); tbaederr wrote: Is this different than `BS.getSourceRange()`? https://github.com/llvm/llvm-project/pull/100761 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Interp] Fix the location of uninitialized base warning (PR #100761)
@@ -122,22 +122,20 @@ static bool CheckFieldsInitialized(InterpState , SourceLocation Loc, } // Check Fields in all bases - for (const Record::Base : R->bases()) { + unsigned BaseIndex = 0; + const CXXRecordDecl *CD = dyn_cast(R->getDecl()); + for (const CXXBaseSpecifier : CD->bases()) { +const Record::Base = *R->getBase(BaseIndex); Pointer P = BasePtr.atField(B.Offset); if (!P.isInitialized()) { - const Descriptor *Desc = BasePtr.getDeclDesc(); - if (Desc->asDecl()) -S.FFDiag(BasePtr.getDeclDesc()->asDecl()->getLocation(), - diag::note_constexpr_uninitialized_base) -<< B.Desc->getType(); - else -S.FFDiag(BasePtr.getDeclDesc()->asExpr()->getExprLoc(), - diag::note_constexpr_uninitialized_base) -<< B.Desc->getType(); - + SourceLocation TypeBeginLoc = BS.getBaseTypeLoc(); + SourceRange Range(TypeBeginLoc, BS.getEndLoc()); + S.FFDiag(TypeBeginLoc, diag::note_constexpr_uninitialized_base) + << B.Desc->getType() << Range; return false; } Result &= CheckFieldsInitialized(S, Loc, P, B.R); +BaseIndex++; tbaederr wrote: ```suggestion ++BaseIndex; ``` https://github.com/llvm/llvm-project/pull/100761 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Interp] Fix the location of uninitialized base warning (PR #100761)
https://github.com/tbaederr edited https://github.com/llvm/llvm-project/pull/100761 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [NFC][Clang][Interp] Add more test for `__builtin_os_log_format_buffer_size` (PR #100566)
https://github.com/tbaederr approved this pull request. https://github.com/llvm/llvm-project/pull/100566 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Interp] Create the variable that holds the value of evaluating the binding (PR #100565)
tbaederr wrote: https://godbolt.org/z/a8TW93h63 Because it isn't a constant expression - at the time of the evaluation of the `static_assert`, the parameter value `cf` is unknown and so initializing `scf` can't work. Rejecting this is correct. https://github.com/llvm/llvm-project/pull/100565 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Interp] Visit `DecompositionDecl` and create a local variable (PR #100400)
@@ -5234,6 +5240,9 @@ bool Compiler::visitDeclRef(const ValueDecl *D, const Expr *E) { return false; }; +if (isa(VD)) tbaederr wrote: ```suggestion // DecompositionDecls are just proxies for us. if (isa(VD)) ``` https://github.com/llvm/llvm-project/pull/100400 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Interp] Visit `DecompositionDecl` and create a local variable (PR #100400)
https://github.com/tbaederr approved this pull request. LGTM with the suggested changes. This might not be perfect wrt. revisiting `DecompositionDecl`s, but we can handle problems when they arise. https://github.com/llvm/llvm-project/pull/100400 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Interp] Visit `DecompositionDecl` and create a local variable (PR #100400)
@@ -3593,8 +3593,14 @@ VarCreationState Compiler::visitDecl(const VarDecl *VD) { if (R.notCreated()) return R; - if (R) -return true; + if (R) { tbaederr wrote: Yes, remove it please. https://github.com/llvm/llvm-project/pull/100400 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Interp] Visit `DecompositionDecl` and create a local variable (PR #100400)
https://github.com/tbaederr edited https://github.com/llvm/llvm-project/pull/100400 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExprConst] Allow non-literal types in C++23 (PR #100062)
Timm =?utf-8?q?Bäder?= Message-ID: In-Reply-To: https://github.com/tbaederr closed https://github.com/llvm/llvm-project/pull/100062 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExprConst] Allow non-literal types in C++23 (PR #100062)
Timm =?utf-8?q?Bäder?= Message-ID: In-Reply-To: https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/100062 >From 695dff600a78e62ec65a964f80438661bd7a522c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 23 Jul 2024 07:02:23 +0200 Subject: [PATCH 1/2] [clang][ExprConst] Allow non-literal types in C++23 Instead of diagnosing non-literal types in C++23, allow them and later diagnose them differently, e.g. because they have a non-constexpr constructor, destructor, etc. --- clang/lib/AST/ExprConstant.cpp | 3 +++ clang/test/CXX/drs/cwg18xx.cpp | 12 .../test/SemaCXX/constant-expression-cxx11.cpp | 18 +++--- .../test/SemaCXX/constant-expression-cxx2b.cpp | 10 +- clang/test/SemaCXX/cxx23-invalid-constexpr.cpp | 13 ++--- 5 files changed, 33 insertions(+), 23 deletions(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index fcb382474ea62..6d4c91f54fcbf 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2404,6 +2404,9 @@ static bool CheckLiteralType(EvalInfo , const Expr *E, if (!E->isPRValue() || E->getType()->isLiteralType(Info.Ctx)) return true; + if (Info.getLangOpts().CPlusPlus23) +return true; + // C++1y: A constant initializer for an object o [...] may also invoke // constexpr constructors for o and its subobjects even if those objects // are of non-literal class types. diff --git a/clang/test/CXX/drs/cwg18xx.cpp b/clang/test/CXX/drs/cwg18xx.cpp index 323e56f9c5278..adfdb738e81c9 100644 --- a/clang/test/CXX/drs/cwg18xx.cpp +++ b/clang/test/CXX/drs/cwg18xx.cpp @@ -3,8 +3,8 @@ // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,cxx98-14,cxx11-17,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,cxx11-17,since-cxx11,since-cxx14,cxx17 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx23,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx23,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors #if __cplusplus == 199711L #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__) @@ -480,8 +480,12 @@ namespace cwg1872 { // cwg1872: 9 static_assert(y == 0); #endif constexpr int z = A().f(); - // since-cxx11-error@-1 {{constexpr variable 'z' must be initialized by a constant expression}} - // since-cxx11-note@-2 {{non-literal type 'A' cannot be used in a constant expression}} + // since-cxx11-error@-1 {{constexpr variable 'z' must be initialized by a constant expression}}a +#if __cplusplus < 202302L + // since-cxx11-note@-3 {{non-literal type 'A' cannot be used in a constant expression}} +#else + // since-cxx23-note@-5 {{cannot construct object of type 'A' with virtual base class in a constant expression}} +#endif #endif } diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index efb391ba0922d..6df8a4740d6cc 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -std=c++23 -isystem %S/Inputs -fsyntax-only -verify=expected,cxx20_23,cxx23-triple x86_64-linux -Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array -Wno-c99-designator -fcxx-exceptions -pedantic %s -Wno-comment -Wno-tautological-pointer-compare -Wno-bool-conversion -// RUN: %clang_cc1 -std=c++20 -isystem %S/Inputs -fsyntax-only -verify=expected,cxx11_20,cxx20_23 -triple x86_64-linux -Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array -Wno-c99-designator -fcxx-exceptions -pedantic %s -Wno-comment -Wno-tautological-pointer-compare -Wno-bool-conversion -// RUN: %clang_cc1 -std=c++11 -isystem %S/Inputs -fsyntax-only
[clang] [clang][ExprConst] Allow non-literal types in C++23 (PR #100062)
Timm =?utf-8?q?Bäder?= Message-ID: In-Reply-To: https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/100062 >From 18a4a08009ecd8e5a557d77028fc4efdbf5901ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 23 Jul 2024 07:02:23 +0200 Subject: [PATCH 1/2] [clang][ExprConst] Allow non-literal types in C++23 Instead of diagnosing non-literal types in C++23, allow them and later diagnose them differently, e.g. because they have a non-constexpr constructor, destructor, etc. --- clang/lib/AST/ExprConstant.cpp | 3 +++ clang/test/CXX/drs/cwg18xx.cpp | 12 .../test/SemaCXX/constant-expression-cxx11.cpp | 18 +++--- .../test/SemaCXX/constant-expression-cxx2b.cpp | 10 +- clang/test/SemaCXX/cxx23-invalid-constexpr.cpp | 13 ++--- 5 files changed, 33 insertions(+), 23 deletions(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 5af712dd7257b..a402e6f204aaf 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2404,6 +2404,9 @@ static bool CheckLiteralType(EvalInfo , const Expr *E, if (!E->isPRValue() || E->getType()->isLiteralType(Info.Ctx)) return true; + if (Info.getLangOpts().CPlusPlus23) +return true; + // C++1y: A constant initializer for an object o [...] may also invoke // constexpr constructors for o and its subobjects even if those objects // are of non-literal class types. diff --git a/clang/test/CXX/drs/cwg18xx.cpp b/clang/test/CXX/drs/cwg18xx.cpp index 323e56f9c5278..adfdb738e81c9 100644 --- a/clang/test/CXX/drs/cwg18xx.cpp +++ b/clang/test/CXX/drs/cwg18xx.cpp @@ -3,8 +3,8 @@ // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,cxx98-14,cxx11-17,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,cxx11-17,since-cxx11,since-cxx14,cxx17 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx23,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx23,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors #if __cplusplus == 199711L #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__) @@ -480,8 +480,12 @@ namespace cwg1872 { // cwg1872: 9 static_assert(y == 0); #endif constexpr int z = A().f(); - // since-cxx11-error@-1 {{constexpr variable 'z' must be initialized by a constant expression}} - // since-cxx11-note@-2 {{non-literal type 'A' cannot be used in a constant expression}} + // since-cxx11-error@-1 {{constexpr variable 'z' must be initialized by a constant expression}}a +#if __cplusplus < 202302L + // since-cxx11-note@-3 {{non-literal type 'A' cannot be used in a constant expression}} +#else + // since-cxx23-note@-5 {{cannot construct object of type 'A' with virtual base class in a constant expression}} +#endif #endif } diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index efb391ba0922d..6df8a4740d6cc 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -std=c++23 -isystem %S/Inputs -fsyntax-only -verify=expected,cxx20_23,cxx23-triple x86_64-linux -Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array -Wno-c99-designator -fcxx-exceptions -pedantic %s -Wno-comment -Wno-tautological-pointer-compare -Wno-bool-conversion -// RUN: %clang_cc1 -std=c++20 -isystem %S/Inputs -fsyntax-only -verify=expected,cxx11_20,cxx20_23 -triple x86_64-linux -Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array -Wno-c99-designator -fcxx-exceptions -pedantic %s -Wno-comment -Wno-tautological-pointer-compare -Wno-bool-conversion -// RUN: %clang_cc1 -std=c++11 -isystem %S/Inputs -fsyntax-only
[clang] [Clang][Interp] Diagnose use sizeless vector type as the argument of `__builtin_vectorelements` (PR #99794)
https://github.com/tbaederr approved this pull request. LGTM, thanks! https://github.com/llvm/llvm-project/pull/99794 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Interp] Diagnose use sizeless vector type as the argument of `__builtin_vectorelements` (PR #99794)
@@ -2735,6 +2736,13 @@ inline bool InvalidDeclRef(InterpState , CodePtr OpPC, return CheckDeclRef(S, OpPC, DR); } +inline bool SizelessVectorElementSize(InterpState , CodePtr OpPC) { tbaederr wrote: If you look at what the current interpreter does: 1) This should use `CCEDiag` instead and 2) the diagnostic should only be emitted if we're in a constant context https://github.com/llvm/llvm-project/pull/99794 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Interp] Diagnose use sizeless vector type as the argument of `__builtin_vectorelements` (PR #99794)
@@ -1698,10 +1698,8 @@ bool Compiler::VisitUnaryExprOrTypeTraitExpr( if (Kind == UETT_VectorElements) { if (const auto *VT = E->getTypeOfArgument()->getAs()) return this->emitConst(VT->getNumElements(), E); - -// FIXME: Apparently we need to catch the fact that a sizeless vector type -// has been passed and diagnose that (at run time). -assert(E->getTypeOfArgument()->isSizelessVectorType()); +if (E->getTypeOfArgument()->isSizelessVectorType()) + return this->emitSizelessVectorElementSize(E); tbaederr wrote: ```suggestion assert(E->getTypeOfArgument()->isSizelessVectorType()); return this->emitSizelessVectorElementSize(E); ``` https://github.com/llvm/llvm-project/pull/99794 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Interp] Diagnose use sizeless vector type as the argument of `__builtin_vectorelements` (PR #99794)
@@ -29,6 +29,7 @@ #include "State.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" +#include "clang/Basic/DiagnosticSema.h" tbaederr wrote: What do we need this include for? https://github.com/llvm/llvm-project/pull/99794 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
tbaederr wrote: Thanks for all the help with this issue. I think I figured it out - there was an unsigned wraparound some time before doing the actual allocation, which caused us to write over the bounds of the allocation. I've pushed https://github.com/llvm/llvm-project/commit/72b3d7bc87019ba7ef268ce322f90382f01b11af to ensure this doesn't happen and https://github.com/llvm/llvm-project/commit/e94e72a0c2293a02ea6c5335ac5fbc2d34de13f1 to implement the dynamic allocation management. https://github.com/llvm/llvm-project/pull/70306 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
tbaederr wrote: > I know there is UB in there > (https://github.com/llvm/llvm-project/issues/94741) so this is not > unsurprising. Ah, interesting. Didn't know about that issue https://github.com/llvm/llvm-project/pull/70306 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
tbaederr wrote: > You can also try it under qemu - > https://linaro.atlassian.net/wiki/spaces/TCWGPUB/pages/29360783374/How+to+Reproduce+32+bit+Arm+Builds+Without+Hardware. https://github.com/llvm/llvm-project/pull/70306 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
https://github.com/tbaederr closed https://github.com/llvm/llvm-project/pull/70306 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/70306 >From 8825030bcb7f2249fbc37a9911b8b5a7afc56d15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 25 Oct 2023 08:33:30 +0200 Subject: [PATCH] [clang][Interp] Implement dynamic memory allocation handling --- clang/lib/AST/CMakeLists.txt | 1 + clang/lib/AST/Interp/Compiler.cpp | 103 + clang/lib/AST/Interp/Compiler.h| 2 + clang/lib/AST/Interp/DynamicAllocator.cpp | 118 + clang/lib/AST/Interp/DynamicAllocator.h| 96 clang/lib/AST/Interp/EvalEmitter.cpp | 23 + clang/lib/AST/Interp/EvaluationResult.cpp | 72 +++ clang/lib/AST/Interp/EvaluationResult.h| 6 + clang/lib/AST/Interp/Interp.cpp| 52 +++ clang/lib/AST/Interp/Interp.h | 151 +++ clang/lib/AST/Interp/InterpBlock.h | 11 +- clang/lib/AST/Interp/InterpState.cpp | 17 + clang/lib/AST/Interp/InterpState.h | 11 + clang/lib/AST/Interp/Opcodes.td| 24 +- clang/lib/AST/Interp/Pointer.h | 1 + clang/test/AST/Interp/new-delete.cpp | 488 + clang/test/Rewriter/rewrite-modern-catch.m | 2 +- clang/test/SemaCXX/delete.cpp | 2 +- clang/test/SemaCXX/new-delete.cpp | 24 +- 19 files changed, 1196 insertions(+), 8 deletions(-) create mode 100644 clang/lib/AST/Interp/DynamicAllocator.cpp create mode 100644 clang/lib/AST/Interp/DynamicAllocator.h create mode 100644 clang/test/AST/Interp/new-delete.cpp diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index ceaad8d3c5a86..70aecb781c2ff 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -75,6 +75,7 @@ add_clang_library(clangAST Interp/InterpBuiltin.cpp Interp/Floating.cpp Interp/EvaluationResult.cpp + Interp/DynamicAllocator.cpp Interp/Interp.cpp Interp/InterpBlock.cpp Interp/InterpFrame.cpp diff --git a/clang/lib/AST/Interp/Compiler.cpp b/clang/lib/AST/Interp/Compiler.cpp index 30dc7f5e4840b..1f43f46c399f1 100644 --- a/clang/lib/AST/Interp/Compiler.cpp +++ b/clang/lib/AST/Interp/Compiler.cpp @@ -2771,6 +2771,109 @@ bool Compiler::VisitCXXInheritedCtorInitExpr( return this->emitCall(F, 0, E); } +template +bool Compiler::VisitCXXNewExpr(const CXXNewExpr *E) { + assert(classifyPrim(E->getType()) == PT_Ptr); + const Expr *Init = E->getInitializer(); + QualType ElementType = E->getAllocatedType(); + std::optional ElemT = classify(ElementType); + unsigned PlacementArgs = E->getNumPlacementArgs(); + bool IsNoThrow = false; + + // FIXME: Better diagnostic. diag::note_constexpr_new_placement + if (PlacementArgs != 0) { +// The only new-placement list we support is of the form (std::nothrow). +// +// FIXME: There is no restriction on this, but it's not clear that any +// other form makes any sense. We get here for cases such as: +// +// new (std::align_val_t{N}) X(int) +// +// (which should presumably be valid only if N is a multiple of +// alignof(int), and in any case can't be deallocated unless N is +// alignof(X) and X has new-extended alignment). +if (PlacementArgs != 1 || !E->getPlacementArg(0)->getType()->isNothrowT()) + return this->emitInvalid(E); + +if (!this->discard(E->getPlacementArg(0))) + return false; +IsNoThrow = true; + } + + const Descriptor *Desc; + if (ElemT) { +if (E->isArray()) + Desc = nullptr; // We're not going to use it in this case. +else + Desc = P.createDescriptor(E, *ElemT, Descriptor::InlineDescMD, +/*IsConst=*/false, /*IsTemporary=*/false, +/*IsMutable=*/false); + } else { +Desc = P.createDescriptor( +E, ElementType.getTypePtr(), +E->isArray() ? std::nullopt : Descriptor::InlineDescMD, +/*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false, Init); + } + + if (E->isArray()) { +std::optional ArraySizeExpr = E->getArraySize(); +if (!ArraySizeExpr) + return false; +PrimType SizeT = classifyPrim((*ArraySizeExpr)->getType()); + +if (!this->visit(*ArraySizeExpr)) + return false; + +if (ElemT) { + // N primitive elements. + if (!this->emitAllocN(SizeT, *ElemT, E, IsNoThrow, E)) +return false; +} else { + // N Composite elements. + if (!this->emitAllocCN(SizeT, Desc, IsNoThrow, E)) +return false; +} + +if (Init && !this->visitInitializer(Init)) + return false; + + } else { +// Allocate just one element. +if (!this->emitAlloc(Desc, E)) + return false; + +if (Init) { + if (ElemT) { +if (!this->visit(Init)) + return false; + +if (!this->emitInit(*ElemT, E)) + return false; + } else { +// Composite. +if (!this->visitInitializer(Init)) + return false; +
[clang] [clang] [Diagnostic] Clarify -Winfinite-recursion message (PR #98763)
https://github.com/tbaederr closed https://github.com/llvm/llvm-project/pull/98763 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Emit bad shift warnings (PR #70307)
https://github.com/tbaederr approved this pull request. https://github.com/llvm/llvm-project/pull/70307 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
@@ -2771,6 +2771,109 @@ bool Compiler::VisitCXXInheritedCtorInitExpr( return this->emitCall(F, 0, E); } +template +bool Compiler::VisitCXXNewExpr(const CXXNewExpr *E) { + assert(classifyPrim(E->getType()) == PT_Ptr); + const Expr *Init = E->getInitializer(); + QualType ElementType = E->getAllocatedType(); + std::optional ElemT = classify(ElementType); + unsigned PlacementArgs = E->getNumPlacementArgs(); + bool IsNoThrow = false; + + // FIXME: Better diagnostic. diag::note_constexpr_new_placement + if (PlacementArgs != 0) { +// The only new-placement list we support is of the form (std::nothrow). +// +// FIXME: There is no restriction on this, but it's not clear that any +// other form makes any sense. We get here for cases such as: tbaederr wrote: Yep, I saw. I'll wait for @cor3ntin to come up with the test cases though :) https://github.com/llvm/llvm-project/pull/70306 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/70306 >From 0731875f41bff19e228b0c31700293ed3379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 25 Oct 2023 08:33:30 +0200 Subject: [PATCH] [clang][Interp] Implement dynamic memory allocation handling --- clang/lib/AST/CMakeLists.txt | 1 + clang/lib/AST/Interp/Compiler.cpp | 103 + clang/lib/AST/Interp/Compiler.h| 2 + clang/lib/AST/Interp/DynamicAllocator.cpp | 118 + clang/lib/AST/Interp/DynamicAllocator.h| 96 clang/lib/AST/Interp/EvalEmitter.cpp | 23 + clang/lib/AST/Interp/EvaluationResult.cpp | 72 +++ clang/lib/AST/Interp/EvaluationResult.h| 6 + clang/lib/AST/Interp/Interp.cpp| 52 +++ clang/lib/AST/Interp/Interp.h | 151 +++ clang/lib/AST/Interp/InterpBlock.h | 11 +- clang/lib/AST/Interp/InterpState.cpp | 17 +- clang/lib/AST/Interp/InterpState.h | 11 + clang/lib/AST/Interp/Opcodes.td| 24 +- clang/lib/AST/Interp/Pointer.h | 1 + clang/test/AST/Interp/new-delete.cpp | 488 + clang/test/Rewriter/rewrite-modern-catch.m | 2 +- clang/test/SemaCXX/delete.cpp | 2 +- clang/test/SemaCXX/new-delete.cpp | 24 +- 19 files changed, 1195 insertions(+), 9 deletions(-) create mode 100644 clang/lib/AST/Interp/DynamicAllocator.cpp create mode 100644 clang/lib/AST/Interp/DynamicAllocator.h create mode 100644 clang/test/AST/Interp/new-delete.cpp diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index ceaad8d3c5a86..70aecb781c2ff 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -75,6 +75,7 @@ add_clang_library(clangAST Interp/InterpBuiltin.cpp Interp/Floating.cpp Interp/EvaluationResult.cpp + Interp/DynamicAllocator.cpp Interp/Interp.cpp Interp/InterpBlock.cpp Interp/InterpFrame.cpp diff --git a/clang/lib/AST/Interp/Compiler.cpp b/clang/lib/AST/Interp/Compiler.cpp index 48e7519f8f89d..4ac0e01df5768 100644 --- a/clang/lib/AST/Interp/Compiler.cpp +++ b/clang/lib/AST/Interp/Compiler.cpp @@ -2771,6 +2771,109 @@ bool Compiler::VisitCXXInheritedCtorInitExpr( return this->emitCall(F, 0, E); } +template +bool Compiler::VisitCXXNewExpr(const CXXNewExpr *E) { + assert(classifyPrim(E->getType()) == PT_Ptr); + const Expr *Init = E->getInitializer(); + QualType ElementType = E->getAllocatedType(); + std::optional ElemT = classify(ElementType); + unsigned PlacementArgs = E->getNumPlacementArgs(); + bool IsNoThrow = false; + + // FIXME: Better diagnostic. diag::note_constexpr_new_placement + if (PlacementArgs != 0) { +// The only new-placement list we support is of the form (std::nothrow). +// +// FIXME: There is no restriction on this, but it's not clear that any +// other form makes any sense. We get here for cases such as: +// +// new (std::align_val_t{N}) X(int) +// +// (which should presumably be valid only if N is a multiple of +// alignof(int), and in any case can't be deallocated unless N is +// alignof(X) and X has new-extended alignment). +if (PlacementArgs != 1 || !E->getPlacementArg(0)->getType()->isNothrowT()) + return this->emitInvalid(E); + +if (!this->discard(E->getPlacementArg(0))) + return false; +IsNoThrow = true; + } + + const Descriptor *Desc; + if (ElemT) { +if (E->isArray()) + Desc = nullptr; // We're not going to use it in this case. +else + Desc = P.createDescriptor(E, *ElemT, Descriptor::InlineDescMD, +/*IsConst=*/false, /*IsTemporary=*/false, +/*IsMutable=*/false); + } else { +Desc = P.createDescriptor( +E, ElementType.getTypePtr(), +E->isArray() ? std::nullopt : Descriptor::InlineDescMD, +/*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false, Init); + } + + if (E->isArray()) { +std::optional ArraySizeExpr = E->getArraySize(); +if (!ArraySizeExpr) + return false; +PrimType SizeT = classifyPrim((*ArraySizeExpr)->getType()); + +if (!this->visit(*ArraySizeExpr)) + return false; + +if (ElemT) { + // N primitive elements. + if (!this->emitAllocN(SizeT, *ElemT, E, IsNoThrow, E)) +return false; +} else { + // N Composite elements. + if (!this->emitAllocCN(SizeT, Desc, IsNoThrow, E)) +return false; +} + +if (Init && !this->visitInitializer(Init)) + return false; + + } else { +// Allocate just one element. +if (!this->emitAlloc(Desc, E)) + return false; + +if (Init) { + if (ElemT) { +if (!this->visit(Init)) + return false; + +if (!this->emitInit(*ElemT, E)) + return false; + } else { +// Composite. +if (!this->visitInitializer(Init)) + return false; +
[clang] [clang-tools-extra] [compiler-rt] clang::Linkage #71049 (PR #80064)
https://github.com/tbaederr closed https://github.com/llvm/llvm-project/pull/80064 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Refactor clang::Linkage (PR #80063)
https://github.com/tbaederr closed https://github.com/llvm/llvm-project/pull/80063 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Parser][ObjC] Add -Wobjc-prefix-length warning option. (PR #97597)
@@ -204,6 +204,89 @@ void Parser::CheckNestedObjCContexts(SourceLocation AtLoc) Diag(Decl->getBeginLoc(), diag::note_objc_container_start) << (int)ock; } +/// An Objective-C public name (a class name or protocol name) is +/// expected to have a prefix as all names are in a single global +/// namespace. +/// +/// If the `-Wobjc-prefix=` option is active, it specifies a list +/// of permitted prefixes; classes and protocols must start with a +/// prefix from that list. Note that in this case, we check that +/// the name matches (?)?, so e.g. +/// if you specify `-Wobjc-prefix=NS`, then `NSURL` would not be valid; +/// you would want to specify `-Wobjc-prefix=NS,NSURL` in that case. +/// +/// If the -Wobjc-prefix-length is set to N, the name must start +/// with N+1 capital letters, which must be followed by a character +/// that is not a capital letter. +/// +/// For instance, for N set to 2, the following are valid: +/// +/// NSString +/// NSArray +/// +/// but these are not: +/// +/// MyString +/// NSKString +/// NSnotAString +/// +/// We make a special exception for NSCF things when the prefix is set +/// to length 2, because that's an unusual special case in the implementation +/// of the Cocoa frameworks. +/// +/// Names that start with underscores are exempt from this check, but +/// are reserved for the system and should not be used by user code. +bool Parser::isObjCPublicNamePrefixAllowed(StringRef name) { tbaederr wrote: Newly introduced parameters and variables should start with an uppercase letter. https://github.com/llvm/llvm-project/pull/97597 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
Timm =?utf-8?q?Bäder?= Message-ID: In-Reply-To: https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/70306 >From a2213c595637d63b48658d2532e00b08fd05427f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Thu, 4 Jul 2024 07:26:27 +0200 Subject: [PATCH 1/2] [clang][Interp] Fix init chain in local initializers --- clang/lib/AST/Interp/Compiler.cpp | 4 +++- clang/test/AST/Interp/records.cpp | 12 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/Interp/Compiler.cpp b/clang/lib/AST/Interp/Compiler.cpp index 775cabf7f8c59..2af4c38c5ac3d 100644 --- a/clang/lib/AST/Interp/Compiler.cpp +++ b/clang/lib/AST/Interp/Compiler.cpp @@ -3577,6 +3577,7 @@ VarCreationState Compiler::visitVarDecl(const VarDecl *VD, bool Topleve return !Init || (checkDecl() && initGlobal(*GlobalIndex)); } else { VariableScope LocalScope(this, VD); +InitLinkScope ILS(this, InitLink::Decl(VD)); if (VarT) { unsigned Offset = this->allocateLocalPrimitive( @@ -3911,7 +3912,8 @@ bool Compiler::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) { SourceLocScope SLS(this, E); bool Old = InitStackActive; - InitStackActive = !isa(E->getUsedContext()); + InitStackActive = + !(E->getUsedContext()->getDeclKind() == Decl::CXXConstructor); bool Result = this->delegate(E->getExpr()); InitStackActive = Old; return Result; diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp index 9f341f5bc6d1d..1554e54275598 100644 --- a/clang/test/AST/Interp/records.cpp +++ b/clang/test/AST/Interp/records.cpp @@ -1482,3 +1482,15 @@ namespace FloatAPValue { ClassTemplateArgRefTemplate ClassTemplateArgRefObj; } #endif + +namespace LocalWithThisPtrInit { + struct S { +int i; +int *p = + }; + constexpr int foo() { +S s{2}; +return *s.p; + } + static_assert(foo() == 2, ""); +} >From 43f20bfd68556d7ba246f90599345077488c6a92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 25 Oct 2023 08:33:30 +0200 Subject: [PATCH 2/2] [clang][Interp] Implement dynamic memory allocation handling --- clang/lib/AST/CMakeLists.txt | 1 + clang/lib/AST/Interp/Compiler.cpp | 103 + clang/lib/AST/Interp/Compiler.h| 2 + clang/lib/AST/Interp/DynamicAllocator.cpp | 118 + clang/lib/AST/Interp/DynamicAllocator.h| 96 clang/lib/AST/Interp/EvalEmitter.cpp | 23 + clang/lib/AST/Interp/EvaluationResult.cpp | 72 +++ clang/lib/AST/Interp/EvaluationResult.h| 6 + clang/lib/AST/Interp/Interp.cpp| 52 +++ clang/lib/AST/Interp/Interp.h | 151 +++ clang/lib/AST/Interp/InterpBlock.h | 11 +- clang/lib/AST/Interp/InterpState.cpp | 17 +- clang/lib/AST/Interp/InterpState.h | 11 + clang/lib/AST/Interp/Opcodes.td| 24 +- clang/lib/AST/Interp/Pointer.h | 1 + clang/test/AST/Interp/new-delete.cpp | 488 + clang/test/Rewriter/rewrite-modern-catch.m | 2 +- clang/test/SemaCXX/delete.cpp | 2 +- clang/test/SemaCXX/new-delete.cpp | 22 +- 19 files changed, 1193 insertions(+), 9 deletions(-) create mode 100644 clang/lib/AST/Interp/DynamicAllocator.cpp create mode 100644 clang/lib/AST/Interp/DynamicAllocator.h create mode 100644 clang/test/AST/Interp/new-delete.cpp diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index ceaad8d3c5a86..70aecb781c2ff 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -75,6 +75,7 @@ add_clang_library(clangAST Interp/InterpBuiltin.cpp Interp/Floating.cpp Interp/EvaluationResult.cpp + Interp/DynamicAllocator.cpp Interp/Interp.cpp Interp/InterpBlock.cpp Interp/InterpFrame.cpp diff --git a/clang/lib/AST/Interp/Compiler.cpp b/clang/lib/AST/Interp/Compiler.cpp index 2af4c38c5ac3d..7ffec61e01d1d 100644 --- a/clang/lib/AST/Interp/Compiler.cpp +++ b/clang/lib/AST/Interp/Compiler.cpp @@ -2756,6 +2756,109 @@ bool Compiler::VisitCXXInheritedCtorInitExpr( return this->emitCall(F, 0, E); } +template +bool Compiler::VisitCXXNewExpr(const CXXNewExpr *E) { + assert(classifyPrim(E->getType()) == PT_Ptr); + const Expr *Init = E->getInitializer(); + QualType ElementType = E->getAllocatedType(); + std::optional ElemT = classify(ElementType); + unsigned PlacementArgs = E->getNumPlacementArgs(); + bool IsNoThrow = false; + + // FIXME: Better diagnostic. diag::note_constexpr_new_placement + if (PlacementArgs != 0) { +// The only new-placement list we support is of the form (std::nothrow). +// +// FIXME: There is no restriction on this, but it's not clear that any +// other form makes any sense. We get here for cases such as: +// +// new (std::align_val_t{N}) X(int) +// +// (which should presumably be valid only if N is a multiple of +// alignof(int), and
[clang] [Clang][ExprConstant] fix constant expression did not evaluate to integer (PR #97146)
@@ -15858,7 +15858,7 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult , } if (const auto *CE = dyn_cast(Exp)) { -if (CE->hasAPValueResult()) { +if (CE->hasAPValueResult() && !CE->getAPValueResult().isLValue()) { tbaederr wrote: It looks like `ConstantExpr::getAPValueResult()` will sometimes create a new APValue, so we should try ti call `getAPValueResult()` only once. https://github.com/llvm/llvm-project/pull/97146 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Implement function pointer type discrimination (PR #96992)
@@ -2220,6 +2220,11 @@ llvm::Constant *ConstantLValueEmitter::emitPointerAuthPointer(const Expr *E) { // The assertions here are all checked by Sema. assert(Result.Val.isLValue()); + const auto *Base = Result.Val.getLValueBase().get(); + if (const auto *Decl = dyn_cast_or_null(Base)) { tbaederr wrote: ```suggestion if (const auto *Decl = dyn_cast_if_present(Base)) { ``` https://github.com/llvm/llvm-project/pull/96992 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Merge ByteCodeExprGen and ByteCodeStmtGen (PR #83683)
tbaederr wrote: That failure looks like it's just a case of https://github.com/llvm/llvm-project/issues/54972 https://github.com/llvm/llvm-project/pull/83683 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Merge ByteCodeExprGen and ByteCodeStmtGen (PR #83683)
https://github.com/tbaederr closed https://github.com/llvm/llvm-project/pull/83683 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Merge ByteCodeExprGen and ByteCodeStmtGen (PR #83683)
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/83683 >From 74550f244eed465d4f0db1787eecb73a09d5881a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Sat, 2 Mar 2024 17:00:26 +0100 Subject: [PATCH] [clang][Interp] Merge ByteCode{Stmt,Expr}Gen --- clang/lib/AST/CMakeLists.txt |3 +- clang/lib/AST/Interp/ByteCodeStmtGen.cpp | 734 clang/lib/AST/Interp/ByteCodeStmtGen.h| 91 -- .../{ByteCodeExprGen.cpp => Compiler.cpp} | 1002 ++--- .../Interp/{ByteCodeExprGen.h => Compiler.h} | 93 +- clang/lib/AST/Interp/Context.cpp | 13 +- clang/lib/AST/Interp/EvalEmitter.h|1 + clang/lib/AST/Interp/Program.cpp |1 - 8 files changed, 911 insertions(+), 1027 deletions(-) delete mode 100644 clang/lib/AST/Interp/ByteCodeStmtGen.cpp delete mode 100644 clang/lib/AST/Interp/ByteCodeStmtGen.h rename clang/lib/AST/Interp/{ByteCodeExprGen.cpp => Compiler.cpp} (81%) rename clang/lib/AST/Interp/{ByteCodeExprGen.h => Compiler.h} (87%) diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 0328666d59b1f..ceaad8d3c5a86 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -65,8 +65,7 @@ add_clang_library(clangAST FormatString.cpp InheritViz.cpp Interp/ByteCodeEmitter.cpp - Interp/ByteCodeExprGen.cpp - Interp/ByteCodeStmtGen.cpp + Interp/Compiler.cpp Interp/Context.cpp Interp/Descriptor.cpp Interp/Disasm.cpp diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp deleted file mode 100644 index 0618ec1aa8f58..0 --- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ /dev/null @@ -1,734 +0,0 @@ -//===--- ByteCodeStmtGen.cpp - Code generator for expressions ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===--===// - -#include "ByteCodeStmtGen.h" -#include "ByteCodeEmitter.h" -#include "Context.h" -#include "Function.h" -#include "PrimType.h" - -using namespace clang; -using namespace clang::interp; - -namespace clang { -namespace interp { - -/// Scope managing label targets. -template class LabelScope { -public: - virtual ~LabelScope() { } - -protected: - LabelScope(ByteCodeStmtGen *Ctx) : Ctx(Ctx) {} - /// ByteCodeStmtGen instance. - ByteCodeStmtGen *Ctx; -}; - -/// Sets the context for break/continue statements. -template class LoopScope final : public LabelScope { -public: - using LabelTy = typename ByteCodeStmtGen::LabelTy; - using OptLabelTy = typename ByteCodeStmtGen::OptLabelTy; - - LoopScope(ByteCodeStmtGen *Ctx, LabelTy BreakLabel, -LabelTy ContinueLabel) - : LabelScope(Ctx), OldBreakLabel(Ctx->BreakLabel), -OldContinueLabel(Ctx->ContinueLabel) { -this->Ctx->BreakLabel = BreakLabel; -this->Ctx->ContinueLabel = ContinueLabel; - } - - ~LoopScope() { -this->Ctx->BreakLabel = OldBreakLabel; -this->Ctx->ContinueLabel = OldContinueLabel; - } - -private: - OptLabelTy OldBreakLabel; - OptLabelTy OldContinueLabel; -}; - -// Sets the context for a switch scope, mapping labels. -template class SwitchScope final : public LabelScope { -public: - using LabelTy = typename ByteCodeStmtGen::LabelTy; - using OptLabelTy = typename ByteCodeStmtGen::OptLabelTy; - using CaseMap = typename ByteCodeStmtGen::CaseMap; - - SwitchScope(ByteCodeStmtGen *Ctx, CaseMap &, - LabelTy BreakLabel, OptLabelTy DefaultLabel) - : LabelScope(Ctx), OldBreakLabel(Ctx->BreakLabel), -OldDefaultLabel(this->Ctx->DefaultLabel), -OldCaseLabels(std::move(this->Ctx->CaseLabels)) { -this->Ctx->BreakLabel = BreakLabel; -this->Ctx->DefaultLabel = DefaultLabel; -this->Ctx->CaseLabels = std::move(CaseLabels); - } - - ~SwitchScope() { -this->Ctx->BreakLabel = OldBreakLabel; -this->Ctx->DefaultLabel = OldDefaultLabel; -this->Ctx->CaseLabels = std::move(OldCaseLabels); - } - -private: - OptLabelTy OldBreakLabel; - OptLabelTy OldDefaultLabel; - CaseMap OldCaseLabels; -}; - -} // namespace interp -} // namespace clang - -template -bool ByteCodeStmtGen::emitLambdaStaticInvokerBody( -const CXXMethodDecl *MD) { - assert(MD->isLambdaStaticInvoker()); - assert(MD->hasBody()); - assert(cast(MD->getBody())->body_empty()); - - const CXXRecordDecl *ClosureClass = MD->getParent(); - const CXXMethodDecl *LambdaCallOp = ClosureClass->getLambdaCallOperator(); - assert(ClosureClass->captures_begin() == ClosureClass->captures_end()); - const Function *Func = this->getFunction(LambdaCallOp); - if (!Func) -return false; - assert(Func->hasThisPointer()); - assert(Func->getNumParams() == (MD->getNumParams() + 1 +
[clang] Performance optimizations for function effects (nonblocking attribute etc.) (PR #96844)
tbaederr wrote: I guess you meant to link to https://llvm-compile-time-tracker.com/compare.php?from=f03cb005eb4ba3c6fb645aca2228e907db8cd452=038b39d3235c6c8151127c34d34f498dd298273c=instructions:u directly? https://github.com/llvm/llvm-project/pull/96844 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][test] Enable a commented-out test (PR #96195)
https://github.com/tbaederr closed https://github.com/llvm/llvm-project/pull/96195 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Clang: Support minimumnum and maximumnum intrinsics (PR #96281)
@@ -215,6 +215,18 @@ def FminF16F128 : Builtin, F16F128MathTemplate { let Prototype = "T(T, T)"; } +def FmaximumNumF16F128 : Builtin, F16F128MathTemplate { + let Spellings = ["__builtin_fmaximum_num"]; + let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const, Constexpr]; + let Prototype = "T(T, T)"; +} + +def FminimumNumF16F128 : Builtin, F16F128MathTemplate { + let Spellings = ["__builtin_fminimum_num"]; + let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const, Constexpr]; tbaederr wrote: Where's the constexpr implementation? https://github.com/llvm/llvm-project/pull/96281 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] WIP: Warn on mismatched RequiresCapability attributes (PR #67520)
tbaederr wrote: > I tried out this WIP on our codebase after we ran into a problem where an > annotation was added to a definition rather than a declaration, leading to a > (silently) missed capability check. > > This addition seems to work fine, but it triggers warnings when annotations > are added to both the definition and declaration. This can be seen here: > [bitcoin/bitcoin#30316](https://github.com/bitcoin/bitcoin/pull/30316) > > I went ahead and PR'd the removals because they're straightforward enough, > but it seems (to me) that those these are all false positives. If the same > annotation is listed in the declaration and definition, should it really warn? No I don't think it should, at least that was not the intention of this patch. As it is right now, the code should warn for attributes listed in the definition, but _now_ in the declaration(s). https://github.com/llvm/llvm-project/pull/67520 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] Reland [clang][Sema, Lex, Parse] Preprocessor embed in C and C++ (PR #95802)
tbaederr wrote: I just pushed https://github.com/llvm/llvm-project/commit/99f5fcb0d1e04125daa404ff14c9cd14b7a2c40b - I don't have time to run _all_ the tests though, so this is a bit of a long shot. If that doesn't fix it, then disabling them for now sounds fine to me. https://github.com/llvm/llvm-project/pull/95802 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] Reland [clang][Sema, Lex, Parse] Preprocessor embed in C and C++ (PR #95802)
tbaederr wrote: Here's a quick patch with the cast inserted: ```diff diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 731153a6ead9..e7fa1a62c277 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -1346,13 +1346,30 @@ bool ByteCodeExprGen::visitInitList(ArrayRef Inits, } } -auto Eval = [&](Expr *Init, unsigned ElemIndex) { - return visitArrayElemInit(ElemIndex, Init); -}; - +E->dump(); unsigned ElementIndex = 0; for (const Expr *Init : Inits) { - if (auto *EmbedS = dyn_cast(Init->IgnoreParenImpCasts())) { + if (const auto *EmbedS = dyn_cast(Init->IgnoreParenImpCasts())) { +QualType TargetType = Init->getType(); +PrimType TargetT = classifyPrim(Init->getType()); +TargetType->dump(); + + +auto Eval = [&](const Expr *Init, unsigned ElemIndex) { + PrimType InitT = classifyPrim(Init->getType()); + if (!this->visit(Init)) +return false; + if (InitT != TargetT) { +if (!this->emitCast(InitT, TargetT, E)) + return false; + } +return this->emitInitElem(TargetT, ElemIndex, Init); +}; + + + + + if (!EmbedS->doForEachDataElement(Eval, ElementIndex)) return false; } else { ``` Can you check if that fixes the problem? https://github.com/llvm/llvm-project/pull/95802 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] Reland [clang][Sema, Lex, Parse] Preprocessor embed in C and C++ (PR #95802)
tbaederr wrote: Do you have a smaller reproducer? Are all the failing build bots big endian? https://github.com/llvm/llvm-project/pull/95802 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][test] Enable a commented-out test (PR #96195)
https://github.com/tbaederr edited https://github.com/llvm/llvm-project/pull/96195 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][test] Enable a commented-out test (PR #96195)
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/96195 I can't reproduce the assertion failure locally, let's see that the precommit CI says about it. >From 4aa4c6cb272852cbaa48267d8e21463d14d3309f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Thu, 20 Jun 2024 16:20:51 +0200 Subject: [PATCH] [clang][test] Enable a commented-out test --- clang/test/CodeGenCXX/temporaries.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/test/CodeGenCXX/temporaries.cpp b/clang/test/CodeGenCXX/temporaries.cpp index 186f4934873fa..f992ce206c581 100644 --- a/clang/test/CodeGenCXX/temporaries.cpp +++ b/clang/test/CodeGenCXX/temporaries.cpp @@ -683,8 +683,7 @@ namespace Vector { // CHECK: store i32 {{.*}}, ptr @_ZGRN6Vector1sE_ // CHECK: store ptr @_ZGRN6Vector1sE_, ptr @_ZN6Vector1sE, int & = S().w[1]; - // FIXME PR16204: The following code leads to an assertion in Sema. - //int & = S().w.y; + int & = S().w.y; } namespace ImplicitTemporaryCleanup { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/70306 >From 34b15ca688eef0fd0c23298957faaa6342d15cfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 25 Oct 2023 08:33:30 +0200 Subject: [PATCH] [clang][Interp] Implement dynamic memory allocation handling --- clang/lib/AST/CMakeLists.txt | 1 + clang/lib/AST/Interp/ByteCodeExprGen.cpp | 103 + clang/lib/AST/Interp/ByteCodeExprGen.h | 2 + clang/lib/AST/Interp/DynamicAllocator.cpp | 118 + clang/lib/AST/Interp/DynamicAllocator.h| 95 clang/lib/AST/Interp/EvalEmitter.cpp | 23 + clang/lib/AST/Interp/EvaluationResult.cpp | 72 +++ clang/lib/AST/Interp/EvaluationResult.h| 6 + clang/lib/AST/Interp/Interp.cpp| 52 +++ clang/lib/AST/Interp/Interp.h | 149 +++ clang/lib/AST/Interp/InterpBlock.h | 21 +- clang/lib/AST/Interp/InterpState.cpp | 17 +- clang/lib/AST/Interp/InterpState.h | 11 + clang/lib/AST/Interp/Opcodes.td| 24 +- clang/lib/AST/Interp/Pointer.h | 1 + clang/test/AST/Interp/new-delete.cpp | 488 + clang/test/Rewriter/rewrite-modern-catch.m | 2 +- clang/test/SemaCXX/delete.cpp | 2 +- clang/test/SemaCXX/new-delete.cpp | 22 +- 19 files changed, 1196 insertions(+), 13 deletions(-) create mode 100644 clang/lib/AST/Interp/DynamicAllocator.cpp create mode 100644 clang/lib/AST/Interp/DynamicAllocator.h create mode 100644 clang/test/AST/Interp/new-delete.cpp diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 0328666d59b1f..df27f1239abe4 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -76,6 +76,7 @@ add_clang_library(clangAST Interp/InterpBuiltin.cpp Interp/Floating.cpp Interp/EvaluationResult.cpp + Interp/DynamicAllocator.cpp Interp/Interp.cpp Interp/InterpBlock.cpp Interp/InterpFrame.cpp diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 06e54e4baaaf5..4eb258c12cafd 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -2656,6 +2656,109 @@ bool ByteCodeExprGen::VisitCXXInheritedCtorInitExpr( return this->emitCall(F, 0, E); } +template +bool ByteCodeExprGen::VisitCXXNewExpr(const CXXNewExpr *E) { + assert(classifyPrim(E->getType()) == PT_Ptr); + const Expr *Init = E->getInitializer(); + QualType ElementType = E->getAllocatedType(); + std::optional ElemT = classify(ElementType); + unsigned PlacementArgs = E->getNumPlacementArgs(); + bool IsNoThrow = false; + + // FIXME: Better diagnostic. diag::note_constexpr_new_placement + if (PlacementArgs != 0) { +// The only new-placement list we support is of the form (std::nothrow). +// +// FIXME: There is no restriction on this, but it's not clear that any +// other form makes any sense. We get here for cases such as: +// +// new (std::align_val_t{N}) X(int) +// +// (which should presumably be valid only if N is a multiple of +// alignof(int), and in any case can't be deallocated unless N is +// alignof(X) and X has new-extended alignment). +if (PlacementArgs != 1 || !E->getPlacementArg(0)->getType()->isNothrowT()) + return this->emitInvalid(E); + +if (!this->discard(E->getPlacementArg(0))) + return false; +IsNoThrow = true; + } + + const Descriptor *Desc; + if (ElemT) { +if (E->isArray()) + Desc = nullptr; // We're not going to use it in this case. +else + Desc = P.createDescriptor(E, *ElemT, Descriptor::InlineDescMD, +/*IsConst=*/false, /*IsTemporary=*/false, +/*IsMutable=*/false); + } else { +Desc = P.createDescriptor( +E, ElementType.getTypePtr(), +E->isArray() ? std::nullopt : Descriptor::InlineDescMD, +/*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false, Init); + } + + if (E->isArray()) { +std::optional ArraySizeExpr = E->getArraySize(); +if (!ArraySizeExpr) + return false; +PrimType SizeT = classifyPrim((*ArraySizeExpr)->getType()); + +if (!this->visit(*ArraySizeExpr)) + return false; + +if (ElemT) { + // N primitive elements. + if (!this->emitAllocN(SizeT, *ElemT, E, IsNoThrow, E)) +return false; +} else { + // N Composite elements. + if (!this->emitAllocCN(SizeT, Desc, IsNoThrow, E)) +return false; +} + +if (Init && !this->visitInitializer(Init)) + return false; + + } else { +// Allocate just one element. +if (!this->emitAlloc(Desc, E)) + return false; + +if (Init) { + if (ElemT) { +if (!this->visit(Init)) + return false; + +if (!this->emitInit(*ElemT, E)) + return false; + } else { +// Composite. +if
[clang] [clang] WIP: Warn on mismatched RequiresCapability attributes (PR #67520)
tbaederr wrote: I've resorted to do this in `ThreadSafety.cpp` now, since all other places where we merge function definition and declaration happen before we have the late-parsed attributes available. >From a diagnostic POV, this seems quite complicated since we have N >declarations and need to report differences in M attributes (and each one of >them can have >=1 parameter...). For the POC implementation here, I've left if >with just reporting a mismatch in attributes. For example with >`test/SemaCXX/warn-thread-safety-analysis.cpp`: ```console error: 'expected-warning' diagnostics seen but not expected: File /home/tbaeder/code/llvm-project/clang/test/SemaCXX/warn-thread-safety-analysis.cpp Line 2171: attribute mismatch between function definition and declaration of 'foo2' File /home/tbaeder/code/llvm-project/clang/test/SemaCXX/warn-thread-safety-analysis.cpp Line 2172: attribute mismatch between function definition and declaration of 'foo3' File /home/tbaeder/code/llvm-project/clang/test/SemaCXX/warn-thread-safety-analysis.cpp Line : attribute mismatch between function definition and declaration of 'fooF2' File /home/tbaeder/code/llvm-project/clang/test/SemaCXX/warn-thread-safety-analysis.cpp Line 3182: attribute mismatch between function definition and declaration of 'foo1' File /home/tbaeder/code/llvm-project/clang/test/SemaCXX/warn-thread-safety-analysis.cpp Line 3183: attribute mismatch between function definition and declaration of 'foo2' File /home/tbaeder/code/llvm-project/clang/test/SemaCXX/warn-thread-safety-analysis.cpp Line 5220: attribute mismatch between function definition and declaration of 'test' File /home/tbaeder/code/llvm-project/clang/test/SemaCXX/warn-thread-safety-analysis.cpp Line 5221: attribute mismatch between function definition and declaration of 'test2' ``` https://github.com/llvm/llvm-project/pull/67520 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] WIP: Warn on mismatched RequiresCapability attributes (PR #67520)
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/67520 >From 800ce47e967593ec149e0187abf6d2cb3ee1b1b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Thu, 20 Jun 2024 07:39:20 +0200 Subject: [PATCH] Warn on RequiresCapability attribute mismatch --- .../clang/Analysis/Analyses/ThreadSafety.h| 4 +++ .../clang/Basic/DiagnosticSemaKinds.td| 4 ++- clang/lib/Analysis/ThreadSafety.cpp | 34 +++ clang/lib/Sema/AnalysisBasedWarnings.cpp | 7 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Analysis/Analyses/ThreadSafety.h b/clang/include/clang/Analysis/Analyses/ThreadSafety.h index 0866b09bab299..169eef811f579 100644 --- a/clang/include/clang/Analysis/Analyses/ThreadSafety.h +++ b/clang/include/clang/Analysis/Analyses/ThreadSafety.h @@ -26,6 +26,7 @@ namespace clang { class AnalysisDeclContext; class FunctionDecl; class NamedDecl; +class Attr; namespace threadSafety { @@ -230,6 +231,9 @@ class ThreadSafetyHandler { /// Warn that there is a cycle in acquired_before/after dependencies. virtual void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) {} + virtual void handleAttributeMismatch(const FunctionDecl *FD1, + const FunctionDecl *FD2) {} + /// Called by the analysis when starting analysis of a function. /// Used to issue suggestions for changes to annotations. virtual void enterFunction(const FunctionDecl *FD) {} diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 14736784cff5f..4e8e6f66ebc8f 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3978,7 +3978,9 @@ def warn_acquired_before : Warning< def warn_acquired_before_after_cycle : Warning< "cycle in acquired_before/after dependencies, starting with '%0'">, InGroup, DefaultIgnore; - +def warn_attribute_mismatch : Warning< + "attribute mismatch between function definition and declaration of %0">, + InGroup, DefaultIgnore; // Thread safety warnings negative capabilities def warn_acquire_requires_negative_cap : Warning< diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp index e25b843c9bf83..6051a5e9d6bd9 100644 --- a/clang/lib/Analysis/ThreadSafety.cpp +++ b/clang/lib/Analysis/ThreadSafety.cpp @@ -2260,6 +2260,37 @@ static bool neverReturns(const CFGBlock *B) { return false; } +template +static SmallVector collectAttrArgs(const FunctionDecl *FD) { + SmallVector Args; + for (const AttrT *A : FD->specific_attrs()) { +for (const Expr *E : A->args()) + Args.push_back(E); + } + + return Args; +} + +static void diagnoseMismatchedFunctionAttrs(const FunctionDecl *FD, +ThreadSafetyHandler ) { + assert(FD); + FD = FD->getDefinition(); + assert(FD); + auto FDArgs = collectAttrArgs(FD); + + for (const FunctionDecl *D = FD->getPreviousDecl(); D; + D = D->getPreviousDecl()) { +auto DArgs = collectAttrArgs(D); + +for (const Expr *E : FDArgs) { + if (!llvm::is_contained(DArgs, E)) { +// FD requires E, but D doesn't. +Handler.handleAttributeMismatch(FD, D); + } +} + } +} + /// Check a function's CFG for thread-safety violations. /// /// We traverse the blocks in the CFG, compute the set of mutexes that are held @@ -2279,6 +2310,9 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext ) { const NamedDecl *D = walker.getDecl(); CurrentFunction = dyn_cast(D); + if (CurrentFunction) +diagnoseMismatchedFunctionAttrs(CurrentFunction, Handler); + if (D->hasAttr()) return; diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 0f604c61fa3af..02d60a803d77a 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2073,6 +2073,13 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler { Warnings.emplace_back(std::move(Warning), getNotes()); } + void handleAttributeMismatch(const FunctionDecl *FD1, + const FunctionDecl *FD2) override { +PartialDiagnosticAt Warning(FD2->getLocation(), +S.PDiag(diag::warn_attribute_mismatch) << FD1); +Warnings.emplace_back(std::move(Warning), getNotes()); + } + void enterFunction(const FunctionDecl* FD) override { CurrentFunction = FD; } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/70306 >From c36e40f5454ebb50e8ec6b83d50ac988f8aa780c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 25 Oct 2023 08:33:30 +0200 Subject: [PATCH] [clang][Interp] Implement dynamic memory allocation handling --- clang/lib/AST/CMakeLists.txt | 1 + clang/lib/AST/Interp/ByteCodeExprGen.cpp | 103 + clang/lib/AST/Interp/ByteCodeExprGen.h | 2 + clang/lib/AST/Interp/Context.cpp | 2 + clang/lib/AST/Interp/DynamicAllocator.cpp | 118 + clang/lib/AST/Interp/DynamicAllocator.h| 95 clang/lib/AST/Interp/EvalEmitter.cpp | 23 + clang/lib/AST/Interp/EvaluationResult.cpp | 72 +++ clang/lib/AST/Interp/EvaluationResult.h| 6 + clang/lib/AST/Interp/Interp.cpp| 52 +++ clang/lib/AST/Interp/Interp.h | 149 +++ clang/lib/AST/Interp/InterpBlock.h | 21 +- clang/lib/AST/Interp/InterpState.cpp | 17 +- clang/lib/AST/Interp/InterpState.h | 11 + clang/lib/AST/Interp/Opcodes.td| 24 +- clang/lib/AST/Interp/Pointer.h | 1 + clang/test/AST/Interp/new-delete.cpp | 488 + clang/test/Rewriter/rewrite-modern-catch.m | 2 +- clang/test/SemaCXX/delete.cpp | 2 +- clang/test/SemaCXX/new-delete.cpp | 22 +- 20 files changed, 1198 insertions(+), 13 deletions(-) create mode 100644 clang/lib/AST/Interp/DynamicAllocator.cpp create mode 100644 clang/lib/AST/Interp/DynamicAllocator.h create mode 100644 clang/test/AST/Interp/new-delete.cpp diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 0328666d59b1f..df27f1239abe4 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -76,6 +76,7 @@ add_clang_library(clangAST Interp/InterpBuiltin.cpp Interp/Floating.cpp Interp/EvaluationResult.cpp + Interp/DynamicAllocator.cpp Interp/Interp.cpp Interp/InterpBlock.cpp Interp/InterpFrame.cpp diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 06e54e4baaaf5..4eb258c12cafd 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -2656,6 +2656,109 @@ bool ByteCodeExprGen::VisitCXXInheritedCtorInitExpr( return this->emitCall(F, 0, E); } +template +bool ByteCodeExprGen::VisitCXXNewExpr(const CXXNewExpr *E) { + assert(classifyPrim(E->getType()) == PT_Ptr); + const Expr *Init = E->getInitializer(); + QualType ElementType = E->getAllocatedType(); + std::optional ElemT = classify(ElementType); + unsigned PlacementArgs = E->getNumPlacementArgs(); + bool IsNoThrow = false; + + // FIXME: Better diagnostic. diag::note_constexpr_new_placement + if (PlacementArgs != 0) { +// The only new-placement list we support is of the form (std::nothrow). +// +// FIXME: There is no restriction on this, but it's not clear that any +// other form makes any sense. We get here for cases such as: +// +// new (std::align_val_t{N}) X(int) +// +// (which should presumably be valid only if N is a multiple of +// alignof(int), and in any case can't be deallocated unless N is +// alignof(X) and X has new-extended alignment). +if (PlacementArgs != 1 || !E->getPlacementArg(0)->getType()->isNothrowT()) + return this->emitInvalid(E); + +if (!this->discard(E->getPlacementArg(0))) + return false; +IsNoThrow = true; + } + + const Descriptor *Desc; + if (ElemT) { +if (E->isArray()) + Desc = nullptr; // We're not going to use it in this case. +else + Desc = P.createDescriptor(E, *ElemT, Descriptor::InlineDescMD, +/*IsConst=*/false, /*IsTemporary=*/false, +/*IsMutable=*/false); + } else { +Desc = P.createDescriptor( +E, ElementType.getTypePtr(), +E->isArray() ? std::nullopt : Descriptor::InlineDescMD, +/*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false, Init); + } + + if (E->isArray()) { +std::optional ArraySizeExpr = E->getArraySize(); +if (!ArraySizeExpr) + return false; +PrimType SizeT = classifyPrim((*ArraySizeExpr)->getType()); + +if (!this->visit(*ArraySizeExpr)) + return false; + +if (ElemT) { + // N primitive elements. + if (!this->emitAllocN(SizeT, *ElemT, E, IsNoThrow, E)) +return false; +} else { + // N Composite elements. + if (!this->emitAllocCN(SizeT, Desc, IsNoThrow, E)) +return false; +} + +if (Init && !this->visitInitializer(Init)) + return false; + + } else { +// Allocate just one element. +if (!this->emitAlloc(Desc, E)) + return false; + +if (Init) { + if (ElemT) { +if (!this->visit(Init)) + return false; + +if (!this->emitInit(*ElemT, E)) + return false; + } else
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
Timm =?utf-8?q?Bäder?= , Timm =?utf-8?q?Bäder?= , Timm =?utf-8?q?Bäder?= Message-ID: In-Reply-To: @@ -2544,6 +2544,85 @@ bool ByteCodeExprGen::VisitCXXInheritedCtorInitExpr( return this->emitCall(F, 0, E); } +template +bool ByteCodeExprGen::VisitCXXNewExpr(const CXXNewExpr *E) { + assert(classifyPrim(E->getType()) == PT_Ptr); tbaederr wrote: Added support for the `std::nothrow` version of it + tests https://github.com/llvm/llvm-project/pull/70306 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
Timm =?utf-8?q?Bäder?= , Timm =?utf-8?q?Bäder?= , Timm =?utf-8?q?Bäder?= Message-ID: In-Reply-To: https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/70306 >From 02256cbbd7860d788d86864e83ec2ddcedb9f0ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 18 Jun 2024 16:45:15 +0200 Subject: [PATCH 1/4] Fixup! -- --- .../clang/Analysis/Analyses/ThreadSafety.h| 2 + clang/lib/Analysis/ThreadSafety.cpp | 42 +++ clang/lib/Sema/AnalysisBasedWarnings.cpp | 5 +++ 3 files changed, 49 insertions(+) diff --git a/clang/include/clang/Analysis/Analyses/ThreadSafety.h b/clang/include/clang/Analysis/Analyses/ThreadSafety.h index 0866b09bab299..79c6f5959afe4 100644 --- a/clang/include/clang/Analysis/Analyses/ThreadSafety.h +++ b/clang/include/clang/Analysis/Analyses/ThreadSafety.h @@ -230,6 +230,8 @@ class ThreadSafetyHandler { /// Warn that there is a cycle in acquired_before/after dependencies. virtual void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) {} + virtual void handleAttributeMismatch() {} + /// Called by the analysis when starting analysis of a function. /// Used to issue suggestions for changes to annotations. virtual void enterFunction(const FunctionDecl *FD) {} diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp index e25b843c9bf83..a42c4ca98ea9b 100644 --- a/clang/lib/Analysis/ThreadSafety.cpp +++ b/clang/lib/Analysis/ThreadSafety.cpp @@ -2260,6 +2260,45 @@ static bool neverReturns(const CFGBlock *B) { return false; } +template +static SmallVector collectAttrArgs(const FunctionDecl *FD) { +SmallVectorArgs; +for (const AttrT *A : FD->specific_attrs()) { + for (const Expr *E : A->args()) +Args.push_back(E); +} + +return Args; +} + +static void diagnoseMismatchedFunctionAttrs(const FunctionDecl *FD, ThreadSafetyHandler ) { + llvm::errs() << __PRETTY_FUNCTION__ << "\n"; + assert(FD); + FD = FD->getDefinition(); + assert(FD); + + FD->dump(); + + auto FDArgs = collectAttrArgs(FD); + + for (const FunctionDecl *D = FD->getPreviousDecl(); D; D = D->getPreviousDecl()) { +D->dump(); +auto DArgs = collectAttrArgs(D); + +llvm::errs() << "FD Args: " << FDArgs.size() << "\n"; +llvm::errs() << " D Args: " << DArgs.size() << "\n"; + +for (const Expr *E : FDArgs) { + if (!llvm::is_contained(DArgs, E)) { +// FD requires E, but D doesn't. +llvm::errs() << "OMG\n"; +Handler.handleAttributeMismatch(); + } +} +llvm::errs() << "---\n"; + } +} + /// Check a function's CFG for thread-safety violations. /// /// We traverse the blocks in the CFG, compute the set of mutexes that are held @@ -2279,6 +2318,9 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext ) { const NamedDecl *D = walker.getDecl(); CurrentFunction = dyn_cast(D); + if (CurrentFunction) +diagnoseMismatchedFunctionAttrs(CurrentFunction, Handler); + if (D->hasAttr()) return; diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 0f604c61fa3af..9eac80603ff88 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2073,6 +2073,11 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler { Warnings.emplace_back(std::move(Warning), getNotes()); } + void handleAttributeMismatch() override { +llvm::errs() << __PRETTY_FUNCTION__ << "\n"; + + } + void enterFunction(const FunctionDecl* FD) override { CurrentFunction = FD; } >From 837ad17e1b1cc2465cd24bebbf5187e430310049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 18 Jun 2024 20:42:18 +0200 Subject: [PATCH 2/4] [clang][Interp][NFC] Fix initializing union APValues The InitElem op assumes an array. --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index d47f6f23c8bc1..61a7394854d40 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -3507,7 +3507,7 @@ bool ByteCodeExprGen::visitAPValueInitializer(const APValue , PrimType T = classifyPrim(RF->Decl->getType()); if (!this->visitAPValue(F, T, E)) return false; -return this->emitInitElem(T, 0, E); +return this->emitInitField(T, RF->Offset, E); } // TODO: Other types. >From ff5713200186b909b55cdc55321f0e25464a1af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 19 Jun 2024 10:09:06 +0200 Subject: [PATCH 3/4] [clang][Interp][NFC] Loosen an assertion --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
@@ -2544,6 +2544,85 @@ bool ByteCodeExprGen::VisitCXXInheritedCtorInitExpr( return this->emitCall(F, 0, E); } +template +bool ByteCodeExprGen::VisitCXXNewExpr(const CXXNewExpr *E) { + assert(classifyPrim(E->getType()) == PT_Ptr); + const Expr *Init = E->getInitializer(); + QualType ElementType = E->getAllocatedType(); + std::optional ElemT = classify(ElementType); + + const Descriptor *Desc; + if (ElemT) { +if (E->isArray()) + Desc = nullptr; // We're not going to use it in this case. +else + Desc = P.createDescriptor(E, *ElemT, Descriptor::InlineDescMD, +/*IsConst=*/false, /*IsTemporary=*/false, +/*IsMutable=*/false); + } else { +Desc = P.createDescriptor( +E, ElementType.getTypePtr(), +E->isArray() ? std::nullopt : Descriptor::InlineDescMD, +/*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false, Init); + } + + if (E->isArray()) { +std::optional ArraySizeExpr = E->getArraySize(); +if (!ArraySizeExpr) tbaederr wrote: That works, we're getting the size expr from the `CXXNewExpr`. https://github.com/llvm/llvm-project/pull/70306 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
https://github.com/tbaederr edited https://github.com/llvm/llvm-project/pull/70306 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
@@ -0,0 +1,119 @@ +//== DynamicAllocator.cpp - Dynamic allocations --*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "DynamicAllocator.h" +#include "InterpBlock.h" +#include "InterpState.h" + +using namespace clang; +using namespace clang::interp; + +DynamicAllocator::~DynamicAllocator() { cleanup(); } + +void DynamicAllocator::cleanup() { + // Invoke destructors of all the blocks and as a last restort, + // reset all the pointers pointing to them to null pointees. + // This should never show up in diagnostics, but it's necessary + // for us to not cause use-after-free problems. + for (auto : AllocationSites) { +auto = Iter.second; +for (auto : AllocSite.Allocations) { + Block *B = reinterpret_cast(Alloc.Memory.get()); + B->invokeDtor(); + if (B->hasPointers()) { +while (B->Pointers) { + Pointer *Next = B->Pointers->Next; + B->Pointers->PointeeStorage.BS.Pointee = nullptr; + B->Pointers = Next; +} +B->Pointers = nullptr; + } +} + } + + AllocationSites.clear(); +} + +Block *DynamicAllocator::allocate(const Expr *Source, PrimType T, + size_t NumElements) { + assert(NumElements > 0); + // Create a new descriptor for an array of the specified size and + // element type. + const Descriptor *D = allocateDescriptor( + Source, T, Descriptor::InlineDescMD, NumElements, /*IsConst=*/false, + /*IsTemporary=*/false, /*IsMutable=*/false); + return allocate(D); +} + +Block *DynamicAllocator::allocate(const Descriptor *ElementDesc, + size_t NumElements) { + assert(NumElements > 0); + // Create a new descriptor for an array of the specified size and + // element type. + const Descriptor *D = allocateDescriptor( + ElementDesc->asExpr(), ElementDesc, Descriptor::InlineDescMD, NumElements, + /*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false); + return allocate(D); +} + +Block *DynamicAllocator::allocate(const Descriptor *D) { + assert(D->asExpr()); + + auto Memory = + std::make_unique(sizeof(Block) + D->getAllocSize()); + auto *B = new (Memory.get()) Block(D, /*isStatic=*/false); + B->invokeCtor(); + + InlineDescriptor *ID = reinterpret_cast(B->rawData()); + ID->Desc = D; + ID->IsActive = true; + ID->Offset = sizeof(InlineDescriptor); + ID->IsBase = false; + ID->IsFieldMutable = false; + ID->IsConst = false; + ID->IsInitialized = false; + assert(ID->Desc); + + B->IsDynamic = true; + + if (auto It = AllocationSites.find(D->asExpr()); It != AllocationSites.end()) +It->second.Allocations.emplace_back(std::move(Memory)); + else +AllocationSites.insert( +{D->asExpr(), AllocationSite(std::move(Memory), D->isArray())}); + return B; +} + +bool DynamicAllocator::deallocate(const Expr *Source, + const Block *BlockToDelete, InterpState ) { + auto It = AllocationSites.find(Source); + if (It == AllocationSites.end()) +return false; + + auto = It->second; + assert(Site.size() > 0); + + // Find the Block to delete. + auto AllocIt = llvm::find_if(Site.Allocations, [&](const Allocation ) { +const Block *B = reinterpret_cast(A.Memory.get()); +return BlockToDelete == B; + }); + + assert(AllocIt != Site.Allocations.end()); + + Block *B = reinterpret_cast(AllocIt->Memory.get()); + B->invokeDtor(); + + S.deallocate(B); + Site.Allocations.erase(AllocIt); + + if (Site.size() == 0) tbaederr wrote: `Size.size()` just returns `Size.Allocations.size()`, so this is affected by the `erase()` call above. https://github.com/llvm/llvm-project/pull/70306 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
@@ -2544,6 +2544,85 @@ bool ByteCodeExprGen::VisitCXXInheritedCtorInitExpr( return this->emitCall(F, 0, E); } +template +bool ByteCodeExprGen::VisitCXXNewExpr(const CXXNewExpr *E) { + assert(classifyPrim(E->getType()) == PT_Ptr); + const Expr *Init = E->getInitializer(); + QualType ElementType = E->getAllocatedType(); + std::optional ElemT = classify(ElementType); + + const Descriptor *Desc; + if (ElemT) { +if (E->isArray()) + Desc = nullptr; // We're not going to use it in this case. +else + Desc = P.createDescriptor(E, *ElemT, Descriptor::InlineDescMD, +/*IsConst=*/false, /*IsTemporary=*/false, +/*IsMutable=*/false); + } else { +Desc = P.createDescriptor( +E, ElementType.getTypePtr(), +E->isArray() ? std::nullopt : Descriptor::InlineDescMD, +/*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false, Init); + } + + if (E->isArray()) { +std::optional ArraySizeExpr = E->getArraySize(); +if (!ArraySizeExpr) + return false; +assert(ArraySizeExpr); +PrimType SizeT = classifyPrim((*ArraySizeExpr)->getType()); + +if (!this->visit(*ArraySizeExpr)) + return false; + +if (ElemT) { + // N primitive elements. + if (!this->emitAllocN(SizeT, *ElemT, E, E)) +return false; +} else { + // N Composite elements. + if (!this->emitAllocCN(SizeT, Desc, E)) +return false; +} + tbaederr wrote: Good catch https://github.com/llvm/llvm-project/pull/70306 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Remove update_options_td_flags.py (PR #95909)
https://github.com/tbaederr closed https://github.com/llvm/llvm-project/pull/95909 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement complex division (PR #94892)
https://github.com/tbaederr closed https://github.com/llvm/llvm-project/pull/94892 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Remove update_options_td_flags.py (PR #95909)
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/95909 The comment says: > This script will be removed after the next LLVM release. but it's still there. Change that. >From 0137a56765c1486b461c21c36d5977469fd6ffef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 18 Jun 2024 13:47:07 +0200 Subject: [PATCH] [clang] Remove update_options_td_flags.py The comment says: > This script will be removed after the next LLVM release. but it's still there. Change that. --- clang/utils/update_options_td_flags.py | 182 - 1 file changed, 182 deletions(-) delete mode 100755 clang/utils/update_options_td_flags.py diff --git a/clang/utils/update_options_td_flags.py b/clang/utils/update_options_td_flags.py deleted file mode 100755 index 9271b453c3fd6..0 --- a/clang/utils/update_options_td_flags.py +++ /dev/null @@ -1,182 +0,0 @@ -#!/usr/bin/env python3 -"""Update Options.td for the flags changes in https://reviews.llvm.org/Dxyz - -This script translates Options.td from using Flags to control option visibility -to using Vis instead. It is meant to be idempotent and usable to help update -downstream forks if they have their own changes to Options.td. - -Usage: -```sh -% update_options_td_flags.py path/to/Options.td > Options.td.new -% mv Options.td.new path/to/Options.td -``` - -This script will be removed after the next LLVM release. -""" - -import argparse -import re -import shutil -import sys -import tempfile - -def rewrite_option_flags(input_file, output_file): -for src_line in input_file: -for dst_line in process_line(src_line): -output_file.write(dst_line) - -def process_line(line): -# We only deal with one thing per line. If multiple things can be -# on the same line (like NegFlag and PosFlag), please preprocess -# that first. -m = re.search(r'((NegFlag|PosFlag)<[A-Za-z]+, |BothFlags<)' - r'\[([A-Za-z0-9, ]+)\](, \[ClangOption\]|(?=>))', line) -if m: -return process_boolflags(m.group(3), line[:m.end(1)], line[m.end():]) -m = re.search(r'\bFlags<\[([A-Za-z0-9, ]*)\]>', line) -if m: -return process_flags(m.group(1), line[:m.start()], line[m.end():]) -m = re.search(r'let Flags = \[([A-Za-z0-9, ]*)\]', line) -if m: -return process_letflags(m.group(1), line[:m.start(1)], line[m.end():]) - -return [line] - -def process_boolflags(flag_group, prefix, suffix): -flags = [f.strip() for f in flag_group.split(',')] if flag_group else [] -if not flags: -return f'{prefix}[], [ClangOption]{suffix}' - -flags_to_keep, vis_mods = translate_flags(flags) -flag_text = f'[{", ".join(flags_to_keep)}]' -vis_text = f'[{", ".join(vis_mods)}]' -new_text = ', '.join([flag_text, vis_text]) - -if prefix.startswith('Both'): -indent = ' ' * len(prefix) -else: -indent = ' ' * (len(prefix) - len(prefix.lstrip()) + len('XyzFlag<')) - -return get_edited_lines(prefix, new_text, suffix, indent=indent) - -def process_flags(flag_group, prefix, suffix): -flags = [f.strip() for f in flag_group.split(',')] - -flags_to_keep, vis_mods = translate_flags(flags) - -flag_text = '' -vis_text = '' -if flags_to_keep: -flag_text = f'Flags<[{", ".join(flags_to_keep)}]>' -if vis_mods: -flag_text += ', ' -if vis_mods: -vis_text = f'Visibility<[{", ".join(vis_mods)}]>' - -return get_edited_lines(prefix, flag_text, vis_text, suffix) - -def process_letflags(flag_group, prefix, suffix): -is_end_comment = prefix.startswith('} //') -if not is_end_comment and not prefix.startswith('let'): -raise AssertionError(f'Unusual let block: {prefix}') - -flags = [f.strip() for f in flag_group.split(',')] - -flags_to_keep, vis_mods = translate_flags(flags) - -lines = [] -if flags_to_keep: -lines += [f'let Flags = [{", ".join(flags_to_keep)}]'] -if vis_mods: -lines += [f'let Visibility = [{", ".join(vis_mods)}]'] - -if is_end_comment: -lines = list(reversed([f'}} // {l}\n' for l in lines])) -else: -lines = [f'{l} in {{\n' for l in lines] -return lines - -def get_edited_lines(prefix, *fragments, indent=' '): -out_lines = [] -current = prefix -for fragment in fragments: -if fragment and len(current) + len(fragment) > 80: -# Make a minimal attempt at reasonable line lengths -if fragment.startswith(',') or fragment.startswith(';'): -# Avoid wrapping the , or ; to the new line -current += fragment[0] -fragment = fragment[1:].lstrip() -out_lines += [current.rstrip() + '\n'] -current = max(' ' * (len(current) - len(current.lstrip())), indent) -current += fragment - -if current.strip(): -out_lines += [current] -return out_lines - -def translate_flags(flags): -
[clang] [clang][Interp] Implement complex division (PR #94892)
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/94892 >From 7a1c16f2fe0b23ffe49789275ffa66b2ac64c4d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Sun, 9 Jun 2024 09:25:24 +0200 Subject: [PATCH] [clang][Interp] Implement Complex division --- clang/lib/AST/ExprConstShared.h | 3 + clang/lib/AST/ExprConstant.cpp | 76 ++-- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 67 ++--- clang/lib/AST/Interp/Interp.h| 72 ++ clang/lib/AST/Interp/Opcodes.td | 4 ++ clang/test/AST/Interp/complex.cpp| 15 + clang/test/SemaCXX/complex-folding.cpp | 1 + 7 files changed, 196 insertions(+), 42 deletions(-) diff --git a/clang/lib/AST/ExprConstShared.h b/clang/lib/AST/ExprConstShared.h index 9decd47e41767..2a7088e4e371a 100644 --- a/clang/lib/AST/ExprConstShared.h +++ b/clang/lib/AST/ExprConstShared.h @@ -62,5 +62,8 @@ GCCTypeClass EvaluateBuiltinClassifyType(QualType T, void HandleComplexComplexMul(llvm::APFloat A, llvm::APFloat B, llvm::APFloat C, llvm::APFloat D, llvm::APFloat , llvm::APFloat ); +void HandleComplexComplexDiv(llvm::APFloat A, llvm::APFloat B, llvm::APFloat C, + llvm::APFloat D, llvm::APFloat , + llvm::APFloat ); #endif diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 3a6c8b4f82cca..9ac53438de8e4 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -15189,6 +15189,48 @@ void HandleComplexComplexMul(APFloat A, APFloat B, APFloat C, APFloat D, } } +void HandleComplexComplexDiv(APFloat A, APFloat B, APFloat C, APFloat D, + APFloat , APFloat ) { + // This is an implementation of complex division according to the + // constraints laid out in C11 Annex G. The implementation uses the + // following naming scheme: + // (a + ib) / (c + id) + + int DenomLogB = 0; + APFloat MaxCD = maxnum(abs(C), abs(D)); + if (MaxCD.isFinite()) { +DenomLogB = ilogb(MaxCD); +C = scalbn(C, -DenomLogB, APFloat::rmNearestTiesToEven); +D = scalbn(D, -DenomLogB, APFloat::rmNearestTiesToEven); + } + APFloat Denom = C * C + D * D; + ResR = + scalbn((A * C + B * D) / Denom, -DenomLogB, APFloat::rmNearestTiesToEven); + ResI = + scalbn((B * C - A * D) / Denom, -DenomLogB, APFloat::rmNearestTiesToEven); + if (ResR.isNaN() && ResI.isNaN()) { +if (Denom.isPosZero() && (!A.isNaN() || !B.isNaN())) { + ResR = APFloat::getInf(ResR.getSemantics(), C.isNegative()) * A; + ResI = APFloat::getInf(ResR.getSemantics(), C.isNegative()) * B; +} else if ((A.isInfinity() || B.isInfinity()) && C.isFinite() && + D.isFinite()) { + A = APFloat::copySign(APFloat(A.getSemantics(), A.isInfinity() ? 1 : 0), +A); + B = APFloat::copySign(APFloat(B.getSemantics(), B.isInfinity() ? 1 : 0), +B); + ResR = APFloat::getInf(ResR.getSemantics()) * (A * C + B * D); + ResI = APFloat::getInf(ResI.getSemantics()) * (B * C - A * D); +} else if (MaxCD.isInfinity() && A.isFinite() && B.isFinite()) { + C = APFloat::copySign(APFloat(C.getSemantics(), C.isInfinity() ? 1 : 0), +C); + D = APFloat::copySign(APFloat(D.getSemantics(), D.isInfinity() ? 1 : 0), +D); + ResR = APFloat::getZero(ResR.getSemantics()) * (A * C + B * D); + ResI = APFloat::getZero(ResI.getSemantics()) * (B * C - A * D); +} + } +} + bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (E->isPtrMemOp() || E->isAssignmentOp() || E->getOpcode() == BO_Comma) return ExprEvaluatorBaseTy::VisitBinaryOperator(E); @@ -15326,39 +15368,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { // No real optimizations we can do here, stub out with zero. B = APFloat::getZero(A.getSemantics()); } -int DenomLogB = 0; -APFloat MaxCD = maxnum(abs(C), abs(D)); -if (MaxCD.isFinite()) { - DenomLogB = ilogb(MaxCD); - C = scalbn(C, -DenomLogB, APFloat::rmNearestTiesToEven); - D = scalbn(D, -DenomLogB, APFloat::rmNearestTiesToEven); -} -APFloat Denom = C * C + D * D; -ResR = scalbn((A * C + B * D) / Denom, -DenomLogB, - APFloat::rmNearestTiesToEven); -ResI = scalbn((B * C - A * D) / Denom, -DenomLogB, - APFloat::rmNearestTiesToEven); -if (ResR.isNaN() && ResI.isNaN()) { - if (Denom.isPosZero() && (!A.isNaN() || !B.isNaN())) { -ResR = APFloat::getInf(ResR.getSemantics(), C.isNegative()) * A; -ResI = APFloat::getInf(ResR.getSemantics(), C.isNegative()) * B; - } else if
[clang] [Clang] [Sema] Ensure noexcept(typeid(E)) checks if E throws when needed (PR #95846)
@@ -,13 +,18 @@ static CanThrowResult canDynamicCastThrow(const CXXDynamicCastExpr *DC) { } static CanThrowResult canTypeidThrow(Sema , const CXXTypeidExpr *DC) { - if (DC->isTypeOperand()) + // Operand is not evaluated, cannot possibly throw + if (!DC->isPotentiallyEvaluated()) return CT_Cannot; if (DC->isValueDependent()) return CT_Dependent; - return DC->hasNullCheck() ? CT_Can : CT_Cannot; + // Can throw std::bad_typeid if a nullptr is dereferenced tbaederr wrote: ```suggestion // Can throw std::bad_typeid if a nullptr is dereferenced. ``` https://github.com/llvm/llvm-project/pull/95846 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] [Sema] Ensure noexcept(typeid(E)) checks if E throws when needed (PR #95846)
@@ -,13 +,18 @@ static CanThrowResult canDynamicCastThrow(const CXXDynamicCastExpr *DC) { } static CanThrowResult canTypeidThrow(Sema , const CXXTypeidExpr *DC) { - if (DC->isTypeOperand()) + // Operand is not evaluated, cannot possibly throw tbaederr wrote: ```suggestion // Operand is not evaluated, cannot possibly throw. ``` https://github.com/llvm/llvm-project/pull/95846 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement Complex-complex multiplication (PR #94891)
https://github.com/tbaederr closed https://github.com/llvm/llvm-project/pull/94891 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement Complex-complex multiplication (PR #94891)
tbaederr wrote: Ping https://github.com/llvm/llvm-project/pull/94891 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement complex division (PR #94892)
Timm =?utf-8?q?B=C3=A4der?= Message-ID: In-Reply-To: tbaederr wrote: Ping https://github.com/llvm/llvm-project/pull/94892 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
tbaederr wrote: Ping https://github.com/llvm/llvm-project/pull/70306 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] SourceLocIdentKind::Function should not be dependent (PR #94942)
@@ -846,6 +846,7 @@ Bug Fixes to C++ Support - Fix a crash caused by improper use of ``__array_extent``. (#GH80474) - Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307), (#GH88081), (#GH89496), (#GH90669) and (#GH91633). +- Fix a crash when SourceLocExpr instantiated in a dependent context. (GH80210). tbaederr wrote: ```suggestion - Fix a crash when SourceLocExpr instantiated in a dependent context. (#GH80210). ``` https://github.com/llvm/llvm-project/pull/94942 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][C++23] update constexpr diagnostics for missing return statements per P2448 (PR #94123)
https://github.com/tbaederr closed https://github.com/llvm/llvm-project/pull/94123 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][C++23] update constexpr diagnostics for missing return statements per P2448 (PR #94123)
tbaederr wrote: @a-tarasyuk Do you need someone else to merge this? https://github.com/llvm/llvm-project/pull/94123 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement complex division (PR #94892)
Timm =?utf-8?q?Bäder?= Message-ID: In-Reply-To: https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/94892 >From b89efd9e0e38a6e79130e0a1b9e8d0443654c6c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Sat, 9 Mar 2024 17:07:24 +0100 Subject: [PATCH 1/2] [clang][Interp] Implement Complex-complex multiplication Share the implementation for floating-point complex-complex multiplication with the current interpreter. This means we need a new opcode for this, but there's no good way around that. --- clang/lib/AST/ExprConstShared.h | 7 ++ clang/lib/AST/ExprConstant.cpp | 106 --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 55 +--- clang/lib/AST/Interp/Interp.h| 57 clang/lib/AST/Interp/Opcodes.td | 4 + clang/test/AST/Interp/complex.cpp| 31 +++ 6 files changed, 201 insertions(+), 59 deletions(-) diff --git a/clang/lib/AST/ExprConstShared.h b/clang/lib/AST/ExprConstShared.h index a97eac85abc69..9decd47e41767 100644 --- a/clang/lib/AST/ExprConstShared.h +++ b/clang/lib/AST/ExprConstShared.h @@ -14,6 +14,9 @@ #ifndef LLVM_CLANG_LIB_AST_EXPRCONSTSHARED_H #define LLVM_CLANG_LIB_AST_EXPRCONSTSHARED_H +namespace llvm { +class APFloat; +} namespace clang { class QualType; class LangOptions; @@ -56,4 +59,8 @@ enum class GCCTypeClass { GCCTypeClass EvaluateBuiltinClassifyType(QualType T, const LangOptions ); +void HandleComplexComplexMul(llvm::APFloat A, llvm::APFloat B, llvm::APFloat C, + llvm::APFloat D, llvm::APFloat , + llvm::APFloat ); + #endif diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 86fb396fabe2d..7c597a238f041 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -15126,6 +15126,62 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { llvm_unreachable("unknown cast resulting in complex value"); } +void HandleComplexComplexMul(APFloat A, APFloat B, APFloat C, APFloat D, + APFloat , APFloat ) { + // This is an implementation of complex multiplication according to the + // constraints laid out in C11 Annex G. The implementation uses the + // following naming scheme: + // (a + ib) * (c + id) + + APFloat AC = A * C; + APFloat BD = B * D; + APFloat AD = A * D; + APFloat BC = B * C; + ResR = AC - BD; + ResI = AD + BC; + if (ResR.isNaN() && ResI.isNaN()) { +bool Recalc = false; +if (A.isInfinity() || B.isInfinity()) { + A = APFloat::copySign(APFloat(A.getSemantics(), A.isInfinity() ? 1 : 0), +A); + B = APFloat::copySign(APFloat(B.getSemantics(), B.isInfinity() ? 1 : 0), +B); + if (C.isNaN()) +C = APFloat::copySign(APFloat(C.getSemantics()), C); + if (D.isNaN()) +D = APFloat::copySign(APFloat(D.getSemantics()), D); + Recalc = true; +} +if (C.isInfinity() || D.isInfinity()) { + C = APFloat::copySign(APFloat(C.getSemantics(), C.isInfinity() ? 1 : 0), +C); + D = APFloat::copySign(APFloat(D.getSemantics(), D.isInfinity() ? 1 : 0), +D); + if (A.isNaN()) +A = APFloat::copySign(APFloat(A.getSemantics()), A); + if (B.isNaN()) +B = APFloat::copySign(APFloat(B.getSemantics()), B); + Recalc = true; +} +if (!Recalc && (AC.isInfinity() || BD.isInfinity() || AD.isInfinity() || +BC.isInfinity())) { + if (A.isNaN()) +A = APFloat::copySign(APFloat(A.getSemantics()), A); + if (B.isNaN()) +B = APFloat::copySign(APFloat(B.getSemantics()), B); + if (C.isNaN()) +C = APFloat::copySign(APFloat(C.getSemantics()), C); + if (D.isNaN()) +D = APFloat::copySign(APFloat(D.getSemantics()), D); + Recalc = true; +} +if (Recalc) { + ResR = APFloat::getInf(A.getSemantics()) * (A * C - B * D); + ResI = APFloat::getInf(A.getSemantics()) * (A * D + B * C); +} + } +} + bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (E->isPtrMemOp() || E->isAssignmentOp() || E->getOpcode() == BO_Comma) return ExprEvaluatorBaseTy::VisitBinaryOperator(E); @@ -15225,55 +15281,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { !handleFloatFloatBinOp(Info, E, ResI, BO_Mul, B)) return false; } else { -// In the fully general case, we need to handle NaNs and infinities -// robustly. -APFloat AC = A * C; -APFloat BD = B * D; -APFloat AD = A * D; -APFloat BC = B * C; -ResR = AC - BD; -ResI = AD + BC; -if (ResR.isNaN() && ResI.isNaN()) { - bool Recalc = false; - if (A.isInfinity() || B.isInfinity()) { -
[clang] [clang][Interp] Implement complex division (PR #94892)
Timm =?utf-8?q?Bäder?= Message-ID: In-Reply-To: https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/94892 Depends on the multiplication PR. >From b89efd9e0e38a6e79130e0a1b9e8d0443654c6c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Sat, 9 Mar 2024 17:07:24 +0100 Subject: [PATCH 1/2] [clang][Interp] Implement Complex-complex multiplication Share the implementation for floating-point complex-complex multiplication with the current interpreter. This means we need a new opcode for this, but there's no good way around that. --- clang/lib/AST/ExprConstShared.h | 7 ++ clang/lib/AST/ExprConstant.cpp | 106 --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 55 +--- clang/lib/AST/Interp/Interp.h| 57 clang/lib/AST/Interp/Opcodes.td | 4 + clang/test/AST/Interp/complex.cpp| 31 +++ 6 files changed, 201 insertions(+), 59 deletions(-) diff --git a/clang/lib/AST/ExprConstShared.h b/clang/lib/AST/ExprConstShared.h index a97eac85abc69..9decd47e41767 100644 --- a/clang/lib/AST/ExprConstShared.h +++ b/clang/lib/AST/ExprConstShared.h @@ -14,6 +14,9 @@ #ifndef LLVM_CLANG_LIB_AST_EXPRCONSTSHARED_H #define LLVM_CLANG_LIB_AST_EXPRCONSTSHARED_H +namespace llvm { +class APFloat; +} namespace clang { class QualType; class LangOptions; @@ -56,4 +59,8 @@ enum class GCCTypeClass { GCCTypeClass EvaluateBuiltinClassifyType(QualType T, const LangOptions ); +void HandleComplexComplexMul(llvm::APFloat A, llvm::APFloat B, llvm::APFloat C, + llvm::APFloat D, llvm::APFloat , + llvm::APFloat ); + #endif diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 86fb396fabe2d..7c597a238f041 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -15126,6 +15126,62 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { llvm_unreachable("unknown cast resulting in complex value"); } +void HandleComplexComplexMul(APFloat A, APFloat B, APFloat C, APFloat D, + APFloat , APFloat ) { + // This is an implementation of complex multiplication according to the + // constraints laid out in C11 Annex G. The implementation uses the + // following naming scheme: + // (a + ib) * (c + id) + + APFloat AC = A * C; + APFloat BD = B * D; + APFloat AD = A * D; + APFloat BC = B * C; + ResR = AC - BD; + ResI = AD + BC; + if (ResR.isNaN() && ResI.isNaN()) { +bool Recalc = false; +if (A.isInfinity() || B.isInfinity()) { + A = APFloat::copySign(APFloat(A.getSemantics(), A.isInfinity() ? 1 : 0), +A); + B = APFloat::copySign(APFloat(B.getSemantics(), B.isInfinity() ? 1 : 0), +B); + if (C.isNaN()) +C = APFloat::copySign(APFloat(C.getSemantics()), C); + if (D.isNaN()) +D = APFloat::copySign(APFloat(D.getSemantics()), D); + Recalc = true; +} +if (C.isInfinity() || D.isInfinity()) { + C = APFloat::copySign(APFloat(C.getSemantics(), C.isInfinity() ? 1 : 0), +C); + D = APFloat::copySign(APFloat(D.getSemantics(), D.isInfinity() ? 1 : 0), +D); + if (A.isNaN()) +A = APFloat::copySign(APFloat(A.getSemantics()), A); + if (B.isNaN()) +B = APFloat::copySign(APFloat(B.getSemantics()), B); + Recalc = true; +} +if (!Recalc && (AC.isInfinity() || BD.isInfinity() || AD.isInfinity() || +BC.isInfinity())) { + if (A.isNaN()) +A = APFloat::copySign(APFloat(A.getSemantics()), A); + if (B.isNaN()) +B = APFloat::copySign(APFloat(B.getSemantics()), B); + if (C.isNaN()) +C = APFloat::copySign(APFloat(C.getSemantics()), C); + if (D.isNaN()) +D = APFloat::copySign(APFloat(D.getSemantics()), D); + Recalc = true; +} +if (Recalc) { + ResR = APFloat::getInf(A.getSemantics()) * (A * C - B * D); + ResI = APFloat::getInf(A.getSemantics()) * (A * D + B * C); +} + } +} + bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (E->isPtrMemOp() || E->isAssignmentOp() || E->getOpcode() == BO_Comma) return ExprEvaluatorBaseTy::VisitBinaryOperator(E); @@ -15225,55 +15281,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { !handleFloatFloatBinOp(Info, E, ResI, BO_Mul, B)) return false; } else { -// In the fully general case, we need to handle NaNs and infinities -// robustly. -APFloat AC = A * C; -APFloat BD = B * D; -APFloat AD = A * D; -APFloat BC = B * C; -ResR = AC - BD; -ResI = AD + BC; -if (ResR.isNaN() && ResI.isNaN()) { - bool Recalc = false; - if
[clang] [clang][Interp] Implement Complex-complex multiplication (PR #94891)
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/94891 Share the implementation for floating-point complex-complex multiplication with the current interpreter. This means we need a new opcode for this, but there's no good way around that. >From b89efd9e0e38a6e79130e0a1b9e8d0443654c6c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Sat, 9 Mar 2024 17:07:24 +0100 Subject: [PATCH] [clang][Interp] Implement Complex-complex multiplication Share the implementation for floating-point complex-complex multiplication with the current interpreter. This means we need a new opcode for this, but there's no good way around that. --- clang/lib/AST/ExprConstShared.h | 7 ++ clang/lib/AST/ExprConstant.cpp | 106 --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 55 +--- clang/lib/AST/Interp/Interp.h| 57 clang/lib/AST/Interp/Opcodes.td | 4 + clang/test/AST/Interp/complex.cpp| 31 +++ 6 files changed, 201 insertions(+), 59 deletions(-) diff --git a/clang/lib/AST/ExprConstShared.h b/clang/lib/AST/ExprConstShared.h index a97eac85abc69..9decd47e41767 100644 --- a/clang/lib/AST/ExprConstShared.h +++ b/clang/lib/AST/ExprConstShared.h @@ -14,6 +14,9 @@ #ifndef LLVM_CLANG_LIB_AST_EXPRCONSTSHARED_H #define LLVM_CLANG_LIB_AST_EXPRCONSTSHARED_H +namespace llvm { +class APFloat; +} namespace clang { class QualType; class LangOptions; @@ -56,4 +59,8 @@ enum class GCCTypeClass { GCCTypeClass EvaluateBuiltinClassifyType(QualType T, const LangOptions ); +void HandleComplexComplexMul(llvm::APFloat A, llvm::APFloat B, llvm::APFloat C, + llvm::APFloat D, llvm::APFloat , + llvm::APFloat ); + #endif diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 86fb396fabe2d..7c597a238f041 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -15126,6 +15126,62 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { llvm_unreachable("unknown cast resulting in complex value"); } +void HandleComplexComplexMul(APFloat A, APFloat B, APFloat C, APFloat D, + APFloat , APFloat ) { + // This is an implementation of complex multiplication according to the + // constraints laid out in C11 Annex G. The implementation uses the + // following naming scheme: + // (a + ib) * (c + id) + + APFloat AC = A * C; + APFloat BD = B * D; + APFloat AD = A * D; + APFloat BC = B * C; + ResR = AC - BD; + ResI = AD + BC; + if (ResR.isNaN() && ResI.isNaN()) { +bool Recalc = false; +if (A.isInfinity() || B.isInfinity()) { + A = APFloat::copySign(APFloat(A.getSemantics(), A.isInfinity() ? 1 : 0), +A); + B = APFloat::copySign(APFloat(B.getSemantics(), B.isInfinity() ? 1 : 0), +B); + if (C.isNaN()) +C = APFloat::copySign(APFloat(C.getSemantics()), C); + if (D.isNaN()) +D = APFloat::copySign(APFloat(D.getSemantics()), D); + Recalc = true; +} +if (C.isInfinity() || D.isInfinity()) { + C = APFloat::copySign(APFloat(C.getSemantics(), C.isInfinity() ? 1 : 0), +C); + D = APFloat::copySign(APFloat(D.getSemantics(), D.isInfinity() ? 1 : 0), +D); + if (A.isNaN()) +A = APFloat::copySign(APFloat(A.getSemantics()), A); + if (B.isNaN()) +B = APFloat::copySign(APFloat(B.getSemantics()), B); + Recalc = true; +} +if (!Recalc && (AC.isInfinity() || BD.isInfinity() || AD.isInfinity() || +BC.isInfinity())) { + if (A.isNaN()) +A = APFloat::copySign(APFloat(A.getSemantics()), A); + if (B.isNaN()) +B = APFloat::copySign(APFloat(B.getSemantics()), B); + if (C.isNaN()) +C = APFloat::copySign(APFloat(C.getSemantics()), C); + if (D.isNaN()) +D = APFloat::copySign(APFloat(D.getSemantics()), D); + Recalc = true; +} +if (Recalc) { + ResR = APFloat::getInf(A.getSemantics()) * (A * C - B * D); + ResI = APFloat::getInf(A.getSemantics()) * (A * D + B * C); +} + } +} + bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (E->isPtrMemOp() || E->isAssignmentOp() || E->getOpcode() == BO_Comma) return ExprEvaluatorBaseTy::VisitBinaryOperator(E); @@ -15225,55 +15281,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { !handleFloatFloatBinOp(Info, E, ResI, BO_Mul, B)) return false; } else { -// In the fully general case, we need to handle NaNs and infinities -// robustly. -APFloat AC = A * C; -APFloat BD = B * D; -APFloat AD = A * D; -APFloat BC = B * C; -ResR = AC - BD; -ResI = AD +
[clang] [clang] Report erroneous floating point results in _Complex math (PR #90588)
https://github.com/tbaederr closed https://github.com/llvm/llvm-project/pull/90588 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Report erroneous floating point results in _Complex math (PR #90588)
tbaederr wrote: > Out of curiosity, why are they not using `__builtin_complex` as requested? I started out replacing a lot of those expressions with `__builtin_complex` but ended up just creating a variable for it so the lines don't get too unwieldy. But then I naturally just used an initlist instead of `__builtin_complex`. https://github.com/llvm/llvm-project/pull/90588 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] WIP: Warn on mismatched RequiresCapability attributes (PR #67520)
tbaederr wrote: @AaronBallman Is the prototype of the implementation here at least sound? Or should this go somewhere completely different? Maybe in one of the TSA source files? https://github.com/llvm/llvm-project/pull/67520 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Report erroneous floating point results in _Complex math (PR #90588)
tbaederr wrote: Ping https://github.com/llvm/llvm-project/pull/90588 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Member Pointers (PR #91303)
https://github.com/tbaederr closed https://github.com/llvm/llvm-project/pull/91303 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] CWG2749: relational operators involving pointers to void (PR #93046)
https://github.com/tbaederr approved this pull request. LGTM. I guess we should close https://github.com/llvm/llvm-project/pull/89449 after merging this. https://github.com/llvm/llvm-project/pull/93046 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] NFCI: Make ASTContext optional in the AST text dumper again (PR #94522)
https://github.com/tbaederr approved this pull request. Can't say much about this functionally, but it fixes my problems, so LGTM from that side. https://github.com/llvm/llvm-project/pull/94522 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Member Pointers (PR #91303)
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/91303 >From 0f047f686ac69549834bfbfdecaa6383c6ab5305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 10 Apr 2024 16:42:36 +0200 Subject: [PATCH] Memberpointers --- clang/lib/AST/CMakeLists.txt | 1 + clang/lib/AST/Interp/ByteCodeExprGen.cpp | 100 - clang/lib/AST/Interp/Context.cpp | 15 +- clang/lib/AST/Interp/Context.h| 2 + clang/lib/AST/Interp/Descriptor.cpp | 1 + clang/lib/AST/Interp/Disasm.cpp | 3 + clang/lib/AST/Interp/Interp.cpp | 30 ++- clang/lib/AST/Interp/Interp.h | 99 + clang/lib/AST/Interp/InterpFrame.cpp | 1 + clang/lib/AST/Interp/InterpStack.cpp | 1 + clang/lib/AST/Interp/InterpStack.h| 3 + clang/lib/AST/Interp/MemberPointer.cpp| 76 +++ clang/lib/AST/Interp/MemberPointer.h | 112 ++ clang/lib/AST/Interp/Opcodes.td | 18 +- clang/lib/AST/Interp/Pointer.cpp | 1 + clang/lib/AST/Interp/Pointer.h| 1 + clang/lib/AST/Interp/PrimType.cpp | 1 + clang/lib/AST/Interp/PrimType.h | 8 +- clang/test/AST/Interp/eval-order.cpp | 4 +- clang/test/AST/Interp/literals.cpp| 7 +- clang/test/AST/Interp/memberpointers.cpp | 197 ++ .../CodeGenCXX/pointers-to-data-members.cpp | 1 + clang/test/SemaCXX/attr-weak.cpp | 1 + .../SemaCXX/nullptr_in_arithmetic_ops.cpp | 1 + clang/unittests/AST/Interp/toAPValue.cpp | 46 25 files changed, 705 insertions(+), 25 deletions(-) create mode 100644 clang/lib/AST/Interp/MemberPointer.cpp create mode 100644 clang/lib/AST/Interp/MemberPointer.h create mode 100644 clang/test/AST/Interp/memberpointers.cpp diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 3faefb54f599f..a5d3dacfc1a84 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -87,6 +87,7 @@ add_clang_library(clangAST Interp/Record.cpp Interp/Source.cpp Interp/State.cpp + Interp/MemberPointer.cpp Interp/InterpShared.cpp ItaniumCXXABI.cpp ItaniumMangle.cpp diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 3671c41ae7039..b0f28c9cec414 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -100,6 +100,35 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { return this->emitMemcpy(CE); } + case CK_DerivedToBaseMemberPointer: { +assert(classifyPrim(CE->getType()) == PT_MemberPtr); +assert(classifyPrim(SubExpr->getType()) == PT_MemberPtr); +const auto *FromMP = SubExpr->getType()->getAs(); +const auto *ToMP = CE->getType()->getAs(); + +unsigned DerivedOffset = collectBaseOffset(QualType(ToMP->getClass(), 0), + QualType(FromMP->getClass(), 0)); + +if (!this->visit(SubExpr)) + return false; + +return this->emitGetMemberPtrBasePop(DerivedOffset, CE); + } + + case CK_BaseToDerivedMemberPointer: { +assert(classifyPrim(CE) == PT_MemberPtr); +assert(classifyPrim(SubExpr) == PT_MemberPtr); +const auto *FromMP = SubExpr->getType()->getAs(); +const auto *ToMP = CE->getType()->getAs(); + +unsigned DerivedOffset = collectBaseOffset(QualType(FromMP->getClass(), 0), + QualType(ToMP->getClass(), 0)); + +if (!this->visit(SubExpr)) + return false; +return this->emitGetMemberPtrBasePop(-DerivedOffset, CE); + } + case CK_UncheckedDerivedToBase: case CK_DerivedToBase: { if (!this->visit(SubExpr)) @@ -187,7 +216,8 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { return this->emitCastFloatingIntegral(*ToT, CE); } - case CK_NullToPointer: { + case CK_NullToPointer: + case CK_NullToMemberPointer: { if (DiscardResult) return true; @@ -326,7 +356,8 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { return this->emitCast(*FromT, *ToT, CE); } - case CK_PointerToBoolean: { + case CK_PointerToBoolean: + case CK_MemberPointerToBoolean: { PrimType PtrT = classifyPrim(SubExpr->getType()); // Just emit p != nullptr for this. @@ -534,8 +565,23 @@ bool ByteCodeExprGen::VisitBinaryOperator(const BinaryOperator *BO) { BO->isComparisonOp()) return this->emitComplexComparison(LHS, RHS, BO); - if (BO->isPtrMemOp()) -return this->visit(RHS); + if (BO->isPtrMemOp()) { +if (!this->visit(LHS)) + return false; + +if (!this->visit(RHS)) + return false; + +if (!this->emitToMemberPtr(BO)) + return false; + +if (classifyPrim(BO) == PT_MemberPtr) + return true; + +if (!this->emitCastMemberPtrPtr(BO)) +
[clang] [clang][Interp] Member Pointers (PR #91303)
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/91303 >From 922a2239a69efe5136a9c8229ef223bfbaad2fe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 10 Apr 2024 16:42:36 +0200 Subject: [PATCH] Memberpointers --- clang/lib/AST/CMakeLists.txt | 1 + clang/lib/AST/Interp/ByteCodeExprGen.cpp | 100 - clang/lib/AST/Interp/Context.cpp | 15 +- clang/lib/AST/Interp/Context.h| 2 + clang/lib/AST/Interp/Descriptor.cpp | 1 + clang/lib/AST/Interp/Disasm.cpp | 3 + clang/lib/AST/Interp/Interp.cpp | 30 ++- clang/lib/AST/Interp/Interp.h | 99 + clang/lib/AST/Interp/InterpFrame.cpp | 1 + clang/lib/AST/Interp/InterpStack.cpp | 1 + clang/lib/AST/Interp/InterpStack.h| 3 + clang/lib/AST/Interp/MemberPointer.cpp| 76 +++ clang/lib/AST/Interp/MemberPointer.h | 112 ++ clang/lib/AST/Interp/Opcodes.td | 18 +- clang/lib/AST/Interp/Pointer.cpp | 1 + clang/lib/AST/Interp/Pointer.h| 1 + clang/lib/AST/Interp/PrimType.cpp | 1 + clang/lib/AST/Interp/PrimType.h | 8 +- clang/test/AST/Interp/eval-order.cpp | 4 +- clang/test/AST/Interp/literals.cpp| 7 +- clang/test/AST/Interp/memberpointers.cpp | 197 ++ .../mangle-ms-templates-memptrs.cpp | 2 +- .../CodeGenCXX/pointers-to-data-members.cpp | 2 +- clang/test/SemaCXX/attr-weak.cpp | 1 + .../SemaCXX/nullptr_in_arithmetic_ops.cpp | 2 +- clang/unittests/AST/Interp/toAPValue.cpp | 46 26 files changed, 706 insertions(+), 28 deletions(-) create mode 100644 clang/lib/AST/Interp/MemberPointer.cpp create mode 100644 clang/lib/AST/Interp/MemberPointer.h create mode 100644 clang/test/AST/Interp/memberpointers.cpp diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 3faefb54f599f..a5d3dacfc1a84 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -87,6 +87,7 @@ add_clang_library(clangAST Interp/Record.cpp Interp/Source.cpp Interp/State.cpp + Interp/MemberPointer.cpp Interp/InterpShared.cpp ItaniumCXXABI.cpp ItaniumMangle.cpp diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 3671c41ae7039..b0f28c9cec414 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -100,6 +100,35 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { return this->emitMemcpy(CE); } + case CK_DerivedToBaseMemberPointer: { +assert(classifyPrim(CE->getType()) == PT_MemberPtr); +assert(classifyPrim(SubExpr->getType()) == PT_MemberPtr); +const auto *FromMP = SubExpr->getType()->getAs(); +const auto *ToMP = CE->getType()->getAs(); + +unsigned DerivedOffset = collectBaseOffset(QualType(ToMP->getClass(), 0), + QualType(FromMP->getClass(), 0)); + +if (!this->visit(SubExpr)) + return false; + +return this->emitGetMemberPtrBasePop(DerivedOffset, CE); + } + + case CK_BaseToDerivedMemberPointer: { +assert(classifyPrim(CE) == PT_MemberPtr); +assert(classifyPrim(SubExpr) == PT_MemberPtr); +const auto *FromMP = SubExpr->getType()->getAs(); +const auto *ToMP = CE->getType()->getAs(); + +unsigned DerivedOffset = collectBaseOffset(QualType(FromMP->getClass(), 0), + QualType(ToMP->getClass(), 0)); + +if (!this->visit(SubExpr)) + return false; +return this->emitGetMemberPtrBasePop(-DerivedOffset, CE); + } + case CK_UncheckedDerivedToBase: case CK_DerivedToBase: { if (!this->visit(SubExpr)) @@ -187,7 +216,8 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { return this->emitCastFloatingIntegral(*ToT, CE); } - case CK_NullToPointer: { + case CK_NullToPointer: + case CK_NullToMemberPointer: { if (DiscardResult) return true; @@ -326,7 +356,8 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { return this->emitCast(*FromT, *ToT, CE); } - case CK_PointerToBoolean: { + case CK_PointerToBoolean: + case CK_MemberPointerToBoolean: { PrimType PtrT = classifyPrim(SubExpr->getType()); // Just emit p != nullptr for this. @@ -534,8 +565,23 @@ bool ByteCodeExprGen::VisitBinaryOperator(const BinaryOperator *BO) { BO->isComparisonOp()) return this->emitComplexComparison(LHS, RHS, BO); - if (BO->isPtrMemOp()) -return this->visit(RHS); + if (BO->isPtrMemOp()) { +if (!this->visit(LHS)) + return false; + +if (!this->visit(RHS)) + return false; + +if (!this->emitToMemberPtr(BO)) + return false; + +if (classifyPrim(BO) == PT_MemberPtr) + return
[clang] [clang][Interp] Member Pointers (PR #91303)
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/91303 >From 34a35dfa66835b8810e27899c9c7978de191f8e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 10 Apr 2024 16:42:36 +0200 Subject: [PATCH] Memberpointers --- clang/lib/AST/CMakeLists.txt | 1 + clang/lib/AST/Interp/ByteCodeExprGen.cpp | 100 - clang/lib/AST/Interp/Context.cpp | 15 +- clang/lib/AST/Interp/Context.h| 2 + clang/lib/AST/Interp/Descriptor.cpp | 1 + clang/lib/AST/Interp/Disasm.cpp | 3 + clang/lib/AST/Interp/Interp.cpp | 30 ++- clang/lib/AST/Interp/Interp.h | 99 + clang/lib/AST/Interp/InterpFrame.cpp | 1 + clang/lib/AST/Interp/InterpStack.cpp | 1 + clang/lib/AST/Interp/InterpStack.h| 3 + clang/lib/AST/Interp/MemberPointer.cpp| 76 +++ clang/lib/AST/Interp/MemberPointer.h | 112 ++ clang/lib/AST/Interp/Opcodes.td | 18 +- clang/lib/AST/Interp/Pointer.cpp | 1 + clang/lib/AST/Interp/Pointer.h| 1 + clang/lib/AST/Interp/PrimType.cpp | 1 + clang/lib/AST/Interp/PrimType.h | 8 +- clang/test/AST/Interp/eval-order.cpp | 4 +- clang/test/AST/Interp/literals.cpp| 7 +- clang/test/AST/Interp/memberpointers.cpp | 197 ++ .../mangle-ms-templates-memptrs.cpp | 2 +- .../CodeGenCXX/pointers-to-data-members.cpp | 2 +- clang/test/SemaCXX/attr-weak.cpp | 1 + .../SemaCXX/nullptr_in_arithmetic_ops.cpp | 2 +- clang/unittests/AST/Interp/toAPValue.cpp | 46 26 files changed, 706 insertions(+), 28 deletions(-) create mode 100644 clang/lib/AST/Interp/MemberPointer.cpp create mode 100644 clang/lib/AST/Interp/MemberPointer.h create mode 100644 clang/test/AST/Interp/memberpointers.cpp diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 3faefb54f599f..a5d3dacfc1a84 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -87,6 +87,7 @@ add_clang_library(clangAST Interp/Record.cpp Interp/Source.cpp Interp/State.cpp + Interp/MemberPointer.cpp Interp/InterpShared.cpp ItaniumCXXABI.cpp ItaniumMangle.cpp diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 3671c41ae7039..b0f28c9cec414 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -100,6 +100,35 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { return this->emitMemcpy(CE); } + case CK_DerivedToBaseMemberPointer: { +assert(classifyPrim(CE->getType()) == PT_MemberPtr); +assert(classifyPrim(SubExpr->getType()) == PT_MemberPtr); +const auto *FromMP = SubExpr->getType()->getAs(); +const auto *ToMP = CE->getType()->getAs(); + +unsigned DerivedOffset = collectBaseOffset(QualType(ToMP->getClass(), 0), + QualType(FromMP->getClass(), 0)); + +if (!this->visit(SubExpr)) + return false; + +return this->emitGetMemberPtrBasePop(DerivedOffset, CE); + } + + case CK_BaseToDerivedMemberPointer: { +assert(classifyPrim(CE) == PT_MemberPtr); +assert(classifyPrim(SubExpr) == PT_MemberPtr); +const auto *FromMP = SubExpr->getType()->getAs(); +const auto *ToMP = CE->getType()->getAs(); + +unsigned DerivedOffset = collectBaseOffset(QualType(FromMP->getClass(), 0), + QualType(ToMP->getClass(), 0)); + +if (!this->visit(SubExpr)) + return false; +return this->emitGetMemberPtrBasePop(-DerivedOffset, CE); + } + case CK_UncheckedDerivedToBase: case CK_DerivedToBase: { if (!this->visit(SubExpr)) @@ -187,7 +216,8 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { return this->emitCastFloatingIntegral(*ToT, CE); } - case CK_NullToPointer: { + case CK_NullToPointer: + case CK_NullToMemberPointer: { if (DiscardResult) return true; @@ -326,7 +356,8 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { return this->emitCast(*FromT, *ToT, CE); } - case CK_PointerToBoolean: { + case CK_PointerToBoolean: + case CK_MemberPointerToBoolean: { PrimType PtrT = classifyPrim(SubExpr->getType()); // Just emit p != nullptr for this. @@ -534,8 +565,23 @@ bool ByteCodeExprGen::VisitBinaryOperator(const BinaryOperator *BO) { BO->isComparisonOp()) return this->emitComplexComparison(LHS, RHS, BO); - if (BO->isPtrMemOp()) -return this->visit(RHS); + if (BO->isPtrMemOp()) { +if (!this->visit(LHS)) + return false; + +if (!this->visit(RHS)) + return false; + +if (!this->emitToMemberPtr(BO)) + return false; + +if (classifyPrim(BO) == PT_MemberPtr) + return
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
tbaederr wrote: Rebased and updated with a lot more tests. https://github.com/llvm/llvm-project/pull/70306 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Implement dynamic memory allocation handling (PR #70306)
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/70306 >From 471d7a14b6475c4d06365b01ac35847276a464ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 25 Oct 2023 08:33:30 +0200 Subject: [PATCH] [clang][Interp] Implement dynamic memory allocation handling --- clang/lib/AST/CMakeLists.txt | 1 + clang/lib/AST/Interp/ByteCodeExprGen.cpp | 79 ++ clang/lib/AST/Interp/ByteCodeExprGen.h | 2 + clang/lib/AST/Interp/DynamicAllocator.cpp | 119 + clang/lib/AST/Interp/DynamicAllocator.h| 95 +++ clang/lib/AST/Interp/EvalEmitter.cpp | 26 ++ clang/lib/AST/Interp/EvaluationResult.cpp | 67 + clang/lib/AST/Interp/EvaluationResult.h| 6 + clang/lib/AST/Interp/Interp.cpp| 49 clang/lib/AST/Interp/Interp.h | 128 ++ clang/lib/AST/Interp/InterpBlock.h | 21 +- clang/lib/AST/Interp/InterpState.cpp | 17 +- clang/lib/AST/Interp/InterpState.h | 11 + clang/lib/AST/Interp/Opcodes.td| 24 +- clang/lib/AST/Interp/Pointer.h | 1 + clang/test/AST/Interp/new-delete.cpp | 274 + clang/test/Rewriter/rewrite-modern-catch.m | 2 +- clang/test/SemaCXX/delete.cpp | 2 +- clang/test/SemaCXX/new-delete.cpp | 22 +- 19 files changed, 933 insertions(+), 13 deletions(-) create mode 100644 clang/lib/AST/Interp/DynamicAllocator.cpp create mode 100644 clang/lib/AST/Interp/DynamicAllocator.h create mode 100644 clang/test/AST/Interp/new-delete.cpp diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 3faefb54f599f..4ab1064f2e0a3 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -76,6 +76,7 @@ add_clang_library(clangAST Interp/InterpBuiltin.cpp Interp/Floating.cpp Interp/EvaluationResult.cpp + Interp/DynamicAllocator.cpp Interp/Interp.cpp Interp/InterpBlock.cpp Interp/InterpFrame.cpp diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 3671c41ae7039..2e78bdfa09ece 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -2471,6 +2471,85 @@ bool ByteCodeExprGen::VisitCXXInheritedCtorInitExpr( return this->emitCall(F, 0, E); } +template +bool ByteCodeExprGen::VisitCXXNewExpr(const CXXNewExpr *E) { + assert(classifyPrim(E->getType()) == PT_Ptr); + const Expr *Init = E->getInitializer(); + QualType ElementType = E->getAllocatedType(); + std::optional ElemT = classify(ElementType); + + const Descriptor *Desc; + if (ElemT) { +if (E->isArray()) + Desc = nullptr; // We're not going to use it in this case. +else + Desc = P.createDescriptor(E, *ElemT, Descriptor::InlineDescMD, +/*IsConst=*/false, /*IsTemporary=*/false, +/*IsMutable=*/false); + } else { +Desc = P.createDescriptor( +E, ElementType.getTypePtr(), +E->isArray() ? std::nullopt : Descriptor::InlineDescMD, +/*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false, Init); + } + + if (E->isArray()) { +std::optional ArraySizeExpr = E->getArraySize(); +if (!ArraySizeExpr) + return false; +assert(ArraySizeExpr); +PrimType SizeT = classifyPrim((*ArraySizeExpr)->getType()); + +if (!this->visit(*ArraySizeExpr)) + return false; + +if (ElemT) { + // N primitive elements. + if (!this->emitAllocN(SizeT, *ElemT, E, E)) +return false; +} else { + // N Composite elements. + if (!this->emitAllocCN(SizeT, Desc, E)) +return false; +} + + } else { +// Allocate just one element. +if (!this->emitAlloc(Desc, E)) + return false; + +if (Init) { + if (ElemT) { +if (!this->visit(Init)) + return false; + +if (!this->emitInit(*ElemT, E)) + return false; + } else { +// Composite. +if (!this->visitInitializer(Init)) + return false; + } +} + } + + if (DiscardResult) +return this->emitPopPtr(E); + + return true; +} + +template +bool ByteCodeExprGen::VisitCXXDeleteExpr(const CXXDeleteExpr *E) { + const Expr *Arg = E->getArgument(); + + // Arg must be an lvalue. + if (!this->visit(Arg)) +return false; + + return this->emitFree(E->isArrayForm(), E); +} + template bool ByteCodeExprGen::VisitExpressionTraitExpr( const ExpressionTraitExpr *E) { diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 44c495240289f..2432beaa223a3 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -128,6 +128,8 @@ class ByteCodeExprGen : public ConstStmtVisitor, bool>, bool VisitConvertVectorExpr(const ConvertVectorExpr *E); bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E); bool
[clang] [Clang] `constexpr` builtin floating point classification / comparison functions (PR #94118)
https://github.com/tbaederr commented: `Interp/` changes LGTM. https://github.com/llvm/llvm-project/pull/94118 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Move CWG2390 test into `cwg23xx.cpp` (PR #94206)
https://github.com/tbaederr approved this pull request. Looks good, thanks https://github.com/llvm/llvm-project/pull/94206 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Interp] Member Pointers (PR #91303)
Timm =?utf-8?q?Bäder?= , Timm =?utf-8?q?Bäder?= , Timm =?utf-8?q?Bäder?= , Timm =?utf-8?q?Bäder?= , Timm =?utf-8?q?Bäder?= , Timm =?utf-8?q?Bäder?= Message-ID: In-Reply-To: https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/91303 >From 30d86295dda9b7aaa06c23b67c54806475266e5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 10 Apr 2024 16:42:36 +0200 Subject: [PATCH 1/7] Memberpointers --- clang/lib/AST/CMakeLists.txt | 1 + clang/lib/AST/Interp/ByteCodeExprGen.cpp | 103 +- clang/lib/AST/Interp/Context.cpp | 15 +- clang/lib/AST/Interp/Context.h| 2 + clang/lib/AST/Interp/Descriptor.cpp | 1 + clang/lib/AST/Interp/Disasm.cpp | 3 + clang/lib/AST/Interp/Interp.cpp | 30 ++- clang/lib/AST/Interp/Interp.h | 99 ++ clang/lib/AST/Interp/InterpFrame.cpp | 1 + clang/lib/AST/Interp/InterpStack.cpp | 1 + clang/lib/AST/Interp/InterpStack.h| 3 + clang/lib/AST/Interp/MemberPointer.cpp| 73 +++ clang/lib/AST/Interp/MemberPointer.h | 112 +++ clang/lib/AST/Interp/Opcodes.td | 18 +- clang/lib/AST/Interp/Pointer.cpp | 1 + clang/lib/AST/Interp/Pointer.h| 1 + clang/lib/AST/Interp/PrimType.cpp | 1 + clang/lib/AST/Interp/PrimType.h | 8 +- clang/test/AST/Interp/eval-order.cpp | 4 +- clang/test/AST/Interp/literals.cpp| 7 +- clang/test/AST/Interp/memberpointers.cpp | 184 ++ .../mangle-ms-templates-memptrs.cpp | 2 +- .../CodeGenCXX/pointers-to-data-members.cpp | 2 +- clang/test/SemaCXX/attr-weak.cpp | 1 + .../SemaCXX/nullptr_in_arithmetic_ops.cpp | 2 +- clang/unittests/AST/Interp/toAPValue.cpp | 46 + 26 files changed, 692 insertions(+), 29 deletions(-) create mode 100644 clang/lib/AST/Interp/MemberPointer.cpp create mode 100644 clang/lib/AST/Interp/MemberPointer.h create mode 100644 clang/test/AST/Interp/memberpointers.cpp diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 3faefb54f599f..a5d3dacfc1a84 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -87,6 +87,7 @@ add_clang_library(clangAST Interp/Record.cpp Interp/Source.cpp Interp/State.cpp + Interp/MemberPointer.cpp Interp/InterpShared.cpp ItaniumCXXABI.cpp ItaniumMangle.cpp diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 6607727b5246f..5f8b94c3a0f94 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -100,6 +100,35 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { return this->emitMemcpy(CE); } + case CK_DerivedToBaseMemberPointer: { +assert(classifyPrim(CE->getType()) == PT_MemberPtr); +assert(classifyPrim(SubExpr->getType()) == PT_MemberPtr); +const auto *FromMP = SubExpr->getType()->getAs(); +const auto *ToMP = CE->getType()->getAs(); + +unsigned DerivedOffset = collectBaseOffset(QualType(ToMP->getClass(), 0), + QualType(FromMP->getClass(), 0)); + +if (!this->visit(SubExpr)) + return false; + +return this->emitGetMemberPtrBasePop(DerivedOffset, CE); + } + + case CK_BaseToDerivedMemberPointer: { +assert(classifyPrim(CE) == PT_MemberPtr); +assert(classifyPrim(SubExpr) == PT_MemberPtr); +const auto *FromMP = SubExpr->getType()->getAs(); +const auto *ToMP = CE->getType()->getAs(); + +unsigned DerivedOffset = collectBaseOffset(QualType(FromMP->getClass(), 0), + QualType(ToMP->getClass(), 0)); + +if (!this->visit(SubExpr)) + return false; +return this->emitGetMemberPtrBasePop(-DerivedOffset, CE); + } + case CK_UncheckedDerivedToBase: case CK_DerivedToBase: { if (!this->visit(SubExpr)) @@ -187,7 +216,8 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { return this->emitCastFloatingIntegral(*ToT, CE); } - case CK_NullToPointer: { + case CK_NullToPointer: + case CK_NullToMemberPointer: { if (DiscardResult) return true; @@ -326,7 +356,8 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { return this->emitCast(*FromT, *ToT, CE); } - case CK_PointerToBoolean: { + case CK_PointerToBoolean: + case CK_MemberPointerToBoolean: { PrimType PtrT = classifyPrim(SubExpr->getType()); // Just emit p != nullptr for this. @@ -534,8 +565,23 @@ bool ByteCodeExprGen::VisitBinaryOperator(const BinaryOperator *BO) { BO->isComparisonOp()) return this->emitComplexComparison(LHS, RHS, BO); - if (BO->isPtrMemOp()) -return this->visit(RHS); + if (BO->isPtrMemOp()) { +if (!this->visit(LHS)) +