From 3a85531e2a23122ce4fb93f941c2c211fca426fb Mon Sep 17 00:00:00 2001 From: tanhongmin Date: Thu, 18 Sep 2025 01:47:19 +0000 Subject: [PATCH 1/7] trait variables & trait binary operator sema desugar at the same time --- clang/include/clang/Sema/Sema.h | 3 + clang/lib/Parse/ParseDecl.cpp | 9 ++ clang/lib/Parse/ParseStmt.cpp | 4 + clang/lib/Sema/BSC/SemaBSCTrait.cpp | 122 +++++++++++++++++++++++++++- clang/lib/Sema/SemaDecl.cpp | 10 ++- clang/lib/Sema/SemaExpr.cpp | 49 +++++------ 6 files changed, 169 insertions(+), 28 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index d8de64a915e3..d6c51a8b164f 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5707,6 +5707,9 @@ public: void ActOnDesugarTraitExprInStruct(InitListExpr *IList, Expr *UO, QualType ElemType, unsigned &Index, DesignatedInitExpr **DIE); + + // 延迟解糖统一入口 + void DesugarTraitInTranslationUnit(Decl *D); #endif ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 2b00eeec46c9..f4738a75adfc 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2309,6 +2309,15 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, } } +#if ENABLE_BSC + // 对声明组进行trait延迟解糖 + if (getLangOpts().BSC && Context == DeclaratorContext::File) { + for (Decl *D : DeclsInGroup) { + Actions.DesugarTraitInTranslationUnit(D); + } + } +#endif + return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup); } diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index f3246b8c5678..65b9667ce16f 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -1373,6 +1373,9 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr } #if ENABLE_BSC + // BSC TRAIT: 原始的即时解糖代码 - 已注释以实施延迟解糖 + // Original eager trait desugaring code - commented out for delayed desugaring implementation + /* if (getLangOpts().BSC && R.isUsable()) { // desugar for trait F *f = &a; if (auto *DS = dyn_cast(R.get())) { @@ -1402,6 +1405,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr } } } + */ #endif if (R.isUsable()) diff --git a/clang/lib/Sema/BSC/SemaBSCTrait.cpp b/clang/lib/Sema/BSC/SemaBSCTrait.cpp index a09089a1d6aa..da4d65145f0c 100644 --- a/clang/lib/Sema/BSC/SemaBSCTrait.cpp +++ b/clang/lib/Sema/BSC/SemaBSCTrait.cpp @@ -12,6 +12,7 @@ #if ENABLE_BSC +#include "TreeTransform.h" #include "TypeLocBuilder.h" #include "clang/AST/ASTContext.h" #include "clang/AST/BSC/DeclBSC.h" @@ -1173,7 +1174,7 @@ bool Sema::IsTraitExpr(Expr *Expr) { RecordDecl *RD = dyn_cast(RT->getDecl()); return (RD && RD->getDesugaredTraitDecl()); } - return false; + return Expr->getType()->hasTraitType(); } ExprResult Sema::ActOnTraitCompare(Scope *S, SourceLocation TokLoc, @@ -1353,4 +1354,123 @@ void Sema::checkBSCFunctionContainsTrait(Decl *D) { } } } + +class BSCTraitDesugarer : public TreeTransform { + using BaseTransform = TreeTransform; + +public: + BSCTraitDesugarer(Sema &SemaRef) : TreeTransform(SemaRef) {} + + void desugarTopLevelDecl(Decl *D); + + Decl *TransformDecl(SourceLocation Loc, Decl *D) { + if (!D) + return D; + llvm::DenseMap::iterator Known = + TransformedLocalDecls.find(D); + if (Known != TransformedLocalDecls.end()) + return Known->second; + VarDecl *VD = dyn_cast(D); + if (!VD) + return D; + if (getSema().TryDesugarTrait(VD->getType())) + return TransformTraitVariableDeclaration(VD); + return D; + } + + ExprResult TransformBinaryOperator(BinaryOperator *E) { + bool LHSIsTrait = getSema().IsTraitExpr(E->getLHS()); + bool RHSIsTrait = getSema().IsTraitExpr(E->getRHS()); + + if (LHSIsTrait || RHSIsTrait) + return TransformTraitBinaryOperations(E); + return BaseTransform::TransformBinaryOperator(E); + } + +private: + Decl *TransformTraitVariableDeclaration(VarDecl *D); + ExprResult TransformTraitBinaryOperations(BinaryOperator *E); +}; + +void BSCTraitDesugarer::desugarTopLevelDecl(Decl *D) { + if (!D) + return; + + if (FunctionDecl *FD = dyn_cast(D)) { + llvm::errs() << "[BSCTraitDesugarer] Processing FunctionDecl: " + << (FD->getNameAsString().empty() ? "" + : FD->getNameAsString()) + << "\n"; + if (FD->hasBody()) { + llvm::errs() << "[BSCTraitDesugarer] Transforming function body...\n"; + Stmt *Body = FD->getBody(); + StmtResult NewBody = TransformStmt(Body); + if (NewBody.isUsable() && NewBody.get() != Body) { + llvm::errs() + << "[BSCTraitDesugarer] Function body transformed successfully\n"; + FD->setBody(NewBody.get()); + } else { + llvm::errs() << "[BSCTraitDesugarer] Function body unchanged\n"; + } + } + } else if (VarDecl *VD = dyn_cast(D)) { + llvm::errs() << "[BSCTraitDesugarer] Processing VarDecl: " + << (VD->getNameAsString().empty() ? "" + : VD->getNameAsString()) + << " of type: " << VD->getType().getAsString() << "\n"; + Decl *NewDecl = getSema().ActOnDesugarTraitInstance(VD); + if (NewDecl && NewDecl != VD) { + llvm::errs() << "[BSCTraitDesugarer] Variable transformed to new type\n"; + } else { + llvm::errs() << "[BSCTraitDesugarer] Variable unchanged\n"; + } + } +} + +Decl *BSCTraitDesugarer::TransformTraitVariableDeclaration(VarDecl *D) { + // 对trait变量进行解糖 + VarDecl *VD = dyn_cast(D); + Decl *NewDecl = getSema().ActOnDesugarTraitInstance(VD); + if (NewDecl && NewDecl != D) { + transformedLocalDecl(D, {NewDecl}); + return NewDecl; + } + return D; +} + +ExprResult +BSCTraitDesugarer::TransformTraitBinaryOperations(BinaryOperator *E) { + BinaryOperatorKind Opc = E->getOpcode(); + Expr *LHS = E->getLHS(); + Expr *RHS = E->getRHS(); + LHS = TransformExpr(LHS).get(); + RHS = TransformExpr(RHS).get(); + + llvm::errs() << "[BSCTraitDesugarer] Processing trait binary operation: " + << BinaryOperator::getOpcodeStr(Opc) << "\n"; + + if (Opc == BO_Assign) { + // 复用现有的ActOnTraitReassign逻辑 + return getSema().ActOnTraitReassign(getSema().getCurScope(), + E->getOperatorLoc(), Opc, LHS, RHS); + } else if (Opc == BO_EQ || Opc == BO_NE) { + // 复用现有的ActOnTraitCompare逻辑 + return getSema().ActOnTraitCompare(getSema().getCurScope(), + E->getOperatorLoc(), Opc, LHS, RHS); + } + + // 其他trait相关操作暂时使用基础转换 + return BaseTransform::TransformBinaryOperator(E); +} + +// 在Sema类中添加对外统一接口 +void Sema::DesugarTraitInTranslationUnit(Decl *D) { +#if ENABLE_BSC + if (!D || !getLangOpts().BSC) + return; + + BSCTraitDesugarer Desugarer(*this); + Desugarer.desugarTopLevelDecl(D); +#endif +} #endif // ENABLE_BSC \ No newline at end of file diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c7bfeb708742..2d08d7b3f1fe 100755 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6532,9 +6532,9 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, #if ENABLE_BSC if (Context.getLangOpts().BSC) { - QualType T = TInfo->getType(); - if (TryDesugarTrait(T)) - AddToScope = false; + // QualType T = TInfo->getType(); + // if (TryDesugarTrait(T)) + // AddToScope = false; // 'safe' or 'unsafe' can only appear before on function or statement or // parenthesized expression. if (D.getDeclSpec().getSafeZoneSpecifier() != SZ_None && @@ -16065,6 +16065,10 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, } // Desugar BSC Function. DesugarDestructorCall(FD); + + // 对函数体进行trait延迟解糖 + DesugarTraitInTranslationUnit(FD); + BSCDataflowAnalysisFlag = false; } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 37def7ff1d96..1f4e8b76c0a8 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2367,8 +2367,9 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, DeclContext *DC = SS.isEmpty() ? CurContext : nullptr; #if ENABLE_BSC if (!ET.isNull()) { - if(getASTContext().BSCDeclContextMap.find(ET.getCanonicalType().getTypePtr()) != - getASTContext().BSCDeclContextMap.end()){ + if (getASTContext().BSCDeclContextMap.find( + ET.getCanonicalType().getTypePtr()) != + getASTContext().BSCDeclContextMap.end()) { DC = getASTContext().BSCDeclContextMap[ET.getCanonicalType().getTypePtr()]; } } @@ -16089,28 +16090,28 @@ ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, #if ENABLE_BSC // Handling reassignments of variable types with trait pointers: - if (getLangOpts().BSC) { - if (LHSExpr->getType()->hasTraitType()) - LHSExpr = LHSExpr->IgnoreCasts(); - if (RHSExpr->getType()->hasTraitType()) - RHSExpr = RHSExpr->IgnoreCasts(); - bool LHSIsTrait = IsTraitExpr(LHSExpr); - bool RHSIsTrait = IsTraitExpr(RHSExpr); - if (LHSIsTrait || RHSIsTrait) { - if (Opc == BO_Assign && LHSIsTrait && !RHSIsTrait) { - if (!(LHSExpr->getType()->isPointerType() && - RHSExpr->isNullPointerConstant(Context, - Expr::NPC_ValueDependentIsNull))) - return ActOnTraitReassign(S, TokLoc, Opc, LHSExpr, RHSExpr); - } - if (Opc == BO_EQ || Opc == BO_NE) { - if ((LHSIsTrait && RHSIsTrait) || - (LHSIsTrait && !LHSExpr->getType()->isPointerType()) || - (RHSIsTrait && !RHSExpr->getType()->isPointerType())) - return ActOnTraitCompare(S, TokLoc, Opc, LHSExpr, RHSExpr); - } - } - } + // if (getLangOpts().BSC) { + // if (LHSExpr->getType()->hasTraitType()) + // LHSExpr = LHSExpr->IgnoreCasts(); + // if (RHSExpr->getType()->hasTraitType()) + // RHSExpr = RHSExpr->IgnoreCasts(); + // bool LHSIsTrait = IsTraitExpr(LHSExpr); + // bool RHSIsTrait = IsTraitExpr(RHSExpr); + // if (LHSIsTrait || RHSIsTrait) { + // if (Opc == BO_Assign && LHSIsTrait && !RHSIsTrait) { + // if (!(LHSExpr->getType()->isPointerType() && + // RHSExpr->isNullPointerConstant(Context, + // Expr::NPC_ValueDependentIsNull))) + // return ActOnTraitReassign(S, TokLoc, Opc, LHSExpr, RHSExpr); + // } + // if (Opc == BO_EQ || Opc == BO_NE) { + // if ((LHSIsTrait && RHSIsTrait) || + // (LHSIsTrait && !LHSExpr->getType()->isPointerType()) || + // (RHSIsTrait && !RHSExpr->getType()->isPointerType())) + // return ActOnTraitCompare(S, TokLoc, Opc, LHSExpr, RHSExpr); + // } + // } + // } QualType LHSCanType = LHSExpr->getType().getCanonicalType(); QualType RHSCanType = RHSExpr->getType().getCanonicalType(); -- Gitee From bc6ed4fc26b703dd70321650a2d76b4e0ee01b61 Mon Sep 17 00:00:00 2001 From: tanhongmin Date: Thu, 18 Sep 2025 06:11:19 +0000 Subject: [PATCH 2/7] separate trait variables sema and desugar --- clang/include/clang/Sema/Sema.h | 1 + clang/lib/Parse/ParseStmt.cpp | 15 +++ clang/lib/Sema/BSC/SemaBSCTrait.cpp | 201 +++++++++++++++++++++++++++- 3 files changed, 215 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index d6c51a8b164f..ad3cd4a41593 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5702,6 +5702,7 @@ public: ExprResult AddAfterStructTrait(ExprResult ULE, SourceLocation DSLoc, std::string ID); VarDecl *ActOnDesugarTraitInstance(Decl *VarDec); + bool ActOnTraitVariableSema(VarDecl *VD); // Sema阶段语义分析 Expr *ConvertParmTraitToStructTrait(Expr *Arg, QualType ProtoArgType, SourceLocation DSLoc); void ActOnDesugarTraitExprInStruct(InitListExpr *IList, Expr *UO, diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 65b9667ce16f..90ea8b6698f0 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -1373,6 +1373,21 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr } #if ENABLE_BSC + if (getLangOpts().BSC && R.isUsable()) { + if (auto *DS = dyn_cast(R.get())) { + if (DS->isSingleDecl()) { + if (VarDecl *VD = dyn_cast(DS->getSingleDecl())) { + Actions.ActOnTraitVariableSema(VD); + } + } else { + for (auto *D : DS->getDeclGroup()) { + if (VarDecl *VD = dyn_cast(D)) { + Actions.ActOnTraitVariableSema(VD); + } + } + } + } + } // BSC TRAIT: 原始的即时解糖代码 - 已注释以实施延迟解糖 // Original eager trait desugaring code - commented out for delayed desugaring implementation /* diff --git a/clang/lib/Sema/BSC/SemaBSCTrait.cpp b/clang/lib/Sema/BSC/SemaBSCTrait.cpp index da4d65145f0c..ce1fe5f092ba 100644 --- a/clang/lib/Sema/BSC/SemaBSCTrait.cpp +++ b/clang/lib/Sema/BSC/SemaBSCTrait.cpp @@ -696,6 +696,67 @@ static int CountPointerLevels(QualType T) { // .data = &s; // .vtable = *struct_S_Trait_I_Vtable; //`} + +bool Sema::ActOnTraitVariableSema(VarDecl *VD) { + if (!VD) + return false; + + QualType TraitType = VD->getType(); + if (!TraitType->isPointerType()) + return false; + // check trait vtable + TraitDecl *TD = nullptr; + TD = TryDesugarTrait(TraitType); + if (!TD) + return false; + if (TD->getVtable() == nullptr) { + Diag(VD->getLocation(), diag::err_typecheck_decl_incomplete_type) + << TraitType; + return false; + } + Expr *Init = VD->getInit(); + if (Init == nullptr) + return true; + if (Init->containsErrors()) + return false; + // check init expr + Expr *UO = Init; + if (CastExpr *Cexpr = dyn_cast(Init)) { + UO = Cexpr->getSubExpr(); + } + QualType InitQT = UO->getType(); + if (CountPointerLevels(TraitType) != CountPointerLevels(InitQT)) { + Diag(UO->getBeginLoc(), + diag::err_typecheck_convert_incompatible_pointer) + << TraitType << InitQT << 4 // operation type: 4 = initializing + << 0; // hint type: 0 = no additional hint + return false; + } + // init with same trait type + QualType InnerTraitQT = TraitType; + while (InnerTraitQT->isPointerType()) + InnerTraitQT = InnerTraitQT->getPointeeType(); + QualType InnerInitQT = InitQT; + while (InnerInitQT->isPointerType()) + InnerInitQT = InnerInitQT->getPointeeType(); + if (Context.hasSameType(InnerInitQT, InnerTraitQT)) { + return true; + } + // init with pointer + bool ExpIsNullPointer = + Init->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull); + QualType CanonicalInnerInitQT = InnerInitQT.getCanonicalType(); + VarDecl *LookupVar = TD->getTypeImpledVarDecl(CanonicalInnerInitQT); + if (!LookupVar && !ExpIsNullPointer) { + Diag(UO->getBeginLoc(), diag::err_type_has_not_impl_trait) + << TraitType << InitQT; + return false; + } + + return true; +} + +// 原有的ActOnDesugarTraitInstance保留,但标记为将要废弃 VarDecl *Sema::ActOnDesugarTraitInstance(Decl *D) { VarDecl *VD = dyn_cast(D); if (!VD) @@ -1390,6 +1451,7 @@ public: private: Decl *TransformTraitVariableDeclaration(VarDecl *D); ExprResult TransformTraitBinaryOperations(BinaryOperator *E); + VarDecl *DesugarTraitVariable(VarDecl *VD); }; void BSCTraitDesugarer::desugarTopLevelDecl(Decl *D) { @@ -1428,9 +1490,8 @@ void BSCTraitDesugarer::desugarTopLevelDecl(Decl *D) { } Decl *BSCTraitDesugarer::TransformTraitVariableDeclaration(VarDecl *D) { - // 对trait变量进行解糖 VarDecl *VD = dyn_cast(D); - Decl *NewDecl = getSema().ActOnDesugarTraitInstance(VD); + Decl *NewDecl = DesugarTraitVariable(VD); if (NewDecl && NewDecl != D) { transformedLocalDecl(D, {NewDecl}); return NewDecl; @@ -1463,6 +1524,142 @@ BSCTraitDesugarer::TransformTraitBinaryOperations(BinaryOperator *E) { return BaseTransform::TransformBinaryOperator(E); } +VarDecl *BSCTraitDesugarer::DesugarTraitVariable(VarDecl *VD) { + if (!VD) + return nullptr; + + QualType TraitType = VD->getType(); + if (!TraitType->isPointerType()) + return nullptr; + TraitDecl *TD = getSema().TryDesugarTrait(TraitType); + if (!TD) + return nullptr; + // get struct type from trait + RecordDecl *RD = nullptr; + if (TraitType.isOwnedQualified()) + RD = TD->getOwnedTrait(); + else if (TraitType.isBorrowQualified()) + RD = TD->getBorrowTrait(); + else + RD = TD->getTrait(); + if (!RD) + return nullptr; + QualType StructType; + if (RD->getDescribedClassTemplate()) { + StructType = + getSema().CompleteRecordType(RD, VD->getTypeSourceInfo()); + } else { + StructType = getSema().Context.getRecordType(RD); + } + if (StructType.isNull()) + return nullptr; + // build final type with same pointer levels as original + StructType = + getSema().Context.getElaboratedType(ETK_Struct, nullptr, StructType); + QualType OriginalPointee = TraitType->getPointeeType(); + QualType TmpType = OriginalPointee.getCanonicalType(); + while (TmpType->isPointerType()) { + StructType = getSema().Context.getPointerType(StructType); + TmpType = TmpType->getPointeeType(); + } + // create new variable with struct type + VarDecl *NewVD = VarDecl::Create( + getSema().Context, getSema().CurContext, VD->getBeginLoc(), + VD->getLocation(), VD->getIdentifier(), StructType, + getSema().Context.getTrivialTypeSourceInfo(StructType), + StorageClass::SC_None); + Expr *Init = VD->getInit(); + Init = TransformExpr(Init).get(); + if (!Init) + return NewVD; + if (Init->containsErrors()) + return NewVD; + // create desugared init expression + Expr *UO = Init; + if (CastExpr *CastInit = dyn_cast(Init)) { + UO = CastInit->getSubExpr(); + } + QualType InitType = UO->getType(); + // check if init with same trait type + QualType InnerInitType = InitType; + while (InnerInitType->isPointerType()) + InnerInitType = InnerInitType->getPointeeType(); + QualType ExpectedTraitType; + if (VD->getType().isOwnedQualified()) + ExpectedTraitType = QualType(TD->getOwnedTrait()->getTypeForDecl(), 0); + else if (VD->getType().isBorrowQualified()) + ExpectedTraitType = QualType(TD->getBorrowTrait()->getTypeForDecl(), 0); + else + ExpectedTraitType = QualType(TD->getTrait()->getTypeForDecl(), 0); + if (dyn_cast(ExpectedTraitType)) { + ExpectedTraitType = getSema().CompleteRecordType( + TD->getTrait(), NewVD->getTypeSourceInfo()); + } + // trait struct to trait struct assignment + if (!ExpectedTraitType.isNull() && + getSema().Context.hasSameType(InnerInitType, ExpectedTraitType)) { + getSema().AddInitializerToDecl(NewVD, UO, false); + return NewVD; + } + // transform pointer type to struct .data type and find .vtable + const PointerType *PT = dyn_cast_or_null(InitType.getTypePtr()); + if (!PT) + return NewVD; + bool IsNullPointer = Init->isNullPointerConstant( + getSema().Context, Expr::NPC_ValueDependentIsNull); + QualType PointeeType = PT->getPointeeType().getCanonicalType(); + VarDecl *VtableVD = TD->getTypeImpledVarDecl(PointeeType); + if (!VtableVD && !IsNullPointer) + return NewVD; + // build initializer list + std::vector InitList; + if (IsNullPointer) { + if (StructType->isPointerType()) { + getSema().AddInitializerToDecl(NewVD, UO, false); + return NewVD; + } + // null pointer case: {NULL, vtable_cast} + RecordDecl *VtableRD = TD->getVtable(); + QualType VtableType = getSema().Context.getRecordType(VtableRD); + if (VtableRD->getDescribedClassTemplate()) { + VtableType = + getSema().CompleteRecordType(VtableRD, VD->getTypeSourceInfo()); + VtableType = + getSema().Context.getElaboratedType(ETK_Struct, nullptr, VtableType); + } + QualType VtablePtr = getSema().Context.getPointerType(VtableType); + ImplicitCastExpr *VtableCast = ImplicitCastExpr::Create( + getSema().Context, VtablePtr, CK_BitCast, UO, nullptr, VK_PRValue, + FPOptionsOverride()); + InitList = {UO, VtableCast}; + } else { + // normal case: {data_cast, &vtable} + QualType VoidPtr = + getSema().Context.getPointerType(getSema().Context.VoidTy); + if (VD->getType().isOwnedQualified()) + VoidPtr.addOwned(); + if (VD->getType().isBorrowQualified()) + VoidPtr.addBorrow(); + ImplicitCastExpr *DataCast = ImplicitCastExpr::Create( + getSema().Context, VoidPtr, CK_BitCast, UO, nullptr, VK_PRValue, + FPOptionsOverride()); + QualType VtableType = VtableVD->getType(); + QualType VtablePtr = getSema().Context.getPointerType(VtableType); + DeclRefExpr *VtableRef = DeclRefExpr::Create( + getSema().Context, NestedNameSpecifierLoc(), SourceLocation(), + VtableVD, false, SourceLocation(), VtableType, VK_LValue); + UnaryOperator *VtableAddr = UnaryOperator::Create( + getSema().Context, VtableRef, UO_AddrOf, VtablePtr, VK_PRValue, + OK_Ordinary, SourceLocation(), false, FPOptionsOverride()); + InitList = {DataCast, VtableAddr}; + } + MutableArrayRef InitExprs = MutableArrayRef(InitList); + ExprResult StructInit = + getSema().ActOnInitList(SourceLocation(), InitExprs, SourceLocation()); + getSema().AddInitializerToDecl(NewVD, StructInit.get(), false); + return NewVD; +} + // 在Sema类中添加对外统一接口 void Sema::DesugarTraitInTranslationUnit(Decl *D) { #if ENABLE_BSC -- Gitee From 937fa54e95efb03013a499960b7054e3a1e5e2a3 Mon Sep 17 00:00:00 2001 From: tanhongmin Date: Mon, 22 Sep 2025 01:51:11 +0000 Subject: [PATCH 3/7] separate trait binary operator sema and desugar --- clang/include/clang/Sema/Sema.h | 2 + clang/lib/Sema/BSC/SemaBSCTrait.cpp | 304 ++++++++++++++++++++++++---- clang/lib/Sema/SemaExpr.cpp | 49 ++++- 3 files changed, 308 insertions(+), 47 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index ad3cd4a41593..6480fb1ea6f7 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5703,6 +5703,8 @@ public: std::string ID); VarDecl *ActOnDesugarTraitInstance(Decl *VarDec); bool ActOnTraitVariableSema(VarDecl *VD); // Sema阶段语义分析 + bool ActOnTraitReassignSema(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr); // Trait赋值语义分析 + bool ActOnTraitCompareSema(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr); // Trait比较语义分析 Expr *ConvertParmTraitToStructTrait(Expr *Arg, QualType ProtoArgType, SourceLocation DSLoc); void ActOnDesugarTraitExprInStruct(InitListExpr *IList, Expr *UO, diff --git a/clang/lib/Sema/BSC/SemaBSCTrait.cpp b/clang/lib/Sema/BSC/SemaBSCTrait.cpp index ce1fe5f092ba..a403b0c3d886 100644 --- a/clang/lib/Sema/BSC/SemaBSCTrait.cpp +++ b/clang/lib/Sema/BSC/SemaBSCTrait.cpp @@ -756,6 +756,73 @@ bool Sema::ActOnTraitVariableSema(VarDecl *VD) { return true; } +bool Sema::ActOnTraitReassignSema(BinaryOperatorKind Opc, Expr *LHSExpr, + Expr *RHSExpr) { + if (!LHSExpr || !RHSExpr) + return false; + if (!LHSExpr->getType()->hasTraitType()) + return false; + if (RHSExpr->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) + return true; + if (!RHSExpr->getType()->isPointerType()) { + Diag(RHSExpr->getBeginLoc(), diag::err_type_has_not_impl_trait) + << LHSExpr->getType() << RHSExpr->getType(); + return false; + } + int LHSPointerLevels = CountPointerLevels(LHSExpr->getType()); + int RHSPointerLevels = CountPointerLevels(RHSExpr->getType()); + if (LHSPointerLevels > 1 && RHSPointerLevels > 1) { + Diag(RHSExpr->getBeginLoc(), diag::err_typecheck_convert_incompatible) + << RHSExpr->getType() << LHSExpr->getType() + << AssignmentAction::AA_Assigning << RHSExpr->getSourceRange(); + } + if (LHSPointerLevels != RHSPointerLevels) { + Diag(RHSExpr->getBeginLoc(), diag::ext_typecheck_convert_pointer_int) + << RHSExpr->getType() << LHSExpr->getType() + << RHSExpr->getSourceRange(); + } + if (LHSPointerLevels == 1 && RHSPointerLevels == 1) { + QualType TraitType = LHSExpr->getType(); + QualType TargetType = + RHSExpr->getType().getUnqualifiedType().getCanonicalType(); + if (Context.hasSameType(TraitType, TargetType)) + return true; + TargetType.removeLocalOwned(); + TraitDecl *TD = TryDesugarTrait(TraitType); + VarDecl *ImplVar = nullptr; + if (TD) + ImplVar = TD->getTypeImpledVarDecl(TargetType->getPointeeType()); + if (!TD || !ImplVar) { + Diag(RHSExpr->getBeginLoc(), diag::err_type_has_not_impl_trait) + << TraitType << TargetType; + return false; + } + } + + return true; +} + +bool Sema::ActOnTraitCompareSema(BinaryOperatorKind Opc, Expr *LHSExpr, + Expr *RHSExpr) { + if (!LHSExpr || !RHSExpr) + return false; + bool LHSIsTrait = IsTraitExpr(LHSExpr); + bool RHSIsTrait = IsTraitExpr(RHSExpr); + if (LHSIsTrait ^ RHSIsTrait) { + Expr *NotTraitExpr = LHSIsTrait ? RHSExpr : LHSExpr; + QualType NotTraitType = NotTraitExpr->getType(); + if (!NotTraitType->isPointerType()) { + Diag(LHSExpr->getBeginLoc(), + diag::err_typecheck_comparison_of_distinct_pointers) + << LHSExpr->getType() << RHSExpr->getType() + << LHSExpr->getSourceRange() << RHSExpr->getSourceRange(); + return false; + } + } + + return true; +} + // 原有的ActOnDesugarTraitInstance保留,但标记为将要废弃 VarDecl *Sema::ActOnDesugarTraitInstance(Decl *D) { VarDecl *VD = dyn_cast(D); @@ -1440,6 +1507,14 @@ public: } ExprResult TransformBinaryOperator(BinaryOperator *E) { + ExprResult LHSResult = TransformExpr(E->getLHS()); + ExprResult RHSResult = TransformExpr(E->getRHS()); + if (LHSResult.isInvalid() || RHSResult.isInvalid()) + return ExprError(); + Expr *LHS = LHSResult.get(); + Expr *RHS = RHSResult.get(); + E->setLHS(LHS); + E->setRHS(RHS); bool LHSIsTrait = getSema().IsTraitExpr(E->getLHS()); bool RHSIsTrait = getSema().IsTraitExpr(E->getRHS()); @@ -1451,7 +1526,10 @@ public: private: Decl *TransformTraitVariableDeclaration(VarDecl *D); ExprResult TransformTraitBinaryOperations(BinaryOperator *E); + VarDecl *DesugarTraitVariable(VarDecl *VD); + ExprResult DesugarTraitReassign(BinaryOperator *E); + ExprResult DesugarTraitCompare(BinaryOperator *E); }; void BSCTraitDesugarer::desugarTopLevelDecl(Decl *D) { @@ -1502,26 +1580,13 @@ Decl *BSCTraitDesugarer::TransformTraitVariableDeclaration(VarDecl *D) { ExprResult BSCTraitDesugarer::TransformTraitBinaryOperations(BinaryOperator *E) { BinaryOperatorKind Opc = E->getOpcode(); - Expr *LHS = E->getLHS(); - Expr *RHS = E->getRHS(); - LHS = TransformExpr(LHS).get(); - RHS = TransformExpr(RHS).get(); - - llvm::errs() << "[BSCTraitDesugarer] Processing trait binary operation: " - << BinaryOperator::getOpcodeStr(Opc) << "\n"; - if (Opc == BO_Assign) { - // 复用现有的ActOnTraitReassign逻辑 - return getSema().ActOnTraitReassign(getSema().getCurScope(), - E->getOperatorLoc(), Opc, LHS, RHS); + return DesugarTraitReassign(E); } else if (Opc == BO_EQ || Opc == BO_NE) { - // 复用现有的ActOnTraitCompare逻辑 - return getSema().ActOnTraitCompare(getSema().getCurScope(), - E->getOperatorLoc(), Opc, LHS, RHS); + return DesugarTraitCompare(E); } - // 其他trait相关操作暂时使用基础转换 - return BaseTransform::TransformBinaryOperator(E); + return ExprError(); } VarDecl *BSCTraitDesugarer::DesugarTraitVariable(VarDecl *VD) { @@ -1534,34 +1599,8 @@ VarDecl *BSCTraitDesugarer::DesugarTraitVariable(VarDecl *VD) { TraitDecl *TD = getSema().TryDesugarTrait(TraitType); if (!TD) return nullptr; - // get struct type from trait - RecordDecl *RD = nullptr; - if (TraitType.isOwnedQualified()) - RD = TD->getOwnedTrait(); - else if (TraitType.isBorrowQualified()) - RD = TD->getBorrowTrait(); - else - RD = TD->getTrait(); - if (!RD) - return nullptr; - QualType StructType; - if (RD->getDescribedClassTemplate()) { - StructType = - getSema().CompleteRecordType(RD, VD->getTypeSourceInfo()); - } else { - StructType = getSema().Context.getRecordType(RD); - } - if (StructType.isNull()) - return nullptr; - // build final type with same pointer levels as original - StructType = - getSema().Context.getElaboratedType(ETK_Struct, nullptr, StructType); - QualType OriginalPointee = TraitType->getPointeeType(); - QualType TmpType = OriginalPointee.getCanonicalType(); - while (TmpType->isPointerType()) { - StructType = getSema().Context.getPointerType(StructType); - TmpType = TmpType->getPointeeType(); - } + QualType StructType = + getSema().DesugarTraitToStructTrait(TD, TraitType, VD->getBeginLoc()); // create new variable with struct type VarDecl *NewVD = VarDecl::Create( getSema().Context, getSema().CurContext, VD->getBeginLoc(), @@ -1660,6 +1699,183 @@ VarDecl *BSCTraitDesugarer::DesugarTraitVariable(VarDecl *VD) { return NewVD; } +ExprResult BSCTraitDesugarer::DesugarTraitReassign(BinaryOperator *E) { + Expr *LHSExpr = E->getLHS(); + Expr *RHSExpr = E->getRHS(); + BinaryOperatorKind Opc = E->getOpcode(); + SourceLocation TokLoc = E->getOperatorLoc(); + // check null assignment + if (RHSExpr->isNullPointerConstant(getSema().Context, + Expr::NPC_ValueDependentIsNull)) { + // null assignment: assign all fields to NULL + SmallVector AssignExprs; + RecordDecl *LHSRecord = + dyn_cast(LHSExpr->getType().getCanonicalType())->getDecl(); + for (RecordDecl::field_iterator I = LHSRecord->field_begin(), + E = LHSRecord->field_end(); + I != E; ++I) { + Expr *FieldExpr = getSema().BuildMemberExpr( + LHSExpr, false, SourceLocation(), NestedNameSpecifierLoc(), + SourceLocation(), *I, DeclAccessPair::make(*I, I->getAccess()), false, + DeclarationNameInfo(), I->getType(), VK_LValue, OK_Ordinary); + AssignExprs.push_back(getSema() + .BuildBinOp(getSema().getCurScope(), TokLoc, + Opc, FieldExpr, RHSExpr) + .get()); + } + return getSema().BuildBinOp(getSema().getCurScope(), TokLoc, BO_Comma, + AssignExprs[0], AssignExprs[1]); + } + // normal assignment + QualType LHSType = LHSExpr->getType(); + Expr *CastedRHS = RHSExpr->IgnoreCasts(); + QualType RHSType = CastedRHS->getType(); + while (LHSType->isPointerType()) { + LHSType = LHSType->getPointeeType(); + if (RHSType->isPointerType()) + RHSType = RHSType->getPointeeType(); + } + // trait to trait assignment + if (!RHSType->isPointerType()) { + return getSema().BuildBinOp(getSema().getCurScope(), TokLoc, Opc, LHSExpr, + CastedRHS); + } + // normal type to trait assignment + RecordDecl *LHSRecord = + dyn_cast(LHSType.getCanonicalType())->getDecl(); + QualType TargetType = CastedRHS->getType() + ->getPointeeType() + .getUnqualifiedType() + .getCanonicalType(); + TargetType.removeLocalOwned(); + Expr *DataAssign = nullptr; + Expr *VtableAssign = nullptr; + for (RecordDecl::field_iterator I = LHSRecord->field_begin(), + E = LHSRecord->field_end(); + I != E; ++I) { + Expr *FieldExpr = getSema().BuildMemberExpr( + LHSExpr, false, SourceLocation(), NestedNameSpecifierLoc(), + SourceLocation(), *I, DeclAccessPair::make(*I, I->getAccess()), false, + DeclarationNameInfo(), I->getType(), VK_LValue, OK_Ordinary); + + if (I->getNameAsString() == "data") { + Expr *CastExpr = ImplicitCastExpr::Create( + getSema().Context, I->getType(), CK_BitCast, CastedRHS, nullptr, + VK_PRValue, FPOptionsOverride()); + DataAssign = getSema() + .BuildBinOp(getSema().getCurScope(), TokLoc, Opc, + FieldExpr, CastExpr) + .get(); + } else { + TraitDecl *TD = LHSRecord->getDesugaredTraitDecl(); + RecordDecl *VtableRecord = TD->getVtable(); + VarDecl *VtableVar = TD->getTypeImpledVarDecl(TargetType); + + QualType VtableType = getSema().Context.getRecordType(VtableRecord); + if (VtableRecord->getDescribedClassTemplate()) + VtableType = getSema().CompleteRecordType( + VtableRecord, VtableVar->getTypeSourceInfo()); + VtableType = + getSema().Context.getElaboratedType(ETK_Struct, nullptr, VtableType); + QualType VtablePtr = getSema().Context.getPointerType(VtableType); + + DeclRefExpr *VtableRef = getSema().BuildDeclRefExpr( + VtableVar, VtableType, VK_LValue, VtableVar->getLocation()); + Expr *VtableAddr = UnaryOperator::Create( + getSema().Context, VtableRef, UO_AddrOf, VtablePtr, VK_PRValue, + OK_Ordinary, SourceLocation(), false, FPOptionsOverride()); + VtableAssign = getSema() + .BuildBinOp(getSema().getCurScope(), TokLoc, Opc, + FieldExpr, VtableAddr) + .get(); + } + } + return getSema().BuildBinOp(getSema().getCurScope(), TokLoc, BO_Comma, + DataAssign, VtableAssign); +} + +ExprResult BSCTraitDesugarer::DesugarTraitCompare(BinaryOperator *E) { + Expr *LHSExpr = E->getLHS(); + Expr *RHSExpr = E->getRHS(); + BinaryOperatorKind Opc = E->getOpcode(); + SourceLocation TokLoc = E->getOperatorLoc(); + bool LHSIsTrait = getSema().IsTraitExpr(LHSExpr); + bool RHSIsTrait = getSema().IsTraitExpr(RHSExpr); + if (LHSIsTrait && RHSIsTrait) { + // both trait types: compare all fields + if (LHSExpr->getType()->isPointerType() || + RHSExpr->getType()->isPointerType()) { + // pointer traits: direct comparison + return getSema().BuildBinOp(getSema().getCurScope(), TokLoc, Opc, LHSExpr, + RHSExpr); + } + // struct traits: field by field comparison + std::vector LHSFields; + RecordDecl *LHSRecord = + dyn_cast(LHSExpr->getType().getCanonicalType())->getDecl(); + for (RecordDecl::field_iterator I = LHSRecord->field_begin(), + E = LHSRecord->field_end(); + I != E; ++I) { + Expr *FieldExpr = getSema().BuildMemberExpr( + LHSExpr, false, SourceLocation(), NestedNameSpecifierLoc(), + SourceLocation(), *I, DeclAccessPair::make(*I, I->getAccess()), false, + DeclarationNameInfo(), I->getType(), VK_LValue, OK_Ordinary); + LHSFields.push_back(FieldExpr); + } + std::vector RHSFields; + RecordDecl *RHSRecord = + dyn_cast(RHSExpr->getType().getCanonicalType())->getDecl(); + for (RecordDecl::field_iterator J = RHSRecord->field_begin(), + F = RHSRecord->field_end(); + J != F; ++J) { + Expr *FieldExpr = getSema().BuildMemberExpr( + RHSExpr, false, SourceLocation(), NestedNameSpecifierLoc(), + SourceLocation(), *J, DeclAccessPair::make(*J, J->getAccess()), false, + DeclarationNameInfo(), J->getType(), VK_LValue, OK_Ordinary); + RHSFields.push_back(FieldExpr); + } + Expr *DataCmp = getSema() + .BuildBinOp(getSema().getCurScope(), TokLoc, Opc, + LHSFields[0], RHSFields[0]) + .get(); + Expr *VtableCmp = getSema() + .BuildBinOp(getSema().getCurScope(), TokLoc, Opc, + LHSFields[1], RHSFields[1]) + .get(); + if (Opc == BO_EQ) { + return getSema().BuildBinOp(getSema().getCurScope(), TokLoc, BO_LAnd, + DataCmp, VtableCmp); + } else if (Opc == BO_NE) { + return getSema().BuildBinOp(getSema().getCurScope(), TokLoc, BO_LOr, + DataCmp, VtableCmp); + } + } + // one trait, one normal type: compare data field only + Expr *TraitExpr = LHSIsTrait ? LHSExpr : RHSExpr; + Expr *NormalExpr = LHSIsTrait ? RHSExpr : LHSExpr; + RecordDecl *TraitRecord = + dyn_cast(TraitExpr->getType().getCanonicalType())->getDecl(); + Expr *DataField = nullptr; + for (RecordDecl::field_iterator I = TraitRecord->field_begin(), + E = TraitRecord->field_end(); + I != E; ++I) { + if (I->getNameAsString() == "data") { + DataField = getSema().BuildMemberExpr( + TraitExpr, false, SourceLocation(), NestedNameSpecifierLoc(), + SourceLocation(), *I, DeclAccessPair::make(*I, I->getAccess()), false, + DeclarationNameInfo(), I->getType(), VK_LValue, OK_Ordinary); + break; + } + } + if (LHSIsTrait) { + return getSema().BuildBinOp(getSema().getCurScope(), TokLoc, Opc, DataField, + NormalExpr); + } else { + return getSema().BuildBinOp(getSema().getCurScope(), TokLoc, Opc, + NormalExpr, DataField); + } +} + // 在Sema类中添加对外统一接口 void Sema::DesugarTraitInTranslationUnit(Decl *D) { #if ENABLE_BSC diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 1f4e8b76c0a8..e775214bc2b7 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -13174,9 +13174,32 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, diagnoseFunctionPointerToVoidComparison(*this, Loc, LHS, RHS, /*isError*/false); } else { - // Invalid - diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS, - /*isError*/ false); +#if ENABLE_BSC + // Allow comparison between implemented pointers to trait types + QualType TraitType = QualType(); + QualType TargetType = QualType(); + if (LHSType->hasTraitType()) { + TraitType = LHSType; + TargetType = RHSType; + } + if (RHSType->hasTraitType()) { + TraitType = RHSType; + TargetType = LHSType; + } + TraitDecl *TD = nullptr; + VarDecl *ImplVar = nullptr; + if (!TraitType.isNull()) + TD = TryDesugarTrait(TraitType); + if (TD) + ImplVar = TD->getTypeImpledVarDecl(TargetType->getPointeeType()); + if (!ImplVar) { +#endif + // Invalid + diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS, + /*isError*/ false); +#if ENABLE_BSC + } +#endif } if (LCanPointeeTy != RCanPointeeTy) { // Treat NULL constant as a special case in OpenCL. @@ -16089,6 +16112,26 @@ ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, DiagnoseBinOpPrecedence(*this, Opc, TokLoc, LHSExpr, RHSExpr); #if ENABLE_BSC + if (getLangOpts().BSC) { + if (LHSExpr->getType()->hasTraitType()) + LHSExpr = LHSExpr->IgnoreCasts(); + if (RHSExpr->getType()->hasTraitType()) + RHSExpr = RHSExpr->IgnoreCasts(); + bool LHSIsTrait = IsTraitExpr(LHSExpr); + bool RHSIsTrait = IsTraitExpr(RHSExpr); + if (LHSIsTrait || RHSIsTrait) { + if (Opc == BO_Assign) { + if (!ActOnTraitReassignSema(Opc, LHSExpr, RHSExpr)) + return ExprError(); + } + if (Opc == BO_EQ || Opc == BO_NE) { + if (!ActOnTraitCompareSema(Opc, LHSExpr, RHSExpr)) + return ExprError(); + } + } + } + // BSC TRAIT: 原始的即时解糖代码 - 已注释以实施延迟解糖 + // Original eager trait desugaring code - commented out for delayed desugaring implementation // Handling reassignments of variable types with trait pointers: // if (getLangOpts().BSC) { // if (LHSExpr->getType()->hasTraitType()) -- Gitee From 573bc62e956d18d6a751de494ff5d87db8d90961 Mon Sep 17 00:00:00 2001 From: tanhongmin Date: Tue, 23 Sep 2025 02:36:24 +0000 Subject: [PATCH 4/7] add sema and desugar support for trait function call --- clang/include/clang/Sema/Sema.h | 2 +- clang/lib/Parse/ParseExpr.cpp | 66 +++++++++++----- clang/lib/Sema/BSC/SemaBSCTrait.cpp | 115 ++++++++++++++++++++++++++++ clang/lib/Sema/SemaExprMember.cpp | 50 ++++++++++++ 4 files changed, 214 insertions(+), 19 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6480fb1ea6f7..febd346bb99c 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5705,12 +5705,12 @@ public: bool ActOnTraitVariableSema(VarDecl *VD); // Sema阶段语义分析 bool ActOnTraitReassignSema(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr); // Trait赋值语义分析 bool ActOnTraitCompareSema(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr); // Trait比较语义分析 + bool ActOnTraitMemberAccessSema(Expr *BaseExpr, SourceLocation OpLoc, tok::TokenKind OpKind, const UnqualifiedId &Member); // Trait成员访问语义分析 Expr *ConvertParmTraitToStructTrait(Expr *Arg, QualType ProtoArgType, SourceLocation DSLoc); void ActOnDesugarTraitExprInStruct(InitListExpr *IList, Expr *UO, QualType ElemType, unsigned &Index, DesignatedInitExpr **DIE); - // 延迟解糖统一入口 void DesugarTraitInTranslationUnit(Decl *D); #endif diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index abd3ccd2bbf8..3a40ed2af537 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -2320,26 +2320,46 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { // postfix-expression: p-e '->' template[opt] id-expression // postfix-expression: p-e '.' template[opt] id-expression #if ENABLE_BSC + bool IsTraitMemberAccess = false; if (getLangOpts().BSC && LHS.get()) { - // FIXME: Should we desugar right here after we see "->"? - // Maybe we should consider doing "Desugar" at a more coarse level. - // FIXME: '(int)a->b' baseExpr should be 'a' rather than '(int)a' QualType T = LHS.get()->getType(); if (!T.isNull() && Actions.TryDesugarTrait(T)) { - // @code - // void f(trait T* t) { - // t->foo(); // see '->', desugar to "t.vtable->foo()" immediately; - // } - // @endcode - if (T->isPointerType()) { - Diag(LHS.get()->getExprLoc(), diag::err_multi_trait_call_func) << Actions.CompleteTraitType(T); + int PointerLevels = 0; + QualType CheckType = T; + while (CheckType->isPointerType()) { + CheckType = CheckType->getPointeeType(); + ++PointerLevels; + } + if (PointerLevels > 1) { + Diag(LHS.get()->getExprLoc(), diag::err_multi_trait_call_func) + << Actions.CompleteTraitType(T); return ExprError(); } - TraitParam = - Actions.AddAfterStructTrait(LHS, Loc, "data").get(); // "t.data" - LHS = Actions.AddAfterStructTrait(LHS, Loc, "vtable"); // "t.vtable" + IsTraitMemberAccess = true; } } + // BSC TRAIT: 原始的立即解糖代码 - 已注释以实施延迟解糖 + // Original eager desugaring code - commented out for delayed desugaring implementation + // if (getLangOpts().BSC && LHS.get()) { + // // FIXME: Should we desugar right here after we see "->"? + // // Maybe we should consider doing "Desugar" at a more coarse level. + // // FIXME: '(int)a->b' baseExpr should be 'a' rather than '(int)a' + // QualType T = LHS.get()->getType(); + // if (!T.isNull() && Actions.TryDesugarTrait(T)) { + // // @code + // // void f(trait T* t) { + // // t->foo(); // see '->', desugar to "t.vtable->foo()" immediately; + // // } + // // @endcode + // if (T->isPointerType()) { + // Diag(LHS.get()->getExprLoc(), diag::err_multi_trait_call_func) << Actions.CompleteTraitType(T); + // return ExprError(); + // } + // TraitParam = + // Actions.AddAfterStructTrait(LHS, Loc, "data").get(); // "t.data" + // LHS = Actions.AddAfterStructTrait(LHS, Loc, "vtable"); // "t.vtable" + // } + // } #endif tok::TokenKind OpKind = Tok.getKind(); SourceLocation OpLoc = ConsumeToken(); // Eat the "." or "->" token. @@ -2457,11 +2477,21 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { LHS = ExprError(); } - if (!LHS.isInvalid()) - LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc, - OpKind, SS, TemplateKWLoc, Name, - CurParsedObjCImpl ? CurParsedObjCImpl->Dcl - : nullptr); + if (!LHS.isInvalid()) { +#if ENABLE_BSC + if (IsTraitMemberAccess && getLangOpts().BSC) { + if (!Actions.ActOnTraitMemberAccessSema(LHS.get(), OpLoc, OpKind, + Name)) { + LHS = ExprError(); + } + } +#endif + if (!LHS.isInvalid()) { + LHS = Actions.ActOnMemberAccessExpr( + getCurScope(), LHS.get(), OpLoc, OpKind, SS, TemplateKWLoc, Name, + CurParsedObjCImpl ? CurParsedObjCImpl->Dcl : nullptr); + } + } if (!LHS.isInvalid()) { if (Tok.is(tok::less)) checkPotentialAngleBracket(LHS); diff --git a/clang/lib/Sema/BSC/SemaBSCTrait.cpp b/clang/lib/Sema/BSC/SemaBSCTrait.cpp index a403b0c3d886..366a82fe391f 100644 --- a/clang/lib/Sema/BSC/SemaBSCTrait.cpp +++ b/clang/lib/Sema/BSC/SemaBSCTrait.cpp @@ -823,6 +823,53 @@ bool Sema::ActOnTraitCompareSema(BinaryOperatorKind Opc, Expr *LHSExpr, return true; } +bool Sema::ActOnTraitMemberAccessSema(Expr *BaseExpr, SourceLocation OpLoc, + tok::TokenKind OpKind, + const UnqualifiedId &Member) { + if (!BaseExpr) + return false; + QualType BaseType = BaseExpr->getType(); + if (!BaseType->hasTraitType()) + return false; + TraitDecl *TD = TryDesugarTrait(BaseType); + if (!TD) { + Diag(OpLoc, diag::err_type_has_not_impl_trait) + << BaseType << BaseExpr->getType(); + return false; + } + // Check trait function member is existed + if (Member.getKind() != UnqualifiedIdKind::IK_Identifier) { + Diag(OpLoc, diag::err_declarator_need_ident); + return false; + } + IdentifierInfo *MemberName = Member.Identifier; + if (!MemberName) { + Diag(OpLoc, diag::err_declarator_need_ident); + return false; + } + RecordDecl *VT = TD->getVtable(); + if (!VT) { + Diag(OpLoc, diag::err_type_has_not_impl_trait) + << BaseType << BaseExpr->getType(); + return false; + } + bool FoundMember = false; + for (RecordDecl::field_iterator FieldIt = VT->field_begin(); + FieldIt != VT->field_end(); ++FieldIt) { + if (FieldIt->getIdentifier() == MemberName) { + FoundMember = true; + break; + } + } + if (!FoundMember) { + Diag(OpLoc, diag::err_no_member) + << MemberName << CompleteTraitType(BaseType); + return false; + } + + return true; +} + // 原有的ActOnDesugarTraitInstance保留,但标记为将要废弃 VarDecl *Sema::ActOnDesugarTraitInstance(Decl *D) { VarDecl *VD = dyn_cast(D); @@ -1523,6 +1570,23 @@ public: return BaseTransform::TransformBinaryOperator(E); } + ExprResult TransformCallExpr(CallExpr *E) { + Expr *Callee = E->getCallee(); + if (!Callee) + return BaseTransform::TransformCallExpr(E); + MemberExpr *ME = dyn_cast(Callee->IgnoreImpCasts()); + if (!ME) + return BaseTransform::TransformCallExpr(E); + Expr *BaseExpr = ME->getBase(); + if (!BaseExpr) + return BaseTransform::TransformCallExpr(E); + QualType BaseType = BaseExpr->getType(); + if (!BaseType->hasTraitType()) + return BaseTransform::TransformCallExpr(E); + + return DesugarTraitFunctionCall(E, ME); + } + private: Decl *TransformTraitVariableDeclaration(VarDecl *D); ExprResult TransformTraitBinaryOperations(BinaryOperator *E); @@ -1530,6 +1594,7 @@ private: VarDecl *DesugarTraitVariable(VarDecl *VD); ExprResult DesugarTraitReassign(BinaryOperator *E); ExprResult DesugarTraitCompare(BinaryOperator *E); + ExprResult DesugarTraitFunctionCall(CallExpr *E, MemberExpr *ME); }; void BSCTraitDesugarer::desugarTopLevelDecl(Decl *D) { @@ -1876,6 +1941,56 @@ ExprResult BSCTraitDesugarer::DesugarTraitCompare(BinaryOperator *E) { } } +ExprResult BSCTraitDesugarer::DesugarTraitFunctionCall(CallExpr *E, + MemberExpr *ME) { + ExprResult BaseResult = TransformExpr(ME->getBase()); + if (BaseResult.isInvalid()) + return ExprError(); + SourceLocation OpLoc = ME->getOperatorLoc(); + SourceLocation MemberLoc = ME->getMemberLoc(); + // Get base.vtable + ExprResult VtableResult = + getSema().AddAfterStructTrait(BaseResult, OpLoc, "vtable"); + if (VtableResult.isInvalid()) + return ExprError(); + // Create vtable->funcname + CXXScopeSpec SS; + SourceLocation TemplateKWLoc; + UnqualifiedId FuncName; + IdentifierInfo *FuncId = ME->getMemberDecl()->getIdentifier(); + if (!FuncId) + return ExprError(); + FuncName.setIdentifier(FuncId, MemberLoc); + ExprResult FunctionResult = getSema().ActOnMemberAccessExpr( + getSema().getCurScope(), VtableResult.get(), OpLoc, tok::arrow, SS, + TemplateKWLoc, FuncName, nullptr); + if (FunctionResult.isInvalid()) + return ExprError(); + // Get base.vdata + ExprResult DataResult = + getSema().AddAfterStructTrait(BaseResult, OpLoc, "data"); + if (DataResult.isInvalid()) + return ExprError(); + // Add .data as the first argument + SmallVector CallArgs; + CallArgs.push_back(DataResult.get()); + for (unsigned i = 0; i < E->getNumArgs(); ++i) { + ExprResult ArgResult = TransformExpr(E->getArg(i)); + if (ArgResult.isInvalid()) + return ExprError(); + CallArgs.push_back(ArgResult.get()); + } + // Create new CallExpr + MultiExprArg Args(CallArgs.data(), CallArgs.size()); + ExprResult NewCall = + getSema().ActOnCallExpr(getSema().getCurScope(), FunctionResult.get(), + E->getBeginLoc(), Args, E->getRParenLoc()); + if (NewCall.isInvalid()) + return ExprError(); + + return NewCall; +} + // 在Sema类中添加对外统一接口 void Sema::DesugarTraitInTranslationUnit(Decl *D) { #if ENABLE_BSC diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 9bf51f3447dc..88b0ccd48b7d 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -2027,6 +2027,56 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, #if ENABLE_BSC DiagnoseInvalidMemberAccessExprInSafeZone(OpLoc, OpKind, Base->getType()); + + // Enable trait * variant use "->"" to call trait methods + if (getLangOpts().BSC && Base->getType()->hasTraitType()) { + IdentifierInfo *MemberII = Name.getAsIdentifierInfo(); + if (!MemberII) { + return ExprError(Diag(OpLoc, diag::err_no_member) + << Name << Base->getType()); + } + QualType MemberType = Context.DependentTy; + if (TraitDecl *TD = TryDesugarTrait(Base->getType())) { + if (RecordDecl *VT = TD->getVtable()) { + for (RecordDecl::field_iterator FieldIt = VT->field_begin(); + FieldIt != VT->field_end(); ++FieldIt) { + if (FieldIt->getIdentifier() == MemberII) { + QualType VtableFuncType = FieldIt->getType()->getPointeeType(); + // Remove the first parameter(This *) of the function type + if (const FunctionProtoType *FPT = + VtableFuncType->getAs()) { + if (FPT->getNumParams() > 0) { + SmallVector NewParams; + for (unsigned i = 1; i < FPT->getNumParams(); ++i) { + NewParams.push_back(FPT->getParamType(i)); + } + + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); + MemberType = Context.getFunctionType(FPT->getReturnType(), + NewParams, EPI); + } else { + MemberType = VtableFuncType; + } + } else { + MemberType = VtableFuncType; + } + break; + } + } + } + } + // Create placeholder MemberExpr + FieldDecl *FakeField = + FieldDecl::Create(Context, nullptr, OpLoc, OpLoc, MemberII, MemberType, + Context.getTrivialTypeSourceInfo(MemberType, OpLoc), + nullptr, false, ICIS_NoInit); + MemberExpr *ME = MemberExpr::Create( + Context, Base, IsArrow, OpLoc, NestedNameSpecifierLoc(), TemplateKWLoc, + FakeField, DeclAccessPair::make(FakeField, AS_public), NameInfo, + TemplateArgs, MemberType, VK_LValue, OK_Ordinary, NOUR_None); + + return ME; + } #endif if (getLangOpts().HLSL && IsArrow) return ExprError(Diag(OpLoc, diag::err_hlsl_operator_unsupported) << 2); -- Gitee From 435318b0e5ce78fc806dade6a4ef50036abc4e4a Mon Sep 17 00:00:00 2001 From: tanhongmin Date: Sun, 28 Sep 2025 08:46:05 +0000 Subject: [PATCH 5/7] desugar function return type and parameters desugar and add function decl mapping between toplevels --- clang/include/clang/Sema/Sema.h | 26 ++- clang/lib/Parse/ParseDecl.cpp | 8 +- clang/lib/Sema/BSC/SemaBSCTrait.cpp | 282 ++++++++++++++++++++-------- clang/lib/Sema/SemaDecl.cpp | 15 +- clang/lib/Sema/SemaExpr.cpp | 21 +++ clang/lib/Sema/SemaStmt.cpp | 3 + clang/lib/Sema/SemaType.cpp | 3 + 7 files changed, 264 insertions(+), 94 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index febd346bb99c..6fcace7c9863 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5702,17 +5702,31 @@ public: ExprResult AddAfterStructTrait(ExprResult ULE, SourceLocation DSLoc, std::string ID); VarDecl *ActOnDesugarTraitInstance(Decl *VarDec); - bool ActOnTraitVariableSema(VarDecl *VD); // Sema阶段语义分析 - bool ActOnTraitReassignSema(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr); // Trait赋值语义分析 - bool ActOnTraitCompareSema(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr); // Trait比较语义分析 - bool ActOnTraitMemberAccessSema(Expr *BaseExpr, SourceLocation OpLoc, tok::TokenKind OpKind, const UnqualifiedId &Member); // Trait成员访问语义分析 + bool ActOnTraitVariableSema(VarDecl *VD); + bool ActOnTraitReassignSema(BinaryOperatorKind Opc, Expr *LHSExpr, + Expr *RHSExpr); + bool ActOnTraitCompareSema(BinaryOperatorKind Opc, Expr *LHSExpr, + Expr *RHSExpr); + bool ActOnTraitMemberAccessSema(Expr *BaseExpr, SourceLocation OpLoc, + tok::TokenKind OpKind, + const UnqualifiedId &Member); Expr *ConvertParmTraitToStructTrait(Expr *Arg, QualType ProtoArgType, SourceLocation DSLoc); void ActOnDesugarTraitExprInStruct(InitListExpr *IList, Expr *UO, QualType ElemType, unsigned &Index, DesignatedInitExpr **DIE); - // 延迟解糖统一入口 - void DesugarTraitInTranslationUnit(Decl *D); + Decl *DesugarTraitInTranslationUnit(Decl *D); + /// Mark Trait processing stage + enum class TraitProcessingStage { SemanticAnalysis, TreeTransform }; + /// Default at SemanticAnalysis stage + TraitProcessingStage CurrentTraitStage = + TraitProcessingStage::SemanticAnalysis; + // Trait FunctionDecl mapping tables + llvm::DenseMap TraitToStructFunctionDeclMap; + llvm::DenseMap StructToTraitFunctionDeclMap; + // Operation to transform Trait FunctionDecl + FunctionDecl *getTraitFunctionDecl(FunctionDecl *TransformedFD); + FunctionDecl *getStructFunction(FunctionDecl *OriginalFD); #endif ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index f4738a75adfc..b9f3c87adc89 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2310,10 +2310,12 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, } #if ENABLE_BSC - // 对声明组进行trait延迟解糖 if (getLangOpts().BSC && Context == DeclaratorContext::File) { - for (Decl *D : DeclsInGroup) { - Actions.DesugarTraitInTranslationUnit(D); + for (size_t i = 0; i < DeclsInGroup.size(); ++i) { + Decl *TransformedD = Actions.DesugarTraitInTranslationUnit(DeclsInGroup[i]); + if (TransformedD && TransformedD != DeclsInGroup[i]) { + DeclsInGroup[i] = TransformedD; + } } } #endif diff --git a/clang/lib/Sema/BSC/SemaBSCTrait.cpp b/clang/lib/Sema/BSC/SemaBSCTrait.cpp index 366a82fe391f..23baf50b1ddd 100644 --- a/clang/lib/Sema/BSC/SemaBSCTrait.cpp +++ b/clang/lib/Sema/BSC/SemaBSCTrait.cpp @@ -1536,20 +1536,34 @@ class BSCTraitDesugarer : public TreeTransform { public: BSCTraitDesugarer(Sema &SemaRef) : TreeTransform(SemaRef) {} - void desugarTopLevelDecl(Decl *D); + Decl *DesugarTopLevelDecl(Decl *D); Decl *TransformDecl(SourceLocation Loc, Decl *D) { if (!D) return D; + // Return transformed local declarations llvm::DenseMap::iterator Known = TransformedLocalDecls.find(D); if (Known != TransformedLocalDecls.end()) return Known->second; + // Return transformed function declarations + if (FunctionDecl *FD = dyn_cast(D)) { + if (FunctionDecl *TransformedFD = getSema().getStructFunction(FD)) + return TransformedFD; + return FD; + } + // Desugar trait types variable declarations VarDecl *VD = dyn_cast(D); if (!VD) return D; - if (getSema().TryDesugarTrait(VD->getType())) - return TransformTraitVariableDeclaration(VD); + if (getSema().TryDesugarTrait(VD->getType())) { + VarDecl *VD = dyn_cast(D); + Decl *NewDecl = DesugarTraitVariable(VD); + if (NewDecl && NewDecl != D) { + transformedLocalDecl(D, {NewDecl}); + return NewDecl; + } + } return D; } @@ -1564,9 +1578,15 @@ public: E->setRHS(RHS); bool LHSIsTrait = getSema().IsTraitExpr(E->getLHS()); bool RHSIsTrait = getSema().IsTraitExpr(E->getRHS()); - - if (LHSIsTrait || RHSIsTrait) - return TransformTraitBinaryOperations(E); + if (LHSIsTrait || RHSIsTrait) { + BinaryOperatorKind Opc = E->getOpcode(); + if (Opc == BO_Assign) { + return DesugarTraitReassign(E); + } else if (Opc == BO_EQ || Opc == BO_NE) { + return DesugarTraitCompare(E); + } + return ExprError(); + } return BaseTransform::TransformBinaryOperator(E); } @@ -1574,6 +1594,36 @@ public: Expr *Callee = E->getCallee(); if (!Callee) return BaseTransform::TransformCallExpr(E); + // Transform trait types function calls (trait type return or parameters) + if (DeclRefExpr *DRE = dyn_cast(Callee->IgnoreImpCasts())) { + if (FunctionDecl *FD = dyn_cast(DRE->getDecl())) { + if (FunctionDecl *TransformedFD = getSema().getStructFunction(FD)) { + // Transform DeclRefExpr + DeclRefExpr *NewDRE = DeclRefExpr::Create( + getSema().getASTContext(), DRE->getQualifierLoc(), + DRE->getTemplateKeywordLoc(), TransformedFD, + false, // RefersToEnclosingVariableOrCapture + DRE->getNameInfo(), TransformedFD->getType(), + DRE->getValueKind()); + // Transform parameters + SmallVector TransformedArgs; + bool ArgChanged = false; + for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) { + ExprResult Arg = getDerived().TransformExpr(E->getArg(i)); + if (Arg.isInvalid()) + return ExprError(); + ArgChanged = ArgChanged || Arg.get() != E->getArg(i); + TransformedArgs.push_back(Arg.get()); + } + // Transform CallExpr + ExprResult Result = getSema().BuildCallExpr( + /*Scope=*/nullptr, NewDRE, E->getBeginLoc(), TransformedArgs, + E->getEndLoc()); + return Result; + } + } + } + // Transform trait variables function calls ( "->func()" ) MemberExpr *ME = dyn_cast(Callee->IgnoreImpCasts()); if (!ME) return BaseTransform::TransformCallExpr(E); @@ -1588,76 +1638,46 @@ public: } private: - Decl *TransformTraitVariableDeclaration(VarDecl *D); - ExprResult TransformTraitBinaryOperations(BinaryOperator *E); - VarDecl *DesugarTraitVariable(VarDecl *VD); ExprResult DesugarTraitReassign(BinaryOperator *E); ExprResult DesugarTraitCompare(BinaryOperator *E); ExprResult DesugarTraitFunctionCall(CallExpr *E, MemberExpr *ME); + FunctionDecl *DesugarFunctionDeclSignature(FunctionDecl *FD); }; -void BSCTraitDesugarer::desugarTopLevelDecl(Decl *D) { +Decl *BSCTraitDesugarer::DesugarTopLevelDecl(Decl *D) { if (!D) - return; - + return D; if (FunctionDecl *FD = dyn_cast(D)) { - llvm::errs() << "[BSCTraitDesugarer] Processing FunctionDecl: " - << (FD->getNameAsString().empty() ? "" - : FD->getNameAsString()) - << "\n"; + // Transform function body + Stmt *TransformedBody = nullptr; if (FD->hasBody()) { - llvm::errs() << "[BSCTraitDesugarer] Transforming function body...\n"; Stmt *Body = FD->getBody(); StmtResult NewBody = TransformStmt(Body); - if (NewBody.isUsable() && NewBody.get() != Body) { - llvm::errs() - << "[BSCTraitDesugarer] Function body transformed successfully\n"; - FD->setBody(NewBody.get()); - } else { - llvm::errs() << "[BSCTraitDesugarer] Function body unchanged\n"; - } + if (NewBody.isUsable()) + TransformedBody = NewBody.get(); + else + TransformedBody = Body; } + // Transform parameters and return type + FD = DesugarFunctionDeclSignature(FD); + // Set transformed body + if (TransformedBody) + FD->setBody(TransformedBody); + return FD; } else if (VarDecl *VD = dyn_cast(D)) { - llvm::errs() << "[BSCTraitDesugarer] Processing VarDecl: " - << (VD->getNameAsString().empty() ? "" - : VD->getNameAsString()) - << " of type: " << VD->getType().getAsString() << "\n"; Decl *NewDecl = getSema().ActOnDesugarTraitInstance(VD); - if (NewDecl && NewDecl != VD) { - llvm::errs() << "[BSCTraitDesugarer] Variable transformed to new type\n"; - } else { - llvm::errs() << "[BSCTraitDesugarer] Variable unchanged\n"; - } - } -} - -Decl *BSCTraitDesugarer::TransformTraitVariableDeclaration(VarDecl *D) { - VarDecl *VD = dyn_cast(D); - Decl *NewDecl = DesugarTraitVariable(VD); - if (NewDecl && NewDecl != D) { - transformedLocalDecl(D, {NewDecl}); - return NewDecl; + if (NewDecl && NewDecl != VD) + return NewDecl; + else + return VD; } return D; } -ExprResult -BSCTraitDesugarer::TransformTraitBinaryOperations(BinaryOperator *E) { - BinaryOperatorKind Opc = E->getOpcode(); - if (Opc == BO_Assign) { - return DesugarTraitReassign(E); - } else if (Opc == BO_EQ || Opc == BO_NE) { - return DesugarTraitCompare(E); - } - - return ExprError(); -} - VarDecl *BSCTraitDesugarer::DesugarTraitVariable(VarDecl *VD) { if (!VD) return nullptr; - QualType TraitType = VD->getType(); if (!TraitType->isPointerType()) return nullptr; @@ -1666,25 +1686,45 @@ VarDecl *BSCTraitDesugarer::DesugarTraitVariable(VarDecl *VD) { return nullptr; QualType StructType = getSema().DesugarTraitToStructTrait(TD, TraitType, VD->getBeginLoc()); - // create new variable with struct type - VarDecl *NewVD = VarDecl::Create( - getSema().Context, getSema().CurContext, VD->getBeginLoc(), - VD->getLocation(), VD->getIdentifier(), StructType, - getSema().Context.getTrivialTypeSourceInfo(StructType), - StorageClass::SC_None); + VarDecl *NewVD = nullptr; + // Transform ParmVarDecl + if (ParmVarDecl *PD = dyn_cast(VD)) { + ParmVarDecl *NewPD = ParmVarDecl::Create( + getSema().Context, PD->getDeclContext(), PD->getInnerLocStart(), + PD->getLocation(), PD->getIdentifier(), StructType, + getSema().Context.getTrivialTypeSourceInfo(StructType), + PD->getStorageClass(), PD->getDefaultArg()); + NewPD->setScopeInfo(PD->getFunctionScopeDepth(), + PD->getFunctionScopeIndex()); + NewPD->setObjCMethodScopeInfo(PD->isObjCMethodParameter()); + NewPD->setKNRPromoted(PD->isKNRPromoted()); + NewVD = NewPD; + } else { + // Transform VarDecl + NewVD = VarDecl::Create( + getSema().Context, getSema().CurContext, VD->getBeginLoc(), + VD->getLocation(), VD->getIdentifier(), StructType, + getSema().Context.getTrivialTypeSourceInfo(StructType), + StorageClass::SC_None); + } + // ParmVarDecl don't need to handle initialization + if (isa(VD)) + return NewVD; + // Transform initialization expression Expr *Init = VD->getInit(); + if (!Init) + return NewVD; Init = TransformExpr(Init).get(); if (!Init) return NewVD; if (Init->containsErrors()) return NewVD; - // create desugared init expression Expr *UO = Init; if (CastExpr *CastInit = dyn_cast(Init)) { UO = CastInit->getSubExpr(); } QualType InitType = UO->getType(); - // check if init with same trait type + // Check if init with same trait type QualType InnerInitType = InitType; while (InnerInitType->isPointerType()) InnerInitType = InnerInitType->getPointeeType(); @@ -1699,13 +1739,13 @@ VarDecl *BSCTraitDesugarer::DesugarTraitVariable(VarDecl *VD) { ExpectedTraitType = getSema().CompleteRecordType( TD->getTrait(), NewVD->getTypeSourceInfo()); } - // trait struct to trait struct assignment + // Create trait struct to trait struct assignment if (!ExpectedTraitType.isNull() && getSema().Context.hasSameType(InnerInitType, ExpectedTraitType)) { getSema().AddInitializerToDecl(NewVD, UO, false); return NewVD; } - // transform pointer type to struct .data type and find .vtable + // Transform pointer type to struct .data type and find .vtable const PointerType *PT = dyn_cast_or_null(InitType.getTypePtr()); if (!PT) return NewVD; @@ -1715,7 +1755,7 @@ VarDecl *BSCTraitDesugarer::DesugarTraitVariable(VarDecl *VD) { VarDecl *VtableVD = TD->getTypeImpledVarDecl(PointeeType); if (!VtableVD && !IsNullPointer) return NewVD; - // build initializer list + // Build initializer list std::vector InitList; if (IsNullPointer) { if (StructType->isPointerType()) { @@ -1732,9 +1772,9 @@ VarDecl *BSCTraitDesugarer::DesugarTraitVariable(VarDecl *VD) { getSema().Context.getElaboratedType(ETK_Struct, nullptr, VtableType); } QualType VtablePtr = getSema().Context.getPointerType(VtableType); - ImplicitCastExpr *VtableCast = ImplicitCastExpr::Create( - getSema().Context, VtablePtr, CK_BitCast, UO, nullptr, VK_PRValue, - FPOptionsOverride()); + ImplicitCastExpr *VtableCast = + ImplicitCastExpr::Create(getSema().Context, VtablePtr, CK_BitCast, UO, + nullptr, VK_PRValue, FPOptionsOverride()); InitList = {UO, VtableCast}; } else { // normal case: {data_cast, &vtable} @@ -1744,14 +1784,14 @@ VarDecl *BSCTraitDesugarer::DesugarTraitVariable(VarDecl *VD) { VoidPtr.addOwned(); if (VD->getType().isBorrowQualified()) VoidPtr.addBorrow(); - ImplicitCastExpr *DataCast = ImplicitCastExpr::Create( - getSema().Context, VoidPtr, CK_BitCast, UO, nullptr, VK_PRValue, - FPOptionsOverride()); + ImplicitCastExpr *DataCast = + ImplicitCastExpr::Create(getSema().Context, VoidPtr, CK_BitCast, UO, + nullptr, VK_PRValue, FPOptionsOverride()); QualType VtableType = VtableVD->getType(); QualType VtablePtr = getSema().Context.getPointerType(VtableType); DeclRefExpr *VtableRef = DeclRefExpr::Create( - getSema().Context, NestedNameSpecifierLoc(), SourceLocation(), - VtableVD, false, SourceLocation(), VtableType, VK_LValue); + getSema().Context, NestedNameSpecifierLoc(), SourceLocation(), VtableVD, + false, SourceLocation(), VtableType, VK_LValue); UnaryOperator *VtableAddr = UnaryOperator::Create( getSema().Context, VtableRef, UO_AddrOf, VtablePtr, VK_PRValue, OK_Ordinary, SourceLocation(), false, FPOptionsOverride()); @@ -1769,7 +1809,7 @@ ExprResult BSCTraitDesugarer::DesugarTraitReassign(BinaryOperator *E) { Expr *RHSExpr = E->getRHS(); BinaryOperatorKind Opc = E->getOpcode(); SourceLocation TokLoc = E->getOperatorLoc(); - // check null assignment + // Check null assignment if (RHSExpr->isNullPointerConstant(getSema().Context, Expr::NPC_ValueDependentIsNull)) { // null assignment: assign all fields to NULL @@ -1991,14 +2031,94 @@ ExprResult BSCTraitDesugarer::DesugarTraitFunctionCall(CallExpr *E, return NewCall; } -// 在Sema类中添加对外统一接口 -void Sema::DesugarTraitInTranslationUnit(Decl *D) { -#if ENABLE_BSC +// API for sema desugar toplevel +Decl *Sema::DesugarTraitInTranslationUnit(Decl *D) { if (!D || !getLangOpts().BSC) - return; + return D; + // Mark desugaring stage + TraitProcessingStage OldStage = CurrentTraitStage; + CurrentTraitStage = TraitProcessingStage::TreeTransform; BSCTraitDesugarer Desugarer(*this); - Desugarer.desugarTopLevelDecl(D); -#endif + Decl *Result = Desugarer.DesugarTopLevelDecl(D); + + // Restore previous stage + CurrentTraitStage = OldStage; + + return Result; } + +FunctionDecl * +BSCTraitDesugarer::DesugarFunctionDeclSignature(FunctionDecl *FD) { + if (!FD) + return FD; + bool NeedsDesugar = false; + // Check parameters + for (unsigned i = 0; i < FD->getNumParams(); ++i) { + ParmVarDecl *Param = FD->getParamDecl(i); + if (getSema().TryDesugarTrait(Param->getType())) { + NeedsDesugar = true; + break; + } + } + // Check return type + if (!NeedsDesugar) { + if (getSema().TryDesugarTrait(FD->getReturnType())) + NeedsDesugar = true; + } + if (!NeedsDesugar) { + return FD; + } + // Create new FunctionDecl with desugared signature + SmallVector NewParams; + SmallVector NewParamTypes; + for (unsigned i = 0; i < FD->getNumParams(); ++i) { + ParmVarDecl *Param = FD->getParamDecl(i); + // Transform parameters + Decl *TransformedParam = TransformDecl(SourceLocation(), Param); + ParmVarDecl *NewParam = cast(TransformedParam); + NewParams.push_back(NewParam); + NewParamTypes.push_back(NewParam->getType()); + } + // Transform return type + QualType NewReturnType = FD->getReturnType(); + if (TraitDecl *TD = getSema().TryDesugarTrait(NewReturnType)) { + QualType StructType = getSema().DesugarTraitToStructTrait(TD, NewReturnType, + SourceLocation()); + NewReturnType = StructType; + } + const FunctionProtoType *OrigFPT = FD->getType()->getAs(); + FunctionProtoType::ExtProtoInfo EPI = OrigFPT->getExtProtoInfo(); + QualType NewFuncType = + getSema().Context.getFunctionType(NewReturnType, NewParamTypes, EPI); + FunctionDecl *NewFD = FunctionDecl::Create( + getSema().Context, FD->getDeclContext(), FD->getInnerLocStart(), + FD->getNameInfo(), NewFuncType, FD->getTypeSourceInfo(), + FD->getStorageClass(), FD->UsesFPIntrin(), FD->isInlineSpecified(), + FD->hasWrittenPrototype(), FD->getConstexprKind(), + FD->getTrailingRequiresClause(), false // isAsyncSpecified + ); + NewFD->setParams(NewParams); + // Update mapping tables + getSema().TraitToStructFunctionDeclMap[FD] = NewFD; + getSema().StructToTraitFunctionDeclMap[NewFD] = FD; + // Replace FD with NewFD in AST + DeclContext *DC = FD->getDeclContext(); + DC->removeDecl(FD); + DC->addDecl(NewFD); + getSema().IdResolver.RemoveDecl(FD); + getSema().IdResolver.AddDecl(NewFD); + return NewFD; +} + +FunctionDecl *Sema::getTraitFunctionDecl(FunctionDecl *TransformedFD) { + auto It = StructToTraitFunctionDeclMap.find(TransformedFD); + return It != StructToTraitFunctionDeclMap.end() ? It->second : nullptr; +} + +FunctionDecl *Sema::getStructFunction(FunctionDecl *OriginalFD) { + auto It = TraitToStructFunctionDeclMap.find(OriginalFD); + return It != TraitToStructFunctionDeclMap.end() ? It->second : nullptr; +} + #endif // ENABLE_BSC \ No newline at end of file diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 2d08d7b3f1fe..f41e51ee0fb7 100755 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -14841,6 +14841,8 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D } #if ENABLE_BSC + /* + // 注释掉参数的即时trait解糖,改为延迟解糖 if (getLangOpts().BSC) if (TraitDecl *TD = TryDesugarTrait(parmDeclType)) { if (!TD->getTrait()) { @@ -14848,6 +14850,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D } parmDeclType = DesugarTraitToStructTrait(TD, parmDeclType, D.getBeginLoc()); } + */ #endif // Temporarily put parameter variables in the translation unit, not @@ -16065,10 +16068,14 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, } // Desugar BSC Function. DesugarDestructorCall(FD); - - // 对函数体进行trait延迟解糖 - DesugarTraitInTranslationUnit(FD); - + + Decl *TransformedFD = DesugarTraitInTranslationUnit(FD); + if (TransformedFD && TransformedFD != FD) { + // Function was transformed, update reference + dcl = TransformedFD; + FD = cast(TransformedFD); + } + BSCDataflowAnalysisFlag = false; } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index e775214bc2b7..4035faf027c9 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6513,6 +6513,8 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, if (ArgIx < Args.size()) { Arg = Args[ArgIx++]; #if ENABLE_BSC + // Commented out immediate trait conversion - now handled by type compatibility checking + /* if (getLangOpts().BSC && TryDesugarTrait(ProtoArgType) && !TryDesugarTrait(Arg->IgnoreParenCasts()->getType())) { Expr *TraitDesugaredExpr = ConvertParmTraitToStructTrait( @@ -6522,6 +6524,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, else return true; } + */ CheckMoveVarMemoryLeak(Arg, Arg->getBeginLoc()); #endif if (RequireCompleteType(Arg->getBeginLoc(), ProtoArgType, @@ -7169,6 +7172,24 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, if (auto *DRE = dyn_cast(NakedFn)) { NDecl = DRE->getDecl(); +#if ENABLE_BSC + // At Sema stage, we need to convert desugared trait function decl + // back to original trait function decl for correct semantic analysis. + if (getLangOpts().BSC) { + if (FunctionDecl *FD = dyn_cast(NDecl)) { + if (CurrentTraitStage == TraitProcessingStage::SemanticAnalysis) { + if (FunctionDecl *OriginalFD = getTraitFunctionDecl(FD)) { + NDecl = OriginalFD; + Fn = DeclRefExpr::Create( + Context, OriginalFD->getQualifierLoc(), SourceLocation(), + OriginalFD, false, SourceLocation(), OriginalFD->getType(), + Fn->getValueKind(), OriginalFD, nullptr, DRE->isNonOdrUse()); + } + } + } + } +#endif + FunctionDecl *FDecl = dyn_cast(NDecl); if (FDecl && FDecl->getBuiltinID()) { // Rewrite the function decl for this builtin by replacing parameters diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 64a83ad41060..18eea6ac20b8 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3998,6 +3998,8 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, if (const FunctionDecl *FD = getCurFunctionDecl()) { FnRetType = FD->getReturnType(); #if ENABLE_BSC + // Commented out immediate trait conversion - now handled by type compatibility checking + /* if (getLangOpts().BSC && TryDesugarTrait(FnRetType) && !TryDesugarTrait(RetValExp->getType())) { Expr *TraitDesugaredExpr = ConvertParmTraitToStructTrait( RetValExp, FnRetType, RetValExp->getBeginLoc()); @@ -4006,6 +4008,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, else return StmtError(); } + */ #endif if (FD->hasAttrs()) Attrs = &FD->getAttrs(); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 39232992907b..1edf3a36642d 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -5169,6 +5169,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } case DeclaratorChunk::Function: { #if ENABLE_BSC + /* + // 注释掉返回值的即时trait解糖,改为延迟解糖 if (LangOpts.BSC) { if (TraitDecl *TD = S.TryDesugarTrait(T)) { if (!TD->getTrait()) { @@ -5181,6 +5183,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, D.DropTypeObject(chunkIndex + 1); } } + */ #endif // If the function declarator has a prototype (i.e. it is not () and // does not have a K&R-style identifier list), then the arguments are part -- Gitee From 126b92d1b3007783a807992b677dce6ce59b4bd0 Mon Sep 17 00:00:00 2001 From: tanhongmin Date: Tue, 30 Sep 2025 17:05:08 +0800 Subject: [PATCH 6/7] refactor mapping to support cross-toplevel usage of global trait variables --- clang/include/clang/Sema/Sema.h | 12 ++--- clang/lib/Sema/BSC/SemaBSCTrait.cpp | 77 ++++++++++++++++++----------- clang/lib/Sema/SemaExpr.cpp | 28 ++++++++--- 3 files changed, 77 insertions(+), 40 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6fcace7c9863..4791340ba57e 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5721,12 +5721,12 @@ public: /// Default at SemanticAnalysis stage TraitProcessingStage CurrentTraitStage = TraitProcessingStage::SemanticAnalysis; - // Trait FunctionDecl mapping tables - llvm::DenseMap TraitToStructFunctionDeclMap; - llvm::DenseMap StructToTraitFunctionDeclMap; - // Operation to transform Trait FunctionDecl - FunctionDecl *getTraitFunctionDecl(FunctionDecl *TransformedFD); - FunctionDecl *getStructFunction(FunctionDecl *OriginalFD); + // Trait mapping tables + llvm::DenseMap TraitDesugaredToUndesugaredDeclMap; + llvm::DenseMap TraitUndesugaredToDesugaredDeclMap; + // Get Desugared or Undesugared Trait Decl + Decl *getUndesugaredDecl(Decl *Desugared); + Decl *getDesugaredDecl(Decl *Undesugared); #endif ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, diff --git a/clang/lib/Sema/BSC/SemaBSCTrait.cpp b/clang/lib/Sema/BSC/SemaBSCTrait.cpp index 23baf50b1ddd..d5b7745cfcf4 100644 --- a/clang/lib/Sema/BSC/SemaBSCTrait.cpp +++ b/clang/lib/Sema/BSC/SemaBSCTrait.cpp @@ -1548,20 +1548,37 @@ public: return Known->second; // Return transformed function declarations if (FunctionDecl *FD = dyn_cast(D)) { - if (FunctionDecl *TransformedFD = getSema().getStructFunction(FD)) - return TransformedFD; + if (FunctionDecl *DesugaredFD = + dyn_cast_or_null(getSema().getDesugaredDecl(FD))) + return DesugaredFD; return FD; } - // Desugar trait types variable declarations - VarDecl *VD = dyn_cast(D); - if (!VD) - return D; - if (getSema().TryDesugarTrait(VD->getType())) { - VarDecl *VD = dyn_cast(D); - Decl *NewDecl = DesugarTraitVariable(VD); - if (NewDecl && NewDecl != D) { - transformedLocalDecl(D, {NewDecl}); - return NewDecl; + // Desugar trait types variable(global or local) declarations + if (VarDecl *VD = dyn_cast(D)) { + // Return transformed Decl + if (VarDecl *DesugaredVD = + dyn_cast_or_null(getSema().getDesugaredDecl(VD))) { + return DesugaredVD; + } + if (getSema().TryDesugarTrait(VD->getType())) { + VarDecl *NewVD = DesugarTraitVariable(VD); + if (NewVD && NewVD != D) { + if (IsGlobalDecl) { + // Desugar global + getSema().TraitUndesugaredToDesugaredDeclMap[VD] = NewVD; + getSema().TraitDesugaredToUndesugaredDeclMap[NewVD] = VD; + // Replace VD with NewVD int AST + DeclContext *DC = VD->getDeclContext(); + DC->removeDecl(VD); + DC->addDecl(NewVD); + getSema().IdResolver.RemoveDecl(VD); + getSema().IdResolver.AddDecl(NewVD); + } else { + // Desugar local + transformedLocalDecl(D, {NewVD}); + } + return NewVD; + } } } return D; @@ -1597,14 +1614,14 @@ public: // Transform trait types function calls (trait type return or parameters) if (DeclRefExpr *DRE = dyn_cast(Callee->IgnoreImpCasts())) { if (FunctionDecl *FD = dyn_cast(DRE->getDecl())) { - if (FunctionDecl *TransformedFD = getSema().getStructFunction(FD)) { + if (FunctionDecl *DesugaredFD = dyn_cast_or_null( + getSema().getDesugaredDecl(FD))) { // Transform DeclRefExpr DeclRefExpr *NewDRE = DeclRefExpr::Create( getSema().getASTContext(), DRE->getQualifierLoc(), - DRE->getTemplateKeywordLoc(), TransformedFD, + DRE->getTemplateKeywordLoc(), DesugaredFD, false, // RefersToEnclosingVariableOrCapture - DRE->getNameInfo(), TransformedFD->getType(), - DRE->getValueKind()); + DRE->getNameInfo(), DesugaredFD->getType(), DRE->getValueKind()); // Transform parameters SmallVector TransformedArgs; bool ArgChanged = false; @@ -1638,6 +1655,8 @@ public: } private: + bool IsGlobalDecl; + VarDecl *DesugarTraitVariable(VarDecl *VD); ExprResult DesugarTraitReassign(BinaryOperator *E); ExprResult DesugarTraitCompare(BinaryOperator *E); @@ -1649,6 +1668,7 @@ Decl *BSCTraitDesugarer::DesugarTopLevelDecl(Decl *D) { if (!D) return D; if (FunctionDecl *FD = dyn_cast(D)) { + IsGlobalDecl = false; // Transform function body Stmt *TransformedBody = nullptr; if (FD->hasBody()) { @@ -1665,12 +1685,13 @@ Decl *BSCTraitDesugarer::DesugarTopLevelDecl(Decl *D) { if (TransformedBody) FD->setBody(TransformedBody); return FD; - } else if (VarDecl *VD = dyn_cast(D)) { - Decl *NewDecl = getSema().ActOnDesugarTraitInstance(VD); - if (NewDecl && NewDecl != VD) + } else if (isa(D)) { + IsGlobalDecl = true; + Decl *NewDecl = TransformDecl(D->getBeginLoc(), D); + if (NewDecl && NewDecl != D) return NewDecl; else - return VD; + return D; } return D; } @@ -2100,8 +2121,8 @@ BSCTraitDesugarer::DesugarFunctionDeclSignature(FunctionDecl *FD) { ); NewFD->setParams(NewParams); // Update mapping tables - getSema().TraitToStructFunctionDeclMap[FD] = NewFD; - getSema().StructToTraitFunctionDeclMap[NewFD] = FD; + getSema().TraitUndesugaredToDesugaredDeclMap[FD] = NewFD; + getSema().TraitDesugaredToUndesugaredDeclMap[NewFD] = FD; // Replace FD with NewFD in AST DeclContext *DC = FD->getDeclContext(); DC->removeDecl(FD); @@ -2111,14 +2132,14 @@ BSCTraitDesugarer::DesugarFunctionDeclSignature(FunctionDecl *FD) { return NewFD; } -FunctionDecl *Sema::getTraitFunctionDecl(FunctionDecl *TransformedFD) { - auto It = StructToTraitFunctionDeclMap.find(TransformedFD); - return It != StructToTraitFunctionDeclMap.end() ? It->second : nullptr; +Decl *Sema::getUndesugaredDecl(Decl *Desugared) { + auto It = TraitDesugaredToUndesugaredDeclMap.find(Desugared); + return It != TraitDesugaredToUndesugaredDeclMap.end() ? It->second : nullptr; } -FunctionDecl *Sema::getStructFunction(FunctionDecl *OriginalFD) { - auto It = TraitToStructFunctionDeclMap.find(OriginalFD); - return It != TraitToStructFunctionDeclMap.end() ? It->second : nullptr; +Decl *Sema::getDesugaredDecl(Decl *Undesugared) { + auto It = TraitUndesugaredToDesugaredDeclMap.find(Undesugared); + return It != TraitUndesugaredToDesugaredDeclMap.end() ? It->second : nullptr; } #endif // ENABLE_BSC \ No newline at end of file diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 4035faf027c9..e623e914e4c3 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2107,6 +2107,20 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, NeedToCaptureVariable(cast(D), NameInfo.getLoc()); #if ENABLE_BSC + // For global trait variables: use undesugared Decl and type in Sema stage + // This allows Sema type checking to pass, and TreeTransform can later + // transform the undesugared Decl to desugared Decl + if (VarDecl *VD = dyn_cast_or_null(D)) { + if (CurrentTraitStage == TraitProcessingStage::SemanticAnalysis) { + if (VarDecl *UndesugaredVD = + dyn_cast_or_null(getUndesugaredDecl(VD))) { + D = UndesugaredVD; + if (FoundD == VD) + FoundD = UndesugaredVD; + Ty = UndesugaredVD->getType(); + } + } + } // Desugar for declRefExpr which refers to async function. if (FunctionDecl *FD = dyn_cast_or_null(D)) { if (FD->isAsyncSpecified()) { @@ -7178,12 +7192,14 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, if (getLangOpts().BSC) { if (FunctionDecl *FD = dyn_cast(NDecl)) { if (CurrentTraitStage == TraitProcessingStage::SemanticAnalysis) { - if (FunctionDecl *OriginalFD = getTraitFunctionDecl(FD)) { - NDecl = OriginalFD; - Fn = DeclRefExpr::Create( - Context, OriginalFD->getQualifierLoc(), SourceLocation(), - OriginalFD, false, SourceLocation(), OriginalFD->getType(), - Fn->getValueKind(), OriginalFD, nullptr, DRE->isNonOdrUse()); + if (FunctionDecl *UndesugaredFD = + dyn_cast_or_null(getUndesugaredDecl(FD))) { + NDecl = UndesugaredFD; + Fn = DeclRefExpr::Create(Context, UndesugaredFD->getQualifierLoc(), + SourceLocation(), UndesugaredFD, false, + SourceLocation(), UndesugaredFD->getType(), + Fn->getValueKind(), UndesugaredFD, nullptr, + DRE->isNonOdrUse()); } } } -- Gitee From 3b7ea7b7e1a716987a567b4ec41d152452180294 Mon Sep 17 00:00:00 2001 From: tanhongmin Date: Fri, 17 Oct 2025 20:55:49 +0800 Subject: [PATCH 7/7] desugar global or local record decl and record variables initlistexpr --- clang/lib/Parse/ParseDecl.cpp | 8 +- clang/lib/Sema/BSC/SemaBSCTrait.cpp | 434 ++++++++++++++++++++++++++-- clang/lib/Sema/SemaDecl.cpp | 49 +++- clang/lib/Sema/SemaExprMember.cpp | 13 + clang/lib/Sema/SemaInit.cpp | 8 +- 5 files changed, 475 insertions(+), 37 deletions(-) diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index b9f3c87adc89..20697ceb9665 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2312,9 +2312,11 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, #if ENABLE_BSC if (getLangOpts().BSC && Context == DeclaratorContext::File) { for (size_t i = 0; i < DeclsInGroup.size(); ++i) { - Decl *TransformedD = Actions.DesugarTraitInTranslationUnit(DeclsInGroup[i]); - if (TransformedD && TransformedD != DeclsInGroup[i]) { - DeclsInGroup[i] = TransformedD; + Decl *TransformedVD = + Actions.DesugarTraitInTranslationUnit(DeclsInGroup[i]); + if (TransformedVD && TransformedVD != DeclsInGroup[i]) { + // Is trait global variables, need to update + DeclsInGroup[i] = TransformedVD; } } } diff --git a/clang/lib/Sema/BSC/SemaBSCTrait.cpp b/clang/lib/Sema/BSC/SemaBSCTrait.cpp index d5b7745cfcf4..2e12448472e1 100644 --- a/clang/lib/Sema/BSC/SemaBSCTrait.cpp +++ b/clang/lib/Sema/BSC/SemaBSCTrait.cpp @@ -1546,20 +1546,19 @@ public: TransformedLocalDecls.find(D); if (Known != TransformedLocalDecls.end()) return Known->second; - // Return transformed function declarations - if (FunctionDecl *FD = dyn_cast(D)) { - if (FunctionDecl *DesugaredFD = - dyn_cast_or_null(getSema().getDesugaredDecl(FD))) - return DesugaredFD; + // Return transformed global declarations + if (Decl *KnownGlobal = + dyn_cast_or_null(getSema().getDesugaredDecl(D))) + return KnownGlobal; + + // If D is a FunctionDecl, it must be desugared at before toplevel or not + // need to be desugared, so return it directly + if (FunctionDecl *FD = dyn_cast(D)) return FD; - } - // Desugar trait types variable(global or local) declarations + + // Desugar trait types variable (global or local) declarations if (VarDecl *VD = dyn_cast(D)) { - // Return transformed Decl - if (VarDecl *DesugaredVD = - dyn_cast_or_null(getSema().getDesugaredDecl(VD))) { - return DesugaredVD; - } + // Case 1: Variable of trait* type if (getSema().TryDesugarTrait(VD->getType())) { VarDecl *NewVD = DesugarTraitVariable(VD); if (NewVD && NewVD != D) { @@ -1580,10 +1579,313 @@ public: return NewVD; } } + // Case 2: Variable of struct type that contains trait* fields + QualType VarType = VD->getType(); + if (const RecordType *RT = VarType->getAs()) { + if (RecordDecl *RD = RT->getDecl()) { + RecordDecl *DesugaredRD = nullptr; + // Search from global desugared declarations + DesugaredRD = + dyn_cast_or_null(getSema().getDesugaredDecl(RD)); + // Search from local desugared declarations + if (!DesugaredRD) { + auto It = TransformedLocalDecls.find(RD); + if (It != TransformedLocalDecls.end()) { + DesugaredRD = dyn_cast(It->second); + } + } + if (DesugaredRD && DesugaredRD != RD) { + // Create new VarDecl with desugared type + QualType NewVarType = getSema().Context.getRecordType(DesugaredRD); + VarDecl *NewVD = VarDecl::Create( + getSema().Context, VD->getDeclContext(), VD->getBeginLoc(), + VD->getLocation(), VD->getIdentifier(), NewVarType, + getSema().Context.getTrivialTypeSourceInfo(NewVarType), + VD->getStorageClass()); + // Transform initializer + Expr *TransformedInit = nullptr; + if (Expr *Init = VD->getInit()) { + ExprResult InitResult = TransformExpr(Init); + if (InitResult.isUsable()) { + TransformedInit = InitResult.get(); + } + } + if (TransformedInit) { + NewVD->setInit(TransformedInit); + } + if (IsGlobalDecl) { + // Update global mappings and AST + getSema().TraitUndesugaredToDesugaredDeclMap[VD] = NewVD; + getSema().TraitDesugaredToUndesugaredDeclMap[NewVD] = VD; + DeclContext *DC = VD->getDeclContext(); + DC->removeDecl(VD); + DC->addDecl(NewVD); + getSema().IdResolver.RemoveDecl(VD); + getSema().IdResolver.AddDecl(NewVD); + } else { + // Update local mappings + transformedLocalDecl(VD, {NewVD}); + } + return NewVD; + } + } + } + } + + // Desugar trait types RecordDecl (global or local) declarations + if (RecordDecl *RD = dyn_cast(D)) { + if (!RD->isThisDeclarationADefinition()) + return RD; + bool NeedDesugarRecordDecl = false; + for (auto *Field : RD->fields()) { + QualType FieldType = Field->getType(); + if (getSema().TryDesugarTrait(FieldType)) + NeedDesugarRecordDecl = true; + break; + } + if (NeedDesugarRecordDecl) { + RecordDecl *NewRD = DesugarTraitRecordDecl(RD); + if (NewRD && NewRD != D) { + if (IsGlobalDecl) { + // Mapping global declarations + getSema().TraitUndesugaredToDesugaredDeclMap[RD] = NewRD; + getSema().TraitDesugaredToUndesugaredDeclMap[NewRD] = RD; + DeclContext *DC = RD->getDeclContext(); + DC->removeDecl(RD); + DC->addDecl(NewRD); + getSema().IdResolver.RemoveDecl(RD); + getSema().IdResolver.AddDecl(NewRD); + } else { + // Mapping local declarations + transformedLocalDecl(D, {NewRD}); + } + return NewRD; + } + } } return D; } + ExprResult TransformInitListExpr(InitListExpr *E) { + // Recursively transform sub-expressions + ExprResult Result = BaseTransform::TransformInitListExpr(E); + + if (Result.isInvalid()) + return Result; + InitListExpr *IList = dyn_cast_or_null(Result.get()); + if (!IList) + return Result; + // Get the type being initialized + IList->setType(E->getType()); + QualType DestType = IList->getType(); + if (DestType.isNull()) + return Result; + const RecordType *RT = DestType->getAs(); + if (!RT) + return Result; + RecordDecl *RD = RT->getDecl()->getDefinition(); + if (!RD) + return Result; + unsigned NumInits = IList->getNumInits(); + if (!NumInits) + return Result; + // Build field list for non-bitfield fields + SmallVector Fields; + for (FieldDecl *Field : RD->fields()) { + if (!Field->isUnnamedBitfield()) + Fields.push_back(Field); + } + // Build a map from Field to its initializer expression + // This will reorder designated initialization to sequential initialization + llvm::DenseMap FieldToInit; + unsigned SequentialFieldIndex = 0; + for (unsigned InitIndex = 0; InitIndex < NumInits; ++InitIndex) { + Expr *Init = IList->getInit(InitIndex); + if (!Init) + continue; + FieldDecl *Field = nullptr; + Expr *InitValue = Init; + if (DesignatedInitExpr *DIE = dyn_cast(Init)) { + // Designated initializer: .field = value + if (DIE->size() == 1 && DIE->getDesignator(0)->isFieldDesignator()) { + Field = DIE->getDesignator(0)->getField(); + if (!Field) { + // Find the field by name + if (IdentifierInfo *FieldName = + DIE->getDesignator(0)->getFieldName()) { + for (FieldDecl *FD : RD->fields()) { + if (FD->getIdentifier() == FieldName) { + Field = FD; + break; + } + } + } + } + InitValue = DIE->getInit(); + } + } else { + // Sequential initializer: use field index + if (SequentialFieldIndex < Fields.size()) { + Field = Fields[SequentialFieldIndex]; + SequentialFieldIndex++; + } + } + if (Field && InitValue) { + FieldToInit[Field] = InitValue; + } + } + // Process each field in order and transform initializers + for (unsigned FieldIndex = 0; FieldIndex < Fields.size(); ++FieldIndex) { + FieldDecl *Field = Fields[FieldIndex]; + auto It = FieldToInit.find(Field); + if (It == FieldToInit.end()) + continue; + Expr *InitValue = It->second; + // Field type is the original trait* type, not the desugared struct type + QualType FieldType = Field->getType(); + QualType InitValueType = InitValue->getType(); + Expr *NewInit = InitValue; + // Case 1: InitValue is InitListExpr (nested struct initialization) + if (InitListExpr *SubIList = dyn_cast(InitValue)) { + ExprResult NewSubList = TransformInitListExpr(SubIList); + if (!NewSubList.isInvalid() && NewSubList.get() != SubIList) { + NewInit = NewSubList.get(); + } + } else { + TraitDecl *TD = getSema().TryDesugarTrait(FieldType); + // Case 2: Field type is trait* and InitValue is corresponding struct + // type + if (TD && InitValueType->isRecordType()) { + QualType DesugaredType = getSema().DesugarTraitToStructTrait( + TD, FieldType, Field->getLocation()); + if (getSema().Context.hasSameType(InitValueType, DesugaredType)) { + // Already desugared struct, just ensure proper value category + ExprResult CorrectRValueInit = + getSema().DefaultLvalueConversion(InitValue); + if (!CorrectRValueInit.isInvalid()) { + NewInit = CorrectRValueInit.get(); + } + } + } + // Case 3: Field type is trait* and InitValue is implied trait* pointer + // type + else if (TD && InitValueType->isPointerType()) { + // Ensure InitValue is an rvalue before processing. + ExprResult CorrectRValueInit = + getSema().DefaultLvalueConversion(InitValue); + if (CorrectRValueInit.isInvalid()) { + continue; + } + Expr *PointerValue = CorrectRValueInit.get(); + // Check if it's a null pointer + bool IsNullPointer = PointerValue->isNullPointerConstant( + getSema().Context, Expr::NPC_ValueDependentIsNull); + // Get the vtable for this type implementing the trait + VarDecl *VTableVar = nullptr; + if (!IsNullPointer) { + QualType PointeeType = + InitValueType->getPointeeType().getCanonicalType(); + VTableVar = TD->getTypeImpledVarDecl(PointeeType); + if (!VTableVar) { + continue; + } + } + // Build the two-field initializer list: {.data, .vtable} + SmallVector Components; + // 1. Build .data field initializer (cast pointer to void*) + QualType VoidPtrType = + getSema().Context.getPointerType(getSema().Context.VoidTy); + if (FieldType.isOwnedQualified()) + VoidPtrType.addOwned(); + if (FieldType.isBorrowQualified()) + VoidPtrType.addBorrow(); + Expr *DataExpr = ImplicitCastExpr::Create( + getSema().Context, VoidPtrType, + IsNullPointer ? CK_NullToPointer : CK_BitCast, PointerValue, + nullptr, VK_PRValue, FPOptionsOverride()); + Components.push_back(DataExpr); + // 2. Build .vtable field initializer + Expr *VTableExpr = nullptr; + if (IsNullPointer) { + RecordDecl *VTableRD = TD->getVtable(); + QualType VTableType = getSema().Context.getRecordType(VTableRD); + if (VTableRD->getDescribedClassTemplate()) { + VTableType = getSema().CompleteRecordType( + VTableRD, Field->getTypeSourceInfo()); + VTableType = getSema().Context.getElaboratedType( + ETK_Struct, nullptr, VTableType); + } + QualType VTablePtrType = + getSema().Context.getPointerType(VTableType); + VTableExpr = ImplicitCastExpr::Create( + getSema().Context, VTablePtrType, CK_NullToPointer, InitValue, + nullptr, VK_PRValue, FPOptionsOverride()); + } else { + QualType VTableType = VTableVar->getType(); + QualType VTablePtrType = + getSema().Context.getPointerType(VTableType); + + DeclRefExpr *VTableRef = DeclRefExpr::Create( + getSema().Context, NestedNameSpecifierLoc(), SourceLocation(), + VTableVar, false, SourceLocation(), VTableType, VK_LValue); + VTableExpr = UnaryOperator::Create( + getSema().Context, VTableRef, UO_AddrOf, VTablePtrType, + VK_PRValue, OK_Ordinary, InitValue->getBeginLoc(), false, + FPOptionsOverride()); + } + Components.push_back(VTableExpr); + // 3. Create the InitListExpr + ExprResult NewStructInitResult = getSema().ActOnInitList( + InitValue->getBeginLoc(), Components, InitValue->getEndLoc()); + if (!NewStructInitResult.isInvalid()) { + Expr *NewStructInit = NewStructInitResult.get(); + QualType DesugaredFieldType = getSema().DesugarTraitToStructTrait( + TD, FieldType, Field->getLocation()); + if (InitListExpr *ILE = dyn_cast(NewStructInit)) { + ILE->setType(DesugaredFieldType); + } + NewInit = NewStructInit; + } + } + // Case 4: Other types (int, float, pointers, etc.) + else { + ExprResult CorrectRValueInit = + getSema().DefaultLvalueConversion(InitValue); + if (!CorrectRValueInit.isInvalid()) { + NewInit = CorrectRValueInit.get(); + } + } + } + // Update the FieldToInit map with transformed init + FieldToInit[Field] = NewInit; + } + // Rebuild InitListExpr in field order + SmallVector OrderedInits; + for (FieldDecl *Field : Fields) { + auto It = FieldToInit.find(Field); + if (It != FieldToInit.end()) { + OrderedInits.push_back(It->second); + } + } + // Update IList with ordered initializers + IList->resizeInits(getSema().Context, OrderedInits.size()); + for (unsigned I = 0; I < OrderedInits.size(); ++I) { + IList->updateInit(getSema().Context, I, OrderedInits[I]); + } + // set InitListExpr type to desugared struct type + RecordDecl *DesugaredRD = nullptr; + llvm::DenseMap::iterator It = + TransformedLocalDecls.find(RD); + if (It != TransformedLocalDecls.end()) { + DesugaredRD = dyn_cast(It->second); + } + if (!DesugaredRD) + DesugaredRD = + dyn_cast_or_null(getSema().getDesugaredDecl(RD)); + IList->setType(getSema().Context.getRecordType(DesugaredRD)); + return Result; + } + ExprResult TransformBinaryOperator(BinaryOperator *E) { ExprResult LHSResult = TransformExpr(E->getLHS()); ExprResult RHSResult = TransformExpr(E->getRHS()); @@ -1658,6 +1960,7 @@ private: bool IsGlobalDecl; VarDecl *DesugarTraitVariable(VarDecl *VD); + RecordDecl *DesugarTraitRecordDecl(RecordDecl *RD); ExprResult DesugarTraitReassign(BinaryOperator *E); ExprResult DesugarTraitCompare(BinaryOperator *E); ExprResult DesugarTraitFunctionCall(CallExpr *E, MemberExpr *ME); @@ -1670,28 +1973,28 @@ Decl *BSCTraitDesugarer::DesugarTopLevelDecl(Decl *D) { if (FunctionDecl *FD = dyn_cast(D)) { IsGlobalDecl = false; // Transform function body - Stmt *TransformedBody = nullptr; + Stmt *NewBody = nullptr; if (FD->hasBody()) { Stmt *Body = FD->getBody(); - StmtResult NewBody = TransformStmt(Body); - if (NewBody.isUsable()) - TransformedBody = NewBody.get(); + StmtResult NewBodyResult = TransformStmt(Body); + if (NewBodyResult.isUsable()) + NewBody = NewBodyResult.get(); else - TransformedBody = Body; + NewBody = Body; } // Transform parameters and return type - FD = DesugarFunctionDeclSignature(FD); + FunctionDecl *NewFD = DesugarFunctionDeclSignature(FD); // Set transformed body - if (TransformedBody) - FD->setBody(TransformedBody); - return FD; - } else if (isa(D)) { + if (NewBody) + NewFD->setBody(NewBody); + return NewFD; + } else if (isa(D)) { + // Set global flag and use TransformDecl to desugar IsGlobalDecl = true; Decl *NewDecl = TransformDecl(D->getBeginLoc(), D); if (NewDecl && NewDecl != D) return NewDecl; - else - return D; + return D; } return D; } @@ -2132,6 +2435,89 @@ BSCTraitDesugarer::DesugarFunctionDeclSignature(FunctionDecl *FD) { return NewFD; } +RecordDecl *BSCTraitDesugarer::DesugarTraitRecordDecl(RecordDecl *RD) { + if (!RD) + return nullptr; + if (!RD->isThisDeclarationADefinition()) + return nullptr; + RecordDecl *NewRD = RecordDecl::Create( + getSema().Context, RD->getTagKind(), RD->getDeclContext(), + RD->getBeginLoc(), RD->getLocation(), RD->getIdentifier(), + RD->getPreviousDecl(), false // DelayTypeCreation + ); + // Copy attributes + if (RD->hasAttrs()) { + for (const Attr *A : RD->attrs()) + NewRD->addAttr(A->clone(getSema().Context)); + } + NewRD->setAccess(RD->getAccess()); + if (RD->isImplicit()) + NewRD->setImplicit(); + if (RD->isModulePrivate()) + NewRD->setModulePrivate(); + NewRD->startDefinition(); + // Process and desugar fields + for (auto *Field : RD->fields()) { + QualType FieldType = Field->getType(); + TraitDecl *TD = getSema().TryDesugarTrait(FieldType); + FieldDecl *NewField = nullptr; + if (TD && !getSema().IsDesugaredFromTraitType(FieldType)) { + // Desugar trait* field + QualType StructType = getSema().DesugarTraitToStructTrait( + TD, FieldType, Field->getBeginLoc()); + if (!StructType.isNull() && + !getSema().Context.hasSameType(StructType, FieldType)) { + TypeSourceInfo *OriginalTSI = Field->getTypeSourceInfo(); + TypeSourceInfo *NewTSI = getSema().Context.getTrivialTypeSourceInfo( + StructType, OriginalTSI ? OriginalTSI->getTypeLoc().getBeginLoc() + : Field->getBeginLoc()); + NewField = FieldDecl::Create( + getSema().Context, NewRD, Field->getInnerLocStart(), + Field->getLocation(), Field->getIdentifier(), StructType, NewTSI, + Field->getBitWidth(), Field->isMutable(), + Field->getInClassInitStyle()); + if (IsGlobalDecl) { + getSema().TraitUndesugaredToDesugaredDeclMap[Field] = NewField; + getSema().TraitDesugaredToUndesugaredDeclMap[NewField] = Field; + } else { + transformedLocalDecl(Field, {NewField}); + } + } + } + if (!NewField) { + // Clone non-trait field or failed desugaring + // FIXME: report desugaring failure + NewField = FieldDecl::Create( + getSema().Context, NewRD, Field->getInnerLocStart(), + Field->getLocation(), Field->getIdentifier(), FieldType, + Field->getTypeSourceInfo(), Field->getBitWidth(), Field->isMutable(), + Field->getInClassInitStyle()); + } + // Copy field attributes + NewField->setAccess(Field->getAccess()); + NewField->setImplicit(Field->isImplicit()); + if (Field->isModulePrivate()) + NewField->setModulePrivate(); + if (Field->isInvalidDecl()) + NewField->setInvalidDecl(); + if (Field->hasAttrs()) { + for (const Attr *A : Field->attrs()) + NewField->addAttr(A->clone(getSema().Context)); + } + if (Field->hasInClassInitializer()) + NewField->setInClassInitializer(Field->getInClassInitializer()); + NewRD->addDecl(NewField); + } + // FIXME: Need to process nested RecordDecls + // for (Decl *SubDecl : RD->decls()) { + // if (auto *NestedRD = dyn_cast(SubDecl)) { + // } else if (!isa(SubDecl)) { + // } + // } + NewRD->completeDefinition(); + return NewRD; +} + Decl *Sema::getUndesugaredDecl(Decl *Desugared) { auto It = TraitDesugaredToUndesugaredDeclMap.find(Desugared); return It != TraitDesugaredToUndesugaredDeclMap.end() ? It->second : nullptr; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index f41e51ee0fb7..01395c0dc6e4 100755 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13133,6 +13133,23 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { return; } +#if ENABLE_BSC + // For variables with desugared trait struct types from other top-level decls, + // restore the original undesugared type before initialization checking + // This ensures both Sema and AST use the undesugared type + QualType VarType = VDecl->getType(); + if (const RecordType *RT = VarType->getAs()) { + if (RecordDecl *RD = RT->getDecl()) { + if (RecordDecl *UndesugaredRD = dyn_cast_or_null( + getUndesugaredDecl(RD))) { + // Replace with undesugared type + QualType UndesugaredType = Context.getRecordType(UndesugaredRD); + VDecl->setType(UndesugaredType); + } + } + } +#endif + // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. if (VDecl->getType()->isUndeducedType()) { // Attempt typo correction early so that the type of the init expression can @@ -17928,6 +17945,22 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD, #if ENABLE_BSC if (getLangOpts().BSC && IsInSafeZone() && IsContainsUnionTag(Tag)) DiagnoseUnionTypeInSafeZone(Tag->getLocation()); + + if (getLangOpts().BSC) { + if (RecordDecl *RD = dyn_cast(Tag)) { + DeclContext *DC = RD->getDeclContext(); + bool IsGlobalScope = DC->isTranslationUnit() || DC->isNamespace(); + // Only desugar Global RecordDecls, local RecordDecls will be handled by TreeTransform + if (IsGlobalScope) { + Decl *TransformedRD = DesugarTraitInTranslationUnit(RD); + if (TransformedRD && TransformedRD != RD) { + // RecordDecl was transformed, update reference + TagD = TransformedRD; + Tag = cast(TransformedRD); + } + } + } + } #endif // Exit this scope of this tag's definition. @@ -18390,14 +18423,16 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, if (getLangOpts().BSC) { if (T->isTraitType()) { Diag(Loc, diag::err_variables_not_trait_pointer); - } else if (T->hasTraitType()) { - TraitDecl *TD = TryDesugarTrait(T); - if (TD && !TD->getTrait()) { - InvalidDecl = true; - } - T = DesugarTraitToStructTrait(TD, T, Loc); - TInfo = Context.getTrivialTypeSourceInfo(T); } + // 取消 struct 声明时 trait 的立即解糖 + // else if (T->hasTraitType()) { + // TraitDecl *TD = TryDesugarTrait(T); + // if (TD && !TD->getTrait()) { + // InvalidDecl = true; + // } + // T = DesugarTraitToStructTrait(TD, T, Loc); + // TInfo = Context.getTrivialTypeSourceInfo(T); + // } } FieldDecl *NewFD = FieldDecl::Create(Context, Tag, TSSL, Loc, II, T, TInfo, BitWidth, Mutable, InitStyle); diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 88b0ccd48b7d..6893705cc732 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -1289,6 +1289,19 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, return ExprError(); #endif +#if ENABLE_BSC + if (getLangOpts().BSC && + CurrentTraitStage == TraitProcessingStage::SemanticAnalysis) { + if (auto *FD = dyn_cast(MemberDecl)) { + if (auto *UndesugaredFD = + dyn_cast_or_null(getUndesugaredDecl(FD))) { + MemberDecl = UndesugaredFD; + FoundDecl = DeclAccessPair::make(UndesugaredFD, FoundDecl.getAccess()); + } + } + } +#endif + if (FieldDecl *FD = dyn_cast(MemberDecl)) return BuildFieldReferenceExpr(BaseExpr, IsArrow, OpLoc, SS, FD, FoundDecl, MemberNameInfo); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index c605201445ff..b9a19f7a8580 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -1357,7 +1357,8 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, // Assign values to variables of TraitPointer type in struct, such as: // "struct S { trait F* a; };" // "struct S s = { &x };" - SemaRef.ActOnDesugarTraitExprInStruct(IList, expr, ElemType, Index, nullptr); + // 取消 initexpr 的立即解糖 + // SemaRef.ActOnDesugarTraitExprInStruct(IList, expr, ElemType, Index, nullptr); #endif if (ElemType->isReferenceType()) @@ -2471,8 +2472,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // Assign values to variables of TraitPointer type in struct, such as: // "struct S s = { .future = &x }" // or "struct S s = { .future = (trait F*)&x }" - SemaRef.ActOnDesugarTraitExprInStruct(IList, DIE->getInit(), - CurrentObjectType, Index, &DIE); + // 取消 initexpr 的立即解糖 + // SemaRef.ActOnDesugarTraitExprInStruct(IList, DIE->getInit(), + // CurrentObjectType, Index, &DIE); #endif if (DesigIdx == DIE->size()) { -- Gitee