@@ -32,10 +32,10 @@ bool IsFlatVec(clang::QualType type) {
3232}
3333
3434// Whether decl may be stored without a Value, if its address is not taken:
35- // scalars, arrays of non-arrays, user-defined structs, unique_ptrs and
36- // vectors , unless they have a destructor, which is called with a pointer to
37- // them.
38- bool CanUnbox (const clang::VarDecl *decl) {
35+ // scalars, arrays of non-arrays, user-defined structs, unique_ptrs, vectors
36+ // and iterators translated to pointers , unless they have a destructor, which
37+ // is called with a pointer to them.
38+ bool CanUnbox (clang::ASTContext &ctx, const clang::VarDecl *decl) {
3939 auto type = decl->getType ();
4040 if (IsFlatVec (type)) {
4141 // Vectors are flat Vecs.
@@ -44,7 +44,8 @@ bool CanUnbox(const clang::VarDecl *decl) {
4444 return false ;
4545 }
4646 } else if (type->isStructureOrClassType ()) {
47- if ((!IsUserDefinedDecl (type->getAsRecordDecl ()) && !IsUniquePtr (type)) ||
47+ if ((!IsUserDefinedDecl (type->getAsRecordDecl ()) && !IsUniquePtr (type) &&
48+ !RuleRegistry::MapsToRefcountPointer (ctx, type)) ||
4849 TypeNeedsDestruction (type)) {
4950 return false ;
5051 }
@@ -194,7 +195,8 @@ class AddressTakenVisitor
194195
195196private:
196197 // The arguments of a call translated by a rule are passed by value or
197- // borrowed, unless the rule takes a pointer to them.
198+ // borrowed, unless the rule takes a pointer to them. A pointer parameter
199+ // receives the value of an argument that is itself translated to a pointer.
198200 void AddRuleArgs (clang::Expr *expr, clang::Expr **args, unsigned num_args) {
199201 auto *rule = RuleRegistry::GetExprRule (ctx_, expr);
200202 if (!rule) {
@@ -203,8 +205,10 @@ class AddressTakenVisitor
203205 // Variadic arguments are not considered.
204206 auto all_args = BuildUnifiedArgs (expr, args, num_args);
205207 for (unsigned i = 0 ; i < all_args.size () && i < rule->params .size (); ++i) {
206- if (!rule->params [i].is_pointer ()) {
207- AddValueUse (IgnoreNoOpCasts (all_args[i]));
208+ auto *arg = IgnoreNoOpCasts (all_args[i]);
209+ if (!rule->params [i].is_pointer () || arg->getType ()->isPointerType () ||
210+ RuleRegistry::MapsToPointer (ctx_, arg->getType ())) {
211+ AddValueUse (arg);
208212 }
209213 }
210214 }
@@ -213,7 +217,14 @@ class AddressTakenVisitor
213217 // without making a pointer to it.
214218 void AddValueUse (clang::Expr *expr, bool write = false ) {
215219 expr = expr->IgnoreParens ();
216- if (auto *member = clang::dyn_cast<clang::MemberExpr>(expr)) {
220+ // The value of a conditional lvalue is the value of either operand; it is
221+ // written through a pointer to the operand.
222+ if (auto *cond = clang::dyn_cast<clang::ConditionalOperator>(expr)) {
223+ if (!write) {
224+ AddValueUse (cond->getTrueExpr ());
225+ AddValueUse (cond->getFalseExpr ());
226+ }
227+ } else if (auto *member = clang::dyn_cast<clang::MemberExpr>(expr)) {
217228 auto *field = clang::dyn_cast<clang::FieldDecl>(member->getMemberDecl ());
218229 // A union member is accessed through a pointer to the union.
219230 if (!member->isArrow () && field && !field->getParent ()->isUnion ()) {
@@ -244,7 +255,7 @@ class AddressTakenVisitor
244255
245256 void AddressTaken (const clang::ValueDecl *decl) {
246257 if (auto *var = clang::dyn_cast<clang::VarDecl>(decl);
247- var && CanUnbox (var)) {
258+ var && CanUnbox (ctx_, var)) {
248259 address_taken_.insert (var);
249260 }
250261 }
@@ -256,13 +267,13 @@ class AddressTakenVisitor
256267};
257268} // namespace
258269
259- BoxedVars::BoxedVars (clang::ASTContext &ctx) {
270+ BoxedVars::BoxedVars (clang::ASTContext &ctx) : ctx_(ctx) {
260271 AddressTakenVisitor (ctx, address_taken_)
261272 .TraverseDecl (ctx.getTranslationUnitDecl ());
262273}
263274
264275bool BoxedVars::contains (const clang::VarDecl *decl) const {
265- return !CanUnbox (decl) || address_taken_.contains (decl);
276+ return !CanUnbox (ctx_, decl) || address_taken_.contains (decl);
266277}
267278
268279namespace {
0 commit comments