#define LLVM_CLANG_AST_DECLOBJC_H
#include "clang/AST/Decl.h"
+#include "clang/AST/SelectorLocationsKind.h"
#include "llvm/ADT/STLExtras.h"
namespace clang {
/// \brief Indicates whether this method has a related result type.
unsigned RelatedResultType : 1;
+
+ /// \brief Whether the locations of the selector identifiers are in a
+ /// "standard" position, a enum SelectorLocationsKind.
+ unsigned SelLocsKind : 2;
// Result type of this method.
QualType MethodDeclType;
// Type source information for the result type.
TypeSourceInfo *ResultTInfo;
- /// ParamInfo - List of pointers to VarDecls for the formal parameters of this
- /// Method.
- ObjCList<ParmVarDecl> ParamInfo;
+ /// \brief Array of ParmVarDecls for the formal parameters of this method
+ /// and optionally followed by selector locations.
+ void *ParamsAndSelLocs;
+ unsigned NumParams;
/// List of attributes for this method declaration.
SourceLocation EndLoc; // the location of the ';' or '}'.
/// constructed by createImplicitParams.
ImplicitParamDecl *CmdDecl;
+ SelectorLocationsKind getSelLocsKind() const {
+ return (SelectorLocationsKind)SelLocsKind;
+ }
+ bool hasStandardSelLocs() const {
+ return getSelLocsKind() != SelLoc_NonStandard;
+ }
+
+ /// \brief Get a pointer to the stored selector identifiers locations array.
+ /// No locations will be stored if HasStandardSelLocs is true.
+ SourceLocation *getStoredSelLocs() {
+ return reinterpret_cast<SourceLocation*>(getParams() + NumParams);
+ }
+ const SourceLocation *getStoredSelLocs() const {
+ return reinterpret_cast<const SourceLocation*>(getParams() + NumParams);
+ }
+
+ /// \brief Get a pointer to the stored selector identifiers locations array.
+ /// No locations will be stored if HasStandardSelLocs is true.
+ ParmVarDecl **getParams() {
+ return reinterpret_cast<ParmVarDecl **>(ParamsAndSelLocs);
+ }
+ const ParmVarDecl *const *getParams() const {
+ return reinterpret_cast<const ParmVarDecl *const *>(ParamsAndSelLocs);
+ }
+
+ /// \brief Get the number of stored selector identifiers locations.
+ /// No locations will be stored if HasStandardSelLocs is true.
+ unsigned getNumStoredSelLocs() const {
+ if (hasStandardSelLocs())
+ return 0;
+ return getNumSelectorLocs();
+ }
+
+ void setParamsAndSelLocs(ASTContext &C,
+ ArrayRef<ParmVarDecl*> Params,
+ ArrayRef<SourceLocation> SelLocs);
+
ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
Selector SelInfo, QualType T,
TypeSourceInfo *ResultTInfo,
IsDefined(isDefined),
DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
RelatedResultType(HasRelatedResultType),
+ SelLocsKind(SelLoc_StandardNoSpace),
MethodDeclType(T), ResultTInfo(ResultTInfo),
+ ParamsAndSelLocs(0), NumParams(0),
EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {
setImplicit(isImplicitlyDeclared);
}
static ObjCMethodDecl *Create(ASTContext &C,
SourceLocation beginLoc,
SourceLocation endLoc,
- ArrayRef<SourceLocation> SelLocs,
Selector SelInfo,
QualType T,
TypeSourceInfo *ResultTInfo,
return SourceRange(getLocation(), EndLoc);
}
+ SourceLocation getSelectorStartLoc() const { return getSelectorLoc(0); }
+ SourceLocation getSelectorLoc(unsigned Index) const {
+ assert(Index < getNumSelectorLocs() && "Index out of range!");
+ if (hasStandardSelLocs())
+ return getStandardSelectorLoc(Index, getSelector(),
+ getSelLocsKind() == SelLoc_StandardWithSpace,
+ llvm::makeArrayRef(const_cast<ParmVarDecl**>(getParams()),
+ NumParams),
+ EndLoc);
+ return getStoredSelLocs()[Index];
+ }
+
+ void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const;
+
+ unsigned getNumSelectorLocs() const {
+ if (isImplicit())
+ return 0;
+ Selector Sel = getSelector();
+ if (Sel.isUnarySelector())
+ return 1;
+ return Sel.getNumArgs();
+ }
+
ObjCInterfaceDecl *getClassInterface();
const ObjCInterfaceDecl *getClassInterface() const {
return const_cast<ObjCMethodDecl*>(this)->getClassInterface();
void setResultTypeSourceInfo(TypeSourceInfo *TInfo) { ResultTInfo = TInfo; }
// Iterator access to formal parameters.
- unsigned param_size() const { return ParamInfo.size(); }
- typedef ObjCList<ParmVarDecl>::iterator param_iterator;
- param_iterator param_begin() const { return ParamInfo.begin(); }
- param_iterator param_end() const { return ParamInfo.end(); }
+ unsigned param_size() const { return NumParams; }
+ typedef const ParmVarDecl *const *param_const_iterator;
+ typedef ParmVarDecl *const *param_iterator;
+ param_const_iterator param_begin() const { return getParams(); }
+ param_const_iterator param_end() const { return getParams() + NumParams; }
+ param_iterator param_begin() { return getParams(); }
+ param_iterator param_end() { return getParams() + NumParams; }
// This method returns and of the parameters which are part of the selector
// name mangling requirements.
- param_iterator sel_param_end() const {
- return ParamInfo.begin() + getSelector().getNumArgs();
+ param_const_iterator sel_param_end() const {
+ return param_begin() + getSelector().getNumArgs();
}
- void setMethodParams(ASTContext &C, ParmVarDecl *const *List, unsigned Num) {
- ParamInfo.set(List, Num, C);
- }
+ void setMethodParams(ASTContext &C,
+ ArrayRef<ParmVarDecl*> Params,
+ ArrayRef<SourceLocation> SelLocs);
// Iterator access to parameter types.
typedef std::const_mem_fun_t<QualType, ParmVarDecl> deref_fun;
- typedef llvm::mapped_iterator<param_iterator, deref_fun> arg_type_iterator;
+ typedef llvm::mapped_iterator<param_const_iterator, deref_fun>
+ arg_type_iterator;
arg_type_iterator arg_type_begin() const {
return llvm::map_iterator(param_begin(), deref_fun(&ParmVarDecl::getType));
static ObjCMethodDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<ObjCMethodDecl *>(const_cast<DeclContext*>(DC));
}
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// ObjCContainerDecl - Represents a container for method declarations.
QualType ArgType;
if (isImplicitProperty()) {
const ObjCMethodDecl *Setter = getImplicitPropertySetter();
- ObjCMethodDecl::param_iterator P = Setter->param_begin();
+ ObjCMethodDecl::param_const_iterator P = Setter->param_begin();
ArgType = (*P)->getType();
} else {
if (ObjCPropertyDecl *PDecl = getExplicitProperty())
if (const ObjCMethodDecl *Setter = PDecl->getSetterMethodDecl()) {
- ObjCMethodDecl::param_iterator P = Setter->param_begin();
+ ObjCMethodDecl::param_const_iterator P = Setter->param_begin();
ArgType = (*P)->getType();
}
if (ArgType.isNull())
class Selector;
class SourceLocation;
class Expr;
+ class ParmVarDecl;
/// \brief Whether all locations of the selector identifiers are in a
/// "standard" position.
ArrayRef<Expr *> Args,
SourceLocation EndLoc);
+/// \brief Returns true if all \arg SelLocs are in a "standard" location.
+SelectorLocationsKind hasStandardSelectorLocs(Selector Sel,
+ ArrayRef<SourceLocation> SelLocs,
+ ArrayRef<ParmVarDecl *> Args,
+ SourceLocation EndLoc);
+
+/// \brief Get the "standard" location of a selector identifier, e.g:
+/// For nullary selectors, immediately before ']': "[foo release]"
+///
+/// \param WithArgSpace if true the standard location is with a space apart
+/// before arguments: "-(id)first: (int)x second: (int)y;"
+/// If false: "-(id)first:(int)x second:(int)y;"
+SourceLocation getStandardSelectorLoc(unsigned Index,
+ Selector Sel,
+ bool WithArgSpace,
+ ArrayRef<ParmVarDecl *> Args,
+ SourceLocation EndLoc);
+
} // end namespace clang
#endif
// The first two arguments (self and _cmd) are pointers; account for
// their size.
CharUnits ParmOffset = 2 * PtrSize;
- for (ObjCMethodDecl::param_iterator PI = Decl->param_begin(),
+ for (ObjCMethodDecl::param_const_iterator PI = Decl->param_begin(),
E = Decl->sel_param_end(); PI != E; ++PI) {
QualType PType = (*PI)->getType();
CharUnits sz = getObjCEncodingTypeSize(PType);
// Argument types.
ParmOffset = 2 * PtrSize;
- for (ObjCMethodDecl::param_iterator PI = Decl->param_begin(),
+ for (ObjCMethodDecl::param_const_iterator PI = Decl->param_begin(),
E = Decl->sel_param_end(); PI != E; ++PI) {
- ParmVarDecl *PVDecl = *PI;
+ const ParmVarDecl *PVDecl = *PI;
QualType PType = PVDecl->getOriginalType();
if (const ArrayType *AT =
dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) {
= ObjCMethodDecl::Create(Importer.getToContext(),
Loc,
Importer.Import(D->getLocEnd()),
- /*FIXME:*/ ArrayRef<SourceLocation>(),
Name.getObjCSelector(),
ResultTy, ResultTInfo, DC,
D->isInstanceMethod(),
ToParams[I]->setOwningFunction(ToMethod);
ToMethod->addDecl(ToParams[I]);
}
- ToMethod->setMethodParams(Importer.getToContext(),
- ToParams.data(), ToParams.size());
+ SmallVector<SourceLocation, 12> SelLocs;
+ D->getSelectorLocs(SelLocs);
+ ToMethod->setMethodParams(Importer.getToContext(), ToParams, SelLocs);
ToMethod->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToMethod);
ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C,
SourceLocation beginLoc,
SourceLocation endLoc,
- ArrayRef<SourceLocation> SelLocs,
Selector SelInfo, QualType T,
TypeSourceInfo *ResultTInfo,
DeclContext *contextDecl,
HasRelatedResultType);
}
+void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C,
+ ArrayRef<ParmVarDecl*> Params,
+ ArrayRef<SourceLocation> SelLocs) {
+ ParamsAndSelLocs = 0;
+ NumParams = Params.size();
+ if (Params.empty() && SelLocs.empty())
+ return;
+
+ unsigned Size = sizeof(ParmVarDecl *) * NumParams +
+ sizeof(SourceLocation) * SelLocs.size();
+ ParamsAndSelLocs = C.Allocate(Size);
+ std::copy(Params.begin(), Params.end(), getParams());
+ std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs());
+}
+
+void ObjCMethodDecl::getSelectorLocs(
+ SmallVectorImpl<SourceLocation> &SelLocs) const {
+ for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i)
+ SelLocs.push_back(getSelectorLoc(i));
+}
+
+void ObjCMethodDecl::setMethodParams(ASTContext &C,
+ ArrayRef<ParmVarDecl*> Params,
+ ArrayRef<SourceLocation> SelLocs) {
+ assert((!SelLocs.empty() || isImplicit()) &&
+ "No selector locs for non-implicit method");
+ if (isImplicit())
+ return setParamsAndSelLocs(C, Params, ArrayRef<SourceLocation>());
+
+ SelLocsKind = hasStandardSelectorLocs(getSelector(), SelLocs, Params, EndLoc);
+ if (SelLocsKind != SelLoc_NonStandard)
+ return setParamsAndSelLocs(C, Params, ArrayRef<SourceLocation>());
+
+ setParamsAndSelLocs(C, Params, SelLocs);
+}
+
/// \brief A definition will return its interface declaration.
/// An interface declaration will return its definition.
/// Otherwise it will return itself.
return Arg->getLocStart();
}
+template <>
+SourceLocation getArgLoc<ParmVarDecl>(ParmVarDecl *Arg) {
+ // -1 to point to left paren of the method parameter's type.
+ return Arg->getLocStart().getLocWithOffset(-1);
+}
+
template <typename T>
SourceLocation getArgLoc(unsigned Index, ArrayRef<T*> Args) {
return Index < Args.size() ? getArgLoc(Args[Index]) : SourceLocation();
return getStandardSelLoc(Index, Sel, WithArgSpace,
getArgLoc(Index, Args), EndLoc);
}
+
+SelectorLocationsKind
+clang::hasStandardSelectorLocs(Selector Sel,
+ ArrayRef<SourceLocation> SelLocs,
+ ArrayRef<ParmVarDecl *> Args,
+ SourceLocation EndLoc) {
+ return hasStandardSelLocs(Sel, SelLocs, Args, EndLoc);
+}
+
+SourceLocation clang::getStandardSelectorLoc(unsigned Index,
+ Selector Sel,
+ bool WithArgSpace,
+ ArrayRef<ParmVarDecl *> Args,
+ SourceLocation EndLoc) {
+ return getStandardSelLoc(Index, Sel, WithArgSpace,
+ getArgLoc(Index, Args), EndLoc);
+}
ArgTys.push_back(Context.getCanonicalParamType(MD->getSelfDecl()->getType()));
ArgTys.push_back(Context.getCanonicalParamType(Context.getObjCSelType()));
// FIXME: Kill copy?
- for (ObjCMethodDecl::param_iterator i = MD->param_begin(),
+ for (ObjCMethodDecl::param_const_iterator i = MD->param_begin(),
e = MD->param_end(); i != e; ++i) {
ArgTys.push_back(Context.getCanonicalParamType((*i)->getType()));
}
// "cmd" pointer is always second argument.
Elts.push_back(getOrCreateType(OMethod->getCmdDecl()->getType(), F));
// Get rest of the arguments.
- for (ObjCMethodDecl::param_iterator PI = OMethod->param_begin(),
+ for (ObjCMethodDecl::param_const_iterator PI = OMethod->param_begin(),
PE = OMethod->param_end(); PI != PE; ++PI)
Elts.push_back(getOrCreateType((*PI)->getType(), F));
args.push_back(OMD->getSelfDecl());
args.push_back(OMD->getCmdDecl());
- for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
+ for (ObjCMethodDecl::param_const_iterator PI = OMD->param_begin(),
E = OMD->param_end(); PI != E; ++PI)
args.push_back(*PI);
Selector cxxSelector = getContext().Selectors.getSelector(0, &II);
ObjCMethodDecl *DTORMethod =
ObjCMethodDecl::Create(getContext(), D->getLocation(), D->getLocation(),
- ArrayRef<SourceLocation>(),
cxxSelector, getContext().VoidTy, 0, D,
/*isInstance=*/true, /*isVariadic=*/false,
/*isSynthesized=*/true, /*isImplicitlyDeclared=*/true,
ObjCMethodDecl *CTORMethod = ObjCMethodDecl::Create(getContext(),
D->getLocation(),
D->getLocation(),
- ArrayRef<SourceLocation>(),
cxxSelector,
getContext().getObjCIdType(), 0,
D, /*isInstance=*/true,
mergeDeclAttributes(newMethod, oldMethod, Context, mergeDeprecation);
// Merge attributes from the parameters.
- for (ObjCMethodDecl::param_iterator oi = oldMethod->param_begin(),
+ ObjCMethodDecl::param_const_iterator oi = oldMethod->param_begin();
+ for (ObjCMethodDecl::param_iterator
ni = newMethod->param_begin(), ne = newMethod->param_end();
ni != ne; ++ni, ++oi)
mergeParamDeclAttributes(*ni, *oi, Context);
Diag(Overridden->getLocation(), diag::note_previous_decl)
<< "method";
}
- for (ObjCMethodDecl::param_iterator oi = Overridden->param_begin(),
- ni = NewMethod->param_begin(), ne = NewMethod->param_end();
+ ObjCMethodDecl::param_const_iterator oi = Overridden->param_begin();
+ for (ObjCMethodDecl::param_iterator
+ ni = NewMethod->param_begin(), ne = NewMethod->param_end();
ni != ne; ++ni, ++oi) {
- ParmVarDecl *oldDecl = (*oi);
+ const ParmVarDecl *oldDecl = (*oi);
ParmVarDecl *newDecl = (*ni);
if (newDecl->hasAttr<NSConsumedAttr>() !=
oldDecl->hasAttr<NSConsumedAttr>()) {
!= right->hasAttr<NSConsumesSelfAttr>()))
return false;
- ObjCMethodDecl::param_iterator
+ ObjCMethodDecl::param_const_iterator
li = left->param_begin(), le = left->param_end(), ri = right->param_begin();
for (; li != le; ++li, ++ri) {
assert(ri != right->param_end() && "Param mismatch");
- ParmVarDecl *lparm = *li, *rparm = *ri;
+ const ParmVarDecl *lparm = *li, *rparm = *ri;
if (!matchTypes(Context, strategy, lparm->getType(), rparm->getType()))
return false;
}
ObjCMethodDecl* ObjCMethod =
- ObjCMethodDecl::Create(Context, MethodLoc, EndLoc, SelectorLocs, Sel,
+ ObjCMethodDecl::Create(Context, MethodLoc, EndLoc, Sel,
resultDeclType,
ResultTInfo,
CurContext,
Params.push_back(Param);
}
- ObjCMethod->setMethodParams(Context, Params.data(), Params.size());
+ ObjCMethod->setMethodParams(Context, Params, SelectorLocs);
ObjCMethod->setObjCDeclQualifier(
CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier()));
// setter, RHS expression is being passed to the setter argument. So,
// type conversion (and comparison) is RHS to setter's argument type.
if (const ObjCMethodDecl *SetterMD = PropRef->getImplicitPropertySetter()) {
- ObjCMethodDecl::param_iterator P = SetterMD->param_begin();
+ ObjCMethodDecl::param_const_iterator P = SetterMD->param_begin();
LHSTy = (*P)->getType();
Consumed = (getLangOptions().ObjCAutoRefCount &&
(*P)->hasAttr<NSConsumedAttr>());
const ObjCMethodDecl *setter
= PropRef->getExplicitProperty()->getSetterMethodDecl();
if (setter) {
- ObjCMethodDecl::param_iterator P = setter->param_begin();
+ ObjCMethodDecl::param_const_iterator P = setter->param_begin();
LHSTy = (*P)->getType();
Consumed = (*P)->hasAttr<NSConsumedAttr>();
}
property->getLocation();
GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc,
- ArrayRef<SourceLocation>(),
property->getGetterName(),
property->getType(), 0, CD, /*isInstance=*/true,
/*isVariadic=*/false, /*isSynthesized=*/true,
property->getLocation();
SetterMethod =
- ObjCMethodDecl::Create(Context, Loc, Loc, ArrayRef<SourceLocation>(),
+ ObjCMethodDecl::Create(Context, Loc, Loc,
property->getSetterName(), Context.VoidTy, 0,
CD, /*isInstance=*/true, /*isVariadic=*/false,
/*isSynthesized=*/true,
SC_None,
SC_None,
0);
- SetterMethod->setMethodParams(Context, &Argument, 1);
+ SetterMethod->setMethodParams(Context, Argument,
+ ArrayRef<SourceLocation>());
AddPropertyAttrs(*this, SetterMethod, property);
Params.reserve(NumParams);
for (unsigned I = 0; I != NumParams; ++I)
Params.push_back(ReadDeclAs<ParmVarDecl>(Record, Idx));
- MD->setMethodParams(Reader.getContext(), Params.data(), NumParams);
+
+ MD->SelLocsKind = Record[Idx++];
+ unsigned NumStoredSelLocs = Record[Idx++];
+ SmallVector<SourceLocation, 16> SelLocs;
+ SelLocs.reserve(NumStoredSelLocs);
+ for (unsigned i = 0; i != NumStoredSelLocs; ++i)
+ SelLocs.push_back(ReadSourceLocation(Record, Idx));
+
+ MD->setParamsAndSelLocs(Reader.getContext(), Params, SelLocs);
}
void ASTDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) {
case DECL_OBJC_METHOD:
D = ObjCMethodDecl::Create(Context, SourceLocation(), SourceLocation(),
- ArrayRef<SourceLocation>(),
Selector(), QualType(), 0, 0);
break;
case DECL_OBJC_INTERFACE:
for (ObjCMethodDecl::param_iterator P = D->param_begin(),
PEnd = D->param_end(); P != PEnd; ++P)
Writer.AddDeclRef(*P, Record);
+
+ Record.push_back(D->SelLocsKind);
+ unsigned NumStoredSelLocs = D->getNumStoredSelLocs();
+ SourceLocation *SelLocs = D->getStoredSelLocs();
+ Record.push_back(NumStoredSelLocs);
+ for (unsigned i = 0; i != NumStoredSelLocs; ++i)
+ Writer.AddSourceLocation(SelLocs[i], Record);
+
Code = serialization::DECL_OBJC_METHOD;
}
II = &D->getASTContext().Idents.get("NSError");
bool hasNSError = false;
- for (ObjCMethodDecl::param_iterator
+ for (ObjCMethodDecl::param_const_iterator
I = D->param_begin(), E = D->param_end(); I != E; ++I) {
if (IsNSError((*I)->getType(), II)) {
hasNSError = true;
// Effects on the parameters.
unsigned parm_idx = 0;
- for (ObjCMethodDecl::param_iterator pi=MD->param_begin(), pe=MD->param_end();
+ for (ObjCMethodDecl::param_const_iterator
+ pi=MD->param_begin(), pe=MD->param_end();
pi != pe; ++pi, ++parm_idx) {
const ParmVarDecl *pd = *pi;
if (pd->getAttr<NSConsumedAttr>()) {
// Delegates are a frequent form of false positives with the retain
// count checker.
unsigned i = 0;
- for (ObjCMethodDecl::param_iterator I = MD->param_begin(),
+ for (ObjCMethodDecl::param_const_iterator I = MD->param_begin(),
E = MD->param_end(); I != E; ++I, ++i)
- if (ParmVarDecl *PD = *I) {
+ if (const ParmVarDecl *PD = *I) {
QualType Ty = Ctx.getCanonicalType(PD->getType());
if (Ty.getLocalUnqualifiedType() == Ctx.VoidPtrTy)
ScratchArgs = AF.add(ScratchArgs, i, StopTracking);