diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-01-28 22:42:45 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-01-28 22:42:45 +0000 |
commit | 3a2b7a18a4504f39e3ded0d2b5749c5c80b8b9b5 (patch) | |
tree | fc4e910b0c160814e3a27e3b19092b2a5bbc41f3 /lib/Sema/SemaDecl.cpp | |
parent | 319d8fc2221fb41b3d332e091bd1e3e53ac05931 (diff) |
Finish semantic analysis for [[carries_dependency]] attribute.
This required plumbing through a new flag to determine whether a ParmVarDecl is
actually a parameter of a function declaration (as opposed to a function
typedef etc, where the attribute is prohibited). Weirdly, this attribute (just
like [[noreturn]]) cannot be applied to a function type, just to a function
declaration (and its parameters).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@173726 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index fb63953de9..e8d14e6bef 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1911,6 +1911,9 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { /// mergeDeclAttributes - Copy attributes from the Old decl to the New one. void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, AvailabilityMergeKind AMK) { + if (!Old->hasAttrs() && !New->hasAttrs()) + return; + // attributes declared post-definition are currently ignored checkNewAttributesAfterDef(*this, New, Old); @@ -1956,7 +1959,25 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, /// to the new one. static void mergeParamDeclAttributes(ParmVarDecl *newDecl, const ParmVarDecl *oldDecl, - ASTContext &C) { + Sema &S) { + // C++11 [dcl.attr.depend]p2: + // The first declaration of a function shall specify the + // carries_dependency attribute for its declarator-id if any declaration + // of the function specifies the carries_dependency attribute. + if (newDecl->hasAttr<CarriesDependencyAttr>() && + !oldDecl->hasAttr<CarriesDependencyAttr>()) { + S.Diag(newDecl->getAttr<CarriesDependencyAttr>()->getLocation(), + diag::err_carries_dependency_missing_on_first_decl) << 1/*Param*/; + // Find the first declaration of the parameter. + // FIXME: Should we build redeclaration chains for function parameters? + const FunctionDecl *FirstFD = + cast<FunctionDecl>(oldDecl->getDeclContext())->getFirstDeclaration(); + const ParmVarDecl *FirstVD = + FirstFD->getParamDecl(oldDecl->getFunctionScopeIndex()); + S.Diag(FirstVD->getLocation(), + diag::note_carries_dependency_missing_first_decl) << 1/*Param*/; + } + if (!oldDecl->hasAttrs()) return; @@ -1970,7 +1991,8 @@ static void mergeParamDeclAttributes(ParmVarDecl *newDecl, 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)); + InheritableAttr *newAttr = + cast<InheritableParamAttr>((*i)->clone(S.Context)); newAttr->setInherited(true); newDecl->addAttr(newAttr); foundAny = true; @@ -2295,6 +2317,18 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { diag::note_noreturn_missing_first_decl); } + // C++11 [dcl.attr.depend]p2: + // The first declaration of a function shall specify the + // carries_dependency attribute for its declarator-id if any declaration + // of the function specifies the carries_dependency attribute. + if (New->hasAttr<CarriesDependencyAttr>() && + !Old->hasAttr<CarriesDependencyAttr>()) { + Diag(New->getAttr<CarriesDependencyAttr>()->getLocation(), + diag::err_carries_dependency_missing_on_first_decl) << 0/*Function*/; + Diag(Old->getFirstDeclaration()->getLocation(), + diag::note_carries_dependency_missing_first_decl) << 0/*Function*/; + } + // (C++98 8.3.5p3): // All declarations for a function shall agree exactly in both the // return type and the parameter-type-list. @@ -2487,7 +2521,7 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, if (New->getNumParams() == Old->getNumParams()) for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) mergeParamDeclAttributes(New->getParamDecl(i), Old->getParamDecl(i), - Context); + *this); if (getLangOpts().CPlusPlus) return MergeCXXFunctionDecl(New, Old, S); @@ -2514,7 +2548,7 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, for (ObjCMethodDecl::param_iterator ni = newMethod->param_begin(), ne = newMethod->param_end(); ni != ne && oi != oe; ++ni, ++oi) - mergeParamDeclAttributes(*ni, *oi, Context); + mergeParamDeclAttributes(*ni, *oi, *this); CheckObjCMethodOverride(newMethod, oldMethod); } |