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:
John McCall 2011-03-02 04:00:57 +00:00
parent 8b1ae6417d
commit f79e87d727
6 changed files with 92 additions and 25 deletions

View File

@ -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.

View File

@ -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];
}

View File

@ -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
};

View File

@ -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);

View File

@ -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);

View File

@ -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;
}