diff options
author | martinboehme <mboehme@google.com> | 2024-03-01 09:27:59 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-01 09:27:59 +0100 |
commit | 128780b06f5bd0e586ee81e1e0e75f63c5664cfc (patch) | |
tree | ec2ef5ae70faa76fec5265f6d1efb0abe6bb1540 /clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp | |
parent | 420928b2fa8b00f23f0adcb19328014592455698 (diff) | |
download | llvm-128780b06f5bd0e586ee81e1e0e75f63c5664cfc.zip llvm-128780b06f5bd0e586ee81e1e0e75f63c5664cfc.tar.gz llvm-128780b06f5bd0e586ee81e1e0e75f63c5664cfc.tar.bz2 |
[clang][dataflow] Correctly treat empty initializer lists for unions. (#82986)
This fixes a crash introduced by
https://github.com/llvm/llvm-project/pull/82348
but also adds additional handling to make sure that we treat empty
initializer
lists for both unions and structs/classes correctly (see tests added in
this
patch).
Diffstat (limited to 'clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp')
-rw-r--r-- | clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index d487944..fd7b06e 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -361,8 +361,8 @@ getFieldsGlobalsAndFuncs(const Stmt &S, FieldSet &Fields, if (const auto *FD = dyn_cast<FieldDecl>(VD)) Fields.insert(FD); } else if (auto *InitList = dyn_cast<InitListExpr>(&S)) { - if (RecordDecl *RD = InitList->getType()->getAsRecordDecl()) - for (const auto *FD : getFieldsForInitListExpr(RD)) + if (InitList->getType()->isRecordType()) + for (const auto *FD : getFieldsForInitListExpr(InitList)) Fields.insert(FD); } } @@ -983,7 +983,7 @@ StorageLocation &Environment::createObjectInternal(const ValueDecl *D, } Value *Val = nullptr; - if (InitExpr) + if (InitExpr) { // In the (few) cases where an expression is intentionally // "uninterpreted", `InitExpr` is not associated with a value. There are // two ways to handle this situation: propagate the status, so that @@ -998,6 +998,11 @@ StorageLocation &Environment::createObjectInternal(const ValueDecl *D, // default value (assuming we don't update the environment API to return // references). Val = getValue(*InitExpr); + + if (!Val && isa<ImplicitValueInitExpr>(InitExpr) && + InitExpr->getType()->isPointerType()) + Val = &getOrCreateNullPointerValue(InitExpr->getType()->getPointeeType()); + } if (!Val) Val = createValue(Ty); @@ -1104,12 +1109,22 @@ RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME, return Env.get<RecordStorageLocation>(*Base); } -std::vector<FieldDecl *> getFieldsForInitListExpr(const RecordDecl *RD) { +std::vector<const FieldDecl *> +getFieldsForInitListExpr(const InitListExpr *InitList) { + const RecordDecl *RD = InitList->getType()->getAsRecordDecl(); + assert(RD != nullptr); + + std::vector<const FieldDecl *> Fields; + + if (InitList->getType()->isUnionType()) { + Fields.push_back(InitList->getInitializedFieldInUnion()); + return Fields; + } + // Unnamed bitfields are only used for padding and do not appear in // `InitListExpr`'s inits. However, those fields do appear in `RecordDecl`'s // field list, and we thus need to remove them before mapping inits to // fields to avoid mapping inits to the wrongs fields. - std::vector<FieldDecl *> Fields; llvm::copy_if( RD->fields(), std::back_inserter(Fields), [](const FieldDecl *Field) { return !Field->isUnnamedBitfield(); }); |