1*e5dd7070Spatrick //===--- SelectorLocationsKind.cpp - Kind of selector locations -*- C++ -*-===//
2*e5dd7070Spatrick //
3*e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5*e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*e5dd7070Spatrick //
7*e5dd7070Spatrick //===----------------------------------------------------------------------===//
8*e5dd7070Spatrick //
9*e5dd7070Spatrick // Describes whether the identifier locations for a selector are "standard"
10*e5dd7070Spatrick // or not.
11*e5dd7070Spatrick //
12*e5dd7070Spatrick //===----------------------------------------------------------------------===//
13*e5dd7070Spatrick
14*e5dd7070Spatrick #include "clang/AST/SelectorLocationsKind.h"
15*e5dd7070Spatrick #include "clang/AST/Expr.h"
16*e5dd7070Spatrick
17*e5dd7070Spatrick using namespace clang;
18*e5dd7070Spatrick
getStandardSelLoc(unsigned Index,Selector Sel,bool WithArgSpace,SourceLocation ArgLoc,SourceLocation EndLoc)19*e5dd7070Spatrick static SourceLocation getStandardSelLoc(unsigned Index,
20*e5dd7070Spatrick Selector Sel,
21*e5dd7070Spatrick bool WithArgSpace,
22*e5dd7070Spatrick SourceLocation ArgLoc,
23*e5dd7070Spatrick SourceLocation EndLoc) {
24*e5dd7070Spatrick unsigned NumSelArgs = Sel.getNumArgs();
25*e5dd7070Spatrick if (NumSelArgs == 0) {
26*e5dd7070Spatrick assert(Index == 0);
27*e5dd7070Spatrick if (EndLoc.isInvalid())
28*e5dd7070Spatrick return SourceLocation();
29*e5dd7070Spatrick IdentifierInfo *II = Sel.getIdentifierInfoForSlot(0);
30*e5dd7070Spatrick unsigned Len = II ? II->getLength() : 0;
31*e5dd7070Spatrick return EndLoc.getLocWithOffset(-Len);
32*e5dd7070Spatrick }
33*e5dd7070Spatrick
34*e5dd7070Spatrick assert(Index < NumSelArgs);
35*e5dd7070Spatrick if (ArgLoc.isInvalid())
36*e5dd7070Spatrick return SourceLocation();
37*e5dd7070Spatrick IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Index);
38*e5dd7070Spatrick unsigned Len = /* selector id */ (II ? II->getLength() : 0) + /* ':' */ 1;
39*e5dd7070Spatrick if (WithArgSpace)
40*e5dd7070Spatrick ++Len;
41*e5dd7070Spatrick return ArgLoc.getLocWithOffset(-Len);
42*e5dd7070Spatrick }
43*e5dd7070Spatrick
44*e5dd7070Spatrick namespace {
45*e5dd7070Spatrick
46*e5dd7070Spatrick template <typename T>
47*e5dd7070Spatrick SourceLocation getArgLoc(T* Arg);
48*e5dd7070Spatrick
49*e5dd7070Spatrick template <>
getArgLoc(Expr * Arg)50*e5dd7070Spatrick SourceLocation getArgLoc<Expr>(Expr *Arg) {
51*e5dd7070Spatrick return Arg->getBeginLoc();
52*e5dd7070Spatrick }
53*e5dd7070Spatrick
54*e5dd7070Spatrick template <>
getArgLoc(ParmVarDecl * Arg)55*e5dd7070Spatrick SourceLocation getArgLoc<ParmVarDecl>(ParmVarDecl *Arg) {
56*e5dd7070Spatrick SourceLocation Loc = Arg->getBeginLoc();
57*e5dd7070Spatrick if (Loc.isInvalid())
58*e5dd7070Spatrick return Loc;
59*e5dd7070Spatrick // -1 to point to left paren of the method parameter's type.
60*e5dd7070Spatrick return Loc.getLocWithOffset(-1);
61*e5dd7070Spatrick }
62*e5dd7070Spatrick
63*e5dd7070Spatrick template <typename T>
getArgLoc(unsigned Index,ArrayRef<T * > Args)64*e5dd7070Spatrick SourceLocation getArgLoc(unsigned Index, ArrayRef<T*> Args) {
65*e5dd7070Spatrick return Index < Args.size() ? getArgLoc(Args[Index]) : SourceLocation();
66*e5dd7070Spatrick }
67*e5dd7070Spatrick
68*e5dd7070Spatrick template <typename T>
hasStandardSelLocs(Selector Sel,ArrayRef<SourceLocation> SelLocs,ArrayRef<T * > Args,SourceLocation EndLoc)69*e5dd7070Spatrick SelectorLocationsKind hasStandardSelLocs(Selector Sel,
70*e5dd7070Spatrick ArrayRef<SourceLocation> SelLocs,
71*e5dd7070Spatrick ArrayRef<T *> Args,
72*e5dd7070Spatrick SourceLocation EndLoc) {
73*e5dd7070Spatrick // Are selector locations in standard position with no space between args ?
74*e5dd7070Spatrick unsigned i;
75*e5dd7070Spatrick for (i = 0; i != SelLocs.size(); ++i) {
76*e5dd7070Spatrick if (SelLocs[i] != getStandardSelectorLoc(i, Sel, /*WithArgSpace=*/false,
77*e5dd7070Spatrick Args, EndLoc))
78*e5dd7070Spatrick break;
79*e5dd7070Spatrick }
80*e5dd7070Spatrick if (i == SelLocs.size())
81*e5dd7070Spatrick return SelLoc_StandardNoSpace;
82*e5dd7070Spatrick
83*e5dd7070Spatrick // Are selector locations in standard position with space between args ?
84*e5dd7070Spatrick for (i = 0; i != SelLocs.size(); ++i) {
85*e5dd7070Spatrick if (SelLocs[i] != getStandardSelectorLoc(i, Sel, /*WithArgSpace=*/true,
86*e5dd7070Spatrick Args, EndLoc))
87*e5dd7070Spatrick return SelLoc_NonStandard;
88*e5dd7070Spatrick }
89*e5dd7070Spatrick
90*e5dd7070Spatrick return SelLoc_StandardWithSpace;
91*e5dd7070Spatrick }
92*e5dd7070Spatrick
93*e5dd7070Spatrick } // anonymous namespace
94*e5dd7070Spatrick
95*e5dd7070Spatrick SelectorLocationsKind
hasStandardSelectorLocs(Selector Sel,ArrayRef<SourceLocation> SelLocs,ArrayRef<Expr * > Args,SourceLocation EndLoc)96*e5dd7070Spatrick clang::hasStandardSelectorLocs(Selector Sel,
97*e5dd7070Spatrick ArrayRef<SourceLocation> SelLocs,
98*e5dd7070Spatrick ArrayRef<Expr *> Args,
99*e5dd7070Spatrick SourceLocation EndLoc) {
100*e5dd7070Spatrick return hasStandardSelLocs(Sel, SelLocs, Args, EndLoc);
101*e5dd7070Spatrick }
102*e5dd7070Spatrick
getStandardSelectorLoc(unsigned Index,Selector Sel,bool WithArgSpace,ArrayRef<Expr * > Args,SourceLocation EndLoc)103*e5dd7070Spatrick SourceLocation clang::getStandardSelectorLoc(unsigned Index,
104*e5dd7070Spatrick Selector Sel,
105*e5dd7070Spatrick bool WithArgSpace,
106*e5dd7070Spatrick ArrayRef<Expr *> Args,
107*e5dd7070Spatrick SourceLocation EndLoc) {
108*e5dd7070Spatrick return getStandardSelLoc(Index, Sel, WithArgSpace,
109*e5dd7070Spatrick getArgLoc(Index, Args), EndLoc);
110*e5dd7070Spatrick }
111*e5dd7070Spatrick
112*e5dd7070Spatrick SelectorLocationsKind
hasStandardSelectorLocs(Selector Sel,ArrayRef<SourceLocation> SelLocs,ArrayRef<ParmVarDecl * > Args,SourceLocation EndLoc)113*e5dd7070Spatrick clang::hasStandardSelectorLocs(Selector Sel,
114*e5dd7070Spatrick ArrayRef<SourceLocation> SelLocs,
115*e5dd7070Spatrick ArrayRef<ParmVarDecl *> Args,
116*e5dd7070Spatrick SourceLocation EndLoc) {
117*e5dd7070Spatrick return hasStandardSelLocs(Sel, SelLocs, Args, EndLoc);
118*e5dd7070Spatrick }
119*e5dd7070Spatrick
getStandardSelectorLoc(unsigned Index,Selector Sel,bool WithArgSpace,ArrayRef<ParmVarDecl * > Args,SourceLocation EndLoc)120*e5dd7070Spatrick SourceLocation clang::getStandardSelectorLoc(unsigned Index,
121*e5dd7070Spatrick Selector Sel,
122*e5dd7070Spatrick bool WithArgSpace,
123*e5dd7070Spatrick ArrayRef<ParmVarDecl *> Args,
124*e5dd7070Spatrick SourceLocation EndLoc) {
125*e5dd7070Spatrick return getStandardSelLoc(Index, Sel, WithArgSpace,
126*e5dd7070Spatrick getArgLoc(Index, Args), EndLoc);
127*e5dd7070Spatrick }
128