Cope with Range-v3's CONCEPT_REQUIRES idiom
llvm-svn: 307197
This commit is contained in:
parent
00fa10b43f
commit
bb33f57045
|
@ -2831,10 +2831,44 @@ static void collectConjunctionTerms(Expr *Clause,
|
|||
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);
|
||||
|
|
|
@ -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@+4 {{default template arguments for a function template are a C++11 extension}}
|
||||
// expected-warning@+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@+4 {{default template arguments for a function template are a C++11 extension}}
|
||||
// expected-warning@+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'}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue