diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaAccess.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCodeComplete.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 120 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 20 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 44 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 67 |
7 files changed, 204 insertions, 71 deletions
diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index bd8d3e95a80..4ecbf0ba776 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -1483,7 +1483,9 @@ void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *D) { DeclContext *DC = D->getDeclContext(); if (FunctionDecl *FN = dyn_cast<FunctionDecl>(D)) { - if (!DC->isFunctionOrMethod()) + if (D->getLexicalDeclContext()->isFunctionOrMethod()) + DC = D->getLexicalDeclContext(); + else DC = FN; } else if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) { DC = cast<DeclContext>(TD->getTemplatedDecl()); diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 5e084eb5d41..e3e17b96018 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -715,8 +715,8 @@ unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) { return CCP_Unlikely; // Context-based decisions. - const DeclContext *DC = ND->getDeclContext()->getRedeclContext(); - if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC)) { + const DeclContext *LexicalDC = ND->getLexicalDeclContext(); + if (LexicalDC->isFunctionOrMethod()) { // _cmd is relatively rare if (const ImplicitParamDecl *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND)) @@ -726,6 +726,8 @@ unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) { return CCP_LocalDeclaration; } + + const DeclContext *DC = ND->getDeclContext()->getRedeclContext(); if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) return CCP_MemberDeclaration; @@ -876,8 +878,8 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { for (; I != IEnd; ++I) { // A tag declaration does not hide a non-tag declaration. if (I->first->hasTagIdentifierNamespace() && - (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | - Decl::IDNS_ObjCProtocol))) + (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | + Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol))) continue; // Protocols are in distinct namespaces from everything else. @@ -1038,7 +1040,9 @@ void ResultBuilder::ExitScope() { bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const { ND = cast<NamedDecl>(ND->getUnderlyingDecl()); - unsigned IDNS = Decl::IDNS_Ordinary; + // If name lookup finds a local extern declaration, then we are in a + // context where it behaves like an ordinary name. + unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern; if (SemaRef.getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; else if (SemaRef.getLangOpts().ObjC1) { @@ -1056,7 +1060,7 @@ bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const { if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) return false; - unsigned IDNS = Decl::IDNS_Ordinary; + unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern; if (SemaRef.getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; else if (SemaRef.getLangOpts().ObjC1) { @@ -1083,7 +1087,7 @@ bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const { bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const { ND = cast<NamedDecl>(ND->getUnderlyingDecl()); - unsigned IDNS = Decl::IDNS_Ordinary; + unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern; if (SemaRef.getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 4d4637fd143..68762e97fa2 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1020,12 +1020,12 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { if (AddToContext) CurContext->addDecl(D); - // Out-of-line definitions shouldn't be pushed into scope in C++. - // Out-of-line variable and function definitions shouldn't even in C. - if ((getLangOpts().CPlusPlus || isa<VarDecl>(D) || isa<FunctionDecl>(D)) && - D->isOutOfLine() && + // Out-of-line definitions shouldn't be pushed into scope in C++, unless they + // are function-local declarations. + if (getLangOpts().CPlusPlus && D->isOutOfLine() && !D->getDeclContext()->getRedeclContext()->Equals( - D->getLexicalDeclContext()->getRedeclContext())) + D->getLexicalDeclContext()->getRedeclContext()) && + !D->getLexicalDeclContext()->isFunctionOrMethod()) return; // Template instantiations should also not be pushed into scope. @@ -2426,7 +2426,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, ? New->getTypeSourceInfo()->getType()->castAs<FunctionType>() : NewType)->getResultType(); QualType ResQT; - if (!Context.hasSameType(OldDeclaredReturnType, NewDeclaredReturnType)) { + if (!Context.hasSameType(OldDeclaredReturnType, NewDeclaredReturnType) && + !((NewQType->isDependentType() || OldQType->isDependentType()) && + New->isLocalExternDecl())) { if (NewDeclaredReturnType->isObjCObjectPointerType() && OldDeclaredReturnType->isObjCObjectPointerType()) ResQT = Context.mergeObjCGCQualifiers(NewQType, OldQType); @@ -2578,6 +2580,14 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, if (OldQTypeForComparison == NewQType) return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld); + if ((NewQType->isDependentType() || OldQType->isDependentType()) && + New->isLocalExternDecl()) { + // It's OK if we couldn't merge types for a local function declaraton + // if either the old or new type is dependent. We'll merge the types + // when we instantiate the function. + return false; + } + // Fall through for conflicting redeclarations and redefinitions. } @@ -2710,7 +2720,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, // local declaration will produce a hard error; if it doesn't // remain visible, a single bogus local redeclaration (which is // actually only a warning) could break all the downstream code. - if (!New->getDeclContext()->isFunctionOrMethod()) + if (!New->getLexicalDeclContext()->isFunctionOrMethod()) New->getIdentifier()->setBuiltinID(Builtin::NotBuiltin); return false; @@ -2820,18 +2830,21 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, NewArray->getElementType())) MergedT = New->getType(); } else if (Old->getType()->isArrayType() && - New->getType()->isIncompleteArrayType()) { + New->getType()->isIncompleteArrayType()) { const ArrayType *OldArray = Context.getAsArrayType(Old->getType()); const ArrayType *NewArray = Context.getAsArrayType(New->getType()); if (Context.hasSameType(OldArray->getElementType(), NewArray->getElementType())) MergedT = Old->getType(); - } else if (New->getType()->isObjCObjectPointerType() - && Old->getType()->isObjCObjectPointerType()) { - MergedT = Context.mergeObjCGCQualifiers(New->getType(), - Old->getType()); + } else if (New->getType()->isObjCObjectPointerType() && + Old->getType()->isObjCObjectPointerType()) { + MergedT = Context.mergeObjCGCQualifiers(New->getType(), + Old->getType()); } } else { + // C 6.2.7p2: + // All declarations that refer to the same object or function shall have + // compatible type. MergedT = Context.mergeTypes(New->getType(), Old->getType()); } if (MergedT.isNull()) { @@ -4308,8 +4321,15 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, // If this has an identifier and is not an invalid redeclaration or // function template specialization, add it to the scope stack. if (New->getDeclName() && AddToScope && - !(D.isRedeclaration() && New->isInvalidDecl())) - PushOnScopeChains(New, S); + !(D.isRedeclaration() && New->isInvalidDecl())) { + // Only make a locally-scoped extern declaration visible if it is the first + // declaration of this entity. Qualified lookup for such an entity should + // only find this declaration if there is no visible declaration of it. + bool AddToContext = !D.isRedeclaration() || !New->isLocalExternDecl(); + PushOnScopeChains(New, S, AddToContext); + if (!AddToContext) + CurContext->addHiddenDecl(New); + } return New; } @@ -4808,6 +4828,30 @@ static bool shouldConsiderLinkage(const FunctionDecl *FD) { llvm_unreachable("Unexpected context"); } +/// Adjust the \c DeclContext for a function or variable that might be a +/// function-local external declaration. +bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) { + if (!DC->isFunctionOrMethod()) + return false; + + // If this is a local extern function or variable declared within a function + // template, don't add it into the enclosing namespace scope until it is + // instantiated; it might have a dependent type right now. + if (DC->isDependentContext()) + return true; + + // C++11 [basic.link]p7: + // When a block scope declaration of an entity with linkage is not found to + // refer to some other declaration, then that entity is a member of the + // innermost enclosing namespace. + // + // Per C++11 [namespace.def]p6, the innermost enclosing namespace is a + // semantically-enclosing namespace, not a lexically-enclosing one. + while (!DC->isFileContext() && !isa<LinkageSpecDecl>(DC)) + DC = DC->getParent(); + return true; +} + NamedDecl * Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo, LookupResult &Previous, @@ -4820,6 +4864,10 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(D.getDeclSpec()); + DeclContext *OriginalDC = DC; + bool IsLocalExternDecl = SC == SC_Extern && + adjustContextForLocalExternDecl(DC); + if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16) { // OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and // half array type (unless the cl_khr_fp16 extension is enabled). @@ -5150,6 +5198,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (NewTemplate) NewTemplate->setLexicalDeclContext(CurContext); + if (IsLocalExternDecl) + NewVD->setLocalExternDecl(); + if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) { if (NewVD->hasLocalStorage()) { // C++11 [dcl.stc]p4: @@ -5277,7 +5328,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // scope and are out-of-semantic-context declarations (if the new // declaration has linkage). FilterLookupForScope( - Previous, DC, S, shouldConsiderLinkage(NewVD), + Previous, OriginalDC, S, shouldConsiderLinkage(NewVD), IsExplicitSpecialization || IsVariableTemplateSpecialization); // Check whether the previous declaration is in the same block scope. This @@ -5286,7 +5337,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewVD->isLocalVarDecl() && NewVD->hasExternalStorage()) NewVD->setPreviousDeclInSameBlockScope( Previous.isSingleResult() && !Previous.isShadowed() && - isDeclInScope(Previous.getFoundDecl(), DC, S, false)); + isDeclInScope(Previous.getFoundDecl(), OriginalDC, S, false)); if (!getLangOpts().CPlusPlus) { D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); @@ -5543,12 +5594,8 @@ static bool checkForConflictWithNonVisibleExternC(Sema &S, const T *ND, LookupResult &Previous) { if (!S.getLangOpts().CPlusPlus) { // In C, when declaring a global variable, look for a corresponding 'extern' - // variable declared in function scope. - // - // FIXME: The corresponding case in C++ does not work. We should instead - // set the semantic DC for an extern local variable to be the innermost - // enclosing namespace, and ensure they are only found by redeclaration - // lookup. + // variable declared in function scope. We don't need this in C++, because + // we find local extern decls in the surrounding file-scope DeclContext. if (ND->getDeclContext()->getRedeclContext()->isTranslationUnit()) { if (NamedDecl *Prev = S.findLocallyScopedExternCDecl(ND->getDeclName())) { Previous.clear(); @@ -6032,6 +6079,7 @@ static NamedDecl *DiagnoseInvalidRedeclaration( bool FDisConst = MD && MD->isConst(); bool IsMember = MD || !IsLocalFriend; + // FIXME: These notes are poorly worded for the local friend case. if (unsigned Idx = NearMatch->second) { ParmVarDecl *FDParam = FD->getParamDecl(Idx-1); SourceLocation Loc = FDParam->getTypeSpecStartLoc(); @@ -6455,6 +6503,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, bool isVirtualOkay = false; + DeclContext *OriginalDC = DC; + bool IsLocalExternDecl = adjustContextForLocalExternDecl(DC); + FunctionDecl *NewFD = CreateNewFunctionDecl(*this, D, DC, R, TInfo, SC, isVirtualOkay); if (!NewFD) return 0; @@ -6462,6 +6513,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer()) NewFD->setTopLevelDeclInObjCContainer(); + // Set the lexical context. If this is a function-scope declaration, or has a + // C++ scope specifier, or is the object of a friend declaration, the lexical + // context will be different from the semantic context. + NewFD->setLexicalDeclContext(CurContext); + + if (IsLocalExternDecl) + NewFD->setLocalExternDecl(); + if (getLangOpts().CPlusPlus) { bool isInline = D.getDeclSpec().isInlineSpecified(); bool isVirtual = D.getDeclSpec().isVirtualSpecified(); @@ -6489,12 +6548,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, isFunctionTemplateSpecialization = false; if (D.isInvalidType()) NewFD->setInvalidDecl(); - - // Set the lexical context. If the declarator has a C++ - // scope specifier, or is the object of a friend declaration, the - // lexical context will be different from the semantic context. - NewFD->setLexicalDeclContext(CurContext); - + // Match up the template parameter lists with the scope specifier, then // determine whether we have a template or a template specialization. bool Invalid = false; @@ -6750,7 +6804,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } // Filter out previous declarations that don't match the scope. - FilterLookupForScope(Previous, DC, S, shouldConsiderLinkage(NewFD), + FilterLookupForScope(Previous, OriginalDC, S, shouldConsiderLinkage(NewFD), isExplicitSpecialization || isFunctionTemplateSpecialization); @@ -9232,21 +9286,21 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD, // Don't warn for OpenCL kernels. if (FD->hasAttr<OpenCLKernelAttr>()) return false; - + bool MissingPrototype = true; for (const FunctionDecl *Prev = FD->getPreviousDecl(); Prev; Prev = Prev->getPreviousDecl()) { // Ignore any declarations that occur in function or method // scope, because they aren't visible from the header. - if (Prev->getDeclContext()->isFunctionOrMethod()) + if (Prev->getLexicalDeclContext()->isFunctionOrMethod()) continue; - + MissingPrototype = !Prev->getType()->isFunctionProtoType(); if (FD->getNumParams() == 0) PossibleZeroParamPrototype = Prev; break; } - + return MissingPrototype; } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index dc33f2faf65..d4f9cc4380a 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -438,9 +438,9 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, // declaration (not even to the same value). // // C++ [dcl.fct.default]p6: - // Except for member functions of class templates, the default arguments - // in a member function definition that appears outside of the class - // definition are added to the set of default arguments provided by the + // Except for member functions of class templates, the default arguments + // in a member function definition that appears outside of the class + // definition are added to the set of default arguments provided by the // member function declaration in the class definition. for (unsigned p = 0, NumParams = Old->getNumParams(); p < NumParams; ++p) { ParmVarDecl *OldParam = Old->getParamDecl(p); @@ -450,9 +450,18 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, bool NewParamHasDfl = NewParam->hasDefaultArg(); NamedDecl *ND = Old; - if (S && !isDeclInScope(ND, New->getDeclContext(), S)) + + // The declaration context corresponding to the scope is the semantic + // parent, unless this is a local function declaration, in which case + // it is that surrounding function. + DeclContext *ScopeDC = New->getLexicalDeclContext(); + if (!ScopeDC->isFunctionOrMethod()) + ScopeDC = New->getDeclContext(); + if (S && !isDeclInScope(ND, ScopeDC, S) && + !New->getDeclContext()->isRecord()) // Ignore default parameters of old decl if they are not in - // the same scope. + // the same scope and this is not an out-of-line definition of + // a member function. OldParamHasDfl = false; if (OldParamHasDfl && NewParamHasDfl) { @@ -11486,6 +11495,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, // declared the function in, if we were permitted to, for error recovery. DC = FunctionContainingLocalClass; } + adjustContextForLocalExternDecl(DC); // C++ [class.friend]p6: // A function can be defined in a friend declaration of a class if and diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index d68bdbb425c..d0366122934 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2459,7 +2459,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS, // turn off ADL anyway). if (isa<UsingShadowDecl>(D)) D = cast<UsingShadowDecl>(D)->getTargetDecl(); - else if (D->getDeclContext()->isFunctionOrMethod()) + else if (D->getLexicalDeclContext()->isFunctionOrMethod()) return false; // C++0x [basic.lookup.argdep]p3: diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index c26960670e2..a645986ac31 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -223,6 +223,8 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind, if (Redeclaration) IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend; } + if (Redeclaration) + IDNS |= Decl::IDNS_LocalExtern; break; case Sema::LookupOperatorName: @@ -847,6 +849,26 @@ static std::pair<DeclContext *, bool> findOuterContext(Scope *S) { return std::make_pair(Lexical, false); } +namespace { +/// An RAII object to specify that we want to find block scope extern +/// declarations. +struct FindLocalExternScope { + FindLocalExternScope(LookupResult &R) + : R(R), OldFindLocalExtern(R.getIdentifierNamespace() & + Decl::IDNS_LocalExtern) { + R.setFindLocalExtern(R.getIdentifierNamespace() & Decl::IDNS_Ordinary); + } + void restore() { + R.setFindLocalExtern(OldFindLocalExtern); + } + ~FindLocalExternScope() { + restore(); + } + LookupResult &R; + bool OldFindLocalExtern; +}; +} + bool Sema::CppLookupName(LookupResult &R, Scope *S) { assert(getLangOpts().CPlusPlus && "Can perform only C++ lookup"); @@ -891,6 +913,10 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { bool VisitedUsingDirectives = false; bool LeftStartingScope = false; DeclContext *OutsideOfTemplateParamDC = 0; + + // When performing a scope lookup, we want to find local extern decls. + FindLocalExternScope FindLocals(R); + for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) { DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()); @@ -1046,7 +1072,12 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { UDirs.visitScopeChain(Initial, S); UDirs.done(); } - + + // If we're not performing redeclaration lookup, do not look for local + // extern declarations outside of a function scope. + if (!R.isForRedeclaration()) + FindLocals.restore(); + // Lookup namespace scope, and global scope. // Unqualified name lookup in C++ requires looking into scopes // that aren't strictly lexical, and therefore we walk through the @@ -1292,6 +1323,9 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { S = S->getParent(); } + // When performing a scope lookup, we want to find local extern decls. + FindLocalExternScope FindLocals(R); + // Scan up the scope chain looking for a decl that matches this // identifier that is in the appropriate namespace. This search // should not take long, as shadowing of names is uncommon, and @@ -1361,6 +1395,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { R.resolveKind(); } + return true; } } else { @@ -2858,7 +2893,11 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, NamedDecl *D = *I; // If the only declaration here is an ordinary friend, consider // it only if it was declared in an associated classes. - if (D->getIdentifierNamespace() == Decl::IDNS_OrdinaryFriend) { + if ((D->getIdentifierNamespace() & Decl::IDNS_Ordinary) == 0) { + // If it's neither ordinarily visible nor a friend, we can't find it. + if ((D->getIdentifierNamespace() & Decl::IDNS_OrdinaryFriend) == 0) + continue; + bool DeclaredInAssociatedClass = false; for (Decl *DI = D; DI; DI = DI->getPreviousDecl()) { DeclContext *LexDC = DI->getLexicalDeclContext(); @@ -3160,6 +3199,7 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, (!S->getParent() && !Visited.alreadyVisitedContext((DeclContext *)S->getEntity())) || ((DeclContext *)S->getEntity())->isFunctionOrMethod()) { + FindLocalExternScope FindLocals(Result); // Walk through the declarations in this Scope. for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end(); D != DEnd; ++D) { diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 8cd37258b6a..e03e8c55c9a 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -347,8 +347,12 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, 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 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, 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 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, } // 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 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, 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 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, 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 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, } } + if (Function->isLocalExternDecl() && !Function->getPreviousDecl()) + DC->makeDeclVisibleInContext(PrincipalDecl); + if (Function->isOverloadedOperator() && !DC->isRecord() && PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) PrincipalDecl->setNonMemberOperator(); @@ -2358,7 +2373,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( return 0; SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, - StartingScope); + Owner, StartingScope); return Var; } @@ -2680,7 +2695,7 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization( 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 @@ VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl( 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 @@ void Sema::BuildVariableInstantiation( 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 @@ void Sema::BuildVariableInstantiation( 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); } |