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; }
|
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"
|
#include "clang/AST/Attrs.inc"
|
||||||
|
|
||||||
/// AttrVec - A vector of Attr, which is how they are stored on the AST.
|
/// AttrVec - A vector of Attr, which is how they are stored on the AST.
|
||||||
|
|
|
@ -89,8 +89,13 @@ class Attr {
|
||||||
code AdditionalMembers = [{}];
|
code AdditionalMembers = [{}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An inheritable attribute is inherited by later redeclarations.
|
||||||
class InheritableAttr : Attr;
|
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
|
// Attributes begin here
|
||||||
//
|
//
|
||||||
|
@ -134,7 +139,7 @@ def Blocks : InheritableAttr {
|
||||||
let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
|
let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
|
||||||
}
|
}
|
||||||
|
|
||||||
def CarriesDependency : InheritableAttr {
|
def CarriesDependency : InheritableParamAttr {
|
||||||
let Spellings = ["carries_dependency"];
|
let Spellings = ["carries_dependency"];
|
||||||
let Subjects = [ParmVar, Function];
|
let Subjects = [ParmVar, Function];
|
||||||
let Namespaces = ["", "std"];
|
let Namespaces = ["", "std"];
|
||||||
|
@ -154,7 +159,7 @@ def CFReturnsNotRetained : InheritableAttr {
|
||||||
let Subjects = [ObjCMethod, Function];
|
let Subjects = [ObjCMethod, Function];
|
||||||
}
|
}
|
||||||
|
|
||||||
def CFConsumed : InheritableAttr {
|
def CFConsumed : InheritableParamAttr {
|
||||||
let Spellings = ["cf_consumed"];
|
let Spellings = ["cf_consumed"];
|
||||||
let Subjects = [ParmVar];
|
let Subjects = [ParmVar];
|
||||||
}
|
}
|
||||||
|
@ -355,7 +360,7 @@ def NSConsumesSelf : InheritableAttr {
|
||||||
let Subjects = [ObjCMethod];
|
let Subjects = [ObjCMethod];
|
||||||
}
|
}
|
||||||
|
|
||||||
def NSConsumed : InheritableAttr {
|
def NSConsumed : InheritableParamAttr {
|
||||||
let Spellings = ["ns_consumed"];
|
let Spellings = ["ns_consumed"];
|
||||||
let Subjects = [ParmVar];
|
let Subjects = [ParmVar];
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ namespace attr {
|
||||||
enum Kind {
|
enum Kind {
|
||||||
#define ATTR(X) X,
|
#define ATTR(X) X,
|
||||||
#define LAST_INHERITABLE_ATTR(X) X, LAST_INHERITABLE = 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"
|
#include "clang/Basic/AttrList.inc"
|
||||||
NUM_ATTRS
|
NUM_ATTRS
|
||||||
};
|
};
|
||||||
|
|
|
@ -1068,6 +1068,7 @@ public:
|
||||||
void MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls);
|
void MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls);
|
||||||
bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
|
bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
|
||||||
bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
|
bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
|
||||||
|
void mergeObjCMethodDecls(ObjCMethodDecl *New, const ObjCMethodDecl *Old);
|
||||||
void MergeVarDeclTypes(VarDecl *New, VarDecl *Old);
|
void MergeVarDeclTypes(VarDecl *New, VarDecl *Old);
|
||||||
void MergeVarDecl(VarDecl *New, LookupResult &OldDecls);
|
void MergeVarDecl(VarDecl *New, LookupResult &OldDecls);
|
||||||
bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old);
|
bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old);
|
||||||
|
|
|
@ -1054,23 +1054,58 @@ DeclHasAttr(const Decl *D, const Attr *A) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MergeDeclAttributes - append attributes from the Old decl to the New one.
|
/// mergeDeclAttributes - Copy attributes from the Old decl to the New one.
|
||||||
static void MergeDeclAttributes(Decl *New, Decl *Old, ASTContext &C) {
|
static void mergeDeclAttributes(Decl *newDecl, const Decl *oldDecl,
|
||||||
if (!Old->hasAttrs())
|
ASTContext &C) {
|
||||||
|
if (!oldDecl->hasAttrs())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
bool foundAny = newDecl->hasAttrs();
|
||||||
|
|
||||||
// Ensure that any moving of objects within the allocated map is done before
|
// Ensure that any moving of objects within the allocated map is done before
|
||||||
// we process them.
|
// we process them.
|
||||||
if (!New->hasAttrs())
|
if (!foundAny) newDecl->setAttrs(AttrVec());
|
||||||
New->setAttrs(AttrVec());
|
|
||||||
for (specific_attr_iterator<InheritableAttr>
|
for (specific_attr_iterator<InheritableAttr>
|
||||||
i = Old->specific_attr_begin<InheritableAttr>(),
|
i = oldDecl->specific_attr_begin<InheritableAttr>(),
|
||||||
e = Old->specific_attr_end<InheritableAttr>(); i != e; ++i) {
|
e = oldDecl->specific_attr_end<InheritableAttr>(); i != e; ++i) {
|
||||||
if (!DeclHasAttr(New, *i)) {
|
if (!DeclHasAttr(newDecl, *i)) {
|
||||||
InheritableAttr *NewAttr = cast<InheritableAttr>((*i)->clone(C));
|
InheritableAttr *newAttr = cast<InheritableAttr>((*i)->clone(C));
|
||||||
NewAttr->setInherited(true);
|
newAttr->setInherited(true);
|
||||||
New->addAttr(NewAttr);
|
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 {
|
namespace {
|
||||||
|
@ -1471,7 +1506,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
|
||||||
/// \returns false
|
/// \returns false
|
||||||
bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
|
bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
|
||||||
// Merge the attributes
|
// Merge the attributes
|
||||||
MergeDeclAttributes(New, Old, Context);
|
mergeDeclAttributes(New, Old, Context);
|
||||||
|
|
||||||
// Merge the storage class.
|
// Merge the storage class.
|
||||||
if (Old->getStorageClass() != SC_Extern &&
|
if (Old->getStorageClass() != SC_Extern &&
|
||||||
|
@ -1486,12 +1521,31 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
|
||||||
if (Old->isDeleted())
|
if (Old->isDeleted())
|
||||||
New->setDeleted();
|
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)
|
if (getLangOptions().CPlusPlus)
|
||||||
return MergeCXXFunctionDecl(New, Old);
|
return MergeCXXFunctionDecl(New, Old);
|
||||||
|
|
||||||
return false;
|
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
|
/// 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,
|
/// as a previous declaration 'Old'. Figure out how to merge their types,
|
||||||
/// emitting diagnostics as appropriate.
|
/// emitting diagnostics as appropriate.
|
||||||
|
@ -1585,7 +1639,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
|
||||||
New->setInvalidDecl();
|
New->setInvalidDecl();
|
||||||
}
|
}
|
||||||
|
|
||||||
MergeDeclAttributes(New, Old, Context);
|
mergeDeclAttributes(New, Old, Context);
|
||||||
|
|
||||||
// Merge the types.
|
// Merge the types.
|
||||||
MergeVarDeclTypes(New, Old);
|
MergeVarDeclTypes(New, Old);
|
||||||
|
|
|
@ -1888,16 +1888,9 @@ Decl *Sema::ActOnMethodDeclaration(
|
||||||
Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
|
Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the interface declared this method, and it was deprecated there,
|
// Merge information down from the interface declaration if we have one.
|
||||||
// mark it deprecated here.
|
|
||||||
if (InterfaceMD)
|
if (InterfaceMD)
|
||||||
if (Attr *DA = InterfaceMD->getAttr<DeprecatedAttr>()) {
|
mergeObjCMethodDecls(ObjCMethod, InterfaceMD);
|
||||||
StringLiteral *SE = StringLiteral::CreateEmpty(Context, 1);
|
|
||||||
ObjCMethod->addAttr(::new (Context)
|
|
||||||
DeprecatedAttr(DA->getLocation(),
|
|
||||||
Context,
|
|
||||||
SE->getString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ObjCMethod;
|
return ObjCMethod;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue