r307197 - Cope with Range-v3's CONCEPT_REQUIRES idiom

Douglas Gregor via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 5 13:20:16 PDT 2017


Author: dgregor
Date: Wed Jul  5 13:20:15 2017
New Revision: 307197

URL: http://llvm.org/viewvc/llvm-project?rev=307197&view=rev
Log:
Cope with Range-v3's CONCEPT_REQUIRES idiom

Modified:
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/SemaTemplate/overload-candidates.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=307197&r1=307196&r2=307197&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Jul  5 13:20:15 2017
@@ -2831,10 +2831,44 @@ static void collectConjunctionTerms(Expr
   Terms.push_back(Clause);
 }
 
+// The ranges-v3 library uses an odd pattern of a top-level "||" with
+// a left-hand side that is value-dependent but never true. Identify
+// the idiom and ignore that term.
+static Expr *lookThroughRangesV3Condition(Preprocessor &PP, Expr *Cond) {
+  // Top-level '||'.
+  auto *BinOp = dyn_cast<BinaryOperator>(Cond->IgnoreParenImpCasts());
+  if (!BinOp) return Cond;
+
+  if (BinOp->getOpcode() != BO_LOr) return Cond;
+
+  // With an inner '==' that has a literal on the right-hand side.
+  Expr *LHS = BinOp->getLHS();
+  auto InnerBinOp = dyn_cast<BinaryOperator>(LHS->IgnoreParenImpCasts());
+  if (!InnerBinOp) return Cond;
+
+  if (InnerBinOp->getOpcode() != BO_EQ ||
+      !isa<IntegerLiteral>(InnerBinOp->getRHS()))
+    return Cond;
+
+  // If the inner binary operation came from a macro expansion named
+  // CONCEPT_REQUIRES or CONCEPT_REQUIRES_, return the right-hand side
+  // of the '||', which is the real, user-provided condition.
+  auto Loc = InnerBinOp->getExprLoc();
+  if (!Loc.isMacroID()) return Cond;
+
+  StringRef MacroName = PP.getImmediateMacroName(Loc);
+  if (MacroName == "CONCEPT_REQUIRES" || MacroName == "CONCEPT_REQUIRES_")
+    return BinOp->getRHS();
+
+  return Cond;
+}
+
 /// Find the failed subexpression within enable_if, and describe it
 /// with a string.
 static std::pair<Expr *, std::string>
 findFailedEnableIfCondition(Sema &S, Expr *Cond) {
+  Cond = lookThroughRangesV3Condition(S.PP, Cond);
+
   // Separate out all of the terms in a conjunction.
   SmallVector<Expr *, 4> Terms;
   collectConjunctionTerms(Cond, Terms);

Modified: cfe/trunk/test/SemaTemplate/overload-candidates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/overload-candidates.cpp?rev=307197&r1=307196&r2=307197&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/overload-candidates.cpp (original)
+++ cfe/trunk/test/SemaTemplate/overload-candidates.cpp Wed Jul  5 13:20:15 2017
@@ -137,4 +137,30 @@ namespace PR15673 {
 #endif
   void wibble() {}
   void wobble() { wibble<int>(); } // expected-error {{no matching function for call to 'wibble'}}
+
+  template<typename T>
+  struct some_passing_trait : std::true_type {};
+
+#if __cplusplus <= 199711L
+  // expected-warning at +4 {{default template arguments for a function template are a C++11 extension}}
+  // expected-warning at +4 {{default template arguments for a function template are a C++11 extension}}
+#endif
+  template<typename T,
+           int n = 42,
+           typename std::enable_if<n == 43 || (some_passing_trait<T>::value && some_trait<T>::value), int>::type = 0>
+  void almost_rangesv3(); // expected-note{{candidate template ignored: requirement '42 == 43 || (some_passing_trait<int>::value && some_trait<int>::value)' was not satisfied}}
+  void test_almost_rangesv3() { almost_rangesv3<int>(); } // expected-error{{no matching function for call to 'almost_rangesv3'}}
+
+  #define CONCEPT_REQUIRES_(...)                                        \
+    int x = 42,                                                         \
+    typename std::enable_if<(x == 43) || (__VA_ARGS__)>::type = 0
+
+#if __cplusplus <= 199711L
+  // expected-warning at +4 {{default template arguments for a function template are a C++11 extension}}
+  // expected-warning at +4 {{default template arguments for a function template are a C++11 extension}}
+#endif
+  template<typename T,
+           CONCEPT_REQUIRES_(some_passing_trait<T>::value && some_trait<T>::value)>
+  void rangesv3(); // expected-note{{candidate template ignored: requirement 'some_trait<int>::value' was not satisfied [with T = int, x = 42]}}
+  void test_rangesv3() { rangesv3<int>(); } // expected-error{{no matching function for call to 'rangesv3'}}
 }




More information about the cfe-commits mailing list