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