forked from OSchip/llvm-project
Support a new InheritableAttr subclass, InheritableParamAttr, which is
used for attributes that are okay to inherit when written on a parameter. Dependent on LLVM r126827. llvm-svn: 126828
This commit is contained in:
parent
8b1ae6417d
commit
f79e87d727
|
@ -120,6 +120,19 @@ public:
|
|||
static bool classof(const InheritableAttr *) { return true; }
|
||||
};
|
||||
|
||||
class InheritableParamAttr : public InheritableAttr {
|
||||
protected:
|
||||
InheritableParamAttr(attr::Kind AK, SourceLocation L)
|
||||
: InheritableAttr(AK, L) {}
|
||||
|
||||
public:
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Attr *A) {
|
||||
return A->getKind() <= attr::LAST_INHERITABLE_PARAM;
|
||||
}
|
||||
static bool classof(const InheritableParamAttr *) { return true; }
|
||||
};
|
||||
|
||||
#include "clang/AST/Attrs.inc"
|
||||
|
||||
/// AttrVec - A vector of Attr, which is how they are stored on the AST.
|
||||
|
|
|
@ -89,8 +89,13 @@ class Attr {
|
|||
code AdditionalMembers = [{}];
|
||||
}
|
||||
|
||||
/// An inheritable attribute is inherited by later redeclarations.
|
||||
class InheritableAttr : Attr;
|
||||
|
||||
/// An inheritable parameter attribute is inherited by later
|
||||
/// redeclarations, even when it's written on a parameter.
|
||||
class InheritableParamAttr : InheritableAttr;
|
||||
|
||||
//
|
||||
// Attributes begin here
|
||||
//
|
||||
|
@ -134,7 +139,7 @@ def Blocks : InheritableAttr {
|
|||
let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
|
||||
}
|
||||
|
||||
def CarriesDependency : InheritableAttr {
|
||||
def CarriesDependency : InheritableParamAttr {
|
||||
let Spellings = ["carries_dependency"];
|
||||
let Subjects = [ParmVar, Function];
|
||||
let Namespaces = ["", "std"];
|
||||
|
@ -154,7 +159,7 @@ def CFReturnsNotRetained : InheritableAttr {
|
|||
let Subjects = [ObjCMethod, Function];
|
||||
}
|
||||
|
||||
def CFConsumed : InheritableAttr {
|
||||
def CFConsumed : InheritableParamAttr {
|
||||
let Spellings = ["cf_consumed"];
|
||||
let Subjects = [ParmVar];
|
||||
}
|
||||
|
@ -355,7 +360,7 @@ def NSConsumesSelf : InheritableAttr {
|
|||
let Subjects = [ObjCMethod];
|
||||
}
|
||||
|
||||
def NSConsumed : InheritableAttr {
|
||||
def NSConsumed : InheritableParamAttr {
|
||||
let Spellings = ["ns_consumed"];
|
||||
let Subjects = [ParmVar];
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace attr {
|
|||
enum Kind {
|
||||
#define ATTR(X) X,
|
||||
#define LAST_INHERITABLE_ATTR(X) X, LAST_INHERITABLE = X,
|
||||
#define LAST_INHERITABLE_PARAM_ATTR(X) X, LAST_INHERITABLE_PARAM = X,
|
||||
#include "clang/Basic/AttrList.inc"
|
||||
NUM_ATTRS
|
||||
};
|
||||
|
|
|
@ -1068,6 +1068,7 @@ public:
|
|||
void MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls);
|
||||
bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
|
||||
bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
|
||||
void mergeObjCMethodDecls(ObjCMethodDecl *New, const ObjCMethodDecl *Old);
|
||||
void MergeVarDeclTypes(VarDecl *New, VarDecl *Old);
|
||||
void MergeVarDecl(VarDecl *New, LookupResult &OldDecls);
|
||||
bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old);
|
||||
|
|
|
@ -1054,23 +1054,58 @@ DeclHasAttr(const Decl *D, const Attr *A) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/// MergeDeclAttributes - append attributes from the Old decl to the New one.
|
||||
static void MergeDeclAttributes(Decl *New, Decl *Old, ASTContext &C) {
|
||||
if (!Old->hasAttrs())
|
||||
/// mergeDeclAttributes - Copy attributes from the Old decl to the New one.
|
||||
static void mergeDeclAttributes(Decl *newDecl, const Decl *oldDecl,
|
||||
ASTContext &C) {
|
||||
if (!oldDecl->hasAttrs())
|
||||
return;
|
||||
|
||||
bool foundAny = newDecl->hasAttrs();
|
||||
|
||||
// Ensure that any moving of objects within the allocated map is done before
|
||||
// we process them.
|
||||
if (!New->hasAttrs())
|
||||
New->setAttrs(AttrVec());
|
||||
if (!foundAny) newDecl->setAttrs(AttrVec());
|
||||
|
||||
for (specific_attr_iterator<InheritableAttr>
|
||||
i = Old->specific_attr_begin<InheritableAttr>(),
|
||||
e = Old->specific_attr_end<InheritableAttr>(); i != e; ++i) {
|
||||
if (!DeclHasAttr(New, *i)) {
|
||||
InheritableAttr *NewAttr = cast<InheritableAttr>((*i)->clone(C));
|
||||
NewAttr->setInherited(true);
|
||||
New->addAttr(NewAttr);
|
||||
i = oldDecl->specific_attr_begin<InheritableAttr>(),
|
||||
e = oldDecl->specific_attr_end<InheritableAttr>(); i != e; ++i) {
|
||||
if (!DeclHasAttr(newDecl, *i)) {
|
||||
InheritableAttr *newAttr = cast<InheritableAttr>((*i)->clone(C));
|
||||
newAttr->setInherited(true);
|
||||
newDecl->addAttr(newAttr);
|
||||
foundAny = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundAny) newDecl->dropAttrs();
|
||||
}
|
||||
|
||||
/// mergeParamDeclAttributes - Copy attributes from the old parameter
|
||||
/// to the new one.
|
||||
static void mergeParamDeclAttributes(ParmVarDecl *newDecl,
|
||||
const ParmVarDecl *oldDecl,
|
||||
ASTContext &C) {
|
||||
if (!oldDecl->hasAttrs())
|
||||
return;
|
||||
|
||||
bool foundAny = newDecl->hasAttrs();
|
||||
|
||||
// Ensure that any moving of objects within the allocated map is
|
||||
// done before we process them.
|
||||
if (!foundAny) newDecl->setAttrs(AttrVec());
|
||||
|
||||
for (specific_attr_iterator<InheritableParamAttr>
|
||||
i = oldDecl->specific_attr_begin<InheritableParamAttr>(),
|
||||
e = oldDecl->specific_attr_end<InheritableParamAttr>(); i != e; ++i) {
|
||||
if (!DeclHasAttr(newDecl, *i)) {
|
||||
InheritableAttr *newAttr = cast<InheritableParamAttr>((*i)->clone(C));
|
||||
newAttr->setInherited(true);
|
||||
newDecl->addAttr(newAttr);
|
||||
foundAny = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundAny) newDecl->dropAttrs();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -1471,7 +1506,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
|
|||
/// \returns false
|
||||
bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
|
||||
// Merge the attributes
|
||||
MergeDeclAttributes(New, Old, Context);
|
||||
mergeDeclAttributes(New, Old, Context);
|
||||
|
||||
// Merge the storage class.
|
||||
if (Old->getStorageClass() != SC_Extern &&
|
||||
|
@ -1486,12 +1521,31 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
|
|||
if (Old->isDeleted())
|
||||
New->setDeleted();
|
||||
|
||||
// Merge attributes from the parameters. These can mismatch with K&R
|
||||
// declarations.
|
||||
if (New->getNumParams() == Old->getNumParams())
|
||||
for (unsigned i = 0, e = New->getNumParams(); i != e; ++i)
|
||||
mergeParamDeclAttributes(New->getParamDecl(i), Old->getParamDecl(i),
|
||||
Context);
|
||||
|
||||
if (getLangOptions().CPlusPlus)
|
||||
return MergeCXXFunctionDecl(New, Old);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
|
||||
const ObjCMethodDecl *oldMethod) {
|
||||
// Merge the attributes.
|
||||
mergeDeclAttributes(newMethod, oldMethod, Context);
|
||||
|
||||
// Merge attributes from the parameters.
|
||||
for (ObjCMethodDecl::param_iterator oi = oldMethod->param_begin(),
|
||||
ni = newMethod->param_begin(), ne = newMethod->param_end();
|
||||
ni != ne; ++ni, ++oi)
|
||||
mergeParamDeclAttributes(*ni, *oi, Context);
|
||||
}
|
||||
|
||||
/// MergeVarDecl - We parsed a variable 'New' which has the same name and scope
|
||||
/// as a previous declaration 'Old'. Figure out how to merge their types,
|
||||
/// emitting diagnostics as appropriate.
|
||||
|
@ -1585,7 +1639,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
|
|||
New->setInvalidDecl();
|
||||
}
|
||||
|
||||
MergeDeclAttributes(New, Old, Context);
|
||||
mergeDeclAttributes(New, Old, Context);
|
||||
|
||||
// Merge the types.
|
||||
MergeVarDeclTypes(New, Old);
|
||||
|
|
|
@ -1888,16 +1888,9 @@ Decl *Sema::ActOnMethodDeclaration(
|
|||
Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
|
||||
}
|
||||
|
||||
// If the interface declared this method, and it was deprecated there,
|
||||
// mark it deprecated here.
|
||||
// Merge information down from the interface declaration if we have one.
|
||||
if (InterfaceMD)
|
||||
if (Attr *DA = InterfaceMD->getAttr<DeprecatedAttr>()) {
|
||||
StringLiteral *SE = StringLiteral::CreateEmpty(Context, 1);
|
||||
ObjCMethod->addAttr(::new (Context)
|
||||
DeprecatedAttr(DA->getLocation(),
|
||||
Context,
|
||||
SE->getString()));
|
||||
}
|
||||
mergeObjCMethodDecls(ObjCMethod, InterfaceMD);
|
||||
|
||||
return ObjCMethod;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue