diff options
author | Michael Kruse <llvm@meinersbur.de> | 2018-08-03 01:21:16 +0000 |
---|---|---|
committer | Michael Kruse <llvm@meinersbur.de> | 2018-08-03 01:21:16 +0000 |
commit | dc5ce72afada30ba99a07157703b00b4ae063f40 (patch) | |
tree | a369be5fa866a27497ffd86da9c4edccb096c358 /clang/lib/Sema/SemaOverload.cpp | |
parent | b99281c9b89b9bfae88ca5b998685cfe1ff3641c (diff) | |
download | bcm5719-llvm-dc5ce72afada30ba99a07157703b00b4ae063f40.tar.gz bcm5719-llvm-dc5ce72afada30ba99a07157703b00b4ae063f40.zip |
Append new attributes to the end of an AttributeList.
Recommit of r335084 after revert in r335516.
... instead of prepending it at the beginning (the original behavior
since implemented in r122535 2010-12-23). This builds up an
AttributeList in the the order in which the attributes appear in the
source.
The reverse order caused nodes for attributes in the AST (e.g. LoopHint)
to be in the reverse order, and therefore printed in the wrong order in
-ast-dump. Some TODO comments mention this. The order was explicitly
reversed for enable_if attribute overload resolution and name mangling,
which is not necessary anymore with this patch.
The change unfortunately has some secondary effect, especially on
diagnostic output. In the simplest cases, the CHECK lines or expected
diagnostic were changed to the the new output. If the kind of
error/warning changed, the attributes' order was changed instead.
This unfortunately causes some 'previous occurrence here' hints to be
textually after the main marker. This typically happens when attributes
are merged, but are incompatible to each other. Interchanging the role
of the the main and note SourceLocation will also cause the case where
two different declaration's attributes (in contrast to multiple
attributes of the same declaration) are merged to be reverse. There is
no easy fix because sometimes previous attributes are merged into a new
declaration's attribute list, sometimes new attributes are added to a
previous declaration's attribute list. Since 'previous occurrence here'
pointing to locations after the main marker is not rare, I left the
markers as-is; it is only relevant when the attributes are declared in
the same declaration anyway.
Differential Revision: https://reviews.llvm.org/D48100
llvm-svn: 338800
Diffstat (limited to 'clang/lib/Sema/SemaOverload.cpp')
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 46 |
1 files changed, 12 insertions, 34 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 08af485ef4c..6b0837849b9 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -6215,24 +6215,6 @@ 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, @@ -6306,9 +6288,8 @@ convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg, EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args, bool MissingImplicitThis) { - SmallVector<EnableIfAttr *, 4> EnableIfAttrs = - getOrderedEnableIfAttrs(Function); - if (EnableIfAttrs.empty()) + auto EnableIfAttrs = Function->specific_attrs<EnableIfAttr>(); + if (EnableIfAttrs.begin() == EnableIfAttrs.end()) return nullptr; SFINAETrap Trap(*this); @@ -6318,7 +6299,7 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args, if (!convertArgsForAvailabilityChecks( *this, Function, /*ThisArg=*/nullptr, Args, Trap, /*MissingImplicitThis=*/true, DiscardedThis, ConvertedArgs)) - return EnableIfAttrs[0]; + return *EnableIfAttrs.begin(); for (auto *EIA : EnableIfAttrs) { APValue Result; @@ -8967,24 +8948,21 @@ static Comparison compareEnableIfAttrs(const Sema &S, const FunctionDecl *Cand1, return Cand1Attr ? Comparison::Better : Comparison::Worse; } - // 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 Cand1Attrs = Cand1->specific_attrs<EnableIfAttr>(); + auto Cand2Attrs = Cand2->specific_attrs<EnableIfAttr>(); auto Cand1I = Cand1Attrs.begin(); llvm::FoldingSetNodeID Cand1ID, Cand2ID; - for (auto &Cand2A : Cand2Attrs) { + for (EnableIfAttr *Cand2A : Cand2Attrs) { Cand1ID.clear(); Cand2ID.clear(); - auto &Cand1A = *Cand1I++; + // It's impossible for Cand1 to be better than (or equal to) Cand2 if Cand1 + // has fewer enable_if attributes than Cand2. + auto Cand1A = Cand1I++; + if (Cand1A == Cand1Attrs.end()) + return Comparison::Worse; + Cand1A->getCond()->Profile(Cand1ID, S.getASTContext(), true); Cand2A->getCond()->Profile(Cand2ID, S.getASTContext(), true); if (Cand1ID != Cand2ID) |