Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 6907b98

Browse files
committed
Cope with Range-v3's CONCEPT_REQUIRES idiom
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@307197 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent d93c41c commit 6907b98

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

lib/Sema/SemaTemplate.cpp

+34
Original file line numberDiff line numberDiff line change
@@ -2831,10 +2831,44 @@ static void collectConjunctionTerms(Expr *Clause,
28312831
Terms.push_back(Clause);
28322832
}
28332833

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+
28342866
/// Find the failed subexpression within enable_if, and describe it
28352867
/// with a string.
28362868
static std::pair<Expr *, std::string>
28372869
findFailedEnableIfCondition(Sema &S, Expr *Cond) {
2870+
Cond = lookThroughRangesV3Condition(S.PP, Cond);
2871+
28382872
// Separate out all of the terms in a conjunction.
28392873
SmallVector<Expr *, 4> Terms;
28402874
collectConjunctionTerms(Cond, Terms);

test/SemaTemplate/overload-candidates.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -137,4 +137,30 @@ namespace PR15673 {
137137
#endif
138138
void wibble() {}
139139
void wobble() { wibble<int>(); } // expected-error {{no matching function for call to 'wibble'}}
140+
141+
template<typename T>
142+
struct some_passing_trait : std::true_type {};
143+
144+
#if __cplusplus <= 199711L
145+
// expected-warning@+4 {{default template arguments for a function template are a C++11 extension}}
146+
// expected-warning@+4 {{default template arguments for a function template are a C++11 extension}}
147+
#endif
148+
template<typename T,
149+
int n = 42,
150+
typename std::enable_if<n == 43 || (some_passing_trait<T>::value && some_trait<T>::value), int>::type = 0>
151+
void almost_rangesv3(); // expected-note{{candidate template ignored: requirement '42 == 43 || (some_passing_trait<int>::value && some_trait<int>::value)' was not satisfied}}
152+
void test_almost_rangesv3() { almost_rangesv3<int>(); } // expected-error{{no matching function for call to 'almost_rangesv3'}}
153+
154+
#define CONCEPT_REQUIRES_(...) \
155+
int x = 42, \
156+
typename std::enable_if<(x == 43) || (__VA_ARGS__)>::type = 0
157+
158+
#if __cplusplus <= 199711L
159+
// expected-warning@+4 {{default template arguments for a function template are a C++11 extension}}
160+
// expected-warning@+4 {{default template arguments for a function template are a C++11 extension}}
161+
#endif
162+
template<typename T,
163+
CONCEPT_REQUIRES_(some_passing_trait<T>::value && some_trait<T>::value)>
164+
void rangesv3(); // expected-note{{candidate template ignored: requirement 'some_trait<int>::value' was not satisfied [with T = int, x = 42]}}
165+
void test_rangesv3() { rangesv3<int>(); } // expected-error{{no matching function for call to 'rangesv3'}}
140166
}

0 commit comments

Comments
 (0)