diff options
author | Douglas Gregor <dgregor@apple.com> | 2017-07-05 20:20:15 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2017-07-05 20:20:15 +0000 |
commit | bb33f570455e7017a18f2ff6e3d2383b211f7e3d (patch) | |
tree | cf79e1a4b6fe5dced0096141e48a4d8e95bb2a0e /clang/lib/Sema/SemaTemplate.cpp | |
parent | 00fa10b43f25d98e88cc81b653dfe8d49327722d (diff) | |
download | bcm5719-llvm-bb33f570455e7017a18f2ff6e3d2383b211f7e3d.tar.gz bcm5719-llvm-bb33f570455e7017a18f2ff6e3d2383b211f7e3d.zip |
Cope with Range-v3's CONCEPT_REQUIRES idiom
llvm-svn: 307197
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 58614322f76..1485b80cf95 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -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); |