Switch the semantic DeclContext for a block-scope declaration of a function or
variable from being the function to being the enclosing namespace scope (in
C++) or the TU (in C). This allows us to fix a selection of related issues
where we would build incorrect redeclaration chains for such declarations, and
fail to notice type mismatches.
Such declarations are put into a new IdentifierNamespace, IDNS_LocalExtern,
which is only found when searching scopes, and not found when searching
DeclContexts. Such a declaration is only made visible in its DeclContext if
there are no non-LocalExtern declarations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191064 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 8cd3725..e03e8c5 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -347,8 +347,12 @@
return 0;
}
+ DeclContext *DC = Owner;
+ if (D->isLocalExternDecl())
+ SemaRef.adjustContextForLocalExternDecl(DC);
+
// Build the instantiated declaration.
- VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner, D->getInnerLocStart(),
+ VarDecl *Var = VarDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(),
D->getLocation(), D->getIdentifier(),
DI->getType(), DI, D->getStorageClass());
@@ -361,7 +365,7 @@
if (SubstQualifier(D, Var))
return 0;
- SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs,
+ SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, Owner,
StartingScope, InstantiatingVarTemplate);
return Var;
}
@@ -1199,11 +1203,13 @@
}
// If we're instantiating a local function declaration, put the result
- // in the owner; otherwise we need to find the instantiated context.
+ // in the enclosing namespace; otherwise we need to find the instantiated
+ // context.
DeclContext *DC;
- if (D->getDeclContext()->isFunctionOrMethod())
+ if (D->isLocalExternDecl()) {
DC = Owner;
- else if (isFriend && QualifierLoc) {
+ SemaRef.adjustContextForLocalExternDecl(DC);
+ } else if (isFriend && QualifierLoc) {
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
DC = SemaRef.computeDeclContext(SS);
@@ -1227,8 +1233,11 @@
if (QualifierLoc)
Function->setQualifierInfo(QualifierLoc);
+ if (D->isLocalExternDecl())
+ Function->setLocalExternDecl();
+
DeclContext *LexicalDC = Owner;
- if (!isFriend && D->isOutOfLine()) {
+ if (!isFriend && D->isOutOfLine() && !D->isLocalExternDecl()) {
assert(D->getDeclContext()->isFileContext());
LexicalDC = D->getDeclContext();
}
@@ -1294,8 +1303,11 @@
bool isExplicitSpecialization = false;
- LookupResult Previous(SemaRef, Function->getDeclName(), SourceLocation(),
- Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+ LookupResult Previous(
+ SemaRef, Function->getDeclName(), SourceLocation(),
+ D->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage
+ : Sema::LookupOrdinaryName,
+ Sema::ForRedeclaration);
if (DependentFunctionTemplateSpecializationInfo *Info
= D->getDependentSpecializationInfo()) {
@@ -1427,6 +1439,9 @@
}
}
+ if (Function->isLocalExternDecl() && !Function->getPreviousDecl())
+ DC->makeDeclVisibleInContext(PrincipalDecl);
+
if (Function->isOverloadedOperator() && !DC->isRecord() &&
PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
PrincipalDecl->setNonMemberOperator();
@@ -2358,7 +2373,7 @@
return 0;
SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs,
- StartingScope);
+ Owner, StartingScope);
return Var;
}
@@ -2680,7 +2695,7 @@
if (VarDecl *Def = PartialSpec->getDefinition(SemaRef.getASTContext()))
PartialSpec = cast<VarTemplatePartialSpecializationDecl>(Def);
SemaRef.BuildVariableInstantiation(InstPartialSpec, PartialSpec, TemplateArgs,
- LateAttrs, StartingScope);
+ LateAttrs, Owner, StartingScope);
InstPartialSpec->setInit(PartialSpec->getInit());
return InstPartialSpec;
@@ -3335,13 +3350,19 @@
void Sema::BuildVariableInstantiation(
VarDecl *NewVar, VarDecl *OldVar,
const MultiLevelTemplateArgumentList &TemplateArgs,
- LateInstantiatedAttrVec *LateAttrs, LocalInstantiationScope *StartingScope,
+ LateInstantiatedAttrVec *LateAttrs, DeclContext *Owner,
+ LocalInstantiationScope *StartingScope,
bool InstantiatingVarTemplate) {
+ // If we are instantiating a local extern declaration, the
+ // instantiation belongs lexically to the containing function.
// If we are instantiating a static data member defined
// out-of-line, the instantiation will have the same lexical
// context (which will be a namespace scope) as the template.
- if (OldVar->isOutOfLine())
+ if (OldVar->isLocalExternDecl()) {
+ NewVar->setLocalExternDecl();
+ NewVar->setLexicalDeclContext(Owner);
+ } else if (OldVar->isOutOfLine())
NewVar->setLexicalDeclContext(OldVar->getLexicalDeclContext());
NewVar->setTSCSpec(OldVar->getTSCSpec());
NewVar->setInitStyle(OldVar->getInitStyle());
@@ -3374,11 +3395,13 @@
if (NewVar->hasAttrs())
CheckAlignasUnderalignment(NewVar);
- LookupResult Previous(*this, NewVar->getDeclName(), NewVar->getLocation(),
- Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+ LookupResult Previous(
+ *this, NewVar->getDeclName(), NewVar->getLocation(),
+ NewVar->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage
+ : Sema::LookupOrdinaryName,
+ Sema::ForRedeclaration);
- if (NewVar->getLexicalDeclContext()->isFunctionOrMethod() &&
- OldVar->getPreviousDecl()) {
+ if (NewVar->isLocalExternDecl() && OldVar->getPreviousDecl()) {
// We have a previous declaration. Use that one, so we merge with the
// right type.
if (NamedDecl *NewPrev = FindInstantiatedDecl(
@@ -3389,13 +3412,13 @@
LookupQualifiedName(Previous, NewVar->getDeclContext(), false);
CheckVariableDeclaration(NewVar, Previous);
- if (OldVar->isOutOfLine()) {
- OldVar->getLexicalDeclContext()->addDecl(NewVar);
- if (!InstantiatingVarTemplate)
+ if (!InstantiatingVarTemplate) {
+ NewVar->getLexicalDeclContext()->addHiddenDecl(NewVar);
+ if (!NewVar->isLocalExternDecl() || !NewVar->getPreviousDecl())
NewVar->getDeclContext()->makeDeclVisibleInContext(NewVar);
- } else {
- if (!InstantiatingVarTemplate)
- NewVar->getDeclContext()->addDecl(NewVar);
+ }
+
+ if (!OldVar->isOutOfLine()) {
if (NewVar->getDeclContext()->isFunctionOrMethod())
CurrentInstantiationScope->InstantiatedLocal(OldVar, NewVar);
}