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