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