diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseCXXInlineMethods.cpp | 4 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 9 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 4 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 42 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 22 |
7 files changed, 70 insertions, 15 deletions
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index 08d6a137f2..e15ab0ae98 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -293,8 +293,8 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { // Introduce the parameters into scope and parse their default // arguments. - ParseScope PrototypeScope(this, - Scope::FunctionPrototypeScope|Scope::DeclScope); + ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | + Scope::FunctionDeclarationScope | Scope::DeclScope); for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) { // Introduce the parameter into scope. Actions.ActOnDelayedCXXMethodParameter(getCurScope(), diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 6acb0b2eb8..a851e2cb85 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -4522,7 +4522,10 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // Enter function-declaration scope, limiting any declarators to the // function prototype scope, including parameter declarators. ParseScope PrototypeScope(this, - Scope::FunctionPrototypeScope|Scope::DeclScope); + Scope::FunctionPrototypeScope|Scope::DeclScope| + (D.isFunctionDeclaratorAFunctionDeclaration() + ? Scope::FunctionDeclarationScope : 0)); + // The paren may be part of a C++ direct initializer, eg. "int x(1);". // In such a case, check if we actually have a function declarator; if it // is not, the declarator has been fully parsed. @@ -4652,7 +4655,9 @@ void Parser::ParseParenDeclarator(Declarator &D) { // Enter function-declaration scope, limiting any declarators to the // function prototype scope, including parameter declarators. ParseScope PrototypeScope(this, - Scope::FunctionPrototypeScope|Scope::DeclScope); + Scope::FunctionPrototypeScope | Scope::DeclScope | + (D.isFunctionDeclaratorAFunctionDeclaration() + ? Scope::FunctionDeclarationScope : 0)); ParseFunctionDeclarator(D, attrs, T, false, RequiresArg); PrototypeScope.Exit(); } diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 45020fb289..613b0bec5d 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -797,6 +797,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( if (Tok.is(tok::l_paren)) { ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | + Scope::FunctionDeclarationScope | Scope::DeclScope); SourceLocation DeclEndLoc; diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 65bfd1c830..b331defaa3 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -1028,8 +1028,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, SmallVector<IdentifierInfo *, 12> KeyIdents; SmallVector<SourceLocation, 12> KeyLocs; SmallVector<Sema::ObjCArgInfo, 12> ArgInfos; - ParseScope PrototypeScope(this, - Scope::FunctionPrototypeScope|Scope::DeclScope); + ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | + Scope::FunctionDeclarationScope | Scope::DeclScope); AttributePool allParamAttrs(AttrFactory); while (1) { diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 20e515d102..1a667daab7 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -1097,7 +1097,8 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { // Enter function-declaration scope, limiting any declarators to the // function prototype scope, including parameter declarators. - ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope|Scope::DeclScope); + ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | + Scope::FunctionDeclarationScope | Scope::DeclScope); // Read all the argument declarations. while (isDeclarationSpecifier()) { 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); } diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index bb77adfd45..adeb8e690f 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -24,6 +24,7 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" #include "llvm/ADT/StringExtras.h" using namespace clang; using namespace sema; @@ -1815,13 +1816,25 @@ static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) { Attr.getAttributeSpellingListIndex())); } -static void handleDependencyAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (!isa<FunctionDecl>(D) && !isa<ParmVarDecl>(D)) { +static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D, + const AttributeList &Attr) { + if (isa<ParmVarDecl>(D)) { + // [[carries_dependency]] can only be applied to a parameter if it is a + // parameter of a function declaration or lambda. + if (!(Scope->getFlags() & clang::Scope::FunctionDeclarationScope)) { + S.Diag(Attr.getLoc(), + diag::err_carries_dependency_param_not_function_decl); + return; + } + } else if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunctionMethodOrParameter; return; } - // FIXME: Actually store the attribute on the declaration + + D->addAttr(::new (S.Context) CarriesDependencyAttr( + Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -4494,7 +4507,8 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_Annotate: handleAnnotateAttr (S, D, Attr); break; case AttributeList::AT_Availability:handleAvailabilityAttr(S, D, Attr); break; case AttributeList::AT_CarriesDependency: - handleDependencyAttr (S, D, Attr); break; + handleDependencyAttr(S, scope, D, Attr); + break; case AttributeList::AT_Common: handleCommonAttr (S, D, Attr); break; case AttributeList::AT_CUDAConstant:handleConstantAttr (S, D, Attr); break; case AttributeList::AT_Constructor: handleConstructorAttr (S, D, Attr); break; |