diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTDumper.cpp | 5 | ||||
-rw-r--r-- | clang/lib/AST/Decl.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 17 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 85 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateVariadic.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 3 |
9 files changed, 77 insertions, 76 deletions
diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp index a3bdd610371..248128861e2 100644 --- a/clang/lib/AST/ASTDumper.cpp +++ b/clang/lib/AST/ASTDumper.cpp @@ -1164,11 +1164,6 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { D->getTemplateSpecializationInfo()) dumpTemplateArgumentList(*FTSI->TemplateArguments); - for (ArrayRef<NamedDecl *>::iterator - I = D->getDeclsInPrototypeScope().begin(), - E = D->getDeclsInPrototypeScope().end(); I != E; ++I) - dumpDecl(*I); - if (!D->param_begin() && D->getNumParams()) dumpChild([=] { OS << "<<NULL params x " << D->getNumParams() << ">>"; }); else diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 2c8061564f4..c3fa1c87aff 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2840,28 +2840,6 @@ void FunctionDecl::setParams(ASTContext &C, } } -void FunctionDecl::setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls) { - assert(DeclsInPrototypeScope.empty() && "Already has prototype decls!"); - - if (!NewDecls.empty()) { - NamedDecl **A = new (getASTContext()) NamedDecl*[NewDecls.size()]; - std::copy(NewDecls.begin(), NewDecls.end(), A); - DeclsInPrototypeScope = llvm::makeArrayRef(A, NewDecls.size()); - // Move declarations introduced in prototype to the function context. - for (auto I : NewDecls) { - DeclContext *DC = I->getDeclContext(); - // Forward-declared reference to an enumeration is not added to - // declaration scope, so skip declaration that is absent from its - // declaration contexts. - if (DC->containsDecl(I)) { - DC->removeDecl(I); - I->setDeclContext(this); - addDecl(I); - } - } - } -} - /// getMinRequiredArguments - Returns the minimum number of arguments /// needed to call this function. This may be fewer than the number of /// function parameters, if some of the parameters have default diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index ea7ab267701..9dda75e3f98 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -5827,6 +5827,21 @@ void Parser::ParseFunctionDeclarator(Declarator &D, } } + // Collect non-parameter declarations from the prototype if this is a function + // declaration. They will be moved into the scope of the function. Only do + // this in C and not C++, where the decls will continue to live in the + // surrounding context. + SmallVector<NamedDecl *, 0> DeclsInPrototype; + if (getCurScope()->getFlags() & Scope::FunctionDeclarationScope && + !getLangOpts().CPlusPlus) { + for (Decl *D : getCurScope()->decls()) { + NamedDecl *ND = dyn_cast<NamedDecl>(D); + if (!ND || isa<ParmVarDecl>(ND)) + continue; + DeclsInPrototype.push_back(ND); + } + } + // Remember that we parsed a function type, and remember the attributes. D.AddTypeInfo(DeclaratorChunk::getFunction(HasProto, IsAmbiguous, @@ -5846,6 +5861,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr, ExceptionSpecTokens, + DeclsInPrototype, StartLoc, LocalEndLoc, D, TrailingReturnType), FnAttrs, EndLoc); diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 4b0a83446e5..caf2320f8fc 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -2842,6 +2842,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { /*NumExceptions=*/0, /*NoexceptExpr=*/nullptr, /*ExceptionSpecTokens=*/nullptr, + /*DeclsInPrototype=*/None, CaretLoc, CaretLoc, ParamInfo), attrs, CaretLoc); diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 83e6ae4ef53..cabc7b5266d 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -1244,6 +1244,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr, /*ExceptionSpecTokens*/nullptr, + /*DeclsInPrototype=*/None, LParenLoc, FunLocalRangeEnd, D, TrailingReturnType), Attr, DeclEndLoc); @@ -1313,6 +1314,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( /*NumExceptions=*/0, /*NoexceptExpr=*/nullptr, /*ExceptionSpecTokens=*/nullptr, + /*DeclsInPrototype=*/None, DeclLoc, DeclEndLoc, D, TrailingReturnType), Attr, DeclEndLoc); diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 4107977533d..cc644c7093b 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -173,6 +173,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, unsigned NumExceptions, Expr *NoexceptExpr, CachedTokens *ExceptionSpecTokens, + ArrayRef<NamedDecl*> + DeclsInPrototype, SourceLocation LocalRangeBegin, SourceLocation LocalRangeEnd, Declarator &TheDeclarator, @@ -204,7 +206,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, I.Fun.ExceptionSpecType = ESpecType; I.Fun.ExceptionSpecLocBeg = ESpecRange.getBegin().getRawEncoding(); I.Fun.ExceptionSpecLocEnd = ESpecRange.getEnd().getRawEncoding(); - I.Fun.NumExceptions = 0; + I.Fun.NumExceptionsOrDecls = 0; I.Fun.Exceptions = nullptr; I.Fun.NoexceptExpr = nullptr; I.Fun.HasTrailingReturnType = TrailingReturnType.isUsable() || @@ -240,7 +242,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, case EST_Dynamic: // new[] an exception array if needed if (NumExceptions) { - I.Fun.NumExceptions = NumExceptions; + I.Fun.NumExceptionsOrDecls = NumExceptions; I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions]; for (unsigned i = 0; i != NumExceptions; ++i) { I.Fun.Exceptions[i].Ty = Exceptions[i]; @@ -257,6 +259,17 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, I.Fun.ExceptionSpecTokens = ExceptionSpecTokens; break; } + + if (!DeclsInPrototype.empty()) { + assert(ESpecType == EST_None && NumExceptions == 0 && + "cannot have exception specifiers and decls in prototype"); + I.Fun.NumExceptionsOrDecls = DeclsInPrototype.size(); + // Copy the array of decls into stable heap storage. + I.Fun.DeclsInPrototype = new NamedDecl *[DeclsInPrototype.size()]; + for (size_t J = 0; J < DeclsInPrototype.size(); ++J) + I.Fun.DeclsInPrototype[J] = DeclsInPrototype[J]; + } + return I; } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 5d13c8fa039..9e764e3f5a7 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8222,8 +8222,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Copy the parameter declarations from the declarator D to the function // declaration NewFD, if they are available. First scavenge them into Params. SmallVector<ParmVarDecl*, 16> Params; - if (D.isFunctionDeclarator()) { - DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); + unsigned FTIIdx; + if (D.isFunctionDeclarator(FTIIdx)) { + DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(FTIIdx).Fun; // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs // function that takes no arguments, not a function that takes a @@ -8241,6 +8242,19 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD->setInvalidDecl(); } } + + if (!getLangOpts().CPlusPlus) { + // In C, find all the non-parameter declarations from the prototype and + // move them into the new function decl context as well. Typically they + // will have been added to the surrounding context of the prototype. + for (NamedDecl *NonParmDecl : FTI.getDeclsInPrototype()) { + DeclContext *OldDC = NonParmDecl->getDeclContext(); + if (OldDC->containsDecl(NonParmDecl)) + OldDC->removeDecl(NonParmDecl); + NonParmDecl->setDeclContext(NewFD); + NewFD->addDecl(NonParmDecl); + } + } } else if (const FunctionProtoType *FT = R->getAs<FunctionProtoType>()) { // When we're declaring a function with a typedef, typeof, etc as in the // following example, we'll need to synthesize (unnamed) @@ -8266,15 +8280,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Finally, we know we have the right number of parameters, install them. NewFD->setParams(Params); - // Find all anonymous symbols defined during the declaration of this function - // and add to NewFD. This lets us track decls such 'enum Y' in: - // - // void f(enum Y {AA} x) {} - // - // which would otherwise incorrectly end up in the translation unit scope. - NewFD->setDeclsInPrototypeScope(DeclsInPrototypeScope); - DeclsInPrototypeScope.clear(); - if (D.getDeclSpec().isNoreturnSpecified()) NewFD->addAttr( ::new(Context) C11NoReturnAttr(D.getDeclSpec().getNoreturnSpecLoc(), @@ -11632,6 +11637,29 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, CheckParmsForFunctionDef(FD->parameters(), /*CheckParameterNames=*/true); + // Add non-parameter declarations already in the function to the current + // scope. + if (FnBodyScope) { + for (Decl *NPD : FD->decls()) { + auto *NonParmDecl = dyn_cast<NamedDecl>(NPD); + if (!NonParmDecl) + continue; + assert(!isa<ParmVarDecl>(NonParmDecl) && + "parameters should not be in newly created FD yet"); + + // If the decl has a name, make it accessible in the current scope. + if (NonParmDecl->getDeclName()) + PushOnScopeChains(NonParmDecl, FnBodyScope, /*AddToContext=*/false); + + // Similarly, dive into enums and fish their constants out, making them + // accessible in this scope. + if (auto *ED = dyn_cast<EnumDecl>(NonParmDecl)) { + for (auto *EI : ED->enumerators()) + PushOnScopeChains(EI, FnBodyScope, /*AddToContext=*/false); + } + } + } + // Introduce our parameters into the function scope for (auto Param : FD->parameters()) { Param->setOwningFunction(FD); @@ -11644,39 +11672,6 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, } } - // If we had any tags defined in the function prototype, - // introduce them into the function scope. - if (FnBodyScope) { - for (ArrayRef<NamedDecl *>::iterator - I = FD->getDeclsInPrototypeScope().begin(), - E = FD->getDeclsInPrototypeScope().end(); - I != E; ++I) { - NamedDecl *D = *I; - - // Some of these decls (like enums) may have been pinned to the - // translation unit for lack of a real context earlier. If so, remove - // from the translation unit and reattach to the current context. - if (D->getLexicalDeclContext() == Context.getTranslationUnitDecl()) { - // Is the decl actually in the context? - if (Context.getTranslationUnitDecl()->containsDecl(D)) - Context.getTranslationUnitDecl()->removeDecl(D); - // Either way, reassign the lexical decl context to our FunctionDecl. - D->setLexicalDeclContext(CurContext); - } - - // If the decl has a non-null name, make accessible in the current scope. - if (!D->getName().empty()) - PushOnScopeChains(D, FnBodyScope, /*AddToContext=*/false); - - // Similarly, dive into enums and fish their constants out, making them - // accessible in this scope. - if (auto *ED = dyn_cast<EnumDecl>(D)) { - for (auto *EI : ED->enumerators()) - PushOnScopeChains(EI, FnBodyScope, /*AddToContext=*/false); - } - } - } - // Ensure that the function's exception specification is instantiated. if (const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>()) ResolveExceptionSpec(D->getLocation(), FPT); @@ -12161,6 +12156,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, /*NumExceptions=*/0, /*NoexceptExpr=*/nullptr, /*ExceptionSpecTokens=*/nullptr, + /*DeclsInPrototype=*/None, Loc, Loc, D), DS.getAttributes(), SourceLocation()); @@ -13430,7 +13426,6 @@ CreateNewDecl: } else if (!PrevDecl) { Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New); } - DeclsInPrototypeScope.push_back(New); } if (Invalid) diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index c278639073b..c8bc2c38809 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -772,7 +772,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { } if (Chunk.Fun.getExceptionSpecType() == EST_Dynamic) { - for (unsigned i = 0; i != Chunk.Fun.NumExceptions; ++i) { + for (unsigned i = 0; i != Chunk.Fun.getNumExceptions(); ++i) { if (Chunk.Fun.Exceptions[i] .Ty.get() ->containsUnexpandedParameterPack()) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 9bfc6ccfdc9..6ea34511212 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -718,6 +718,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state, /*NumExceptions=*/0, /*NoexceptExpr=*/nullptr, /*ExceptionSpecTokens=*/nullptr, + /*DeclsInPrototype=*/None, loc, loc, declarator)); // For consistency, make sure the state still has us as processing @@ -4469,7 +4470,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (FTI.getExceptionSpecType() == EST_Dynamic) { // FIXME: It's rather inefficient to have to split into two vectors // here. - unsigned N = FTI.NumExceptions; + unsigned N = FTI.getNumExceptions(); DynamicExceptions.reserve(N); DynamicExceptionRanges.reserve(N); for (unsigned I = 0; I != N; ++I) { |