From 99a7238b1acc6f4f41d39aeec6f25049375a24ec Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 3 Sep 2013 21:00:58 +0000 Subject: [PATCH] Refactor computation of whether a variable declaration's type should be merged with a prior declaration. No functionality change intended. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189850 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 3 +- lib/Sema/SemaDecl.cpp | 74 ++++++++++++++++++--------------------- 2 files changed, 36 insertions(+), 41 deletions(-) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index cc8535ae30..03c88be75e 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1867,8 +1867,7 @@ public: bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, Scope *S, bool MergeTypeWithOld); void mergeObjCMethodDecls(ObjCMethodDecl *New, ObjCMethodDecl *Old); - void MergeVarDecl(VarDecl *New, LookupResult &Previous, - bool MergeTypeWithPrevious); + void MergeVarDecl(VarDecl *New, LookupResult &Previous); void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld); void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old); bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 6bfecd8e51..b6032339f7 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2863,11 +2863,40 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, } // Don't actually update the type on the new declaration if the old - // declaration was a extern declaration in a different scope. + // declaration was an extern declaration in a different scope. if (MergeTypeWithOld) New->setType(MergedT); } +static bool mergeTypeWithPrevious(Sema &S, VarDecl *NewVD, VarDecl *OldVD, + LookupResult &Previous) { + // C11 6.2.7p4: + // For an identifier with internal or external linkage declared + // in a scope in which a prior declaration of that identifier is + // visible, if the prior declaration specifies internal or + // external linkage, the type of the identifier at the later + // declaration becomes the composite type. + // + // If the variable isn't visible, we do not merge with its type. + if (Previous.isShadowed()) + return false; + + if (S.getLangOpts().CPlusPlus) { + // C++11 [dcl.array]p3: + // If there is a preceding declaration of the entity in the same + // scope in which the bound was specified, an omitted array bound + // is taken to be the same as in that earlier declaration. + return NewVD->isPreviousDeclInSameBlockScope() || + (!OldVD->getLexicalDeclContext()->isFunctionOrMethod() && + !NewVD->getLexicalDeclContext()->isFunctionOrMethod()); + } else { + // If the old declaration was function-local, don't merge with its + // type unless we're in the same function. + return !OldVD->getLexicalDeclContext()->isFunctionOrMethod() || + OldVD->getLexicalDeclContext() == NewVD->getLexicalDeclContext(); + } +} + /// MergeVarDecl - We just parsed a variable 'New' which has the same name /// and scope as a previous declaration 'Old'. Figure out how to resolve this /// situation, merging decls or emitting diagnostics as appropriate. @@ -2876,8 +2905,7 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, /// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative /// definitions here, since the initializer hasn't been attached. /// -void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous, - bool MergeTypeWithPrevious) { +void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { // If the new decl is already invalid, don't do any other checking. if (New->isInvalidDecl()) return; @@ -2926,7 +2954,8 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous, } // Merge the types. - MergeVarDeclTypes(New, Old, MergeTypeWithPrevious); + MergeVarDeclTypes(New, Old, mergeTypeWithPrevious(*this, New, Old, Previous)); + if (New->isInvalidDecl()) return; @@ -5711,48 +5740,15 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) { // If we did not find anything by this name, look for a non-visible // extern "C" declaration with the same name. - // - // The actual standards text here is: - // - // C++11 [basic.link]p6: - // The name of a function declared in block scope and the name - // of a variable declared by a block scope extern declaration - // have linkage. If there is a visible declaration of an entity - // with linkage having the same name and type, ignoring entities - // declared outside the innermost enclosing namespace scope, the - // block scope declaration declares that same entity and - // receives the linkage of the previous declaration. - // - // C++11 [dcl.array]p3: - // If there is a preceding declaration of the entity in the same - // scope in which the bound was specified, an omitted array bound - // is taken to be the same as in that earlier declaration. - // - // C11 6.2.7p4: - // For an identifier with internal or external linkage declared - // in a scope in which a prior declaration of that identifier is - // visible, if the prior declaration specifies internal or - // external linkage, the type of the identifier at the later - // declaration becomes the composite type. - // - // The most important point here is that we're not allowed to - // update our understanding of the type according to declarations - // not in scope (in C++) or not visible (in C). - bool MergeTypeWithPrevious; if (Previous.empty() && checkForConflictWithNonVisibleExternC(*this, NewVD, Previous)) - MergeTypeWithPrevious = false; - else - MergeTypeWithPrevious = - !Previous.isShadowed() && - (!getLangOpts().CPlusPlus || NewVD->isPreviousDeclInSameBlockScope() || - !NewVD->getLexicalDeclContext()->isFunctionOrMethod()); + Previous.setShadowed(); // Filter out any non-conflicting previous declarations. filterNonConflictingPreviousDecls(Context, NewVD, Previous); if (!Previous.empty()) { - MergeVarDecl(NewVD, Previous, MergeTypeWithPrevious); + MergeVarDecl(NewVD, Previous); return true; } return false; -- 2.40.0