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 17 using namespace clang; 18 19 static 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 44 namespace { 45 46 template <typename T> 47 SourceLocation getArgLoc(T* Arg); 48 49 template <> 50 SourceLocation getArgLoc<Expr>(Expr *Arg) { 51 return Arg->getBeginLoc(); 52 } 53 54 template <> 55 SourceLocation 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 63 template <typename T> 64 SourceLocation getArgLoc(unsigned Index, ArrayRef<T*> Args) { 65 return Index < Args.size() ? getArgLoc(Args[Index]) : SourceLocation(); 66 } 67 68 template <typename T> 69 SelectorLocationsKind 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 95 SelectorLocationsKind 96 clang::hasStandardSelectorLocs(Selector Sel, 97 ArrayRef<SourceLocation> SelLocs, 98 ArrayRef<Expr *> Args, 99 SourceLocation EndLoc) { 100 return hasStandardSelLocs(Sel, SelLocs, Args, EndLoc); 101 } 102 103 SourceLocation 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 112 SelectorLocationsKind 113 clang::hasStandardSelectorLocs(Selector Sel, 114 ArrayRef<SourceLocation> SelLocs, 115 ArrayRef<ParmVarDecl *> Args, 116 SourceLocation EndLoc) { 117 return hasStandardSelLocs(Sel, SelLocs, Args, EndLoc); 118 } 119 120 SourceLocation 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