diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/Sema.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Sema/Sema.cpp | 606 |
1 files changed, 419 insertions, 187 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/Sema.cpp b/contrib/llvm-project/clang/lib/Sema/Sema.cpp index 191d89ea75c9..2d4e6d1d058c 100644 --- a/contrib/llvm-project/clang/lib/Sema/Sema.cpp +++ b/contrib/llvm-project/clang/lib/Sema/Sema.cpp @@ -33,10 +33,12 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Sema/CXXFieldCollector.h" #include "clang/Sema/DelayedDiagnostic.h" +#include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/ExternalSemaSource.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/MultiplexExternalSemaSource.h" #include "clang/Sema/ObjCMethodList.h" +#include "clang/Sema/RISCVIntrinsicManager.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaConsumer.h" @@ -45,8 +47,10 @@ #include "clang/Sema/TemplateInstCallback.h" #include "clang/Sema/TypoCorrection.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/TimeProfiler.h" +#include <optional> using namespace clang; using namespace sema; @@ -60,6 +64,16 @@ ModuleLoader &Sema::getModuleLoader() const { return PP.getModuleLoader(); } DarwinSDKInfo * Sema::getDarwinSDKInfoForAvailabilityChecking(SourceLocation Loc, StringRef Platform) { + auto *SDKInfo = getDarwinSDKInfoForAvailabilityChecking(); + if (!SDKInfo && !WarnedDarwinSDKInfoMissing) { + Diag(Loc, diag::warn_missing_sdksettings_for_availability_checking) + << Platform; + WarnedDarwinSDKInfoMissing = true; + } + return SDKInfo; +} + +DarwinSDKInfo *Sema::getDarwinSDKInfoForAvailabilityChecking() { if (CachedDarwinSDKInfo) return CachedDarwinSDKInfo->get(); auto SDKInfo = parseDarwinSDKInfo( @@ -71,8 +85,6 @@ Sema::getDarwinSDKInfoForAvailabilityChecking(SourceLocation Loc, } if (!SDKInfo) llvm::consumeError(SDKInfo.takeError()); - Diag(Loc, diag::warn_missing_sdksettings_for_availability_checking) - << Platform; CachedDarwinSDKInfo = std::unique_ptr<DarwinSDKInfo>(); return nullptr; } @@ -106,6 +118,9 @@ PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context, } } + // Shorten the data output if needed + Policy.EntireContentsOfLargeArray = false; + return Policy; } @@ -126,9 +141,9 @@ public: void reset() { S = nullptr; } - virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, - SrcMgr::CharacteristicKind FileType, - FileID PrevFID) override { + void FileChanged(SourceLocation Loc, FileChangeReason Reason, + SrcMgr::CharacteristicKind FileType, + FileID PrevFID) override { if (!S) return; switch (Reason) { @@ -137,9 +152,9 @@ public: SourceLocation IncludeLoc = SM.getIncludeLoc(SM.getFileID(Loc)); if (IncludeLoc.isValid()) { if (llvm::timeTraceProfilerEnabled()) { - const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(Loc)); - llvm::timeTraceProfilerBegin( - "Source", FE != nullptr ? FE->getName() : StringRef("<unknown>")); + OptionalFileEntryRef FE = SM.getFileEntryRefForID(SM.getFileID(Loc)); + llvm::timeTraceProfilerBegin("Source", FE ? FE->getName() + : StringRef("<unknown>")); } IncludeStack.push_back(IncludeLoc); @@ -169,14 +184,14 @@ public: } // end namespace clang const unsigned Sema::MaxAlignmentExponent; -const unsigned Sema::MaximumAlignment; +const uint64_t Sema::MaximumAlignment; Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter) - : ExternalSource(nullptr), isMultiplexExternalSource(false), - CurFPFeatures(pp.getLangOpts()), LangOpts(pp.getLangOpts()), PP(pp), - Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()), - SourceMgr(PP.getSourceManager()), CollectStats(false), + : ExternalSource(nullptr), CurFPFeatures(pp.getLangOpts()), + LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer), + Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), + APINotes(SourceMgr, LangOpts), CollectStats(false), CodeCompleter(CodeCompleter), CurContext(nullptr), OriginalLexicalContext(nullptr), MSStructPragmaOn(false), MSPointerToMemberRepresentationMethod( @@ -184,15 +199,15 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, VtorDispStack(LangOpts.getVtorDispMode()), AlignPackStack(AlignPackInfo(getLangOpts().XLPragmaPack)), DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr), - CodeSegStack(nullptr), FpPragmaStack(FPOptionsOverride()), - CurInitSeg(nullptr), VisContext(nullptr), - PragmaAttributeCurrentTargetDecl(nullptr), - IsBuildingRecoveryCallExpr(false), Cleanup{}, LateTemplateParser(nullptr), + CodeSegStack(nullptr), StrictGuardStackCheckStack(false), + FpPragmaStack(FPOptionsOverride()), CurInitSeg(nullptr), + VisContext(nullptr), PragmaAttributeCurrentTargetDecl(nullptr), + IsBuildingRecoveryCallExpr(false), LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp), - StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr), - StdCoroutineTraitsCache(nullptr), CXXTypeInfoDecl(nullptr), - MSVCGuidDecl(nullptr), NSNumberDecl(nullptr), NSValueDecl(nullptr), - NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr), + StdInitializerList(nullptr), StdCoroutineTraitsCache(nullptr), + CXXTypeInfoDecl(nullptr), StdSourceLocationImplDecl(nullptr), + NSNumberDecl(nullptr), NSValueDecl(nullptr), NSStringDecl(nullptr), + StringWithUTF8StringMethod(nullptr), ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr), ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr), DictionaryWithObjectsMethod(nullptr), GlobalNewDeleteDeclared(false), @@ -204,10 +219,9 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, ArgumentPackSubstitutionIndex(-1), CurrentInstantiationScope(nullptr), DisableTypoCorrection(false), TyposCorrected(0), AnalysisWarnings(*this), ThreadSafetyDeclCache(nullptr), VarDataSharingAttributesStack(nullptr), - CurScope(nullptr), Ident_super(nullptr), Ident___float128(nullptr) { + CurScope(nullptr), Ident_super(nullptr) { assert(pp.TUKind == TUKind); TUScope = nullptr; - isConstantEvaluatedOverride = false; LoadedExternalKnownNamespaces = false; for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I) @@ -222,6 +236,9 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, // Tell diagnostics how to render things from the AST library. Diags.SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &Context); + // This evaluation context exists to ensure that there's always at least one + // valid evaluation context available. It is never removed from the + // evaluation stack. ExprEvalContexts.emplace_back( ExpressionEvaluationContext::PotentiallyEvaluated, 0, CleanupInfo{}, nullptr, ExpressionEvaluationContextRecord::EK_Other); @@ -234,6 +251,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, SemaPPCallbackHandler = Callbacks.get(); PP.addPPCallbacks(std::move(Callbacks)); SemaPPCallbackHandler->set(*this); + + CurFPFeatures.setFPEvalMethod(PP.getCurrentFPEvalMethod()); } // Anchor Sema's type info to this TU. @@ -311,8 +330,9 @@ void Sema::Initialize() { if (getLangOpts().MSVCCompat) { if (getLangOpts().CPlusPlus && IdResolver.begin(&Context.Idents.get("type_info")) == IdResolver.end()) - PushOnScopeChains(Context.buildImplicitRecord("type_info", TTK_Class), - TUScope); + PushOnScopeChains( + Context.buildImplicitRecord("type_info", TagTypeKind::Class), + TUScope); addImplicitTypedef("size_t", Context.getSizeType()); } @@ -324,9 +344,12 @@ void Sema::Initialize() { Context.getTargetInfo().getSupportedOpenCLOpts(), getLangOpts()); addImplicitTypedef("sampler_t", Context.OCLSamplerTy); addImplicitTypedef("event_t", Context.OCLEventTy); - if (getLangOpts().OpenCLCPlusPlus || getLangOpts().OpenCLVersion >= 200) { - addImplicitTypedef("clk_event_t", Context.OCLClkEventTy); - addImplicitTypedef("queue_t", Context.OCLQueueTy); + auto OCLCompatibleVersion = getLangOpts().getOpenCLCompatibleVersion(); + if (OCLCompatibleVersion >= 200) { + if (getLangOpts().OpenCLCPlusPlus || getLangOpts().Blocks) { + addImplicitTypedef("clk_event_t", Context.OCLClkEventTy); + addImplicitTypedef("queue_t", Context.OCLQueueTy); + } if (getLangOpts().OpenCLPipes) addImplicitTypedef("reserve_id_t", Context.OCLReserveIDTy); addImplicitTypedef("atomic_int", Context.getAtomicType(Context.IntTy)); @@ -367,6 +390,11 @@ void Sema::Initialize() { AddPointerSizeDependentTypes(); } + if (getOpenCLOptions().isSupported("cl_khr_fp16", getLangOpts())) { + auto AtomicHalfT = Context.getAtomicType(Context.HalfTy); + addImplicitTypedef("atomic_half", AtomicHalfT); + } + std::vector<QualType> Atomic64BitTypes; if (getOpenCLOptions().isSupported("cl_khr_int64_base_atomics", getLangOpts()) && @@ -389,7 +417,6 @@ void Sema::Initialize() { } } - #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ if (getOpenCLOptions().isSupported(#Ext, getLangOpts())) { \ addImplicitTypedef(#ExtType, Context.Id##Ty); \ @@ -403,13 +430,10 @@ void Sema::Initialize() { #include "clang/Basic/AArch64SVEACLETypes.def" } - if (Context.getTargetInfo().getTriple().isPPC64() && - Context.getTargetInfo().hasFeature("paired-vector-memops")) { - if (Context.getTargetInfo().hasFeature("mma")) { + if (Context.getTargetInfo().getTriple().isPPC64()) { #define PPC_VECTOR_MMA_TYPE(Name, Id, Size) \ addImplicitTypedef(#Name, Context.Id##Ty); #include "clang/Basic/PPCTypes.def" - } #define PPC_VECTOR_VSX_TYPE(Name, Id, Size) \ addImplicitTypedef(#Name, Context.Id##Ty); #include "clang/Basic/PPCTypes.def" @@ -421,6 +445,13 @@ void Sema::Initialize() { #include "clang/Basic/RISCVVTypes.def" } + if (Context.getTargetInfo().getTriple().isWasm() && + Context.getTargetInfo().hasFeature("reference-types")) { +#define WASM_TYPE(Name, Id, SingletonId) \ + addImplicitTypedef(Name, Context.SingletonId); +#include "clang/Basic/WebAssemblyReferenceTypes.def" + } + if (Context.getTargetInfo().hasBuiltinMSVaList()) { DeclarationName MSVaList = &Context.Idents.get("__builtin_ms_va_list"); if (IdResolver.begin(MSVaList) == IdResolver.end()) @@ -451,13 +482,9 @@ Sema::~Sema() { = dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource())) ExternalSema->ForgetSema(); - // If Sema's ExternalSource is the multiplexer - we own it. - if (isMultiplexExternalSource) - delete ExternalSource; - // Delete cached satisfactions. std::vector<ConstraintSatisfaction *> Satisfactions; - Satisfactions.reserve(Satisfactions.size()); + Satisfactions.reserve(SatisfactionCache.size()); for (auto &Node : SatisfactionCache) Satisfactions.push_back(&Node); for (auto *Node : Satisfactions) @@ -528,12 +555,10 @@ void Sema::addExternalSource(ExternalSemaSource *E) { return; } - if (isMultiplexExternalSource) - static_cast<MultiplexExternalSemaSource*>(ExternalSource)->addSource(*E); - else { - ExternalSource = new MultiplexExternalSemaSource(*ExternalSource, *E); - isMultiplexExternalSource = true; - } + if (auto *Ex = dyn_cast<MultiplexExternalSemaSource>(ExternalSource)) + Ex->AddSource(E); + else + ExternalSource = new MultiplexExternalSemaSource(ExternalSource.get(), E); } /// Print out statistics about the semantic analysis. @@ -548,29 +573,34 @@ void Sema::PrintStats() const { void Sema::diagnoseNullableToNonnullConversion(QualType DstType, QualType SrcType, SourceLocation Loc) { - Optional<NullabilityKind> ExprNullability = SrcType->getNullability(Context); + std::optional<NullabilityKind> ExprNullability = SrcType->getNullability(); if (!ExprNullability || (*ExprNullability != NullabilityKind::Nullable && *ExprNullability != NullabilityKind::NullableResult)) return; - Optional<NullabilityKind> TypeNullability = DstType->getNullability(Context); + std::optional<NullabilityKind> TypeNullability = DstType->getNullability(); if (!TypeNullability || *TypeNullability != NullabilityKind::NonNull) return; Diag(Loc, diag::warn_nullability_lost) << SrcType << DstType; } -void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr* E) { - if (Diags.isIgnored(diag::warn_zero_as_null_pointer_constant, - E->getBeginLoc())) - return; +void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr *E) { // nullptr only exists from C++11 on, so don't warn on its absence earlier. if (!getLangOpts().CPlusPlus11) return; if (Kind != CK_NullToPointer && Kind != CK_NullToMemberPointer) return; - if (E->IgnoreParenImpCasts()->getType()->isNullPtrType()) + + const Expr *EStripped = E->IgnoreParenImpCasts(); + if (EStripped->getType()->isNullPtrType()) + return; + if (isa<GNUNullExpr>(EStripped)) + return; + + if (Diags.isIgnored(diag::warn_zero_as_null_pointer_constant, + E->getBeginLoc())) return; // Don't diagnose the conversion from a 0 literal to a null pointer argument @@ -580,8 +610,16 @@ void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr* E) { CodeSynthesisContext::RewritingOperatorAsSpaceship) return; + // Ignore null pointers in defaulted comparison operators. + FunctionDecl *FD = getCurFunctionDecl(); + if (FD && FD->isDefaulted()) { + return; + } + // If it is a macro from system header, and if the macro name is not "NULL", // do not warn. + // Note that uses of "NULL" will be ignored above on systems that define it + // as __null. SourceLocation MaybeMacroLoc = E->getBeginLoc(); if (Diags.getSuppressSystemWarnings() && SourceMgr.isInSystemMacro(MaybeMacroLoc) && @@ -754,15 +792,15 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) { return false; } -static bool isFunctionOrVarDeclExternC(NamedDecl *ND) { - if (auto *FD = dyn_cast<FunctionDecl>(ND)) +static bool isFunctionOrVarDeclExternC(const NamedDecl *ND) { + if (const auto *FD = dyn_cast<FunctionDecl>(ND)) return FD->isExternC(); return cast<VarDecl>(ND)->isExternC(); } /// Determine whether ND is an external-linkage function or variable whose /// type has no linkage. -bool Sema::isExternalWithNoLinkageType(ValueDecl *VD) { +bool Sema::isExternalWithNoLinkageType(const ValueDecl *VD) const { // Note: it's not quite enough to check whether VD has UniqueExternalLinkage, // because we also want to catch the case where its type has VisibleNoLinkage, // which does not affect the linkage of VD. @@ -794,7 +832,7 @@ void Sema::getUndefinedButUsed( continue; } - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { + if (const auto *FD = dyn_cast<FunctionDecl>(ND)) { if (FD->isDefined()) continue; if (FD->isExternallyVisible() && @@ -805,7 +843,7 @@ void Sema::getUndefinedButUsed( if (FD->getBuiltinID()) continue; } else { - auto *VD = cast<VarDecl>(ND); + const auto *VD = cast<VarDecl>(ND); if (VD->hasDefinition() != VarDecl::DeclarationOnly) continue; if (VD->isExternallyVisible() && @@ -832,9 +870,10 @@ static void checkUndefinedButUsed(Sema &S) { // Collect all the still-undefined entities with internal linkage. SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined; S.getUndefinedButUsed(Undefined); + S.UndefinedButUsed.clear(); if (Undefined.empty()) return; - for (auto Undef : Undefined) { + for (const auto &Undef : Undefined) { ValueDecl *VD = cast<ValueDecl>(Undef.first); SourceLocation UseLoc = Undef.second; @@ -885,8 +924,6 @@ static void checkUndefinedButUsed(Sema &S) { if (UseLoc.isValid()) S.Diag(UseLoc, diag::note_used_here); } - - S.UndefinedButUsed.clear(); } void Sema::LoadExternalWeakUndeclaredIdentifiers() { @@ -896,7 +933,7 @@ void Sema::LoadExternalWeakUndeclaredIdentifiers() { SmallVector<std::pair<IdentifierInfo *, WeakInfo>, 4> WeakIDs; ExternalSource->ReadWeakUndeclaredIdentifiers(WeakIDs); for (auto &WeakID : WeakIDs) - WeakUndeclaredIdentifiers.insert(WeakID); + (void)WeakUndeclaredIdentifiers[WeakID.first].insert(WeakID.second); } @@ -920,7 +957,7 @@ static bool MethodsAndNestedClassesComplete(const CXXRecordDecl *RD, I != E && Complete; ++I) { if (const CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(*I)) Complete = M->isDefined() || M->isDefaulted() || - (M->isPure() && !isa<CXXDestructorDecl>(M)); + (M->isPureVirtual() && !isa<CXXDestructorDecl>(M)); else if (const FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(*I)) // If the template function is marked as late template parsed at this // point, it has not been instantiated and therefore we have not @@ -997,15 +1034,9 @@ void Sema::emitAndClearUnusedLocalTypedefWarnings() { /// is parsed. Note that the ASTContext may have already injected some /// declarations. void Sema::ActOnStartOfTranslationUnit() { - if (getLangOpts().ModulesTS && - (getLangOpts().getCompilingModule() == LangOptions::CMK_ModuleInterface || - getLangOpts().getCompilingModule() == LangOptions::CMK_None)) { - // We start in an implied global module fragment. - SourceLocation StartOfTU = - SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); - ActOnGlobalModuleFragmentDecl(StartOfTU); - ModuleScopes.back().ImplicitGlobalModuleFragment = true; - } + if (getLangOpts().CPlusPlusModules && + getLangOpts().getCompilingModule() == LangOptions::CMK_HeaderUnit) + HandleStartOfHeaderUnit(); } void Sema::ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind) { @@ -1119,6 +1150,7 @@ void Sema::ActOnEndOfTranslationUnit() { DiagnoseUnterminatedPragmaAlignPack(); DiagnoseUnterminatedPragmaAttribute(); + DiagnoseUnterminatedOpenMPDeclareTarget(); // All delayed member exception specs should be checked or we end up accepting // incompatible declarations. @@ -1147,19 +1179,21 @@ void Sema::ActOnEndOfTranslationUnit() { // Check for #pragma weak identifiers that were never declared LoadExternalWeakUndeclaredIdentifiers(); - for (auto WeakID : WeakUndeclaredIdentifiers) { - if (WeakID.second.getUsed()) + for (const auto &WeakIDs : WeakUndeclaredIdentifiers) { + if (WeakIDs.second.empty()) continue; - Decl *PrevDecl = LookupSingleName(TUScope, WeakID.first, SourceLocation(), + Decl *PrevDecl = LookupSingleName(TUScope, WeakIDs.first, SourceLocation(), LookupOrdinaryName); if (PrevDecl != nullptr && !(isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl))) - Diag(WeakID.second.getLocation(), diag::warn_attribute_wrong_decl_type) - << "'weak'" << ExpectedVariableOrFunction; + for (const auto &WI : WeakIDs.second) + Diag(WI.getLocation(), diag::warn_attribute_wrong_decl_type) + << "'weak'" << /*isRegularKeyword=*/0 << ExpectedVariableOrFunction; else - Diag(WeakID.second.getLocation(), diag::warn_weak_identifier_undeclared) - << WeakID.first; + for (const auto &WI : WeakIDs.second) + Diag(WI.getLocation(), diag::warn_weak_identifier_undeclared) + << WeakIDs.first; } if (LangOpts.CPlusPlus11 && @@ -1174,9 +1208,8 @@ void Sema::ActOnEndOfTranslationUnit() { // A global-module-fragment is only permitted within a module unit. bool DiagnosedMissingModuleDeclaration = false; - if (!ModuleScopes.empty() && - ModuleScopes.back().Module->Kind == Module::GlobalModuleFragment && - !ModuleScopes.back().ImplicitGlobalModuleFragment) { + if (!ModuleScopes.empty() && ModuleScopes.back().Module->Kind == + Module::ExplicitGlobalModuleFragment) { Diag(ModuleScopes.back().BeginLoc, diag::err_module_declaration_missing_after_global_module_introducer); DiagnosedMissingModuleDeclaration = true; @@ -1187,9 +1220,7 @@ void Sema::ActOnEndOfTranslationUnit() { // module declaration by now. if (getLangOpts().getCompilingModule() == LangOptions::CMK_ModuleInterface && - (ModuleScopes.empty() || - !ModuleScopes.back().Module->isModulePurview()) && - !DiagnosedMissingModuleDeclaration) { + !isCurrentModulePurview() && !DiagnosedMissingModuleDeclaration) { // FIXME: Make a better guess as to where to put the module declaration. Diag(getSourceManager().getLocForStartOfFile( getSourceManager().getMainFileID()), @@ -1215,15 +1246,63 @@ void Sema::ActOnEndOfTranslationUnit() { ModMap.resolveConflicts(Mod, /*Complain=*/false); // Queue the submodules, so their exports will also be resolved. - Stack.append(Mod->submodule_begin(), Mod->submodule_end()); + auto SubmodulesRange = Mod->submodules(); + Stack.append(SubmodulesRange.begin(), SubmodulesRange.end()); } } + // Now we can decide whether the modules we're building need an initializer. + if (Module *CurrentModule = getCurrentModule(); + CurrentModule && CurrentModule->isInterfaceOrPartition()) { + auto DoesModNeedInit = [this](Module *M) { + if (!getASTContext().getModuleInitializers(M).empty()) + return true; + for (auto [Exported, _] : M->Exports) + if (Exported->isNamedModuleInterfaceHasInit()) + return true; + for (Module *I : M->Imports) + if (I->isNamedModuleInterfaceHasInit()) + return true; + + return false; + }; + + CurrentModule->NamedModuleHasInit = + DoesModNeedInit(CurrentModule) || + llvm::any_of(CurrentModule->submodules(), + [&](auto *SubM) { return DoesModNeedInit(SubM); }); + } + // Warnings emitted in ActOnEndOfTranslationUnit() should be emitted for // modules when they are built, not every time they are used. emitAndClearUnusedLocalTypedefWarnings(); } + // C++ standard modules. Diagnose cases where a function is declared inline + // in the module purview but has no definition before the end of the TU or + // the start of a Private Module Fragment (if one is present). + if (!PendingInlineFuncDecls.empty()) { + for (auto *D : PendingInlineFuncDecls) { + if (auto *FD = dyn_cast<FunctionDecl>(D)) { + bool DefInPMF = false; + if (auto *FDD = FD->getDefinition()) { + DefInPMF = FDD->getOwningModule()->isPrivateModule(); + if (!DefInPMF) + continue; + } + Diag(FD->getLocation(), diag::err_export_inline_not_defined) + << DefInPMF; + // If we have a PMF it should be at the end of the ModuleScopes. + if (DefInPMF && + ModuleScopes.back().Module->Kind == Module::PrivateModuleFragment) { + Diag(ModuleScopes.back().BeginLoc, + diag::note_private_module_fragment); + } + } + } + PendingInlineFuncDecls.clear(); + } + // C99 6.9.2p2: // A declaration of an identifier for an object that has file // scope without an initializer, and without a storage-class @@ -1237,8 +1316,8 @@ void Sema::ActOnEndOfTranslationUnit() { // translation unit, with an initializer equal to 0. llvm::SmallSet<VarDecl *, 32> Seen; for (TentativeDefinitionsType::iterator - T = TentativeDefinitions.begin(ExternalSource), - TEnd = TentativeDefinitions.end(); + T = TentativeDefinitions.begin(ExternalSource.get()), + TEnd = TentativeDefinitions.end(); T != TEnd; ++T) { VarDecl *VD = (*T)->getActingDefinition(); @@ -1253,8 +1332,8 @@ void Sema::ActOnEndOfTranslationUnit() { // Set the length of the array to 1 (C99 6.9.2p5). Diag(VD->getLocation(), diag::warn_tentative_incomplete_array); llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true); - QualType T = Context.getConstantArrayType(ArrayT->getElementType(), One, - nullptr, ArrayType::Normal, 0); + QualType T = Context.getConstantArrayType( + ArrayT->getElementType(), One, nullptr, ArraySizeModifier::Normal, 0); VD->setType(T); } else if (RequireCompleteType(VD->getLocation(), VD->getType(), diag::err_tentative_def_incomplete_type)) @@ -1268,7 +1347,7 @@ void Sema::ActOnEndOfTranslationUnit() { Consumer.CompleteTentativeDefinition(VD); } - for (auto D : ExternalDeclarations) { + for (auto *D : ExternalDeclarations) { if (!D || D->isInvalidDecl() || D->getPreviousDecl() || !D->isUsed()) continue; @@ -1282,8 +1361,9 @@ void Sema::ActOnEndOfTranslationUnit() { if (!Diags.hasErrorOccurred() && TUKind != TU_Module) { // Output warning for unused file scoped decls. for (UnusedFileScopedDeclsType::iterator - I = UnusedFileScopedDecls.begin(ExternalSource), - E = UnusedFileScopedDecls.end(); I != E; ++I) { + I = UnusedFileScopedDecls.begin(ExternalSource.get()), + E = UnusedFileScopedDecls.end(); + I != E; ++I) { if (ShouldRemoveFromUnused(this, *I)) continue; @@ -1293,10 +1373,14 @@ void Sema::ActOnEndOfTranslationUnit() { DiagD = FD; if (DiagD->isDeleted()) continue; // Deleted functions are supposed to be unused. + SourceRange DiagRange = DiagD->getLocation(); + if (const ASTTemplateArgumentListInfo *ASTTAL = + DiagD->getTemplateSpecializationArgsAsWritten()) + DiagRange.setEnd(ASTTAL->RAngleLoc); if (DiagD->isReferenced()) { if (isa<CXXMethodDecl>(DiagD)) Diag(DiagD->getLocation(), diag::warn_unneeded_member_function) - << DiagD; + << DiagD << DiagRange; else { if (FD->getStorageClass() == SC_Static && !FD->isInlineSpecified() && @@ -1304,40 +1388,46 @@ void Sema::ActOnEndOfTranslationUnit() { SourceMgr.getExpansionLoc(FD->getLocation()))) Diag(DiagD->getLocation(), diag::warn_unneeded_static_internal_decl) - << DiagD; + << DiagD << DiagRange; else Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl) - << /*function*/ 0 << DiagD; + << /*function=*/0 << DiagD << DiagRange; } } else { if (FD->getDescribedFunctionTemplate()) Diag(DiagD->getLocation(), diag::warn_unused_template) - << /*function*/ 0 << DiagD; + << /*function=*/0 << DiagD << DiagRange; else Diag(DiagD->getLocation(), isa<CXXMethodDecl>(DiagD) ? diag::warn_unused_member_function : diag::warn_unused_function) - << DiagD; + << DiagD << DiagRange; } } else { const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition(); if (!DiagD) DiagD = cast<VarDecl>(*I); + SourceRange DiagRange = DiagD->getLocation(); + if (const auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(DiagD)) { + if (const ASTTemplateArgumentListInfo *ASTTAL = + VTSD->getTemplateArgsInfo()) + DiagRange.setEnd(ASTTAL->RAngleLoc); + } if (DiagD->isReferenced()) { Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl) - << /*variable*/ 1 << DiagD; + << /*variable=*/1 << DiagD << DiagRange; + } else if (DiagD->getDescribedVarTemplate()) { + Diag(DiagD->getLocation(), diag::warn_unused_template) + << /*variable=*/1 << DiagD << DiagRange; } else if (DiagD->getType().isConstQualified()) { const SourceManager &SM = SourceMgr; if (SM.getMainFileID() != SM.getFileID(DiagD->getLocation()) || !PP.getLangOpts().IsHeaderFile) Diag(DiagD->getLocation(), diag::warn_unused_const_variable) - << DiagD; + << DiagD << DiagRange; } else { - if (DiagD->getDescribedVarTemplate()) - Diag(DiagD->getLocation(), diag::warn_unused_template) - << /*variable*/ 1 << DiagD; - else - Diag(DiagD->getLocation(), diag::warn_unused_variable) << DiagD; + Diag(DiagD->getLocation(), diag::warn_unused_variable) + << DiagD << DiagRange; } } } @@ -1350,9 +1440,7 @@ void Sema::ActOnEndOfTranslationUnit() { // source. RecordCompleteMap RecordsComplete; RecordCompleteMap MNCComplete; - for (NamedDeclSetType::iterator I = UnusedPrivateFields.begin(), - E = UnusedPrivateFields.end(); I != E; ++I) { - const NamedDecl *D = *I; + for (const NamedDecl *D : UnusedPrivateFields) { const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()); if (RD && !RD->isUnion() && IsRecordFullyDefined(RD, RecordsComplete, MNCComplete)) { @@ -1373,6 +1461,8 @@ void Sema::ActOnEndOfTranslationUnit() { } } + AnalysisWarnings.IssueWarnings(Context.getTranslationUnitDecl()); + // Check we've noticed that we're no longer parsing the initializer for every // variable. If we miss cases, then at best we have a performance issue and // at worst a rejects-valid bug. @@ -1388,19 +1478,18 @@ void Sema::ActOnEndOfTranslationUnit() { // Helper functions. //===----------------------------------------------------------------------===// -DeclContext *Sema::getFunctionLevelDeclContext() { +DeclContext *Sema::getFunctionLevelDeclContext(bool AllowLambda) const { DeclContext *DC = CurContext; while (true) { if (isa<BlockDecl>(DC) || isa<EnumDecl>(DC) || isa<CapturedDecl>(DC) || isa<RequiresExprBodyDecl>(DC)) { DC = DC->getParent(); - } else if (isa<CXXMethodDecl>(DC) && + } else if (!AllowLambda && isa<CXXMethodDecl>(DC) && cast<CXXMethodDecl>(DC)->getOverloadedOperator() == OO_Call && cast<CXXRecordDecl>(DC->getParent())->isLambda()) { DC = DC->getParent()->getParent(); - } - else break; + } else break; } return DC; @@ -1409,8 +1498,8 @@ DeclContext *Sema::getFunctionLevelDeclContext() { /// getCurFunctionDecl - If inside of a function body, this returns a pointer /// to the function decl for the function being parsed. If we're currently /// in a 'block', this returns the containing context. -FunctionDecl *Sema::getCurFunctionDecl() { - DeclContext *DC = getFunctionLevelDeclContext(); +FunctionDecl *Sema::getCurFunctionDecl(bool AllowLambda) const { + DeclContext *DC = getFunctionLevelDeclContext(AllowLambda); return dyn_cast<FunctionDecl>(DC); } @@ -1421,7 +1510,7 @@ ObjCMethodDecl *Sema::getCurMethodDecl() { return dyn_cast<ObjCMethodDecl>(DC); } -NamedDecl *Sema::getCurFunctionOrMethodDecl() { +NamedDecl *Sema::getCurFunctionOrMethodDecl() const { DeclContext *DC = getFunctionLevelDeclContext(); if (isa<ObjCMethodDecl>(DC) || isa<FunctionDecl>(DC)) return cast<NamedDecl>(DC); @@ -1430,7 +1519,7 @@ NamedDecl *Sema::getCurFunctionOrMethodDecl() { LangAS Sema::getDefaultCXXMethodAddrSpace() const { if (getLangOpts().OpenCL) - return LangAS::opencl_generic; + return getASTContext().getDefaultOpenCLPointeeAddrSpace(); return LangAS::Default; } @@ -1442,7 +1531,7 @@ void Sema::EmitCurrentDiagnostic(unsigned DiagID) { // eliminated. If it truly cannot be (for example, there is some reentrancy // issue I am not seeing yet), then there should at least be a clarifying // comment somewhere. - if (Optional<TemplateDeductionInfo*> Info = isSFINAEContext()) { + if (std::optional<TemplateDeductionInfo *> Info = isSFINAEContext()) { switch (DiagnosticIDs::getDiagnosticSFINAEResponse( Diags.getCurrentDiagID())) { case DiagnosticIDs::SFINAE_Report: @@ -1555,7 +1644,7 @@ bool Sema::hasUncompilableErrorOccurred() const { // Print notes showing how we can reach FD starting from an a priori // known-callable function. -static void emitCallStackNotes(Sema &S, FunctionDecl *FD) { +static void emitCallStackNotes(Sema &S, const FunctionDecl *FD) { auto FnIt = S.DeviceKnownEmittedFns.find(FD); while (FnIt != S.DeviceKnownEmittedFns.end()) { // Respect error limit. @@ -1737,7 +1826,7 @@ void Sema::emitDeferredDiags() { return; DeferredDiagnosticsEmitter DDE(*this); - for (auto D : DeclsToCheckForDeferredDiags) + for (auto *D : DeclsToCheckForDeferredDiags) DDE.checkRecordedDecl(D); } @@ -1767,7 +1856,8 @@ void Sema::emitDeferredDiags() { Sema::SemaDiagnosticBuilder::SemaDiagnosticBuilder(Kind K, SourceLocation Loc, unsigned DiagID, - FunctionDecl *Fn, Sema &S) + const FunctionDecl *Fn, + Sema &S) : S(S), Loc(Loc), DiagID(DiagID), Fn(Fn), ShowCallStack(K == K_ImmediateWithCallStack || K == K_Deferred) { switch (K) { @@ -1813,11 +1903,12 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() { } Sema::SemaDiagnosticBuilder -Sema::targetDiag(SourceLocation Loc, unsigned DiagID, FunctionDecl *FD) { +Sema::targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD) { FD = FD ? FD : getCurFunctionDecl(); if (LangOpts.OpenMP) - return LangOpts.OpenMPIsDevice ? diagIfOpenMPDeviceCode(Loc, DiagID, FD) - : diagIfOpenMPHostCode(Loc, DiagID, FD); + return LangOpts.OpenMPIsTargetDevice + ? diagIfOpenMPDeviceCode(Loc, DiagID, FD) + : diagIfOpenMPHostCode(Loc, DiagID, FD); if (getLangOpts().CUDA) return getLangOpts().CUDAIsDevice ? CUDADiagIfDeviceCode(Loc, DiagID) : CUDADiagIfHostCode(Loc, DiagID); @@ -1852,10 +1943,19 @@ Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID, return DB; } -void Sema::checkDeviceDecl(ValueDecl *D, SourceLocation Loc) { - if (isUnevaluatedContext()) +void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) { + if (isUnevaluatedContext() || Ty.isNull()) return; + // The original idea behind checkTypeSupport function is that unused + // declarations can be replaced with an array of bytes of the same size during + // codegen, such replacement doesn't seem to be possible for types without + // constant byte size like zero length arrays. So, do a deep check for SYCL. + if (D && LangOpts.SYCLIsDevice) { + llvm::DenseSet<QualType> Visited; + deepTypeCheckForSYCLDevice(Loc, Visited, D); + } + Decl *C = cast<Decl>(getCurLexicalContext()); // Memcpy operations for structs containing a member with unsupported type @@ -1872,46 +1972,131 @@ void Sema::checkDeviceDecl(ValueDecl *D, SourceLocation Loc) { // Try to associate errors with the lexical context, if that is a function, or // the value declaration otherwise. - FunctionDecl *FD = - isa<FunctionDecl>(C) ? cast<FunctionDecl>(C) : dyn_cast<FunctionDecl>(D); - auto CheckType = [&](QualType Ty) { + const FunctionDecl *FD = isa<FunctionDecl>(C) + ? cast<FunctionDecl>(C) + : dyn_cast_or_null<FunctionDecl>(D); + + auto CheckDeviceType = [&](QualType Ty) { if (Ty->isDependentType()) return; - if (Ty->isExtIntType()) { - if (!Context.getTargetInfo().hasExtIntType()) { - targetDiag(Loc, diag::err_device_unsupported_type, FD) - << D << false /*show bit size*/ << 0 /*bitsize*/ + if (Ty->isBitIntType()) { + if (!Context.getTargetInfo().hasBitIntType()) { + PartialDiagnostic PD = PDiag(diag::err_target_unsupported_type); + if (D) + PD << D; + else + PD << "expression"; + targetDiag(Loc, PD, FD) + << false /*show bit size*/ << 0 /*bitsize*/ << false /*return*/ << Ty << Context.getTargetInfo().getTriple().str(); } return; } + // Check if we are dealing with two 'long double' but with different + // semantics. + bool LongDoubleMismatched = false; + if (Ty->isRealFloatingType() && Context.getTypeSize(Ty) == 128) { + const llvm::fltSemantics &Sem = Context.getFloatTypeSemantics(Ty); + if ((&Sem != &llvm::APFloat::PPCDoubleDouble() && + !Context.getTargetInfo().hasFloat128Type()) || + (&Sem == &llvm::APFloat::PPCDoubleDouble() && + !Context.getTargetInfo().hasIbm128Type())) + LongDoubleMismatched = true; + } + if ((Ty->isFloat16Type() && !Context.getTargetInfo().hasFloat16Type()) || - ((Ty->isFloat128Type() || - (Ty->isRealFloatingType() && Context.getTypeSize(Ty) == 128)) && - !Context.getTargetInfo().hasFloat128Type()) || + (Ty->isFloat128Type() && !Context.getTargetInfo().hasFloat128Type()) || + (Ty->isIbm128Type() && !Context.getTargetInfo().hasIbm128Type()) || (Ty->isIntegerType() && Context.getTypeSize(Ty) == 128 && - !Context.getTargetInfo().hasInt128Type())) { - if (targetDiag(Loc, diag::err_device_unsupported_type, FD) - << D << true /*show bit size*/ + !Context.getTargetInfo().hasInt128Type()) || + (Ty->isBFloat16Type() && !Context.getTargetInfo().hasBFloat16Type() && + !LangOpts.CUDAIsDevice) || + LongDoubleMismatched) { + PartialDiagnostic PD = PDiag(diag::err_target_unsupported_type); + if (D) + PD << D; + else + PD << "expression"; + + if (targetDiag(Loc, PD, FD) + << true /*show bit size*/ << static_cast<unsigned>(Context.getTypeSize(Ty)) << Ty - << Context.getTargetInfo().getTriple().str()) - D->setInvalidDecl(); - targetDiag(D->getLocation(), diag::note_defined_here, FD) << D; + << false /*return*/ << Context.getTargetInfo().getTriple().str()) { + if (D) + D->setInvalidDecl(); + } + if (D) + targetDiag(D->getLocation(), diag::note_defined_here, FD) << D; } }; - QualType Ty = D->getType(); - CheckType(Ty); + auto CheckType = [&](QualType Ty, bool IsRetTy = false) { + if (LangOpts.SYCLIsDevice || + (LangOpts.OpenMP && LangOpts.OpenMPIsTargetDevice) || + LangOpts.CUDAIsDevice) + CheckDeviceType(Ty); + + QualType UnqualTy = Ty.getCanonicalType().getUnqualifiedType(); + const TargetInfo &TI = Context.getTargetInfo(); + if (!TI.hasLongDoubleType() && UnqualTy == Context.LongDoubleTy) { + PartialDiagnostic PD = PDiag(diag::err_target_unsupported_type); + if (D) + PD << D; + else + PD << "expression"; + + if (Diag(Loc, PD, FD) + << false /*show bit size*/ << 0 << Ty << false /*return*/ + << TI.getTriple().str()) { + if (D) + D->setInvalidDecl(); + } + if (D) + targetDiag(D->getLocation(), diag::note_defined_here, FD) << D; + } + + bool IsDouble = UnqualTy == Context.DoubleTy; + bool IsFloat = UnqualTy == Context.FloatTy; + if (IsRetTy && !TI.hasFPReturn() && (IsDouble || IsFloat)) { + PartialDiagnostic PD = PDiag(diag::err_target_unsupported_type); + if (D) + PD << D; + else + PD << "expression"; + + if (Diag(Loc, PD, FD) + << false /*show bit size*/ << 0 << Ty << true /*return*/ + << TI.getTriple().str()) { + if (D) + D->setInvalidDecl(); + } + if (D) + targetDiag(D->getLocation(), diag::note_defined_here, FD) << D; + } + + if (TI.hasRISCVVTypes() && Ty->isRVVSizelessBuiltinType()) + checkRVVTypeSupport(Ty, Loc, D); + + // Don't allow SVE types in functions without a SVE target. + if (Ty->isSVESizelessBuiltinType() && FD && FD->hasBody()) { + llvm::StringMap<bool> CallerFeatureMap; + Context.getFunctionFeatureMap(CallerFeatureMap, FD); + if (!Builtin::evaluateRequiredTargetFeatures("sve", CallerFeatureMap) && + !Builtin::evaluateRequiredTargetFeatures("sme", CallerFeatureMap)) + Diag(D->getLocation(), diag::err_sve_vector_in_non_sve_target) << Ty; + } + }; + CheckType(Ty); if (const auto *FPTy = dyn_cast<FunctionProtoType>(Ty)) { for (const auto &ParamTy : FPTy->param_types()) CheckType(ParamTy); - CheckType(FPTy->getReturnType()); + CheckType(FPTy->getReturnType(), /*IsRetTy=*/true); } if (const auto *FNPTy = dyn_cast<FunctionNoProtoType>(Ty)) - CheckType(FNPTy->getReturnType()); + CheckType(FNPTy->getReturnType(), /*IsRetTy=*/true); } /// Looks through the macro-expansion chain for the given @@ -1980,11 +2165,13 @@ void Sema::PushFunctionScope() { void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) { FunctionScopes.push_back(new BlockScopeInfo(getDiagnostics(), BlockScope, Block)); + CapturingFunctionScopes++; } LambdaScopeInfo *Sema::PushLambdaScope() { LambdaScopeInfo *const LSI = new LambdaScopeInfo(getDiagnostics()); FunctionScopes.push_back(LSI); + CapturingFunctionScopes++; return LSI; } @@ -2011,7 +2198,7 @@ static void checkEscapingByref(VarDecl *VD, Sema &S) { new (S.Context) DeclRefExpr(S.Context, VD, false, T, VK_LValue, Loc); ExprResult Result; auto IE = InitializedEntity::InitializeBlock(Loc, T); - if (S.getLangOpts().CPlusPlus2b) { + if (S.getLangOpts().CPlusPlus23) { auto *E = ImplicitCastExpr::Create(S.Context, T, CK_NoOp, VarRef, nullptr, VK_XValue, FPOptionsOverride()); Result = S.PerformCopyInitialization(IE, SourceLocation(), E); @@ -2106,6 +2293,8 @@ Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP, void Sema::PoppedFunctionScopeDeleter:: operator()(sema::FunctionScopeInfo *Scope) const { + if (!Scope->isPlainFunction()) + Self->CapturingFunctionScopes--; // Stash the function scope for later reuse if it's for a normal function. if (Scope->isPlainFunction() && !Self->CachedFunctionScope) Self->CachedFunctionScope.reset(Scope); @@ -2114,7 +2303,8 @@ operator()(sema::FunctionScopeInfo *Scope) const { } void Sema::PushCompoundScope(bool IsStmtExpr) { - getCurFunction()->CompoundScopes.push_back(CompoundScopeInfo(IsStmtExpr)); + getCurFunction()->CompoundScopes.push_back( + CompoundScopeInfo(IsStmtExpr, getCurFPFeatures())); } void Sema::PopCompoundScope() { @@ -2180,7 +2370,8 @@ FunctionScopeInfo *Sema::getEnclosingFunction() const { LambdaScopeInfo *Sema::getEnclosingLambda() const { for (auto *Scope : llvm::reverse(FunctionScopes)) { if (auto *LSI = dyn_cast<sema::LambdaScopeInfo>(Scope)) { - if (LSI->Lambda && !LSI->Lambda->Encloses(CurContext)) { + if (LSI->Lambda && !LSI->Lambda->Encloses(CurContext) && + LSI->AfterParameterList) { // We have switched contexts due to template instantiation. // FIXME: We should swap out the FunctionScopes during code synthesis // so that we don't need to check for this. @@ -2206,8 +2397,8 @@ LambdaScopeInfo *Sema::getCurLambda(bool IgnoreNonLambdaCapturingScope) { return nullptr; } auto *CurLSI = dyn_cast<LambdaScopeInfo>(*I); - if (CurLSI && CurLSI->Lambda && - !CurLSI->Lambda->Encloses(CurContext)) { + if (CurLSI && CurLSI->Lambda && CurLSI->CallOperator && + !CurLSI->Lambda->Encloses(CurContext) && CurLSI->AfterParameterList) { // We have switched contexts due to template instantiation. assert(!CodeSynthesisContexts.empty()); return nullptr; @@ -2232,7 +2423,7 @@ void Sema::ActOnComment(SourceRange Comment) { SourceMgr.isInSystemHeader(Comment.getBegin())) return; RawComment RC(SourceMgr, Comment, LangOpts.CommentOpts, false); - if (RC.isAlmostTrailingComment()) { + if (RC.isAlmostTrailingComment() || RC.hasUnsupportedSplice(SourceMgr)) { SourceRange MagicMarkerRange(Comment.getBegin(), Comment.getBegin().getLocWithOffset(3)); StringRef MagicMarkerText; @@ -2243,6 +2434,11 @@ void Sema::ActOnComment(SourceRange Comment) { case RawComment::RCK_OrdinaryC: MagicMarkerText = "/**<"; break; + case RawComment::RCK_Invalid: + // FIXME: are there other scenarios that could produce an invalid + // raw comment here? + Diag(Comment.getBegin(), diag::warn_splice_in_doxygen_comment); + return; default: llvm_unreachable("if this is an almost Doxygen comment, " "it should be ordinary"); @@ -2341,7 +2537,7 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy, if (IsMemExpr && !E.isTypeDependent()) { Sema::TentativeAnalysisScope Trap(*this); ExprResult R = BuildCallToMemberFunction(nullptr, &E, SourceLocation(), - None, SourceLocation()); + std::nullopt, SourceLocation()); if (R.isUsable()) { ZeroArgCallReturnTy = R.get()->getType(); return true; @@ -2349,8 +2545,8 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy, return false; } - if (const DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E.IgnoreParens())) { - if (const FunctionDecl *Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) { + if (const auto *DeclRef = dyn_cast<DeclRefExpr>(E.IgnoreParens())) { + if (const auto *Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) { if (Fun->getMinRequiredArguments() == 0) ZeroArgCallReturnTy = Fun->getReturnType(); return true; @@ -2367,8 +2563,7 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy, if (!FunTy) FunTy = ExprTy->getAs<FunctionType>(); - if (const FunctionProtoType *FPT = - dyn_cast_or_null<FunctionProtoType>(FunTy)) { + if (const auto *FPT = dyn_cast_if_present<FunctionProtoType>(FunTy)) { if (FPT->getNumParams() == 0) ZeroArgCallReturnTy = FunTy->getReturnType(); return true; @@ -2399,12 +2594,15 @@ static void noteOverloads(Sema &S, const UnresolvedSetImpl &Overloads, continue; } - NamedDecl *Fn = (*It)->getUnderlyingDecl(); + const NamedDecl *Fn = (*It)->getUnderlyingDecl(); // Don't print overloads for non-default multiversioned functions. if (const auto *FD = Fn->getAsFunction()) { if (FD->isMultiVersion() && FD->hasAttr<TargetAttr>() && !FD->getAttr<TargetAttr>()->isDefaultVersion()) continue; + if (FD->isMultiVersion() && FD->hasAttr<TargetVersionAttr>() && + !FD->getAttr<TargetVersionAttr>()->isDefaultVersion()) + continue; } S.Diag(Fn->getLocation(), diag::note_possible_target_of_call); ++ShownOverloads; @@ -2426,7 +2624,7 @@ static void notePlausibleOverloads(Sema &S, SourceLocation Loc, UnresolvedSet<2> PlausibleOverloads; for (OverloadExpr::decls_iterator It = Overloads.begin(), DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) { - const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*It); + const auto *OverloadDecl = cast<FunctionDecl>(*It); QualType OverloadResultTy = OverloadDecl->getReturnType(); if (IsPlausibleResult(OverloadResultTy)) PlausibleOverloads.addDecl(It.getDecl()); @@ -2438,7 +2636,7 @@ static void notePlausibleOverloads(Sema &S, SourceLocation Loc, /// putting parentheses after it. Notably, expressions with unary /// operators can't be because the unary operator will start parsing /// outside the call. -static bool IsCallableWithAppend(Expr *E) { +static bool IsCallableWithAppend(const Expr *E) { E = E->IgnoreImplicit(); return (!isa<CStyleCastExpr>(E) && !isa<UnaryOperator>(E) && @@ -2466,32 +2664,36 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, bool (*IsPlausibleResult)(QualType)) { SourceLocation Loc = E.get()->getExprLoc(); SourceRange Range = E.get()->getSourceRange(); - - QualType ZeroArgCallTy; UnresolvedSet<4> Overloads; - if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) && - !ZeroArgCallTy.isNull() && - (!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) { - // At this point, we know E is potentially callable with 0 - // arguments and that it returns something of a reasonable type, - // so we can emit a fixit and carry on pretending that E was - // actually a CallExpr. - SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd()); - bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get()); - Diag(Loc, PD) << /*zero-arg*/ 1 << IsMV << Range - << (IsCallableWithAppend(E.get()) - ? FixItHint::CreateInsertion(ParenInsertionLoc, "()") - : FixItHint()); - if (!IsMV) - notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult); - - // FIXME: Try this before emitting the fixit, and suppress diagnostics - // while doing so. - E = BuildCallExpr(nullptr, E.get(), Range.getEnd(), None, - Range.getEnd().getLocWithOffset(1)); - return true; - } + // If this is a SFINAE context, don't try anything that might trigger ADL + // prematurely. + if (!isSFINAEContext()) { + QualType ZeroArgCallTy; + if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) && + !ZeroArgCallTy.isNull() && + (!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) { + // At this point, we know E is potentially callable with 0 + // arguments and that it returns something of a reasonable type, + // so we can emit a fixit and carry on pretending that E was + // actually a CallExpr. + SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd()); + bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get()); + Diag(Loc, PD) << /*zero-arg*/ 1 << IsMV << Range + << (IsCallableWithAppend(E.get()) + ? FixItHint::CreateInsertion(ParenInsertionLoc, + "()") + : FixItHint()); + if (!IsMV) + notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult); + + // FIXME: Try this before emitting the fixit, and suppress diagnostics + // while doing so. + E = BuildCallExpr(nullptr, E.get(), Range.getEnd(), std::nullopt, + Range.getEnd().getLocWithOffset(1)); + return true; + } + } if (!ForceComplain) return false; bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get()); @@ -2508,12 +2710,6 @@ IdentifierInfo *Sema::getSuperIdentifier() const { return Ident_super; } -IdentifierInfo *Sema::getFloat128Identifier() const { - if (!Ident___float128) - Ident___float128 = &Context.Idents.get("__float128"); - return Ident___float128; -} - void Sema::PushCapturedRegionScope(Scope *S, CapturedDecl *CD, RecordDecl *RD, CapturedRegionKind K, unsigned OpenMPCaptureLevel) { @@ -2523,6 +2719,7 @@ void Sema::PushCapturedRegionScope(Scope *S, CapturedDecl *CD, RecordDecl *RD, OpenMPCaptureLevel); CSI->ReturnType = Context.VoidTy; FunctionScopes.push_back(CSI); + CapturingFunctionScopes++; } CapturedRegionScopeInfo *Sema::getCurCapturedRegion() { @@ -2536,3 +2733,38 @@ const llvm::MapVector<FieldDecl *, Sema::DeleteLocs> & Sema::getMismatchingDeleteExpressions() const { return DeleteExprs; } + +Sema::FPFeaturesStateRAII::FPFeaturesStateRAII(Sema &S) + : S(S), OldFPFeaturesState(S.CurFPFeatures), + OldOverrides(S.FpPragmaStack.CurrentValue), + OldEvalMethod(S.PP.getCurrentFPEvalMethod()), + OldFPPragmaLocation(S.PP.getLastFPEvalPragmaLocation()) {} + +Sema::FPFeaturesStateRAII::~FPFeaturesStateRAII() { + S.CurFPFeatures = OldFPFeaturesState; + S.FpPragmaStack.CurrentValue = OldOverrides; + S.PP.setCurrentFPEvalMethod(OldFPPragmaLocation, OldEvalMethod); +} + +bool Sema::isDeclaratorFunctionLike(Declarator &D) { + assert(D.getCXXScopeSpec().isSet() && + "can only be called for qualified names"); + + auto LR = LookupResult(*this, D.getIdentifier(), D.getBeginLoc(), + LookupOrdinaryName, forRedeclarationInCurContext()); + DeclContext *DC = computeDeclContext(D.getCXXScopeSpec(), + !D.getDeclSpec().isFriendSpecified()); + if (!DC) + return false; + + LookupQualifiedName(LR, DC); + bool Result = llvm::all_of(LR, [](Decl *Dcl) { + if (NamedDecl *ND = dyn_cast<NamedDecl>(Dcl)) { + ND = ND->getUnderlyingDecl(); + return isa<FunctionDecl>(ND) || isa<FunctionTemplateDecl>(ND) || + isa<UsingDecl>(ND); + } + return false; + }); + return Result; +} |