diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h --- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h @@ -86,14 +86,51 @@ /*Logger=*/nullptr}); ~DataflowAnalysisContext(); + /// Creates a `T` (some subclass of `StorageLocation`), forwarding `args` to + /// the constructor, and returns a reference to it. + /// + /// The `DataflowAnalysisContext` takes ownership of the created object. The + /// object will be destroyed when the `DataflowAnalysisContext` is destroyed. + template + std::enable_if_t::value, T &> + create(Args &&...args) { + // Note: If allocation of individual `StorageLocation`s turns out to be + // costly, consider creating specializations of `create` for commonly + // used `StorageLocation` subclasses and make them use a `BumpPtrAllocator`. + return *cast( + Locs.emplace_back(std::make_unique(std::forward(args)...)) + .get()); + } + + /// Creates a `T` (some subclass of `Value`), forwarding `args` to the + /// constructor, and returns a reference to it. + /// + /// The `DataflowAnalysisContext` takes ownership of the created object. The + /// object will be destroyed when the `DataflowAnalysisContext` is destroyed. + template + std::enable_if_t::value, T &> + create(Args &&...args) { + // Note: If allocation of individual `Value`s turns out to be costly, + // consider creating specializations of `create` for commonly used + // `Value` subclasses and make them use a `BumpPtrAllocator`. + return *cast( + Vals.emplace_back(std::make_unique(std::forward(args)...)) + .get()); + } + /// Takes ownership of `Loc` and returns a reference to it. /// + /// This function is deprecated. Instead of + /// `takeOwnership(std::make_unique(args))`, prefer + /// `create(args)`. + /// /// Requirements: /// /// `Loc` must not be null. template - std::enable_if_t::value, T &> - takeOwnership(std::unique_ptr Loc) { + LLVM_DEPRECATED("use create instead", "") + std::enable_if_t::value, + T &> takeOwnership(std::unique_ptr Loc) { assert(Loc != nullptr); Locs.push_back(std::move(Loc)); return *cast(Locs.back().get()); @@ -101,12 +138,17 @@ /// Takes ownership of `Val` and returns a reference to it. /// + /// This function is deprecated. Instead of + /// `takeOwnership(std::make_unique(args))`, prefer + /// `create(args)`. + /// /// Requirements: /// /// `Val` must not be null. template - std::enable_if_t::value, T &> - takeOwnership(std::unique_ptr Val) { + LLVM_DEPRECATED("use create instead", "") + std::enable_if_t::value, T &> takeOwnership( + std::unique_ptr Val) { assert(Val != nullptr); Vals.push_back(std::move(Val)); return *cast(Vals.back().get()); @@ -170,9 +212,9 @@ } /// Creates an atomic boolean value. - AtomicBoolValue &createAtomicBoolValue() { - return takeOwnership(std::make_unique()); - } + LLVM_DEPRECATED("use create instead", + "create") + AtomicBoolValue &createAtomicBoolValue() { return create(); } /// Creates a Top value for booleans. Each instance is unique and can be /// assigned a distinct truth value during solving. @@ -182,9 +224,8 @@ /// implementation so that `Top iff Top` has a consistent meaning, regardless /// of the identity of `Top`. Moreover, I think the meaning should be /// `false`. - TopBoolValue &createTopBoolValue() { - return takeOwnership(std::make_unique()); - } + LLVM_DEPRECATED("use create instead", "create") + TopBoolValue &createTopBoolValue() { return create(); } /// Returns a boolean value that represents the conjunction of `LHS` and /// `RHS`. Subsequent calls with the same arguments, regardless of their diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h --- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -319,27 +319,59 @@ /// is assigned a storage location in the environment, otherwise returns null. Value *getValue(const Expr &E, SkipPast SP) const; + /// Creates a `T` (some subclass of `StorageLocation`), forwarding `args` to + /// the constructor, and returns a reference to it. + /// + /// The analysis context takes ownership of the created object. The object + /// will be destroyed when the analysis context is destroyed. + template + std::enable_if_t::value, T &> + create(Args &&...args) { + return DACtx->create(std::forward(args)...); + } + + /// Creates a `T` (some subclass of `Value`), forwarding `args` to the + /// constructor, and returns a reference to it. + /// + /// The analysis context takes ownership of the created object. The object + /// will be destroyed when the analysis context is destroyed. + template + std::enable_if_t::value, T &> + create(Args &&...args) { + return DACtx->create(std::forward(args)...); + } + /// Transfers ownership of `Loc` to the analysis context and returns a /// reference to it. /// + /// This function is deprecated. Instead of + /// `takeOwnership(std::make_unique(args))`, prefer + /// `create(args)`. + /// /// Requirements: /// /// `Loc` must not be null. template - std::enable_if_t::value, T &> - takeOwnership(std::unique_ptr Loc) { + LLVM_DEPRECATED("use create instead", "") + std::enable_if_t::value, + T &> takeOwnership(std::unique_ptr Loc) { return DACtx->takeOwnership(std::move(Loc)); } /// Transfers ownership of `Val` to the analysis context and returns a /// reference to it. /// + /// This function is deprecated. Instead of + /// `takeOwnership(std::make_unique(args))`, prefer + /// `create(args)`. + /// /// Requirements: /// /// `Val` must not be null. template - std::enable_if_t::value, T &> - takeOwnership(std::unique_ptr Val) { + LLVM_DEPRECATED("use create instead", "") + std::enable_if_t::value, T &> takeOwnership( + std::unique_ptr Val) { return DACtx->takeOwnership(std::move(Val)); } diff --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp --- a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp @@ -59,10 +59,9 @@ : getReferencedFields(Type); for (const FieldDecl *Field : Fields) FieldLocs.insert({Field, &createStorageLocation(Field->getType())}); - return takeOwnership( - std::make_unique(Type, std::move(FieldLocs))); + return create(Type, std::move(FieldLocs)); } - return takeOwnership(std::make_unique(Type)); + return create(Type); } StorageLocation & @@ -90,8 +89,7 @@ auto Res = NullPointerVals.try_emplace(CanonicalPointeeType, nullptr); if (Res.second) { auto &PointeeLoc = createStorageLocation(CanonicalPointeeType); - Res.first->second = - &takeOwnership(std::make_unique(PointeeLoc)); + Res.first->second = &create(PointeeLoc); } return *Res.first->second; } @@ -112,8 +110,7 @@ auto Res = ConjunctionVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS), nullptr); if (Res.second) - Res.first->second = - &takeOwnership(std::make_unique(LHS, RHS)); + Res.first->second = &create(LHS, RHS); return *Res.first->second; } @@ -125,15 +122,14 @@ auto Res = DisjunctionVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS), nullptr); if (Res.second) - Res.first->second = - &takeOwnership(std::make_unique(LHS, RHS)); + Res.first->second = &create(LHS, RHS); return *Res.first->second; } BoolValue &DataflowAnalysisContext::getOrCreateNegation(BoolValue &Val) { auto Res = NegationVals.try_emplace(&Val, nullptr); if (Res.second) - Res.first->second = &takeOwnership(std::make_unique(Val)); + Res.first->second = &create(Val); return *Res.first->second; } @@ -144,8 +140,7 @@ auto Res = ImplicationVals.try_emplace(std::make_pair(&LHS, &RHS), nullptr); if (Res.second) - Res.first->second = - &takeOwnership(std::make_unique(LHS, RHS)); + Res.first->second = &create(LHS, RHS); return *Res.first->second; } @@ -157,8 +152,7 @@ auto Res = BiconditionalVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS), nullptr); if (Res.second) - Res.first->second = - &takeOwnership(std::make_unique(LHS, RHS)); + Res.first->second = &create(LHS, RHS); return *Res.first->second; } diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -359,7 +359,7 @@ QualType ParamType = Param->getType(); if (ParamType->isReferenceType()) { - auto &Val = takeOwnership(std::make_unique(*ArgLoc)); + auto &Val = create(*ArgLoc); setValue(Loc, Val); } else if (auto *ArgVal = getValue(*ArgLoc)) { setValue(Loc, *ArgVal); @@ -685,7 +685,7 @@ // with integers, and so distinguishing them serves no purpose, but could // prevent convergence. CreatedValuesCount++; - return &takeOwnership(std::make_unique()); + return &create(); } if (Type->isReferenceType()) { @@ -702,7 +702,7 @@ setValue(PointeeLoc, *PointeeVal); } - return &takeOwnership(std::make_unique(PointeeLoc)); + return &create(PointeeLoc); } if (Type->isPointerType()) { @@ -719,7 +719,7 @@ setValue(PointeeLoc, *PointeeVal); } - return &takeOwnership(std::make_unique(PointeeLoc)); + return &create(PointeeLoc); } if (Type->isStructureOrClassType() || Type->isUnionType()) { @@ -739,8 +739,7 @@ Visited.erase(FieldType.getCanonicalType()); } - return &takeOwnership( - std::make_unique(std::move(FieldValues))); + return &create(std::move(FieldValues)); } return nullptr; diff --git a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp --- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp +++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp @@ -221,9 +221,9 @@ /// Creates a symbolic value for an `optional` value using `HasValueVal` as the /// symbolic value of its "has_value" property. StructValue &createOptionalValue(Environment &Env, BoolValue &HasValueVal) { - auto OptionalVal = std::make_unique(); - setHasValue(*OptionalVal, HasValueVal); - return Env.takeOwnership(std::move(OptionalVal)); + auto &OptionalVal = Env.create(); + setHasValue(OptionalVal, HasValueVal); + return OptionalVal; } /// Returns the symbolic value that represents the "has_value" property of the @@ -312,8 +312,8 @@ return nullptr; auto &ValueLoc = Env.createStorageLocation(Ty); Env.setValue(ValueLoc, *ValueVal); - auto ValueRef = std::make_unique(ValueLoc); - OptionalVal.setProperty("value", Env.takeOwnership(std::move(ValueRef))); + auto &ValueRef = Env.create(ValueLoc); + OptionalVal.setProperty("value", ValueRef); return &ValueLoc; } diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -237,7 +237,7 @@ Env.setStorageLocation(*S, *DeclLoc); } else { auto &Loc = Env.createStorageLocation(*S); - auto &Val = Env.takeOwnership(std::make_unique(*DeclLoc)); + auto &Val = Env.create(*DeclLoc); Env.setStorageLocation(*S, Loc); Env.setValue(Loc, Val); } @@ -276,8 +276,7 @@ // FIXME: reuse the ReferenceValue instead of creating a new one. if (auto *InitExprLoc = Env.getStorageLocation(*InitExpr, SkipPast::Reference)) { - auto &Val = - Env.takeOwnership(std::make_unique(*InitExprLoc)); + auto &Val = Env.create(*InitExprLoc); Env.setValue(Loc, Val); } } else if (auto *InitExprVal = Env.getValue(*InitExpr, SkipPast::None)) { @@ -423,8 +422,8 @@ auto &Loc = Env.createStorageLocation(*S); Env.setStorageLocation(*S, Loc); - Env.setValue(Loc, Env.takeOwnership(std::make_unique( - SubExprVal->getPointeeLoc()))); + Env.setValue(Loc, + Env.create(SubExprVal->getPointeeLoc())); break; } case UO_AddrOf: { @@ -437,8 +436,7 @@ break; auto &PointerLoc = Env.createStorageLocation(*S); - auto &PointerVal = - Env.takeOwnership(std::make_unique(*PointeeLoc)); + auto &PointerVal = Env.create(*PointeeLoc); Env.setStorageLocation(*S, PointerLoc); Env.setValue(PointerLoc, PointerVal); break; @@ -468,8 +466,7 @@ auto &Loc = Env.createStorageLocation(*S); Env.setStorageLocation(*S, Loc); - Env.setValue(Loc, Env.takeOwnership( - std::make_unique(*ThisPointeeLoc))); + Env.setValue(Loc, Env.create(*ThisPointeeLoc)); } void VisitReturnStmt(const ReturnStmt *S) { @@ -523,8 +520,7 @@ } else { auto &Loc = Env.createStorageLocation(*S); Env.setStorageLocation(*S, Loc); - Env.setValue(Loc, Env.takeOwnership( - std::make_unique(*VarDeclLoc))); + Env.setValue(Loc, Env.create(*VarDeclLoc)); } return; } @@ -558,8 +554,7 @@ } else { auto &Loc = Env.createStorageLocation(*S); Env.setStorageLocation(*S, Loc); - Env.setValue( - Loc, Env.takeOwnership(std::make_unique(MemberLoc))); + Env.setValue(Loc, Env.create(MemberLoc)); } } diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp --- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp +++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp @@ -312,8 +312,7 @@ if (Member->getType()->isReferenceType()) { auto &MemberLoc = ThisLoc.getChild(*Member); - Env.setValue(MemberLoc, Env.takeOwnership(std::make_unique( - *InitStmtLoc))); + Env.setValue(MemberLoc, Env.create(*InitStmtLoc)); } else { auto &MemberLoc = ThisLoc.getChild(*Member); Env.setValue(MemberLoc, *InitStmtVal);