diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:33:12 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:33:12 +0000 |
| commit | ef915aab0ac566c55bfb0d7a9f6635bb5d94d4af (patch) | |
| tree | ac935cfa19985d33098fc13e288b5ac830672dba /lib/Sema | |
| parent | 325377b57338e700317f5e423e5b0f1c08d99a39 (diff) | |
Notes
Diffstat (limited to 'lib/Sema')
| -rw-r--r-- | lib/Sema/AnalysisBasedWarnings.cpp | 150 | ||||
| -rw-r--r-- | lib/Sema/Sema.cpp | 3 | ||||
| -rw-r--r-- | lib/Sema/SemaCUDA.cpp | 6 | ||||
| -rw-r--r-- | lib/Sema/SemaDecl.cpp | 37 | ||||
| -rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 60 | ||||
| -rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 6 | ||||
| -rw-r--r-- | lib/Sema/SemaExpr.cpp | 1 | ||||
| -rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 4 | ||||
| -rw-r--r-- | lib/Sema/SemaLookup.cpp | 14 | ||||
| -rw-r--r-- | lib/Sema/SemaTemplate.cpp | 3 | ||||
| -rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 4 | ||||
| -rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 15 |
12 files changed, 270 insertions, 33 deletions
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index db688b12cbcf..934e13e72d05 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -279,6 +279,150 @@ static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD, } //===----------------------------------------------------------------------===// +// Check for throw in a non-throwing function. +//===----------------------------------------------------------------------===// +enum ThrowState { + FoundNoPathForThrow, + FoundPathForThrow, + FoundPathWithNoThrowOutFunction, +}; + +static bool isThrowCaught(const CXXThrowExpr *Throw, + const CXXCatchStmt *Catch) { + const Type *ThrowType = nullptr; + if (Throw->getSubExpr()) + ThrowType = Throw->getSubExpr()->getType().getTypePtrOrNull(); + if (!ThrowType) + return false; + const Type *CaughtType = Catch->getCaughtType().getTypePtrOrNull(); + if (!CaughtType) + return true; + if (ThrowType->isReferenceType()) + ThrowType = ThrowType->castAs<ReferenceType>() + ->getPointeeType() + ->getUnqualifiedDesugaredType(); + if (CaughtType->isReferenceType()) + CaughtType = CaughtType->castAs<ReferenceType>() + ->getPointeeType() + ->getUnqualifiedDesugaredType(); + if (CaughtType == ThrowType) + return true; + const CXXRecordDecl *CaughtAsRecordType = + CaughtType->getPointeeCXXRecordDecl(); + const CXXRecordDecl *ThrowTypeAsRecordType = ThrowType->getAsCXXRecordDecl(); + if (CaughtAsRecordType && ThrowTypeAsRecordType) + return ThrowTypeAsRecordType->isDerivedFrom(CaughtAsRecordType); + return false; +} + +static bool isThrowCaughtByHandlers(const CXXThrowExpr *CE, + const CXXTryStmt *TryStmt) { + for (unsigned H = 0, E = TryStmt->getNumHandlers(); H < E; ++H) { + if (isThrowCaught(CE, TryStmt->getHandler(H))) + return true; + } + return false; +} + +static bool doesThrowEscapePath(CFGBlock Block, SourceLocation &OpLoc) { + for (const auto &B : Block) { + if (B.getKind() != CFGElement::Statement) + continue; + const auto *CE = dyn_cast<CXXThrowExpr>(B.getAs<CFGStmt>()->getStmt()); + if (!CE) + continue; + + OpLoc = CE->getThrowLoc(); + for (const auto &I : Block.succs()) { + if (!I.isReachable()) + continue; + if (const auto *Terminator = + dyn_cast_or_null<CXXTryStmt>(I->getTerminator())) + if (isThrowCaughtByHandlers(CE, Terminator)) + return false; + } + return true; + } + return false; +} + +static bool hasThrowOutNonThrowingFunc(SourceLocation &OpLoc, CFG *BodyCFG) { + + unsigned ExitID = BodyCFG->getExit().getBlockID(); + + SmallVector<ThrowState, 16> States(BodyCFG->getNumBlockIDs(), + FoundNoPathForThrow); + States[BodyCFG->getEntry().getBlockID()] = FoundPathWithNoThrowOutFunction; + + SmallVector<CFGBlock *, 16> Stack; + Stack.push_back(&BodyCFG->getEntry()); + while (!Stack.empty()) { + CFGBlock *CurBlock = Stack.back(); + Stack.pop_back(); + + unsigned ID = CurBlock->getBlockID(); + ThrowState CurState = States[ID]; + if (CurState == FoundPathWithNoThrowOutFunction) { + if (ExitID == ID) + continue; + + if (doesThrowEscapePath(*CurBlock, OpLoc)) + CurState = FoundPathForThrow; + } + + // Loop over successor blocks and add them to the Stack if their state + // changes. + for (const auto &I : CurBlock->succs()) + if (I.isReachable()) { + unsigned NextID = I->getBlockID(); + if (NextID == ExitID && CurState == FoundPathForThrow) { + States[NextID] = CurState; + } else if (States[NextID] < CurState) { + States[NextID] = CurState; + Stack.push_back(I); + } + } + } + // Return true if the exit node is reachable, and only reachable through + // a throw expression. + return States[ExitID] == FoundPathForThrow; +} + +static void EmitDiagForCXXThrowInNonThrowingFunc(Sema &S, SourceLocation OpLoc, + const FunctionDecl *FD) { + if (!S.getSourceManager().isInSystemHeader(OpLoc)) { + S.Diag(OpLoc, diag::warn_throw_in_noexcept_func) << FD; + if (S.getLangOpts().CPlusPlus11 && + (isa<CXXDestructorDecl>(FD) || + FD->getDeclName().getCXXOverloadedOperator() == OO_Delete || + FD->getDeclName().getCXXOverloadedOperator() == OO_Array_Delete)) + S.Diag(FD->getLocation(), diag::note_throw_in_dtor); + else + S.Diag(FD->getLocation(), diag::note_throw_in_function); + } +} + +static void checkThrowInNonThrowingFunc(Sema &S, const FunctionDecl *FD, + AnalysisDeclContext &AC) { + CFG *BodyCFG = AC.getCFG(); + if (!BodyCFG) + return; + if (BodyCFG->getExit().pred_empty()) + return; + SourceLocation OpLoc; + if (hasThrowOutNonThrowingFunc(OpLoc, BodyCFG)) + EmitDiagForCXXThrowInNonThrowingFunc(S, OpLoc, FD); +} + +static bool isNoexcept(const FunctionDecl *FD) { + const auto *FPT = FD->getType()->castAs<FunctionProtoType>(); + if (FPT->getExceptionSpecType() != EST_None && + FPT->isNothrow(FD->getASTContext())) + return true; + return false; +} + +//===----------------------------------------------------------------------===// // Check for missing return value. //===----------------------------------------------------------------------===// @@ -2127,6 +2271,12 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, } } + // Check for throw out of non-throwing function. + if (!Diags.isIgnored(diag::warn_throw_in_noexcept_func, D->getLocStart())) + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + if (S.getLangOpts().CPlusPlus && isNoexcept(FD)) + checkThrowInNonThrowingFunc(S, FD, AC); + // If none of the previous checks caused a CFG build, trigger one here // for -Wtautological-overlap-compare if (!Diags.isIgnored(diag::warn_tautological_overlap_comparison, diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index e7b0914641ff..007a5e483e6c 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -740,6 +740,9 @@ void Sema::ActOnEndOfTranslationUnit() { // Load pending instantiations from the external source. SmallVector<PendingImplicitInstantiation, 4> Pending; ExternalSource->ReadPendingInstantiations(Pending); + for (auto PII : Pending) + if (auto Func = dyn_cast<FunctionDecl>(PII.first)) + Func->setInstantiationIsPending(true); PendingInstantiations.insert(PendingInstantiations.begin(), Pending.begin(), Pending.end()); } diff --git a/lib/Sema/SemaCUDA.cpp b/lib/Sema/SemaCUDA.cpp index b938ac387c4d..cac5f682275e 100644 --- a/lib/Sema/SemaCUDA.cpp +++ b/lib/Sema/SemaCUDA.cpp @@ -629,12 +629,6 @@ static bool IsKnownEmitted(Sema &S, FunctionDecl *FD) { // emitted, because (say) the definition could include "inline". FunctionDecl *Def = FD->getDefinition(); - // We may currently be parsing the body of FD, in which case - // FD->getDefinition() will be null, but we still want to treat FD as though - // it's a definition. - if (!Def && FD->willHaveBody()) - Def = FD; - if (Def && !isDiscardableGVALinkage(S.getASTContext().GetGVALinkageForFunction(Def))) return true; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index cba220daf774..e340456bc6da 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -7260,11 +7260,11 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { NewVD->setInvalidDecl(); return; } - // OpenCL v1.1 s6.5.2 and s6.5.3 no local or constant variables - // in functions. if (T.getAddressSpace() == LangAS::opencl_constant || T.getAddressSpace() == LangAS::opencl_local) { FunctionDecl *FD = getCurFunctionDecl(); + // OpenCL v1.1 s6.5.2 and s6.5.3: no local or constant variables + // in functions. if (FD && !FD->hasAttr<OpenCLKernelAttr>()) { if (T.getAddressSpace() == LangAS::opencl_constant) Diag(NewVD->getLocation(), diag::err_opencl_function_variable) @@ -7275,6 +7275,20 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { NewVD->setInvalidDecl(); return; } + // OpenCL v2.0 s6.5.2 and s6.5.3: local and constant variables must be + // in the outermost scope of a kernel function. + if (FD && FD->hasAttr<OpenCLKernelAttr>()) { + if (!getCurScope()->isFunctionScope()) { + if (T.getAddressSpace() == LangAS::opencl_constant) + Diag(NewVD->getLocation(), diag::err_opencl_addrspace_scope) + << "constant"; + else + Diag(NewVD->getLocation(), diag::err_opencl_addrspace_scope) + << "local"; + NewVD->setInvalidDecl(); + return; + } + } } else if (T.getAddressSpace() != LangAS::Default) { // Do not allow other address spaces on automatic variable. Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 1; @@ -12218,6 +12232,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (FD) { FD->setBody(Body); + FD->setWillHaveBody(false); if (getLangOpts().CPlusPlus14) { if (!FD->isInvalidDecl() && Body && !FD->isDependentContext() && @@ -13075,7 +13090,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation ScopedEnumKWLoc, bool ScopedEnumUsesClassTag, TypeResult UnderlyingType, - bool IsTypeSpecifier, SkipBodyInfo *SkipBody) { + bool IsTypeSpecifier, bool IsTemplateParamOrArg, + SkipBodyInfo *SkipBody) { // If this is not a definition, it must have a name. IdentifierInfo *OrigName = Name; assert((Name != nullptr || TUK == TUK_Definition) && @@ -13345,11 +13361,11 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // also need to do a redeclaration lookup there, just in case // there's a shadow friend decl. if (Name && Previous.empty() && - (TUK == TUK_Reference || TUK == TUK_Friend)) { + (TUK == TUK_Reference || TUK == TUK_Friend || IsTemplateParamOrArg)) { if (Invalid) goto CreateNewDecl; assert(SS.isEmpty()); - if (TUK == TUK_Reference) { + if (TUK == TUK_Reference || IsTemplateParamOrArg) { // C++ [basic.scope.pdecl]p5: // -- for an elaborated-type-specifier of the form // @@ -13782,7 +13798,8 @@ CreateNewDecl: // C++11 [dcl.type]p3: // A type-specifier-seq shall not define a class or enumeration [...]. - if (getLangOpts().CPlusPlus && IsTypeSpecifier && TUK == TUK_Definition) { + if (getLangOpts().CPlusPlus && (IsTypeSpecifier || IsTemplateParamOrArg) && + TUK == TUK_Definition) { Diag(New->getLocation(), diag::err_type_defined_in_type_specifier) << Context.getTagDeclType(New); Invalid = true; @@ -16089,7 +16106,10 @@ void Sema::ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod) { // lexically within the module. if (getLangOpts().trackLocalOwningModule()) { for (auto *DC = CurContext; DC; DC = DC->getLexicalParent()) { - cast<Decl>(DC)->setHidden(true); + cast<Decl>(DC)->setModuleOwnershipKind( + getLangOpts().ModulesLocalVisibility + ? Decl::ModuleOwnershipKind::VisibleWhenImported + : Decl::ModuleOwnershipKind::Visible); cast<Decl>(DC)->setLocalOwningModule(Mod); } } @@ -16129,7 +16149,8 @@ void Sema::ActOnModuleEnd(SourceLocation EomLoc, Module *Mod) { for (auto *DC = CurContext; DC; DC = DC->getLexicalParent()) { cast<Decl>(DC)->setLocalOwningModule(getCurrentModule()); if (!getCurrentModule()) - cast<Decl>(DC)->setHidden(false); + cast<Decl>(DC)->setModuleOwnershipKind( + Decl::ModuleOwnershipKind::Unowned); } } } diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index b43642f5493b..e8503427536d 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -6903,6 +6903,32 @@ static bool ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K, return true; } +static bool +shouldDiagnoseAvailabilityByDefault(const ASTContext &Context, + const VersionTuple &DeploymentVersion, + const VersionTuple &DeclVersion) { + const auto &Triple = Context.getTargetInfo().getTriple(); + VersionTuple ForceAvailabilityFromVersion; + switch (Triple.getOS()) { + case llvm::Triple::IOS: + case llvm::Triple::TvOS: + ForceAvailabilityFromVersion = VersionTuple(/*Major=*/11); + break; + case llvm::Triple::WatchOS: + ForceAvailabilityFromVersion = VersionTuple(/*Major=*/4); + break; + case llvm::Triple::Darwin: + case llvm::Triple::MacOSX: + ForceAvailabilityFromVersion = VersionTuple(/*Major=*/10, /*Minor=*/13); + break; + default: + // New targets should always warn about availability. + return Triple.getVendor() == llvm::Triple::Apple; + } + return DeploymentVersion >= ForceAvailabilityFromVersion || + DeclVersion >= ForceAvailabilityFromVersion; +} + static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, Decl *Ctx, const NamedDecl *D, StringRef Message, SourceLocation Loc, @@ -6991,13 +7017,26 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, } break; - case AR_NotYetIntroduced: - diag = diag::warn_partial_availability; - diag_message = diag::warn_partial_message; - diag_fwdclass_message = diag::warn_partial_fwdclass_message; + case AR_NotYetIntroduced: { + // We would like to emit the diagnostic even if -Wunguarded-availability is + // not specified for deployment targets >= to iOS 11 or equivalent or + // for declarations that were introduced in iOS 11 (macOS 10.13, ...) or + // later. + const AvailabilityAttr *AA = getAttrForPlatform(S.getASTContext(), D); + VersionTuple Introduced = AA->getIntroduced(); + bool NewWarning = shouldDiagnoseAvailabilityByDefault( + S.Context, S.Context.getTargetInfo().getPlatformMinVersion(), + Introduced); + diag = NewWarning ? diag::warn_partial_availability_new + : diag::warn_partial_availability; + diag_message = NewWarning ? diag::warn_partial_message_new + : diag::warn_partial_message; + diag_fwdclass_message = NewWarning ? diag::warn_partial_fwdclass_message_new + : diag::warn_partial_fwdclass_message; property_note_select = /* partial */ 2; available_here_select_kind = /* partial */ 3; break; + } case AR_Available: llvm_unreachable("Warning for availability of available declaration?"); @@ -7317,7 +7356,18 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( if (!ShouldDiagnoseAvailabilityInContext(SemaRef, Result, Introduced, Ctx)) return; - SemaRef.Diag(Range.getBegin(), diag::warn_unguarded_availability) + // We would like to emit the diagnostic even if -Wunguarded-availability is + // not specified for deployment targets >= to iOS 11 or equivalent or + // for declarations that were introduced in iOS 11 (macOS 10.13, ...) or + // later. + unsigned DiagKind = + shouldDiagnoseAvailabilityByDefault( + SemaRef.Context, + SemaRef.Context.getTargetInfo().getPlatformMinVersion(), Introduced) + ? diag::warn_unguarded_availability_new + : diag::warn_unguarded_availability; + + SemaRef.Diag(Range.getBegin(), DiagKind) << Range << D << AvailabilityAttr::getPrettyPlatformName( SemaRef.getASTContext().getTargetInfo().getPlatformName()) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 844299bb87cf..453ece9d9c4d 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -13394,7 +13394,8 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, /*ScopedEnumKWLoc=*/SourceLocation(), /*ScopedEnumUsesClassTag=*/false, /*UnderlyingType=*/TypeResult(), - /*IsTypeSpecifier=*/false); + /*IsTypeSpecifier=*/false, + /*IsTemplateParamOrArg=*/false); } NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); @@ -13878,6 +13879,9 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { return; } + // Deleted function does not have a body. + Fn->setWillHaveBody(false); + if (const FunctionDecl *Prev = Fn->getPreviousDecl()) { // Don't consider the implicit declaration we generate for explicit // specializations. FIXME: Do not generate these implicit declarations. diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 75a6903392ea..f49df6b3216d 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -13732,6 +13732,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, // call to such a function. InstantiateFunctionDefinition(PointOfInstantiation, Func); else { + Func->setInstantiationIsPending(true); PendingInstantiations.push_back(std::make_pair(Func, PointOfInstantiation)); // Notify the consumer that a function was implicitly instantiated. diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index a9ff21bc41ab..710ead30790f 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2630,7 +2630,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, // Make the function visible to name lookup, even if we found it in // an unimported module. It either is an implicitly-declared global // allocation function, or is suppressing that function. - Func->setHidden(false); + Func->setVisibleDespiteOwningModule(); return; } } @@ -2662,7 +2662,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, FnType, /*TInfo=*/nullptr, SC_None, false, true); Alloc->setImplicit(); // Global allocation functions should always be visible. - Alloc->setHidden(false); + Alloc->setVisibleDespiteOwningModule(); // Implicit sized deallocation functions always have default visibility. Alloc->addAttr( diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 1fb25f4e0e7c..2e7fb875a276 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -862,6 +862,16 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { if (!Record->isCompleteDefinition()) return Found; + // For conversion operators, 'operator auto' should only match + // 'operator auto'. Since 'auto' is not a type, it shouldn't be considered + // as a candidate for template substitution. + auto *ContainedDeducedType = + R.getLookupName().getCXXNameType()->getContainedDeducedType(); + if (R.getLookupName().getNameKind() == + DeclarationName::CXXConversionFunctionName && + ContainedDeducedType && ContainedDeducedType->isUndeducedType()) + return Found; + for (CXXRecordDecl::conversion_iterator U = Record->conversion_begin(), UEnd = Record->conversion_end(); U != UEnd; ++U) { FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(*U); @@ -1331,7 +1341,7 @@ void Sema::makeMergedDefinitionVisible(NamedDecl *ND) { Context.mergeDefinitionIntoModule(ND, M); else // We're not building a module; just make the definition visible. - ND->setHidden(false); + ND->setVisibleDespiteOwningModule(); // If ND is a template declaration, make the template parameters // visible too. They're not (necessarily) within a mergeable DeclContext. @@ -1518,7 +1528,7 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) { !SemaRef.getLangOpts().ModulesLocalVisibility) { // Cache the fact that this declaration is implicitly visible because // its parent has a visible definition. - D->setHidden(false); + D->setVisibleDespiteOwningModule(); } return true; } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 1eea151a4ec8..a8923ce9e27d 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -8612,7 +8612,8 @@ Sema::ActOnExplicitInstantiation(Scope *S, /*ModulePrivateLoc=*/SourceLocation(), MultiTemplateParamsArg(), Owned, IsDependent, SourceLocation(), false, TypeResult(), - /*IsTypeSpecifier*/false); + /*IsTypeSpecifier*/false, + /*IsTemplateParamOrArg*/false); assert(!IsDependent && "explicit instantiation of dependent name not yet handled"); if (!TagD) diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index fe92dd8ac653..f4f0c804aee1 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -2045,7 +2045,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, // The instantiation is visible here, even if it was first declared in an // unimported module. - Instantiation->setHidden(false); + Instantiation->setVisibleDespiteOwningModule(); // FIXME: This loses the as-written tag kind for an explicit instantiation. Instantiation->setTagKind(Pattern->getTagKind()); @@ -2247,7 +2247,7 @@ bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation, // The instantiation is visible here, even if it was first declared in an // unimported module. - Instantiation->setHidden(false); + Instantiation->setVisibleDespiteOwningModule(); // Enter the scope of this instantiation. We don't use // PushDeclContext because we don't have a scope. diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 148ce24293a0..abe912fb548b 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1782,6 +1782,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, Previous.clear(); } + if (isFriend) + Function->setObjectOfFriendDecl(); + SemaRef.CheckFunctionDeclaration(/*Scope*/ nullptr, Function, Previous, isExplicitSpecialization); @@ -3782,6 +3785,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // Try again at the end of the translation unit (at which point a // definition will be required). assert(!Recursive); + Function->setInstantiationIsPending(true); PendingInstantiations.push_back( std::make_pair(Function, PointOfInstantiation)); } else if (TSK == TSK_ImplicitInstantiation) { @@ -3801,6 +3805,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // Postpone late parsed template instantiations. if (PatternDecl->isLateTemplateParsed() && !LateTemplateParser) { + Function->setInstantiationIsPending(true); PendingInstantiations.push_back( std::make_pair(Function, PointOfInstantiation)); return; @@ -3863,7 +3868,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // The instantiation is visible here, even if it was first declared in an // unimported module. - Function->setHidden(false); + Function->setVisibleDespiteOwningModule(); // Copy the inner loc start from the pattern. Function->setInnerLocStart(PatternDecl->getInnerLocStart()); @@ -4269,7 +4274,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, // The instantiation is visible here, even if it was first declared in an // unimported module. - Var->setHidden(false); + Var->setVisibleDespiteOwningModule(); // If we're performing recursive template instantiation, create our own // queue of pending implicit instantiations that we will instantiate @@ -4285,9 +4290,6 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, InstantiateVariableInitializer(Var, PatternDecl, TemplateArgs); PreviousContext.pop(); - // FIXME: Need to inform the ASTConsumer that we instantiated the - // initializer? - // This variable may have local implicit instantiations that need to be // instantiated within this scope. LocalInstantiations.perform(); @@ -4397,7 +4399,6 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, if (Def->isStaticDataMember() && !Def->isOutOfLine()) { // We're instantiating an inline static data member whose definition was // provided inside the class. - // FIXME: Update record? InstantiateVariableInitializer(Var, Def, TemplateArgs); } else if (!VarSpec) { Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(), @@ -5146,6 +5147,8 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { TSK_ExplicitInstantiationDefinition; InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true, DefinitionRequired, true); + if (Function->isDefined()) + Function->setInstantiationIsPending(false); continue; } |
