@@ -2831,10 +2831,44 @@ static void collectConjunctionTerms(Expr *Clause,
2831
2831
Terms.push_back (Clause);
2832
2832
}
2833
2833
2834
+ // The ranges-v3 library uses an odd pattern of a top-level "||" with
2835
+ // a left-hand side that is value-dependent but never true. Identify
2836
+ // the idiom and ignore that term.
2837
+ static Expr *lookThroughRangesV3Condition (Preprocessor &PP, Expr *Cond) {
2838
+ // Top-level '||'.
2839
+ auto *BinOp = dyn_cast<BinaryOperator>(Cond->IgnoreParenImpCasts ());
2840
+ if (!BinOp) return Cond;
2841
+
2842
+ if (BinOp->getOpcode () != BO_LOr) return Cond;
2843
+
2844
+ // With an inner '==' that has a literal on the right-hand side.
2845
+ Expr *LHS = BinOp->getLHS ();
2846
+ auto InnerBinOp = dyn_cast<BinaryOperator>(LHS->IgnoreParenImpCasts ());
2847
+ if (!InnerBinOp) return Cond;
2848
+
2849
+ if (InnerBinOp->getOpcode () != BO_EQ ||
2850
+ !isa<IntegerLiteral>(InnerBinOp->getRHS ()))
2851
+ return Cond;
2852
+
2853
+ // If the inner binary operation came from a macro expansion named
2854
+ // CONCEPT_REQUIRES or CONCEPT_REQUIRES_, return the right-hand side
2855
+ // of the '||', which is the real, user-provided condition.
2856
+ auto Loc = InnerBinOp->getExprLoc ();
2857
+ if (!Loc.isMacroID ()) return Cond;
2858
+
2859
+ StringRef MacroName = PP.getImmediateMacroName (Loc);
2860
+ if (MacroName == " CONCEPT_REQUIRES" || MacroName == " CONCEPT_REQUIRES_" )
2861
+ return BinOp->getRHS ();
2862
+
2863
+ return Cond;
2864
+ }
2865
+
2834
2866
// / Find the failed subexpression within enable_if, and describe it
2835
2867
// / with a string.
2836
2868
static std::pair<Expr *, std::string>
2837
2869
findFailedEnableIfCondition (Sema &S, Expr *Cond) {
2870
+ Cond = lookThroughRangesV3Condition (S.PP , Cond);
2871
+
2838
2872
// Separate out all of the terms in a conjunction.
2839
2873
SmallVector<Expr *, 4 > Terms;
2840
2874
collectConjunctionTerms (Cond, Terms);
0 commit comments