|
@@ -6189,6 +6189,24 @@ Sema::SelectBestMethod(Selector Sel, MultiExprArg Args, bool IsInstance,
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
+// specific_attr_iterator iterates over enable_if attributes in reverse, and
|
|
|
+// enable_if is order-sensitive. As a result, we need to reverse things
|
|
|
+// sometimes. Size of 4 elements is arbitrary.
|
|
|
+static SmallVector<EnableIfAttr *, 4>
|
|
|
+getOrderedEnableIfAttrs(const FunctionDecl *Function) {
|
|
|
+ SmallVector<EnableIfAttr *, 4> Result;
|
|
|
+ if (!Function->hasAttrs())
|
|
|
+ return Result;
|
|
|
+
|
|
|
+ const auto &FuncAttrs = Function->getAttrs();
|
|
|
+ for (Attr *Attr : FuncAttrs)
|
|
|
+ if (auto *EnableIf = dyn_cast<EnableIfAttr>(Attr))
|
|
|
+ Result.push_back(EnableIf);
|
|
|
+
|
|
|
+ std::reverse(Result.begin(), Result.end());
|
|
|
+ return Result;
|
|
|
+}
|
|
|
+
|
|
|
static bool
|
|
|
convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg,
|
|
|
ArrayRef<Expr *> Args, Sema::SFINAETrap &Trap,
|
|
@@ -6262,9 +6280,9 @@ convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg,
|
|
|
|
|
|
EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
|
|
|
bool MissingImplicitThis) {
|
|
|
- auto EnableIfAttrs = Function->specific_attrs<EnableIfAttr>();
|
|
|
-
|
|
|
- if (EnableIfAttrs.begin() == EnableIfAttrs.end())
|
|
|
+ SmallVector<EnableIfAttr *, 4> EnableIfAttrs =
|
|
|
+ getOrderedEnableIfAttrs(Function);
|
|
|
+ if (EnableIfAttrs.empty())
|
|
|
return nullptr;
|
|
|
|
|
|
SFINAETrap Trap(*this);
|
|
@@ -6274,7 +6292,7 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
|
|
|
if (!convertArgsForAvailabilityChecks(
|
|
|
*this, Function, /*ThisArg=*/nullptr, Args, Trap,
|
|
|
/*MissingImplicitThis=*/true, DiscardedThis, ConvertedArgs))
|
|
|
- return *EnableIfAttrs.begin();
|
|
|
+ return EnableIfAttrs[0];
|
|
|
|
|
|
for (auto *EIA : EnableIfAttrs) {
|
|
|
APValue Result;
|
|
@@ -8923,21 +8941,24 @@ static Comparison compareEnableIfAttrs(const Sema &S, const FunctionDecl *Cand1,
|
|
|
return Cand1Attr ? Comparison::Better : Comparison::Worse;
|
|
|
}
|
|
|
|
|
|
- auto Cand1Attrs = Cand1->specific_attrs<EnableIfAttr>();
|
|
|
- auto Cand2Attrs = Cand2->specific_attrs<EnableIfAttr>();
|
|
|
+ // FIXME: The next several lines are just
|
|
|
+ // specific_attr_iterator<EnableIfAttr> but going in declaration order,
|
|
|
+ // instead of reverse order which is how they're stored in the AST.
|
|
|
+ auto Cand1Attrs = getOrderedEnableIfAttrs(Cand1);
|
|
|
+ auto Cand2Attrs = getOrderedEnableIfAttrs(Cand2);
|
|
|
+
|
|
|
+ // It's impossible for Cand1 to be better than (or equal to) Cand2 if Cand1
|
|
|
+ // has fewer enable_if attributes than Cand2.
|
|
|
+ if (Cand1Attrs.size() < Cand2Attrs.size())
|
|
|
+ return Comparison::Worse;
|
|
|
|
|
|
auto Cand1I = Cand1Attrs.begin();
|
|
|
llvm::FoldingSetNodeID Cand1ID, Cand2ID;
|
|
|
- for (auto Cand2A : Cand2Attrs) {
|
|
|
+ for (auto &Cand2A : Cand2Attrs) {
|
|
|
Cand1ID.clear();
|
|
|
Cand2ID.clear();
|
|
|
|
|
|
- // It's impossible for Cand1 to be better than (or equal to) Cand2 if Cand1
|
|
|
- // has fewer enable_if attributes than Cand2.
|
|
|
- if (Cand1I == Cand1Attrs.end())
|
|
|
- return Comparison::Worse;
|
|
|
- auto Cand1A = Cand1I++;
|
|
|
-
|
|
|
+ auto &Cand1A = *Cand1I++;
|
|
|
Cand1A->getCond()->Profile(Cand1ID, S.getASTContext(), true);
|
|
|
Cand2A->getCond()->Profile(Cand2ID, S.getASTContext(), true);
|
|
|
if (Cand1ID != Cand2ID)
|