2929#include " clang/Lex/Preprocessor.h"
3030#include " llvm/ADT/APInt.h"
3131#include " llvm/ADT/APSInt.h"
32+ #include " llvm/ADT/PointerIntPair.h"
3233#include " llvm/ADT/STLFunctionalExtras.h"
3334#include " llvm/ADT/SmallSet.h"
3435#include " llvm/ADT/SmallVector.h"
@@ -426,8 +427,9 @@ const Expr *findCountArg(const Expr *Count, const CallExpr *Call) {
426427 return Call->getArg (Index);
427428}
428429
429- // Mapping: dependent decl -> value.
430- using DependentValuesTy = llvm::DenseMap<const ValueDecl *, const Expr *>;
430+ // Mapping: (DependentDecl, Deref) -> Value.
431+ using DeclDerefPair = llvm::PointerIntPair<const ValueDecl *, 1 , bool >;
432+ using DependentValuesTy = llvm::DenseMap<DeclDerefPair, const Expr *>;
431433
432434// Given the call expr, find the mapping from the dependent parameter to the
433435// argument that is passed to that parameter.
@@ -445,7 +447,8 @@ getDependentValuesFromCall(const CountAttributedType *CAT,
445447 return std::nullopt ;
446448
447449 const Expr *Arg = Call->getArg (Index);
448- [[maybe_unused]] bool Inserted = Values.insert ({PVD, Arg}).second ;
450+ [[maybe_unused]] bool Inserted =
451+ Values.insert ({{PVD, /* Deref=*/ false }, Arg}).second ;
449452 assert (Inserted);
450453 }
451454 return {std::move (Values)};
@@ -499,50 +502,57 @@ struct CompatibleCountExprVisitor
499502 const Expr *
500503 trySubstituteAndSimplify (const Expr *E, bool &hasBeenSubstituted,
501504 const DependentValuesTy *DependentValues) const {
505+ auto trySubstitute = [&](const ValueDecl *VD, bool Deref) -> const Expr * {
506+ if (hasBeenSubstituted || !DependentValues)
507+ return nullptr ;
508+ auto It = DependentValues->find ({VD, Deref});
509+ return It != DependentValues->end () ? It->second : nullptr ;
510+ };
511+
502512 // Attempts to simplify `E`: if `E` has the form `*&e`, return `e`;
503513 // return `E` without change otherwise:
504- auto trySimplifyDerefAddressof =
505- [](const Expr *E,
506- const DependentValuesTy
507- *DependentValues, // Deref may need subsitution
508- bool &hasBeenSubstituted) -> const Expr * {
514+ auto trySimplifyDeref = [&](const Expr *E) -> const Expr * {
509515 const auto *Deref = dyn_cast<UnaryOperator>(E->IgnoreParenImpCasts ());
510516
511517 if (!Deref || Deref->getOpcode () != UO_Deref)
512518 return E;
513519
514520 const Expr *DerefOperand = Deref->getSubExpr ()->IgnoreParenImpCasts ();
515521
522+ // Just simplify `*&...`.
516523 if (const auto *UO = dyn_cast<UnaryOperator>(DerefOperand))
517524 if (UO->getOpcode () == UO_AddrOf)
518525 return UO->getSubExpr ();
526+
519527 if (const auto *DRE = dyn_cast<DeclRefExpr>(DerefOperand)) {
520- if (!DependentValues || hasBeenSubstituted)
521- return E;
522-
523- if (auto I = DependentValues->find (DRE->getDecl ());
524- I != DependentValues->end ())
525- if (const auto *UO = dyn_cast<UnaryOperator>(
526- I->getSecond ()->IgnoreParenImpCasts ()))
527- if (UO->getOpcode () == UO_AddrOf) {
528- hasBeenSubstituted = true ;
529- return UO->getSubExpr ();
530- }
528+ // Substitute `*x`.
529+ if (const auto *Sub = trySubstitute (DRE->getDecl (), /* Deref=*/ true )) {
530+ hasBeenSubstituted = true ;
531+ return Sub;
532+ }
533+
534+ // Substitute `x` in `*x` if we have `x -> &...` in our mapping.
535+ if (const auto *Sub = trySubstitute (DRE->getDecl (), /* Deref=*/ false )) {
536+ if (const auto *UO =
537+ dyn_cast<UnaryOperator>(Sub->IgnoreParenImpCasts ());
538+ UO && UO->getOpcode () == UO_AddrOf) {
539+ hasBeenSubstituted = true ;
540+ return UO->getSubExpr ();
541+ }
542+ }
531543 }
544+
532545 return E;
533546 };
534547
535- if (!hasBeenSubstituted && DependentValues) {
536- if (const auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts ())) {
537- if (auto It = DependentValues->find (DRE->getDecl ());
538- It != DependentValues->end ()) {
539- hasBeenSubstituted = true ;
540- return trySimplifyDerefAddressof (It->second , nullptr ,
541- hasBeenSubstituted);
542- }
548+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts ())) {
549+ if (const auto *Sub = trySubstitute (DRE->getDecl (), /* Deref=*/ false )) {
550+ hasBeenSubstituted = true ;
551+ return trySimplifyDeref (Sub);
543552 }
544553 }
545- return trySimplifyDerefAddressof (E, DependentValues, hasBeenSubstituted);
554+
555+ return trySimplifyDeref (E);
546556 }
547557
548558 explicit CompatibleCountExprVisitor (
@@ -673,6 +683,13 @@ struct CompatibleCountExprVisitor
673683 bool hasOtherBeenSubstituted) {
674684 if (SelfUO->getOpcode () != UO_Deref)
675685 return false ; // We don't support any other unary operator
686+
687+ const auto *SimplifiedSelf = trySubstituteAndSimplify (
688+ SelfUO, hasSelfBeenSubstituted, DependentValuesSelf);
689+ if (SimplifiedSelf != SelfUO)
690+ return Visit (SimplifiedSelf, Other, hasSelfBeenSubstituted,
691+ hasOtherBeenSubstituted);
692+
676693 Other = trySubstituteAndSimplify (Other, hasOtherBeenSubstituted,
677694 DependentValuesOther);
678695 if (const auto *OtherUO =
@@ -681,13 +698,7 @@ struct CompatibleCountExprVisitor
681698 return Visit (SelfUO->getSubExpr (), OtherUO->getSubExpr (),
682699 hasSelfBeenSubstituted, hasOtherBeenSubstituted);
683700 }
684- // If `Other` is not a dereference expression, try to simplify `SelfUO`:
685- const auto *SimplifiedSelf = trySubstituteAndSimplify (
686- SelfUO, hasSelfBeenSubstituted, DependentValuesSelf);
687701
688- if (SimplifiedSelf != SelfUO)
689- return Visit (SimplifiedSelf, Other, hasSelfBeenSubstituted,
690- hasOtherBeenSubstituted);
691702 return false ;
692703 }
693704
0 commit comments