From: John McCall Date: Wed, 2 Mar 2011 04:00:57 +0000 (+0000) Subject: Support a new InheritableAttr subclass, InheritableParamAttr, which is X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=eca5d22c16eb784e5f35ca816fa22e0c0e060417;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126828 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 67968fde2d..502b9f775f 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -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. diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 3e62d411d5..57e5be4ae8 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -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]; } diff --git a/include/clang/Basic/AttrKinds.h b/include/clang/Basic/AttrKinds.h index 65c4f98c95..9d5ae588c5 100644 --- a/include/clang/Basic/AttrKinds.h +++ b/include/clang/Basic/AttrKinds.h @@ -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 }; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 5ad041f67e..fcc29442a5 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 9d90499759..70c405c132 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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 - i = Old->specific_attr_begin(), - e = Old->specific_attr_end(); i != e; ++i) { - if (!DeclHasAttr(New, *i)) { - InheritableAttr *NewAttr = cast((*i)->clone(C)); - NewAttr->setInherited(true); - New->addAttr(NewAttr); + i = oldDecl->specific_attr_begin(), + e = oldDecl->specific_attr_end(); i != e; ++i) { + if (!DeclHasAttr(newDecl, *i)) { + InheritableAttr *newAttr = cast((*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 + i = oldDecl->specific_attr_begin(), + e = oldDecl->specific_attr_end(); i != e; ++i) { + if (!DeclHasAttr(newDecl, *i)) { + InheritableAttr *newAttr = cast((*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); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 652318f720..24ca4e6164 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -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()) { - StringLiteral *SE = StringLiteral::CreateEmpty(Context, 1); - ObjCMethod->addAttr(::new (Context) - DeprecatedAttr(DA->getLocation(), - Context, - SE->getString())); - } + mergeObjCMethodDecls(ObjCMethod, InterfaceMD); return ObjCMethod; }