diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index d8de64a915e3b41a8de2f402a6e558ce75bddf70..4791340ba57e3612f1b58bcd0305991a3ec3d741 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5702,11 +5702,31 @@ public: ExprResult AddAfterStructTrait(ExprResult ULE, SourceLocation DSLoc, std::string ID); VarDecl *ActOnDesugarTraitInstance(Decl *VarDec); + 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); + Decl *DesugarTraitInTranslationUnit(Decl *D); + /// Mark Trait processing stage + enum class TraitProcessingStage { SemanticAnalysis, TreeTransform }; + /// Default at SemanticAnalysis stage + TraitProcessingStage CurrentTraitStage = + TraitProcessingStage::SemanticAnalysis; + // 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/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 2b00eeec46c9a1e741bc165832ad1f5c6d55a567..20697ceb966546cc10329bc0ea3225137c22af48 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2309,6 +2309,19 @@ 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 *TransformedVD = + Actions.DesugarTraitInTranslationUnit(DeclsInGroup[i]); + if (TransformedVD && TransformedVD != DeclsInGroup[i]) { + // Is trait global variables, need to update + DeclsInGroup[i] = TransformedVD; + } + } + } +#endif + return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup); } diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index abd3ccd2bbf83bf334a653fe80efe429ec220e1d..3a40ed2af53714301e45374611cca8a95bd26b05 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/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index f3246b8c567817f7801a4eb5ef9cdec8fd39ce8c..90ea8b6698f0039233d386efb48ad57bd138ef4b 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -1373,6 +1373,24 @@ 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 + /* if (getLangOpts().BSC && R.isUsable()) { // desugar for trait F *f = &a; if (auto *DS = dyn_cast(R.get())) { @@ -1402,6 +1420,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 a09089a1d6aa4f0b41a5b7501fb806ac84af1311..2e12448472e1ce5930622e3de961364d689b67b4 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" @@ -695,6 +696,181 @@ 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; +} + +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; +} + +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); if (!VD) @@ -1173,7 +1349,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 +1529,1003 @@ void Sema::checkBSCFunctionContainsTrait(Decl *D) { } } } + +class BSCTraitDesugarer : public TreeTransform { + using BaseTransform = TreeTransform; + +public: + BSCTraitDesugarer(Sema &SemaRef) : TreeTransform(SemaRef) {} + + 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 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 + if (VarDecl *VD = dyn_cast(D)) { + // Case 1: Variable of trait* type + 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; + } + } + // 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()); + 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()); + 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); + } + + ExprResult TransformCallExpr(CallExpr *E) { + 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 *DesugaredFD = dyn_cast_or_null( + getSema().getDesugaredDecl(FD))) { + // Transform DeclRefExpr + DeclRefExpr *NewDRE = DeclRefExpr::Create( + getSema().getASTContext(), DRE->getQualifierLoc(), + DRE->getTemplateKeywordLoc(), DesugaredFD, + false, // RefersToEnclosingVariableOrCapture + DRE->getNameInfo(), DesugaredFD->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); + 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: + bool IsGlobalDecl; + + VarDecl *DesugarTraitVariable(VarDecl *VD); + RecordDecl *DesugarTraitRecordDecl(RecordDecl *RD); + ExprResult DesugarTraitReassign(BinaryOperator *E); + ExprResult DesugarTraitCompare(BinaryOperator *E); + ExprResult DesugarTraitFunctionCall(CallExpr *E, MemberExpr *ME); + FunctionDecl *DesugarFunctionDeclSignature(FunctionDecl *FD); +}; + +Decl *BSCTraitDesugarer::DesugarTopLevelDecl(Decl *D) { + if (!D) + return D; + if (FunctionDecl *FD = dyn_cast(D)) { + IsGlobalDecl = false; + // Transform function body + Stmt *NewBody = nullptr; + if (FD->hasBody()) { + Stmt *Body = FD->getBody(); + StmtResult NewBodyResult = TransformStmt(Body); + if (NewBodyResult.isUsable()) + NewBody = NewBodyResult.get(); + else + NewBody = Body; + } + // Transform parameters and return type + FunctionDecl *NewFD = DesugarFunctionDeclSignature(FD); + // Set transformed body + 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; + return D; + } + return D; +} + +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; + QualType StructType = + getSema().DesugarTraitToStructTrait(TD, TraitType, VD->getBeginLoc()); + 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; + 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()); + } + // 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 + 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; +} + +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); + } +} + +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; +} + +// API for sema desugar toplevel +Decl *Sema::DesugarTraitInTranslationUnit(Decl *D) { + if (!D || !getLangOpts().BSC) + return D; + // Mark desugaring stage + TraitProcessingStage OldStage = CurrentTraitStage; + CurrentTraitStage = TraitProcessingStage::TreeTransform; + + BSCTraitDesugarer Desugarer(*this); + 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().TraitUndesugaredToDesugaredDeclMap[FD] = NewFD; + getSema().TraitDesugaredToUndesugaredDeclMap[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; +} + +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; +} + +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/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c7bfeb708742410a78779ed7784f85b0ef63b584..01395c0dc6e48a2700ed80586c489ce1bf5f5bc1 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 && @@ -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 @@ -14841,6 +14858,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 +14867,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,6 +16085,14 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, } // Desugar BSC Function. DesugarDestructorCall(FD); + + Decl *TransformedFD = DesugarTraitInTranslationUnit(FD); + if (TransformedFD && TransformedFD != FD) { + // Function was transformed, update reference + dcl = TransformedFD; + FD = cast(TransformedFD); + } + BSCDataflowAnalysisFlag = false; } } @@ -17917,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. @@ -18379,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/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 37def7ff1d965244fa7a4fe6ba29bcea7b6f55ac..e623e914e4c33700a331dffb899f52c05c876283 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()) { @@ -2367,8 +2381,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()]; } } @@ -6512,6 +6527,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( @@ -6521,6 +6538,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, else return true; } + */ CheckMoveVarMemoryLeak(Arg, Arg->getBeginLoc()); #endif if (RequireCompleteType(Arg->getBeginLoc(), ProtoArgType, @@ -7168,6 +7186,26 @@ 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 *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()); + } + } + } + } +#endif + FunctionDecl *FDecl = dyn_cast(NDecl); if (FDecl && FDecl->getBuiltinID()) { // Rewrite the function decl for this builtin by replacing parameters @@ -13173,9 +13211,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. @@ -16088,7 +16149,6 @@ ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, DiagnoseBinOpPrecedence(*this, Opc, TokLoc, LHSExpr, RHSExpr); #if ENABLE_BSC - // Handling reassignments of variable types with trait pointers: if (getLangOpts().BSC) { if (LHSExpr->getType()->hasTraitType()) LHSExpr = LHSExpr->IgnoreCasts(); @@ -16097,20 +16157,41 @@ ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, 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_Assign) { + if (!ActOnTraitReassignSema(Opc, LHSExpr, RHSExpr)) + return ExprError(); } 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 (!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()) + // 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(); diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 9bf51f3447dc2dc272b0d5cd3e8a9d9d22dcd140..6893705cc732eb50699db73eb681923d49cfa1c8 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); @@ -2027,6 +2040,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); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index c605201445ff4ac62a3d2fcc0525be5f894d3f0c..b9a19f7a85809dc48ff22089c983e8d89322e649 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()) { diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 64a83ad410605e4a28341c7e8b2748d8dec777c1..18eea6ac20b8ef54bdf5dcba5a95aca49145285d 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 39232992907b972bcff895a39dab2cdeca6ebdef..1edf3a36642d9fb1117571e5346682c5baca2533 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