@@ -2544,6 +2544,19 @@ Stmt *BlockExpr::getBody() {
25442544// ===----------------------------------------------------------------------===//
25452545// Generic Expression Routines
25462546// ===----------------------------------------------------------------------===//
2547+ namespace {
2548+ // / Helper to determine wether \c E is a CXXConstructExpr constructing
2549+ // / a DecompositionDecl. Used to skip Clang-generated calls to std::get
2550+ // / for structured bindings.
2551+ bool IsDecompositionDeclRefExpr (const Expr *E) {
2552+ const Expr *Unrwapped = E->IgnoreUnlessSpelledInSource ();
2553+ const DeclRefExpr *Ref = llvm::dyn_cast_or_null<DeclRefExpr>(Unrwapped);
2554+ if (!Ref)
2555+ return false ;
2556+
2557+ return llvm::isa_and_nonnull<DecompositionDecl *>(Ref->getDecl ());
2558+ }
2559+ } // namespace
25472560
25482561bool Expr::isReadIfDiscardedInCPlusPlus11 () const {
25492562 // In C++11, discarded-value expressions of a certain form are special,
@@ -3163,15 +3176,28 @@ Expr *Expr::IgnoreUnlessSpelledInSource() {
31633176 // Used when Clang generates calls to std::get for decomposing
31643177 // structured bindings.
31653178 auto IgnoreImplicitCallSingleStep = [](Expr *E) {
3166- if (auto *C = dyn_cast<CallExpr>(E)) {
3167- auto NumArgs = C->getNumArgs ();
3168- if (NumArgs == 1 ||
3169- (NumArgs > 1 && isa<CXXDefaultArgExpr>(C->getArg (1 )))) {
3170- Expr *A = C->getArg (0 );
3171- if (A->getSourceRange () == E->getSourceRange ())
3172- return A;
3173- }
3174- }
3179+ auto *C = dyn_cast<CallExpr>(E);
3180+ if (!C)
3181+ return E;
3182+
3183+ // Looking for calls to a std::get, which usually just takes
3184+ // 1 argument (i.e., the structure being decomposed). If it has
3185+ // more than 1 argument, the others need to be defaulted.
3186+ unsigned NumArgs = C->getNumArgs ();
3187+ if (NumArgs > 1 && !isa<CXXDefaultArgExpr>(C->getArg (1 )))
3188+ return E;
3189+
3190+ Expr *A = C->getArg (0 );
3191+
3192+ // This was spelled out in source. Don't ignore.
3193+ if (A->getSourceRange () != E->getSourceRange ())
3194+ return E;
3195+
3196+ // If the argument refers to a DecompositionDecl construction,
3197+ // ignore it.
3198+ if (IsDecompositionDeclRefExpr (A))
3199+ return A;
3200+
31753201 return E;
31763202 };
31773203
0 commit comments