summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp85
1 files changed, 40 insertions, 45 deletions
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)
OpenPOWER on IntegriCloud