diff options
Diffstat (limited to 'clang/lib/Sema/Sema.cpp')
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 135 |
1 files changed, 99 insertions, 36 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 08957ce9fada..0f0305422454 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -46,8 +46,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; @@ -185,20 +187,19 @@ 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), - CodeCompleter(CodeCompleter), CurContext(nullptr), + : ExternalSource(nullptr), CurFPFeatures(pp.getLangOpts()), + LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer), + Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), + CollectStats(false), CodeCompleter(CodeCompleter), CurContext(nullptr), OriginalLexicalContext(nullptr), MSStructPragmaOn(false), MSPointerToMemberRepresentationMethod( LangOpts.getMSPointerToMemberRepresentationMethod()), VtorDispStack(LangOpts.getVtorDispMode()), AlignPackStack(AlignPackInfo(getLangOpts().XLPragmaPack)), DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr), - CodeSegStack(nullptr), FpPragmaStack(FPOptionsOverride()), - CurInitSeg(nullptr), VisContext(nullptr), - PragmaAttributeCurrentTargetDecl(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), @@ -473,10 +474,6 @@ 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()); @@ -550,12 +547,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. @@ -570,22 +565,19 @@ 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; @@ -595,6 +587,10 @@ void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr* E) { if (E->IgnoreParenImpCasts()->getType()->isNullPtrType()) 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 // in a synthesized call to operator<=>. if (!CodeSynthesisContexts.empty() && @@ -602,6 +598,12 @@ 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. SourceLocation MaybeMacroLoc = E->getBeginLoc(); @@ -1216,9 +1218,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()), @@ -1253,6 +1253,33 @@ void Sema::ActOnEndOfTranslationUnit() { 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()) { + assert(FDD->getOwningModule() && + FDD->getOwningModule()->isModulePurview()); + 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 @@ -1266,8 +1293,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(); @@ -1297,7 +1324,7 @@ void Sema::ActOnEndOfTranslationUnit() { Consumer.CompleteTentativeDefinition(VD); } - for (auto D : ExternalDeclarations) { + for (auto *D : ExternalDeclarations) { if (!D || D->isInvalidDecl() || D->getPreviousDecl() || !D->isUsed()) continue; @@ -1311,8 +1338,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; @@ -1470,7 +1498,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: @@ -1765,7 +1793,7 @@ void Sema::emitDeferredDiags() { return; DeferredDiagnosticsEmitter DDE(*this); - for (auto D : DeclsToCheckForDeferredDiags) + for (auto *D : DeclsToCheckForDeferredDiags) DDE.checkRecordedDecl(D); } @@ -2008,6 +2036,15 @@ void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) { if (D) targetDiag(D->getLocation(), diag::note_defined_here, FD) << 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)) + Diag(D->getLocation(), diag::err_sve_vector_in_non_sve_target) << Ty; + } }; CheckType(Ty); @@ -2448,7 +2485,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; @@ -2512,6 +2549,9 @@ static void noteOverloads(Sema &S, const UnresolvedSetImpl &Overloads, 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; @@ -2598,7 +2638,7 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, // FIXME: Try this before emitting the fixit, and suppress diagnostics // while doing so. - E = BuildCallExpr(nullptr, E.get(), Range.getEnd(), None, + E = BuildCallExpr(nullptr, E.get(), Range.getEnd(), std::nullopt, Range.getEnd().getLocWithOffset(1)); return true; } @@ -2659,3 +2699,26 @@ Sema::FPFeaturesStateRAII::~FPFeaturesStateRAII() { 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 = std::all_of(LR.begin(), LR.end(), [](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; +} |