diff --git a/clang/lib/Analysis/BSC/BSCNullabilityCheck.cpp b/clang/lib/Analysis/BSC/BSCNullabilityCheck.cpp index dd0e64a5b37454d338eff0111e2c39de29c0b4c3..79ffd703b9d5769cf73b9844bc93d9b2a8003eff 100644 --- a/clang/lib/Analysis/BSC/BSCNullabilityCheck.cpp +++ b/clang/lib/Analysis/BSC/BSCNullabilityCheck.cpp @@ -115,7 +115,7 @@ public: void VisitDeclStmt(DeclStmt *S); void HandleVarDeclInit(DeclStmt *DS, VarDecl *VD); void HandlePointerInit(DeclStmt *DS, VarDecl *VD); - void HandleStructInit(DeclStmt *DS, VarDecl *VD); + void HandleStructUnionInit(DeclStmt *DS, VarDecl *VD); void HandleFieldInit(DeclStmt *DS, VarDecl *VD, FieldDecl *FD, Expr *FieldInit, std::string FullFieldPath); void VisitBinaryOperator(BinaryOperator *BO); @@ -128,7 +128,7 @@ public: void SetCFGBlocksByExpr(Expr *PtrE, const CFGBlock *NonNullBlock, const CFGBlock *NullableBlock); void PassConditionStatusToSuccBlocks(Stmt *Cond); - void HandleNestedStructInit(DeclStmt *DS, VarDecl *TopVD, RecordDecl *RD, + void HandleNestedStructUnionInit(DeclStmt *DS, VarDecl *TopVD, RecordDecl *RD, InitListExpr *InitList, std::string FieldPrefix); }; } // namespace @@ -310,7 +310,7 @@ void TransferFunctions::HandleVarDeclInit(DeclStmt *DS, VarDecl *VD) { if (VQT->isPointerType()) HandlePointerInit(DS, VD); else if (VQT->isRecordType()) - HandleStructInit(DS, VD); + HandleStructUnionInit(DS, VD); } // Init a pointer variable @@ -331,7 +331,7 @@ void TransferFunctions::HandlePointerInit(DeclStmt *DS, VarDecl *VD) { } // Init a struct variable with pointer fields. -void TransferFunctions::HandleStructInit(DeclStmt *DS, VarDecl *VD) { +void TransferFunctions::HandleStructUnionInit(DeclStmt *DS, VarDecl *VD) { if (auto RecTy = dyn_cast(VD->getType().getCanonicalType())) { if (RecordDecl *RD = RecTy->getDecl()) { if (Expr *Init = VD->getInit()) { @@ -351,14 +351,14 @@ void TransferFunctions::HandleStructInit(DeclStmt *DS, VarDecl *VD) { break; } if (auto InitListE = dyn_cast(Init)) { - HandleNestedStructInit(DS, VD, RD, InitListE, ""); + HandleNestedStructUnionInit(DS, VD, RD, InitListE, ""); } } } } } -void TransferFunctions::HandleNestedStructInit(DeclStmt *DS, VarDecl *TopVD, +void TransferFunctions::HandleNestedStructUnionInit(DeclStmt *DS, VarDecl *TopVD, RecordDecl *RD, InitListExpr *InitList, std::string FieldPrefix) { @@ -390,11 +390,13 @@ void TransferFunctions::HandleNestedStructInit(DeclStmt *DS, VarDecl *TopVD, dyn_cast(FD->getType().getCanonicalType())) { if (RecordDecl *nestedRD = nestedRecTy->getDecl()) { if (auto nestedInitList = dyn_cast(fieldInit)) { - HandleNestedStructInit(DS, TopVD, nestedRD, nestedInitList, + HandleNestedStructUnionInit(DS, TopVD, nestedRD, nestedInitList, fullFieldPath); } } } + if (RD->isUnion()) + break; } } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index c605201445ff4ac62a3d2fcc0525be5f894d3f0c..1c51eaede728624ee245e5c4e94d0eb271b7714b 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -781,8 +781,15 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, if (const RecordType *RType = ILE->getType()->getAs()) { const RecordDecl *RDecl = RType->getDecl(); if (RDecl->isUnion() && ILE->getInitializedFieldInUnion()) - FillInEmptyInitForField(0, ILE->getInitializedFieldInUnion(), - Entity, ILE, RequiresSecondPass, FillWithNoInit); +#if ENABLE_BSC + { + ILE->resizeInits(SemaRef.Context, 1); +#endif + FillInEmptyInitForField(0, ILE->getInitializedFieldInUnion(), Entity, ILE, + RequiresSecondPass, FillWithNoInit); +#if ENABLE_BSC + } +#endif else if (RDecl->isUnion() && isa(RDecl) && cast(RDecl)->hasInClassInitializer()) { for (auto *Field : RDecl->fields()) { diff --git a/clang/test/BSC/Positive/SafeZone/safe_initialize_union/safe_initialize_union.cbs b/clang/test/BSC/Positive/SafeZone/safe_initialize_union/safe_initialize_union.cbs new file mode 100644 index 0000000000000000000000000000000000000000..4f02d25517f71b84ecfed89fc3a704da69e7846a --- /dev/null +++ b/clang/test/BSC/Positive/SafeZone/safe_initialize_union/safe_initialize_union.cbs @@ -0,0 +1,47 @@ +// RUN: %clang %s -o %t.output +// RUN: %t.output +// expected-no-diagnostics + +union Union1 { + int x; +}; + +union Union2 { + int x; + char y; +}; + +union Union3 { + int x; + int y; +}; + +union Union4 { + char x; + int y; +}; + +int main() +{ + safe + { + union Union1 u11 = {}; + union Union1 u12 = {1}; + + union Union2 u21 = {}; + union Union2 u22 = {1}; + + union Union3 u31 = {}; + union Union3 u32 = {1}; + + union Union4 u41 = {}; + union Union4 u42 = {1}; + union Union4 u43 = {'1'}; + + unsafe{ + if(u11.x==0 && u12.x==1 && u21.x==0 && u22.x==1 && u31.x==0 && u32.x==1 && u41.x==0 && u42.x==1 && u43.x=='1') + return 0; + return 1; + } + } +} \ No newline at end of file