forked from OSchip/llvm-project
Refactor computation of whether a variable declaration's type should be merged
with a prior declaration. No functionality change intended. llvm-svn: 189850
This commit is contained in:
parent
c656b8e402
commit
3c78578f33
clang
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue