diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2015-11-10 21:28:44 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2015-11-10 21:28:44 +0000 |
commit | ae6ebd3af525c23c6216b76dd28a282790dce78f (patch) | |
tree | 2a5c4d4171297adb8b9edadf927bed30bae45563 /clang/lib | |
parent | 2d5fb8cac4ec7b6f763c6f91b52f6a954ad99942 (diff) | |
download | bcm5719-llvm-ae6ebd3af525c23c6216b76dd28a282790dce78f.tar.gz bcm5719-llvm-ae6ebd3af525c23c6216b76dd28a282790dce78f.zip |
Implement __attribute__((internal_linkage)).
The attrubite is applicable to functions and variables and changes
the linkage of the subject to internal.
This is the same functionality as C-style "static", but applicable to
class methods; and the same as anonymouns namespaces, but can apply
to individual methods of a class.
Following the proposal in
http://lists.llvm.org/pipermail/cfe-dev/2015-October/045580.html
llvm-svn: 252648
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Decl.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 24 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 79 |
3 files changed, 98 insertions, 13 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index f7600799ba4..0f6e8b09706 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1217,6 +1217,10 @@ getOutermostEnclosingLambda(const CXXRecordDecl *Record) { static LinkageInfo computeLVForDecl(const NamedDecl *D, LVComputationKind computation) { + // Internal_linkage attribute overrides other considerations. + if (D->hasAttr<InternalLinkageAttr>()) + return LinkageInfo::internal(); + // Objective-C: treat all Objective-C declarations as having external // linkage. switch (D->getKind()) { @@ -1307,6 +1311,10 @@ class LinkageComputer { public: static LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation) { + // Internal_linkage attribute overrides other considerations. + if (D->hasAttr<InternalLinkageAttr>()) + return LinkageInfo::internal(); + if (computation == LVForLinkageOnly && D->hasCachedLinkage()) return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 009fe16f948..92bbadd627d 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2216,6 +2216,15 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, NewAttr = S.mergeMinSizeAttr(D, MA->getRange(), AttrSpellingListIndex); else if (const auto *OA = dyn_cast<OptimizeNoneAttr>(Attr)) NewAttr = S.mergeOptimizeNoneAttr(D, OA->getRange(), AttrSpellingListIndex); + else if (const auto *InternalLinkageA = dyn_cast<InternalLinkageAttr>(Attr)) + NewAttr = S.mergeInternalLinkageAttr( + D, InternalLinkageA->getRange(), + &S.Context.Idents.get(InternalLinkageA->getSpelling()), + AttrSpellingListIndex); + else if (const auto *CommonA = dyn_cast<CommonAttr>(Attr)) + NewAttr = S.mergeCommonAttr(D, CommonA->getRange(), + &S.Context.Idents.get(CommonA->getSpelling()), + AttrSpellingListIndex); else if (isa<AlignedAttr>(Attr)) // AlignedAttrs are handled separately, because we need to handle all // such attributes on a declaration at the same time. @@ -2664,6 +2673,13 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, } } + if (New->hasAttr<InternalLinkageAttr>() && + !Old->hasAttr<InternalLinkageAttr>()) { + Diag(New->getLocation(), diag::err_internal_linkage_redeclaration) + << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + New->dropAttr<InternalLinkageAttr>(); + } // If a function is first declared with a calling convention, but is later // declared or defined without one, all following decls assume the calling @@ -3377,6 +3393,14 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { New->dropAttr<WeakImportAttr>(); } + if (New->hasAttr<InternalLinkageAttr>() && + !Old->hasAttr<InternalLinkageAttr>()) { + Diag(New->getLocation(), diag::err_internal_linkage_redeclaration) + << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + New->dropAttr<InternalLinkageAttr>(); + } + // Merge the types. VarDecl *MostRecent = Old->getMostRecentDecl(); if (MostRecent != Old) { diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 5b85bf0da2c..a9473d2e119 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -244,11 +244,12 @@ static bool checkUInt32Argument(Sema &S, const AttributeList &Attr, /// \brief Diagnose mutually exclusive attributes when present on a given /// declaration. Returns true if diagnosed. template <typename AttrTy> -static bool checkAttrMutualExclusion(Sema &S, Decl *D, - const AttributeList &Attr) { +static bool checkAttrMutualExclusion(Sema &S, Decl *D, SourceRange Range, + IdentifierInfo *Ident) { if (AttrTy *A = D->getAttr<AttrTy>()) { - S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) - << Attr.getName() << A; + S.Diag(Range.getBegin(), diag::err_attributes_are_not_compatible) << Ident + << A; + S.Diag(A->getLocation(), diag::note_conflicting_attribute); return true; } return false; @@ -1523,7 +1524,7 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (checkAttrMutualExclusion<HotAttr>(S, D, Attr)) + if (checkAttrMutualExclusion<HotAttr>(S, D, Attr.getRange(), Attr.getName())) return; D->addAttr(::new (S.Context) ColdAttr(Attr.getRange(), S.Context, @@ -1531,7 +1532,7 @@ static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (checkAttrMutualExclusion<ColdAttr>(S, D, Attr)) + if (checkAttrMutualExclusion<ColdAttr>(S, D, Attr.getRange(), Attr.getName())) return; D->addAttr(::new (S.Context) HotAttr(Attr.getRange(), S.Context, @@ -1573,12 +1574,13 @@ static void handleRestrictAttr(Sema &S, Decl *D, const AttributeList &Attr) { static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.LangOpts.CPlusPlus) { S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang) - << Attr.getName() << AttributeLangSupport::Cpp; + << Attr.getName() << AttributeLangSupport::Cpp; return; } - D->addAttr(::new (S.Context) CommonAttr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); + if (CommonAttr *CA = S.mergeCommonAttr(D, Attr.getRange(), Attr.getName(), + Attr.getAttributeSpellingListIndex())) + D->addAttr(CA); } static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) { @@ -1703,7 +1705,8 @@ static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D, static void handleNotTailCalledAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (checkAttrMutualExclusion<AlwaysInlineAttr>(S, D, Attr)) + if (checkAttrMutualExclusion<AlwaysInlineAttr>(S, D, Attr.getRange(), + Attr.getName())) return; D->addAttr(::new (S.Context) NotTailCalledAttr( @@ -3392,6 +3395,42 @@ AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D, SourceRange Range, AttrSpellingListIndex); } +CommonAttr *Sema::mergeCommonAttr(Decl *D, SourceRange Range, + IdentifierInfo *Ident, + unsigned AttrSpellingListIndex) { + if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, Range, Ident)) + return nullptr; + + return ::new (Context) CommonAttr(Range, Context, AttrSpellingListIndex); +} + +InternalLinkageAttr * +Sema::mergeInternalLinkageAttr(Decl *D, SourceRange Range, + IdentifierInfo *Ident, + unsigned AttrSpellingListIndex) { + if (auto VD = dyn_cast<VarDecl>(D)) { + // Attribute applies to Var but not any subclass of it (like ParmVar, + // ImplicitParm or VarTemplateSpecialization). + if (VD->getKind() != Decl::Var) { + Diag(Range.getBegin(), diag::warn_attribute_wrong_decl_type) + << Ident << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass + : ExpectedVariableOrFunction); + return nullptr; + } + // Attribute does not apply to non-static local variables. + if (VD->hasLocalStorage()) { + Diag(VD->getLocation(), diag::warn_internal_linkage_local_storage); + return nullptr; + } + } + + if (checkAttrMutualExclusion<CommonAttr>(*this, D, Range, Ident)) + return nullptr; + + return ::new (Context) + InternalLinkageAttr(Range, Context, AttrSpellingListIndex); +} + MinSizeAttr *Sema::mergeMinSizeAttr(Decl *D, SourceRange Range, unsigned AttrSpellingListIndex) { if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) { @@ -3428,7 +3467,8 @@ OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, SourceRange Range, static void handleAlwaysInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, Attr)) + if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, Attr.getRange(), + Attr.getName())) return; if (AlwaysInlineAttr *Inline = S.mergeAlwaysInlineAttr( @@ -4014,7 +4054,8 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl *D, static void handleCFAuditedTransferAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (checkAttrMutualExclusion<CFUnknownTransferAttr>(S, D, Attr)) + if (checkAttrMutualExclusion<CFUnknownTransferAttr>(S, D, Attr.getRange(), + Attr.getName())) return; D->addAttr(::new (S.Context) @@ -4024,7 +4065,8 @@ static void handleCFAuditedTransferAttr(Sema &S, Decl *D, static void handleCFUnknownTransferAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (checkAttrMutualExclusion<CFAuditedTransferAttr>(S, D, Attr)) + if (checkAttrMutualExclusion<CFAuditedTransferAttr>(S, D, Attr.getRange(), + Attr.getName())) return; D->addAttr(::new (S.Context) @@ -4646,6 +4688,14 @@ static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } +static void handleInternalLinkageAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (InternalLinkageAttr *Internal = + S.mergeInternalLinkageAttr(D, Attr.getRange(), Attr.getName(), + Attr.getAttributeSpellingListIndex())) + D->addAttr(Internal); +} + /// Handles semantic checking for features that are common to all attributes, /// such as checking whether a parameter was properly specified, or the correct /// number of arguments were passed, etc. @@ -5090,6 +5140,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_OpenCLImageAccess: handleSimpleAttribute<OpenCLImageAccessAttr>(S, D, Attr); break; + case AttributeList::AT_InternalLinkage: + handleInternalLinkageAttr(S, D, Attr); + break; // Microsoft attributes: case AttributeList::AT_MSNoVTable: |