29
29
#include " clang/Lex/Preprocessor.h"
30
30
#include " llvm/ADT/APInt.h"
31
31
#include " llvm/ADT/APSInt.h"
32
+ #include " llvm/ADT/PointerIntPair.h"
32
33
#include " llvm/ADT/STLFunctionalExtras.h"
33
34
#include " llvm/ADT/SmallSet.h"
34
35
#include " llvm/ADT/SmallVector.h"
@@ -426,8 +427,9 @@ const Expr *findCountArg(const Expr *Count, const CallExpr *Call) {
426
427
return Call->getArg (Index);
427
428
}
428
429
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 *>;
431
433
432
434
// Given the call expr, find the mapping from the dependent parameter to the
433
435
// argument that is passed to that parameter.
@@ -445,7 +447,8 @@ getDependentValuesFromCall(const CountAttributedType *CAT,
445
447
return std::nullopt ;
446
448
447
449
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 ;
449
452
assert (Inserted);
450
453
}
451
454
return {std::move (Values)};
@@ -499,50 +502,57 @@ struct CompatibleCountExprVisitor
499
502
const Expr *
500
503
trySubstituteAndSimplify (const Expr *E, bool &hasBeenSubstituted,
501
504
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
+
502
512
// Attempts to simplify `E`: if `E` has the form `*&e`, return `e`;
503
513
// 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 * {
509
515
const auto *Deref = dyn_cast<UnaryOperator>(E->IgnoreParenImpCasts ());
510
516
511
517
if (!Deref || Deref->getOpcode () != UO_Deref)
512
518
return E;
513
519
514
520
const Expr *DerefOperand = Deref->getSubExpr ()->IgnoreParenImpCasts ();
515
521
522
+ // Just simplify `*&...`.
516
523
if (const auto *UO = dyn_cast<UnaryOperator>(DerefOperand))
517
524
if (UO->getOpcode () == UO_AddrOf)
518
525
return UO->getSubExpr ();
526
+
519
527
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
+ }
531
543
}
544
+
532
545
return E;
533
546
};
534
547
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);
543
552
}
544
553
}
545
- return trySimplifyDerefAddressof (E, DependentValues, hasBeenSubstituted);
554
+
555
+ return trySimplifyDeref (E);
546
556
}
547
557
548
558
explicit CompatibleCountExprVisitor (
@@ -673,6 +683,13 @@ struct CompatibleCountExprVisitor
673
683
bool hasOtherBeenSubstituted) {
674
684
if (SelfUO->getOpcode () != UO_Deref)
675
685
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
+
676
693
Other = trySubstituteAndSimplify (Other, hasOtherBeenSubstituted,
677
694
DependentValuesOther);
678
695
if (const auto *OtherUO =
@@ -681,13 +698,7 @@ struct CompatibleCountExprVisitor
681
698
return Visit (SelfUO->getSubExpr (), OtherUO->getSubExpr (),
682
699
hasSelfBeenSubstituted, hasOtherBeenSubstituted);
683
700
}
684
- // If `Other` is not a dereference expression, try to simplify `SelfUO`:
685
- const auto *SimplifiedSelf = trySubstituteAndSimplify (
686
- SelfUO, hasSelfBeenSubstituted, DependentValuesSelf);
687
701
688
- if (SimplifiedSelf != SelfUO)
689
- return Visit (SimplifiedSelf, Other, hasSelfBeenSubstituted,
690
- hasOtherBeenSubstituted);
691
702
return false ;
692
703
}
693
704
0 commit comments