diff options
author | James Molloy <james.molloy@arm.com> | 2012-02-29 10:24:19 +0000 |
---|---|---|
committer | James Molloy <james.molloy@arm.com> | 2012-02-29 10:24:19 +0000 |
commit | 16f1f717af196b1448258857b2e6dcfe144b39d0 (patch) | |
tree | 931424cf36ea32c824895fc76e378e277cd0ceed /lib/Sema/SemaDecl.cpp | |
parent | 4fafeb6452a79794726a1adc53fb5e2a5887c5f9 (diff) |
Reapply r151638 and r151641.
The bug that was caught by Apple's internal buildbots was valid and also showed another bug in my implementation.
These are now fixed, with regression tests added to catch them both (not Darwin-specific).
Original log:
====================
Revert r151638 because it causes assertion hit on PCH creation for Cocoa.h
Original log:
---------------------
Correctly track tags and enum members defined in the prototype of a function, and ensure they are properly scoped.
This fixes code such as:
enum e {x, y};
int f(enum {y, x} n) {
return 0;
}
This finally fixes PR5464 and PR5477.
---------------------
I also reverted r151641 which was enhancement on top of r151638.
====================
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151712 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 74 |
1 files changed, 73 insertions, 1 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index f091d858b5..7a0ae94739 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1249,6 +1249,15 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { } } +void Sema::ActOnStartFunctionDeclarator() { + ++InFunctionDeclarator; +} + +void Sema::ActOnEndFunctionDeclarator() { + assert(InFunctionDeclarator); + --InFunctionDeclarator; +} + /// \brief Look for an Objective-C class in the translation unit. /// /// \param Id The name of the Objective-C class we're looking for. If @@ -5241,6 +5250,15 @@ 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(); + // Process the non-inheritable attributes on this declaration. ProcessDeclAttributes(S, NewFD, D, /*NonInheritable=*/true, /*Inheritable=*/false); @@ -7225,6 +7243,43 @@ 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 (llvm::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? + for (DeclContext::decl_iterator DI = Context.getTranslationUnitDecl()->decls_begin(), + DE = Context.getTranslationUnitDecl()->decls_end(); DI != DE; ++DI) { + if (*DI == D) { + Context.getTranslationUnitDecl()->removeDecl(D); + break; + } + } + // 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 (EnumDecl *ED = dyn_cast<EnumDecl>(D)) { + for (EnumDecl::enumerator_iterator EI = ED->enumerator_begin(), + EE = ED->enumerator_end(); EI != EE; ++EI) + PushOnScopeChains(*EI, FnBodyScope, /*AddToContext=*/false); + } + } + } + // Checking attributes of current function definition // dllimport attribute. DLLImportAttr *DA = FD->getAttr<DLLImportAttr>(); @@ -8177,7 +8232,12 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, !isa<CXXRecordDecl>(Def) || cast<CXXRecordDecl>(Def)->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { - Diag(NameLoc, diag::err_redefinition) << Name; + // A redeclaration in function prototype scope in C isn't + // visible elsewhere, so merely issue a warning. + if (!getLangOptions().CPlusPlus && S->containedInPrototypeScope()) + Diag(NameLoc, diag::warn_redefinition_in_param_list) << Name; + else + Diag(NameLoc, diag::err_redefinition) << Name; Diag(Def->getLocation(), diag::note_previous_definition); // If this is a redefinition, recover by making this // struct be anonymous, which will make any later @@ -8459,6 +8519,12 @@ CreateNewDecl: II->isStr("FILE")) Context.setFILEDecl(New); + // If we were in function prototype scope (and not in C++ mode), add this + // tag to the list of decls to inject into the function definition scope. + if (S->isFunctionPrototypeScope() && !getLangOptions().CPlusPlus && + InFunctionDeclarator && Name) + DeclsInPrototypeScope.push_back(New); + OwnedDecl = true; return New; } @@ -10142,6 +10208,12 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, Enum->completeDefinition(BestType, BestPromotionType, NumPositiveBits, NumNegativeBits); + + // If we're declaring a function, ensure this decl isn't forgotten about - + // it needs to go into the function scope. + if (InFunctionDeclarator) + DeclsInPrototypeScope.push_back(Enum); + } Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, |