diff options
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 47 | 
1 files changed, 34 insertions, 13 deletions
| diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 34ac5c16470..d730bb27a1f 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -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) | 

