10b57cec5SDimitry Andric //===--- SelectorLocationsKind.cpp - Kind of selector locations -*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Describes whether the identifier locations for a selector are "standard" 100b57cec5SDimitry Andric // or not. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "clang/AST/SelectorLocationsKind.h" 150b57cec5SDimitry Andric #include "clang/AST/Expr.h" 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric using namespace clang; 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric static SourceLocation getStandardSelLoc(unsigned Index, 200b57cec5SDimitry Andric Selector Sel, 210b57cec5SDimitry Andric bool WithArgSpace, 220b57cec5SDimitry Andric SourceLocation ArgLoc, 230b57cec5SDimitry Andric SourceLocation EndLoc) { 240b57cec5SDimitry Andric unsigned NumSelArgs = Sel.getNumArgs(); 250b57cec5SDimitry Andric if (NumSelArgs == 0) { 260b57cec5SDimitry Andric assert(Index == 0); 270b57cec5SDimitry Andric if (EndLoc.isInvalid()) 280b57cec5SDimitry Andric return SourceLocation(); 29*0fca6ea1SDimitry Andric const IdentifierInfo *II = Sel.getIdentifierInfoForSlot(0); 300b57cec5SDimitry Andric unsigned Len = II ? II->getLength() : 0; 310b57cec5SDimitry Andric return EndLoc.getLocWithOffset(-Len); 320b57cec5SDimitry Andric } 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric assert(Index < NumSelArgs); 350b57cec5SDimitry Andric if (ArgLoc.isInvalid()) 360b57cec5SDimitry Andric return SourceLocation(); 37*0fca6ea1SDimitry Andric const IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Index); 380b57cec5SDimitry Andric unsigned Len = /* selector id */ (II ? II->getLength() : 0) + /* ':' */ 1; 390b57cec5SDimitry Andric if (WithArgSpace) 400b57cec5SDimitry Andric ++Len; 410b57cec5SDimitry Andric return ArgLoc.getLocWithOffset(-Len); 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric namespace { 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric template <typename T> 470b57cec5SDimitry Andric SourceLocation getArgLoc(T* Arg); 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric template <> 500b57cec5SDimitry Andric SourceLocation getArgLoc<Expr>(Expr *Arg) { 510b57cec5SDimitry Andric return Arg->getBeginLoc(); 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric template <> 550b57cec5SDimitry Andric SourceLocation getArgLoc<ParmVarDecl>(ParmVarDecl *Arg) { 560b57cec5SDimitry Andric SourceLocation Loc = Arg->getBeginLoc(); 570b57cec5SDimitry Andric if (Loc.isInvalid()) 580b57cec5SDimitry Andric return Loc; 590b57cec5SDimitry Andric // -1 to point to left paren of the method parameter's type. 600b57cec5SDimitry Andric return Loc.getLocWithOffset(-1); 610b57cec5SDimitry Andric } 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric template <typename T> 640b57cec5SDimitry Andric SourceLocation getArgLoc(unsigned Index, ArrayRef<T*> Args) { 650b57cec5SDimitry Andric return Index < Args.size() ? getArgLoc(Args[Index]) : SourceLocation(); 660b57cec5SDimitry Andric } 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric template <typename T> 690b57cec5SDimitry Andric SelectorLocationsKind hasStandardSelLocs(Selector Sel, 700b57cec5SDimitry Andric ArrayRef<SourceLocation> SelLocs, 710b57cec5SDimitry Andric ArrayRef<T *> Args, 720b57cec5SDimitry Andric SourceLocation EndLoc) { 730b57cec5SDimitry Andric // Are selector locations in standard position with no space between args ? 740b57cec5SDimitry Andric unsigned i; 750b57cec5SDimitry Andric for (i = 0; i != SelLocs.size(); ++i) { 760b57cec5SDimitry Andric if (SelLocs[i] != getStandardSelectorLoc(i, Sel, /*WithArgSpace=*/false, 770b57cec5SDimitry Andric Args, EndLoc)) 780b57cec5SDimitry Andric break; 790b57cec5SDimitry Andric } 800b57cec5SDimitry Andric if (i == SelLocs.size()) 810b57cec5SDimitry Andric return SelLoc_StandardNoSpace; 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric // Are selector locations in standard position with space between args ? 840b57cec5SDimitry Andric for (i = 0; i != SelLocs.size(); ++i) { 850b57cec5SDimitry Andric if (SelLocs[i] != getStandardSelectorLoc(i, Sel, /*WithArgSpace=*/true, 860b57cec5SDimitry Andric Args, EndLoc)) 870b57cec5SDimitry Andric return SelLoc_NonStandard; 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric return SelLoc_StandardWithSpace; 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric } // anonymous namespace 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric SelectorLocationsKind 960b57cec5SDimitry Andric clang::hasStandardSelectorLocs(Selector Sel, 970b57cec5SDimitry Andric ArrayRef<SourceLocation> SelLocs, 980b57cec5SDimitry Andric ArrayRef<Expr *> Args, 990b57cec5SDimitry Andric SourceLocation EndLoc) { 1000b57cec5SDimitry Andric return hasStandardSelLocs(Sel, SelLocs, Args, EndLoc); 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric SourceLocation clang::getStandardSelectorLoc(unsigned Index, 1040b57cec5SDimitry Andric Selector Sel, 1050b57cec5SDimitry Andric bool WithArgSpace, 1060b57cec5SDimitry Andric ArrayRef<Expr *> Args, 1070b57cec5SDimitry Andric SourceLocation EndLoc) { 1080b57cec5SDimitry Andric return getStandardSelLoc(Index, Sel, WithArgSpace, 1090b57cec5SDimitry Andric getArgLoc(Index, Args), EndLoc); 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric SelectorLocationsKind 1130b57cec5SDimitry Andric clang::hasStandardSelectorLocs(Selector Sel, 1140b57cec5SDimitry Andric ArrayRef<SourceLocation> SelLocs, 1150b57cec5SDimitry Andric ArrayRef<ParmVarDecl *> Args, 1160b57cec5SDimitry Andric SourceLocation EndLoc) { 1170b57cec5SDimitry Andric return hasStandardSelLocs(Sel, SelLocs, Args, EndLoc); 1180b57cec5SDimitry Andric } 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric SourceLocation clang::getStandardSelectorLoc(unsigned Index, 1210b57cec5SDimitry Andric Selector Sel, 1220b57cec5SDimitry Andric bool WithArgSpace, 1230b57cec5SDimitry Andric ArrayRef<ParmVarDecl *> Args, 1240b57cec5SDimitry Andric SourceLocation EndLoc) { 1250b57cec5SDimitry Andric return getStandardSelLoc(Index, Sel, WithArgSpace, 1260b57cec5SDimitry Andric getArgLoc(Index, Args), EndLoc); 1270b57cec5SDimitry Andric } 128