Home | History | Annotate | Line # | Download | only in AST
      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