diff options
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 845 |
1 files changed, 624 insertions, 221 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 507e4a6cd4365..3e2b61ae8cdf6 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -21,6 +21,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/EvaluatedExprVisitor.h" +#include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/NonTrivialTypeVisitor.h" #include "clang/AST/StmtCXX.h" @@ -47,6 +48,7 @@ #include <algorithm> #include <cstring> #include <functional> +#include <unordered_map> using namespace clang; using namespace sema; @@ -136,6 +138,7 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const { case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___bf16: case tok::kw__Float16: case tok::kw___float128: case tok::kw_wchar_t: @@ -747,7 +750,10 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, Diag(IILoc, IsTemplateName ? diag::err_no_member_template : diag::err_typename_nested_not_found) << II << DC << SS->getRange(); - else if (isDependentScopeSpecifier(*SS)) { + else if (SS->isValid() && SS->getScopeRep()->containsErrors()) { + SuggestedType = + ActOnTypenameType(S, SourceLocation(), *SS, *II, IILoc).get(); + } else if (isDependentScopeSpecifier(*SS)) { unsigned DiagID = diag::err_typename_missing; if (getLangOpts().MSVCCompat && isMicrosoftMissingTypename(SS, S)) DiagID = diag::ext_typename_missing; @@ -924,7 +930,7 @@ Corrected: return NameClassification::NonType(D); } - if (getLangOpts().CPlusPlus2a && SS.isEmpty() && NextToken.is(tok::less)) { + if (getLangOpts().CPlusPlus20 && SS.isEmpty() && NextToken.is(tok::less)) { // In C++20 onwards, this could be an ADL-only call to a function // template, and we're required to assume that this is a template name. // @@ -1067,7 +1073,7 @@ Corrected: Result, /*AllowFunctionTemplates=*/true, /*AllowDependent=*/false, /*AllowNonTemplateFunctions*/ SS.isEmpty() && - getLangOpts().CPlusPlus2a))) { + getLangOpts().CPlusPlus20))) { // C++ [temp.names]p3: // After name lookup (3.4) finds that a name is a template-name or that // an operator-function-id or a literal- operator-id refers to a set of @@ -1153,6 +1159,10 @@ Corrected: return ParsedType::make(T); } + if (isa<ConceptDecl>(FirstDecl)) + return NameClassification::Concept( + TemplateName(cast<TemplateDecl>(FirstDecl))); + // We can have a type template here if we're classifying a template argument. if (isa<TemplateDecl>(FirstDecl) && !isa<FunctionTemplateDecl>(FirstDecl) && !isa<VarTemplateDecl>(FirstDecl)) @@ -1250,47 +1260,8 @@ Sema::getTemplateNameKindForDiagnostics(TemplateName Name) { return TemplateNameKindForDiagnostics::DependentTemplate; } -// Determines the context to return to after temporarily entering a -// context. This depends in an unnecessarily complicated way on the -// exact ordering of callbacks from the parser. -DeclContext *Sema::getContainingDC(DeclContext *DC) { - - // Functions defined inline within classes aren't parsed until we've - // finished parsing the top-level class, so the top-level class is - // the context we'll need to return to. - // A Lambda call operator whose parent is a class must not be treated - // as an inline member function. A Lambda can be used legally - // either as an in-class member initializer or a default argument. These - // are parsed once the class has been marked complete and so the containing - // context would be the nested class (when the lambda is defined in one); - // If the class is not complete, then the lambda is being used in an - // ill-formed fashion (such as to specify the width of a bit-field, or - // in an array-bound) - in which case we still want to return the - // lexically containing DC (which could be a nested class). - if (isa<FunctionDecl>(DC) && !isLambdaCallOperator(DC)) { - DC = DC->getLexicalParent(); - - // A function not defined within a class will always return to its - // lexical context. - if (!isa<CXXRecordDecl>(DC)) - return DC; - - // A C++ inline method/friend is parsed *after* the topmost class - // it was declared in is fully parsed ("complete"); the topmost - // class is the context we need to return to. - while (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC->getLexicalParent())) - DC = RD; - - // Return the declaration context of the topmost class the inline method is - // declared in. - return DC; - } - - return DC->getLexicalParent(); -} - void Sema::PushDeclContext(Scope *S, DeclContext *DC) { - assert(getContainingDC(DC) == CurContext && + assert(DC->getLexicalParent() == CurContext && "The next DeclContext should be lexically contained in the current one."); CurContext = DC; S->setEntity(DC); @@ -1299,7 +1270,7 @@ void Sema::PushDeclContext(Scope *S, DeclContext *DC) { void Sema::PopDeclContext() { assert(CurContext && "DeclContext imbalance!"); - CurContext = getContainingDC(CurContext); + CurContext = CurContext->getLexicalParent(); assert(CurContext && "Popped translation unit!"); } @@ -1351,6 +1322,12 @@ void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) { CurContext = DC; S->setEntity(DC); + + if (S->getParent()->isTemplateParamScope()) { + // Also set the corresponding entities for all immediately-enclosing + // template parameter scopes. + EnterTemplatedContext(S->getParent(), DC); + } } void Sema::ExitDeclaratorContext(Scope *S) { @@ -1366,6 +1343,49 @@ void Sema::ExitDeclaratorContext(Scope *S) { // disappear. } +void Sema::EnterTemplatedContext(Scope *S, DeclContext *DC) { + assert(S->isTemplateParamScope() && + "expected to be initializing a template parameter scope"); + + // C++20 [temp.local]p7: + // In the definition of a member of a class template that appears outside + // of the class template definition, the name of a member of the class + // template hides the name of a template-parameter of any enclosing class + // templates (but not a template-parameter of the member if the member is a + // class or function template). + // C++20 [temp.local]p9: + // In the definition of a class template or in the definition of a member + // of such a template that appears outside of the template definition, for + // each non-dependent base class (13.8.2.1), if the name of the base class + // or the name of a member of the base class is the same as the name of a + // template-parameter, the base class name or member name hides the + // template-parameter name (6.4.10). + // + // This means that a template parameter scope should be searched immediately + // after searching the DeclContext for which it is a template parameter + // scope. For example, for + // template<typename T> template<typename U> template<typename V> + // void N::A<T>::B<U>::f(...) + // we search V then B<U> (and base classes) then U then A<T> (and base + // classes) then T then N then ::. + unsigned ScopeDepth = getTemplateDepth(S); + for (; S && S->isTemplateParamScope(); S = S->getParent(), --ScopeDepth) { + DeclContext *SearchDCAfterScope = DC; + for (; DC; DC = DC->getLookupParent()) { + if (const TemplateParameterList *TPL = + cast<Decl>(DC)->getDescribedTemplateParams()) { + unsigned DCDepth = TPL->getDepth() + 1; + if (DCDepth > ScopeDepth) + continue; + if (ScopeDepth == DCDepth) + SearchDCAfterScope = DC = DC->getLookupParent(); + break; + } + } + S->setLookupEntity(SearchDCAfterScope); + } +} + void Sema::ActOnReenterFunctionContext(Scope* S, Decl *D) { // We assume that the caller has already called // ActOnReenterTemplateScope so getTemplatedDecl() works. @@ -2586,11 +2606,15 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, AMK == Sema::AMK_ProtocolImplementation)) NewAttr = nullptr; else if (const auto *UA = dyn_cast<UuidAttr>(Attr)) - NewAttr = S.mergeUuidAttr(D, *UA, UA->getGuid()); + NewAttr = S.mergeUuidAttr(D, *UA, UA->getGuid(), UA->getGuidDecl()); else if (const auto *SLHA = dyn_cast<SpeculativeLoadHardeningAttr>(Attr)) NewAttr = S.mergeSpeculativeLoadHardeningAttr(D, *SLHA); else if (const auto *SLHA = dyn_cast<NoSpeculativeLoadHardeningAttr>(Attr)) NewAttr = S.mergeNoSpeculativeLoadHardeningAttr(D, *SLHA); + else if (const auto *IMA = dyn_cast<WebAssemblyImportModuleAttr>(Attr)) + NewAttr = S.mergeImportModuleAttr(D, *IMA); + else if (const auto *INA = dyn_cast<WebAssemblyImportNameAttr>(Attr)) + NewAttr = S.mergeImportNameAttr(D, *INA); else if (Attr->shouldInheritEvenIfAlreadyPresent() || !DeclHasAttr(D, Attr)) NewAttr = cast<InheritableAttr>(Attr->clone(S.Context)); @@ -2707,6 +2731,18 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { --E; continue; } + } else if (isa<LoaderUninitializedAttr>(NewAttribute)) { + // If there is a C definition followed by a redeclaration with this + // attribute then there are two different definitions. In C++, prefer the + // standard diagnostics. + if (!S.getLangOpts().CPlusPlus) { + S.Diag(NewAttribute->getLocation(), + diag::err_loader_uninitialized_redeclaration); + S.Diag(Def->getLocation(), diag::note_previous_definition); + NewAttributes.erase(NewAttributes.begin() + I); + --E; + continue; + } } else if (isa<SelectAnyAttr>(NewAttribute) && cast<VarDecl>(New)->isInline() && !cast<VarDecl>(New)->isInlineSpecified()) { @@ -2716,6 +2752,11 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { // honored it. ++I; continue; + } else if (isa<OMPDeclareVariantAttr>(NewAttribute)) { + // We allow to add OMP[Begin]DeclareVariantAttr to be added to + // declarations after defintions. + ++I; + continue; } S.Diag(NewAttribute->getLocation(), @@ -2736,23 +2777,21 @@ static void diagnoseMissingConstinit(Sema &S, const VarDecl *InitDecl, // enough of the attribute list spelling information to extract that without // heroics. std::string SuitableSpelling; - if (S.getLangOpts().CPlusPlus2a) - SuitableSpelling = - S.PP.getLastMacroWithSpelling(InsertLoc, {tok::kw_constinit}); + if (S.getLangOpts().CPlusPlus20) + SuitableSpelling = std::string( + S.PP.getLastMacroWithSpelling(InsertLoc, {tok::kw_constinit})); if (SuitableSpelling.empty() && S.getLangOpts().CPlusPlus11) - SuitableSpelling = S.PP.getLastMacroWithSpelling( - InsertLoc, - {tok::l_square, tok::l_square, S.PP.getIdentifierInfo("clang"), - tok::coloncolon, - S.PP.getIdentifierInfo("require_constant_initialization"), - tok::r_square, tok::r_square}); + SuitableSpelling = std::string(S.PP.getLastMacroWithSpelling( + InsertLoc, {tok::l_square, tok::l_square, + S.PP.getIdentifierInfo("clang"), tok::coloncolon, + S.PP.getIdentifierInfo("require_constant_initialization"), + tok::r_square, tok::r_square})); if (SuitableSpelling.empty()) - SuitableSpelling = S.PP.getLastMacroWithSpelling( - InsertLoc, - {tok::kw___attribute, tok::l_paren, tok::r_paren, - S.PP.getIdentifierInfo("require_constant_initialization"), - tok::r_paren, tok::r_paren}); - if (SuitableSpelling.empty() && S.getLangOpts().CPlusPlus2a) + SuitableSpelling = std::string(S.PP.getLastMacroWithSpelling( + InsertLoc, {tok::kw___attribute, tok::l_paren, tok::r_paren, + S.PP.getIdentifierInfo("require_constant_initialization"), + tok::r_paren, tok::r_paren})); + if (SuitableSpelling.empty() && S.getLangOpts().CPlusPlus20) SuitableSpelling = "constinit"; if (SuitableSpelling.empty() && S.getLangOpts().CPlusPlus11) SuitableSpelling = "[[clang::require_constant_initialization]]"; @@ -3884,11 +3923,11 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, if (!NewArray->isIncompleteArrayType() && !NewArray->isDependentType()) { for (VarDecl *PrevVD = Old->getMostRecentDecl(); PrevVD; PrevVD = PrevVD->getPreviousDecl()) { - const ArrayType *PrevVDTy = Context.getAsArrayType(PrevVD->getType()); + QualType PrevVDTy = PrevVD->getType(); if (PrevVDTy->isIncompleteArrayType() || PrevVDTy->isDependentType()) continue; - if (!Context.hasSameType(NewArray, PrevVDTy)) + if (!Context.hasSameType(New->getType(), PrevVDTy)) return diagnoseVarDeclTypeMismatch(*this, New, PrevVD); } } @@ -4344,6 +4383,87 @@ void Sema::handleTagNumbering(const TagDecl *Tag, Scope *TagScope) { } } +namespace { +struct NonCLikeKind { + enum { + None, + BaseClass, + DefaultMemberInit, + Lambda, + Friend, + OtherMember, + Invalid, + } Kind = None; + SourceRange Range; + + explicit operator bool() { return Kind != None; } +}; +} + +/// Determine whether a class is C-like, according to the rules of C++ +/// [dcl.typedef] for anonymous classes with typedef names for linkage. +static NonCLikeKind getNonCLikeKindForAnonymousStruct(const CXXRecordDecl *RD) { + if (RD->isInvalidDecl()) + return {NonCLikeKind::Invalid, {}}; + + // C++ [dcl.typedef]p9: [P1766R1] + // An unnamed class with a typedef name for linkage purposes shall not + // + // -- have any base classes + if (RD->getNumBases()) + return {NonCLikeKind::BaseClass, + SourceRange(RD->bases_begin()->getBeginLoc(), + RD->bases_end()[-1].getEndLoc())}; + bool Invalid = false; + for (Decl *D : RD->decls()) { + // Don't complain about things we already diagnosed. + if (D->isInvalidDecl()) { + Invalid = true; + continue; + } + + // -- have any [...] default member initializers + if (auto *FD = dyn_cast<FieldDecl>(D)) { + if (FD->hasInClassInitializer()) { + auto *Init = FD->getInClassInitializer(); + return {NonCLikeKind::DefaultMemberInit, + Init ? Init->getSourceRange() : D->getSourceRange()}; + } + continue; + } + + // FIXME: We don't allow friend declarations. This violates the wording of + // P1766, but not the intent. + if (isa<FriendDecl>(D)) + return {NonCLikeKind::Friend, D->getSourceRange()}; + + // -- declare any members other than non-static data members, member + // enumerations, or member classes, + if (isa<StaticAssertDecl>(D) || isa<IndirectFieldDecl>(D) || + isa<EnumDecl>(D)) + continue; + auto *MemberRD = dyn_cast<CXXRecordDecl>(D); + if (!MemberRD) { + if (D->isImplicit()) + continue; + return {NonCLikeKind::OtherMember, D->getSourceRange()}; + } + + // -- contain a lambda-expression, + if (MemberRD->isLambda()) + return {NonCLikeKind::Lambda, MemberRD->getSourceRange()}; + + // and all member classes shall also satisfy these requirements + // (recursively). + if (MemberRD->isThisDeclarationADefinition()) { + if (auto Kind = getNonCLikeKindForAnonymousStruct(MemberRD)) + return Kind; + } + } + + return {Invalid ? NonCLikeKind::Invalid : NonCLikeKind::None, {}}; +} + void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec, TypedefNameDecl *NewTD) { if (TagFromDeclSpec->isInvalidDecl()) @@ -4364,27 +4484,51 @@ void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec, return; } - // If we've already computed linkage for the anonymous tag, then - // adding a typedef name for the anonymous decl can change that - // linkage, which might be a serious problem. Diagnose this as - // unsupported and ignore the typedef name. TODO: we should - // pursue this as a language defect and establish a formal rule - // for how to handle it. - if (TagFromDeclSpec->hasLinkageBeenComputed()) { - Diag(NewTD->getLocation(), diag::err_typedef_changes_linkage); + // C++ [dcl.typedef]p9: [P1766R1, applied as DR] + // An unnamed class with a typedef name for linkage purposes shall [be + // C-like]. + // + // FIXME: Also diagnose if we've already computed the linkage. That ideally + // shouldn't happen, but there are constructs that the language rule doesn't + // disallow for which we can't reasonably avoid computing linkage early. + const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TagFromDeclSpec); + NonCLikeKind NonCLike = RD ? getNonCLikeKindForAnonymousStruct(RD) + : NonCLikeKind(); + bool ChangesLinkage = TagFromDeclSpec->hasLinkageBeenComputed(); + if (NonCLike || ChangesLinkage) { + if (NonCLike.Kind == NonCLikeKind::Invalid) + return; + + unsigned DiagID = diag::ext_non_c_like_anon_struct_in_typedef; + if (ChangesLinkage) { + // If the linkage changes, we can't accept this as an extension. + if (NonCLike.Kind == NonCLikeKind::None) + DiagID = diag::err_typedef_changes_linkage; + else + DiagID = diag::err_non_c_like_anon_struct_in_typedef; + } - SourceLocation tagLoc = TagFromDeclSpec->getInnerLocStart(); - tagLoc = getLocForEndOfToken(tagLoc); + SourceLocation FixitLoc = + getLocForEndOfToken(TagFromDeclSpec->getInnerLocStart()); + llvm::SmallString<40> TextToInsert; + TextToInsert += ' '; + TextToInsert += NewTD->getIdentifier()->getName(); - llvm::SmallString<40> textToInsert; - textToInsert += ' '; - textToInsert += NewTD->getIdentifier()->getName(); - Diag(tagLoc, diag::note_typedef_changes_linkage) - << FixItHint::CreateInsertion(tagLoc, textToInsert); - return; + Diag(FixitLoc, DiagID) + << isa<TypeAliasDecl>(NewTD) + << FixItHint::CreateInsertion(FixitLoc, TextToInsert); + if (NonCLike.Kind != NonCLikeKind::None) { + Diag(NonCLike.Range.getBegin(), diag::note_non_c_like_anon_struct) + << NonCLike.Kind - 1 << NonCLike.Range; + } + Diag(NewTD->getLocation(), diag::note_typedef_for_linkage_here) + << NewTD << isa<TypeAliasDecl>(NewTD); + + if (ChangesLinkage) + return; } - // Otherwise, set this is the anon-decl typedef for the tag. + // Otherwise, set this as the anon-decl typedef for the tag. TagFromDeclSpec->setTypedefNameForAnonDecl(NewTD); } @@ -4915,6 +5059,10 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // define non-static data members. [Note: nested types and // functions cannot be declared within an anonymous union. ] for (auto *Mem : Record->decls()) { + // Ignore invalid declarations; we already diagnosed them. + if (Mem->isInvalidDecl()) + continue; + if (auto *FD = dyn_cast<FieldDecl>(Mem)) { // C++ [class.union]p3: // An anonymous union shall not have private or protected @@ -5138,8 +5286,8 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, Chain.push_back(Anon); RecordDecl *RecordDef = Record->getDefinition(); - if (RequireCompleteType(Anon->getLocation(), RecTy, - diag::err_field_incomplete) || + if (RequireCompleteSizedType(Anon->getLocation(), RecTy, + diag::err_field_incomplete_or_sizeless) || InjectAnonymousStructOrUnionMembers(*this, S, CurContext, RecordDef, AS_none, Chain)) { Anon->setInvalidDecl(); @@ -6142,6 +6290,8 @@ bool Sema::inferObjCARCLifetime(ValueDecl *decl) { void Sema::deduceOpenCLAddressSpace(ValueDecl *Decl) { if (Decl->getType().hasAddressSpace()) return; + if (Decl->getType()->isDependentType()) + return; if (VarDecl *Var = dyn_cast<VarDecl>(Decl)) { QualType Type = Var->getType(); if (Type->isSamplerT() || Type->isVoidType()) @@ -6468,6 +6618,8 @@ static bool shouldConsiderLinkage(const VarDecl *VD) { return true; if (DC->isRecord()) return false; + if (isa<RequiresExprBodyDecl>(DC)) + return false; llvm_unreachable("Unexpected context"); } @@ -6753,28 +6905,49 @@ NamedDecl *Sema::ActOnVariableDeclarator( if (SC == SC_Static && CurContext->isRecord()) { if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) { - if (RD->isLocalClass()) + // Walk up the enclosing DeclContexts to check for any that are + // incompatible with static data members. + const DeclContext *FunctionOrMethod = nullptr; + const CXXRecordDecl *AnonStruct = nullptr; + for (DeclContext *Ctxt = DC; Ctxt; Ctxt = Ctxt->getParent()) { + if (Ctxt->isFunctionOrMethod()) { + FunctionOrMethod = Ctxt; + break; + } + const CXXRecordDecl *ParentDecl = dyn_cast<CXXRecordDecl>(Ctxt); + if (ParentDecl && !ParentDecl->getDeclName()) { + AnonStruct = ParentDecl; + break; + } + } + if (FunctionOrMethod) { + // C++ [class.static.data]p5: A local class shall not have static data + // members. Diag(D.getIdentifierLoc(), diag::err_static_data_member_not_allowed_in_local_class) - << Name << RD->getDeclName(); - - // C++98 [class.union]p1: If a union contains a static data member, - // the program is ill-formed. C++11 drops this restriction. - if (RD->isUnion()) + << Name << RD->getDeclName() << RD->getTagKind(); + } else if (AnonStruct) { + // C++ [class.static.data]p4: Unnamed classes and classes contained + // directly or indirectly within unnamed classes shall not contain + // static data members. + Diag(D.getIdentifierLoc(), + diag::err_static_data_member_not_allowed_in_anon_struct) + << Name << AnonStruct->getTagKind(); + Invalid = true; + } else if (RD->isUnion()) { + // C++98 [class.union]p1: If a union contains a static data member, + // the program is ill-formed. C++11 drops this restriction. Diag(D.getIdentifierLoc(), getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_static_data_member_in_union : diag::ext_static_data_member_in_union) << Name; - // We conservatively disallow static data members in anonymous structs. - else if (!RD->getDeclName()) - Diag(D.getIdentifierLoc(), - diag::err_static_data_member_not_allowed_in_anon_struct) - << Name << RD->isUnion(); + } } } // Match up the template parameter lists with the scope specifier, then // determine whether we have a template or a template specialization. + bool InvalidScope = false; TemplateParams = MatchTemplateParametersToScopeSpecifier( D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(), D.getCXXScopeSpec(), @@ -6782,7 +6955,8 @@ NamedDecl *Sema::ActOnVariableDeclarator( ? D.getName().TemplateId : nullptr, TemplateParamLists, - /*never a friend*/ false, IsMemberSpecialization, Invalid); + /*never a friend*/ false, IsMemberSpecialization, InvalidScope); + Invalid |= InvalidScope; if (TemplateParams) { if (!TemplateParams->size() && @@ -6918,7 +7092,8 @@ NamedDecl *Sema::ActOnVariableDeclarator( diag::err_thread_non_global) << DeclSpec::getSpecifierName(TSCS); else if (!Context.getTargetInfo().isTLSSupported()) { - if (getLangOpts().CUDA || getLangOpts().OpenMPIsDevice) { + if (getLangOpts().CUDA || getLangOpts().OpenMPIsDevice || + getLangOpts().SYCLIsDevice) { // Postpone error emission until we've collected attributes required to // figure out whether it's a host or device variable and whether the // error should be ignored. @@ -6946,6 +7121,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( case CSK_constexpr: NewVD->setConstexpr(true); + MaybeAddCUDAConstantAttr(NewVD); // C++1z [dcl.spec.constexpr]p1: // A static data member declared with the constexpr specifier is // implicitly an inline variable. @@ -7019,13 +7195,18 @@ NamedDecl *Sema::ActOnVariableDeclarator( // Handle attributes prior to checking for duplicates in MergeVarDecl ProcessDeclAttributes(S, NewVD, D); - if (getLangOpts().CUDA || getLangOpts().OpenMPIsDevice) { + if (getLangOpts().CUDA || getLangOpts().OpenMPIsDevice || + getLangOpts().SYCLIsDevice) { if (EmitTLSUnsupportedError && ((getLangOpts().CUDA && DeclAttrsMatchCUDAMode(getLangOpts(), NewVD)) || (getLangOpts().OpenMPIsDevice && OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(NewVD)))) Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), diag::err_thread_unsupported); + + if (EmitTLSUnsupportedError && + (LangOpts.SYCLIsDevice || (LangOpts.OpenMP && LangOpts.OpenMPIsDevice))) + targetDiag(D.getIdentifierLoc(), diag::err_thread_unsupported); // CUDA B.2.5: "__shared__ and __constant__ variables have implied static // storage [duration]." if (SC == SC_None && S->getFnParent() != nullptr && @@ -7680,6 +7861,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { if (NewVD->isFileVarDecl() || NewVD->isStaticLocal() || NewVD->hasExternalStorage()) { if (!T->isSamplerT() && + !T->isDependentType() && !(T.getAddressSpace() == LangAS::opencl_constant || (T.getAddressSpace() == LangAS::opencl_global && (getLangOpts().OpenCLVersion == 200 || @@ -7822,6 +8004,12 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { return; } + if (!NewVD->hasLocalStorage() && T->isSizelessType()) { + Diag(NewVD->getLocation(), diag::err_sizeless_nonlocal) << T; + NewVD->setInvalidDecl(); + return; + } + if (isVM && NewVD->hasAttr<BlocksAttr>()) { Diag(NewVD->getLocation(), diag::err_block_on_vm); NewVD->setInvalidDecl(); @@ -7909,30 +8097,8 @@ struct FindOverriddenMethod { return false; } }; - -enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted }; } // end anonymous namespace -/// Report an error regarding overriding, along with any relevant -/// overridden methods. -/// -/// \param DiagID the primary error to report. -/// \param MD the overriding method. -/// \param OEK which overrides to include as notes. -static void ReportOverrides(Sema& S, unsigned DiagID, const CXXMethodDecl *MD, - OverrideErrorKind OEK = OEK_All) { - S.Diag(MD->getLocation(), DiagID) << MD->getDeclName(); - for (const CXXMethodDecl *O : MD->overridden_methods()) { - // This check (& the OEK parameter) could be replaced by a predicate, but - // without lambdas that would be overkill. This is still nicer than writing - // out the diag loop 3 times. - if ((OEK == OEK_All) || - (OEK == OEK_NonDeleted && !O->isDeleted()) || - (OEK == OEK_Deleted && O->isDeleted())) - S.Diag(O->getLocation(), diag::note_overridden_virtual_function); - } -} - /// AddOverriddenMethods - See if a method overrides any in the base classes, /// and if so, check that it's a valid override and remember it. bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { @@ -7941,8 +8107,6 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { FindOverriddenMethod FOM; FOM.Method = MD; FOM.S = this; - bool hasDeletedOverridenMethods = false; - bool hasNonDeletedOverridenMethods = false; bool AddedAny = false; if (DC->lookupInBases(FOM, Paths)) { for (auto *I : Paths.found_decls()) { @@ -7952,21 +8116,12 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { !CheckOverridingFunctionAttributes(MD, OldMD) && !CheckOverridingFunctionExceptionSpec(MD, OldMD) && !CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) { - hasDeletedOverridenMethods |= OldMD->isDeleted(); - hasNonDeletedOverridenMethods |= !OldMD->isDeleted(); AddedAny = true; } } } } - if (hasDeletedOverridenMethods && !MD->isDeleted()) { - ReportOverrides(*this, diag::err_non_deleted_override, MD, OEK_Deleted); - } - if (hasNonDeletedOverridenMethods && MD->isDeleted()) { - ReportOverrides(*this, diag::err_deleted_override, MD, OEK_NonDeleted); - } - return AddedAny; } @@ -8654,11 +8809,24 @@ static Scope *getTagInjectionScope(Scope *S, const LangOptions &LangOpts) { NamedDecl* Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo, LookupResult &Previous, - MultiTemplateParamsArg TemplateParamLists, + MultiTemplateParamsArg TemplateParamListsRef, bool &AddToScope) { QualType R = TInfo->getType(); assert(R->isFunctionType()); + if (R.getCanonicalType()->castAs<FunctionType>()->getCmseNSCallAttr()) + Diag(D.getIdentifierLoc(), diag::err_function_decl_cmse_ns_call); + + SmallVector<TemplateParameterList *, 4> TemplateParamLists; + for (TemplateParameterList *TPL : TemplateParamListsRef) + TemplateParamLists.push_back(TPL); + if (TemplateParameterList *Invented = D.getInventedTemplateParameterList()) { + if (!TemplateParamLists.empty() && + Invented->getDepth() == TemplateParamLists.back()->getDepth()) + TemplateParamLists.back() = Invented; + else + TemplateParamLists.push_back(Invented); + } // TODO: consider using NameInfo for diagnostic. DeclarationNameInfo NameInfo = GetNameForDeclarator(D); @@ -8738,15 +8906,16 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Match up the template parameter lists with the scope specifier, then // determine whether we have a template or a template specialization. bool Invalid = false; - if (TemplateParameterList *TemplateParams = - MatchTemplateParametersToScopeSpecifier( - D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(), - D.getCXXScopeSpec(), - D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId - ? D.getName().TemplateId - : nullptr, - TemplateParamLists, isFriend, isMemberSpecialization, - Invalid)) { + TemplateParameterList *TemplateParams = + MatchTemplateParametersToScopeSpecifier( + D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(), + D.getCXXScopeSpec(), + D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId + ? D.getName().TemplateId + : nullptr, + TemplateParamLists, isFriend, isMemberSpecialization, + Invalid); + if (TemplateParams) { if (TemplateParams->size() > 0) { // This is a function template @@ -8779,7 +8948,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // For source fidelity, store the other template param lists. if (TemplateParamLists.size() > 1) { NewFD->setTemplateParameterListsInfo(Context, - TemplateParamLists.drop_back(1)); + ArrayRef<TemplateParameterList *>(TemplateParamLists) + .drop_back(1)); } } else { // This is a function template specialization. @@ -8914,9 +9084,24 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // C++11 [dcl.constexpr]p3: functions declared constexpr are required to // be either constructors or to return a literal type. Therefore, // destructors cannot be declared constexpr. - if (isa<CXXDestructorDecl>(NewFD) && !getLangOpts().CPlusPlus2a) { + if (isa<CXXDestructorDecl>(NewFD) && + (!getLangOpts().CPlusPlus20 || ConstexprKind == CSK_consteval)) { Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor) << ConstexprKind; + NewFD->setConstexprKind(getLangOpts().CPlusPlus20 ? CSK_unspecified : CSK_constexpr); + } + // C++20 [dcl.constexpr]p2: An allocation function, or a + // deallocation function shall not be declared with the consteval + // specifier. + if (ConstexprKind == CSK_consteval && + (NewFD->getOverloadedOperator() == OO_New || + NewFD->getOverloadedOperator() == OO_Array_New || + NewFD->getOverloadedOperator() == OO_Delete || + NewFD->getOverloadedOperator() == OO_Array_Delete)) { + Diag(D.getDeclSpec().getConstexprSpecLoc(), + diag::err_invalid_consteval_decl_kind) + << NewFD; + NewFD->setConstexprKind(CSK_constexpr); } } @@ -8945,8 +9130,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } // If a function is defined as defaulted or deleted, mark it as such now. - // FIXME: Does this ever happen? ActOnStartOfFunctionDef forces the function - // definition kind to FDK_Definition. + // We'll do the relevant checks on defaulted / deleted functions later. switch (D.getFunctionDefinitionKind()) { case FDK_Declaration: case FDK_Definition: @@ -9808,6 +9992,18 @@ static bool CheckMultiVersionValue(Sema &S, const FunctionDecl *FD) { return false; } +// Provide a white-list of attributes that are allowed to be combined with +// multiversion functions. +static bool AttrCompatibleWithMultiVersion(attr::Kind Kind, + MultiVersionKind MVType) { + switch (Kind) { + default: + return false; + case attr::Used: + return MVType == MultiVersionKind::Target; + } +} + static bool HasNonMultiVersionAttributes(const FunctionDecl *FD, MultiVersionKind MVType) { for (const Attr *A : FD->attrs()) { @@ -9823,7 +10019,9 @@ static bool HasNonMultiVersionAttributes(const FunctionDecl *FD, return true; break; default: - return true; + if (!AttrCompatibleWithMultiVersion(A->getKind(), MVType)) + return true; + break; } } return false; @@ -10562,9 +10760,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, return Redeclaration; } } - } else if (CXXConversionDecl *Conversion - = dyn_cast<CXXConversionDecl>(NewFD)) { - ActOnConversionDeclarator(Conversion); } else if (auto *Guide = dyn_cast<CXXDeductionGuideDecl>(NewFD)) { if (auto *TD = Guide->getDescribedFunctionTemplate()) CheckDeductionGuideTemplate(TD); @@ -10581,12 +10776,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, if (!Method->isFunctionTemplateSpecialization() && !Method->getDescribedFunctionTemplate() && Method->isCanonicalDecl()) { - if (AddOverriddenMethods(Method->getParent(), Method)) { - // If the function was marked as "static", we have a problem. - if (NewFD->getStorageClass() == SC_Static) { - ReportOverrides(*this, diag::err_static_overrides_virtual, Method); - } - } + AddOverriddenMethods(Method->getParent(), Method); } if (Method->isVirtual() && NewFD->getTrailingRequiresClause()) // C++2a [class.virtual]p6 @@ -10598,6 +10788,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, checkThisInStaticMemberFunctionType(Method); } + if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD)) + ActOnConversionDeclarator(Conversion); + // Extra checking for C++ overloaded operators (C++ [over.oper]). if (NewFD->isOverloadedOperator() && CheckOverloadedOperatorDeclaration(NewFD)) { @@ -11363,6 +11556,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl, bool Sema::DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit, Expr *Init) { + assert(!Init || !Init->containsErrors()); QualType DeducedType = deduceVarTypeFromInitializer( VDecl, VDecl->getDeclName(), VDecl->getType(), VDecl->getTypeSourceInfo(), VDecl->getSourceRange(), DirectInit, Init); @@ -11396,6 +11590,9 @@ bool Sema::DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit, void Sema::checkNonTrivialCUnionInInitializer(const Expr *Init, SourceLocation Loc) { + if (auto *EWC = dyn_cast<ExprWithCleanups>(Init)) + Init = EWC->getSubExpr(); + if (auto *CE = dyn_cast<ConstantExpr>(Init)) Init = CE->getSubExpr(); @@ -11698,7 +11895,15 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { // TypoExpr. ExprResult Res = CorrectDelayedTyposInExpr(Init, VDecl); if (!Res.isUsable()) { + // There are unresolved typos in Init, just drop them. + // FIXME: improve the recovery strategy to preserve the Init. + RealDecl->setInvalidDecl(); + return; + } + if (Res.get()->containsErrors()) { + // Invalidate the decl as we don't know the type for recovery-expr yet. RealDecl->setInvalidDecl(); + VDecl->setInit(Res.get()); return; } Init = Res.get(); @@ -11790,6 +11995,13 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { return; } + // The LoaderUninitialized attribute acts as a definition (of undef). + if (VDecl->hasAttr<LoaderUninitializedAttr>()) { + Diag(VDecl->getLocation(), diag::err_loader_uninitialized_cant_init); + VDecl->setInvalidDecl(); + return; + } + // Get the decls type and save a reference for later, since // CheckInitializerTypes may change it. QualType DclT = VDecl->getType(), SavT = DclT; @@ -11821,7 +12033,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { // Try to correct any TypoExprs in the initialization arguments. for (size_t Idx = 0; Idx < Args.size(); ++Idx) { ExprResult Res = CorrectDelayedTyposInExpr( - Args[Idx], VDecl, [this, Entity, Kind](Expr *E) { + Args[Idx], VDecl, /*RecoverUncorrectedTypos=*/false, + [this, Entity, Kind](Expr *E) { InitializationSequence Init(*this, Entity, Kind, MultiExprArg(E)); return Init.Failed() ? ExprError() : E; }); @@ -11839,7 +12052,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { /*TreatUnavailableAsInvalid=*/false); ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT); if (Result.isInvalid()) { - VDecl->setInvalidDecl(); + // If the provied initializer fails to initialize the var decl, + // we attach a recovery expr for better recovery. + auto RecoveryExpr = + CreateRecoveryExpr(Init->getBeginLoc(), Init->getEndLoc(), Args); + if (RecoveryExpr.get()) + VDecl->setInit(RecoveryExpr.get()); return; } @@ -12100,6 +12318,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { VDecl->setInitStyle(VarDecl::ListInit); } + if (LangOpts.OpenMP && VDecl->isFileVarDecl()) + DeclsToCheckForDeferredDiags.push_back(VDecl); CheckCompleteVariableDeclaration(VDecl); } @@ -12120,7 +12340,7 @@ void Sema::ActOnInitializerError(Decl *D) { BD->setInvalidDecl(); // Auto types are meaningless if we can't make sense of the initializer. - if (ParsingInitForAutoVars.count(D)) { + if (VD->getType()->isUndeducedType()) { D->setInvalidDecl(); return; } @@ -12203,6 +12423,22 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { return; } + if (!Var->isInvalidDecl() && RealDecl->hasAttr<LoaderUninitializedAttr>()) { + if (CXXRecordDecl *RD = Var->getType()->getAsCXXRecordDecl()) { + if (!RD->hasTrivialDefaultConstructor()) { + Diag(Var->getLocation(), diag::err_loader_uninitialized_trivial_ctor); + Var->setInvalidDecl(); + return; + } + } + if (Var->getStorageClass() == SC_Extern) { + Diag(Var->getLocation(), diag::err_loader_uninitialized_extern_decl) + << Var; + Var->setInvalidDecl(); + return; + } + } + VarDecl::DefinitionKind DefKind = Var->isThisDeclarationADefinition(); if (!Var->isInvalidDecl() && DefKind != VarDecl::DeclarationOnly && Var->getType().hasNonTrivialToPrimitiveDefaultInitializeCUnion()) @@ -12260,9 +12496,9 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { if (!Var->isInvalidDecl()) { if (const IncompleteArrayType *ArrayT = Context.getAsIncompleteArrayType(Type)) { - if (RequireCompleteType(Var->getLocation(), - ArrayT->getElementType(), - diag::err_illegal_decl_array_incomplete_type)) + if (RequireCompleteSizedType( + Var->getLocation(), ArrayT->getElementType(), + diag::err_array_incomplete_or_sizeless_type)) Var->setInvalidDecl(); } else if (Var->getStorageClass() == SC_Static) { // C99 6.9.2p3: If the declaration of an identifier for an object is @@ -12378,12 +12614,18 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { InitializationSequence InitSeq(*this, Entity, Kind, None); ExprResult Init = InitSeq.Perform(*this, Entity, Kind, None); - if (Init.isInvalid()) - Var->setInvalidDecl(); - else if (Init.get()) { + + if (Init.get()) { Var->setInit(MaybeCreateExprWithCleanups(Init.get())); // This is important for template substitution. Var->setInitStyle(VarDecl::CallInit); + } else if (Init.isInvalid()) { + // If default-init fails, attach a recovery-expr initializer to track + // that initialization was attempted and failed. + auto RecoveryExpr = + CreateRecoveryExpr(Var->getLocation(), Var->getLocation(), {}); + if (RecoveryExpr.get()) + Var->setInit(RecoveryExpr.get()); } CheckCompleteVariableDeclaration(Var); @@ -12507,6 +12749,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { var->getDeclContext()->getRedeclContext()->isFileContext() && var->isExternallyVisible() && var->hasLinkage() && !var->isInline() && !var->getDescribedVarTemplate() && + !isa<VarTemplatePartialSpecializationDecl>(var) && !isTemplateInstantiation(var->getTemplateSpecializationKind()) && !getDiagnostics().isIgnored(diag::warn_missing_variable_declarations, var->getLocation())) { @@ -12559,7 +12802,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { if (GlobalStorage && var->isThisDeclarationADefinition() && !inTemplateInstantiation()) { PragmaStack<StringLiteral *> *Stack = nullptr; - int SectionFlags = ASTContext::PSF_Implicit | ASTContext::PSF_Read; + int SectionFlags = ASTContext::PSF_Read; if (var->getType().isConstQualified()) Stack = &ConstSegStack; else if (!var->getInit()) { @@ -12569,14 +12812,19 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { Stack = &DataSegStack; SectionFlags |= ASTContext::PSF_Write; } - if (Stack->CurrentValue && !var->hasAttr<SectionAttr>()) + if (const SectionAttr *SA = var->getAttr<SectionAttr>()) { + if (SA->getSyntax() == AttributeCommonInfo::AS_Declspec) + SectionFlags |= ASTContext::PSF_Implicit; + UnifySection(SA->getName(), SectionFlags, var); + } else if (Stack->CurrentValue) { + SectionFlags |= ASTContext::PSF_Implicit; + auto SectionName = Stack->CurrentValue->getString(); var->addAttr(SectionAttr::CreateImplicit( - Context, Stack->CurrentValue->getString(), - Stack->CurrentPragmaLocation, AttributeCommonInfo::AS_Pragma, - SectionAttr::Declspec_allocate)); - if (const SectionAttr *SA = var->getAttr<SectionAttr>()) - if (UnifySection(SA->getName(), SectionFlags, var)) + Context, SectionName, Stack->CurrentPragmaLocation, + AttributeCommonInfo::AS_Pragma, SectionAttr::Declspec_allocate)); + if (UnifySection(SectionName, SectionFlags, var)) var->dropAttr<SectionAttr>(); + } // Apply the init_seg attribute if this has an initializer. If the // initializer turns out to not be dynamic, we'll end up ignoring this @@ -13013,13 +13261,15 @@ Sema::BuildDeclaratorGroup(MutableArrayRef<Decl *> Group) { DeducedDecl = D; } else if (!Context.hasSameType(DT->getDeducedType(), Deduced)) { auto *AT = dyn_cast<AutoType>(DT); - Diag(D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(), - diag::err_auto_different_deductions) - << (AT ? (unsigned)AT->getKeyword() : 3) - << Deduced << DeducedDecl->getDeclName() - << DT->getDeducedType() << D->getDeclName() - << DeducedDecl->getInit()->getSourceRange() - << D->getInit()->getSourceRange(); + auto Dia = Diag(D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(), + diag::err_auto_different_deductions) + << (AT ? (unsigned)AT->getKeyword() : 3) << Deduced + << DeducedDecl->getDeclName() << DT->getDeducedType() + << D->getDeclName(); + if (DeducedDecl->hasInit()) + Dia << DeducedDecl->getInit()->getSourceRange(); + if (D->getInit()) + Dia << D->getInit()->getSourceRange(); D->setInvalidDecl(); break; } @@ -13398,9 +13648,28 @@ Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D, assert(D.isFunctionDeclarator() && "Not a function declarator!"); Scope *ParentScope = FnBodyScope->getParent(); + // Check if we are in an `omp begin/end declare variant` scope. If we are, and + // we define a non-templated function definition, we will create a declaration + // instead (=BaseFD), and emit the definition with a mangled name afterwards. + // The base function declaration will have the equivalent of an `omp declare + // variant` annotation which specifies the mangled definition as a + // specialization function under the OpenMP context defined as part of the + // `omp begin declare variant`. + FunctionDecl *BaseFD = nullptr; + if (LangOpts.OpenMP && isInOpenMPDeclareVariantScope() && + TemplateParameterLists.empty()) + BaseFD = ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope( + ParentScope, D); + D.setFunctionDefinitionKind(FDK_Definition); Decl *DP = HandleDeclarator(ParentScope, D, TemplateParameterLists); - return ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody); + Decl *Dcl = ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody); + + if (BaseFD) + ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope( + cast<FunctionDecl>(Dcl), BaseFD); + + return Dcl; } void Sema::ActOnFinishInlineFunctionDef(FunctionDecl *D) { @@ -13593,13 +13862,12 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator, VarDecl *VD = C.getCapturedVar(); if (VD->isInitCapture()) S.CurrentInstantiationScope->InstantiatedLocal(VD, VD); - QualType CaptureType = VD->getType(); const bool ByRef = C.getCaptureKind() == LCK_ByRef; LSI->addCapture(VD, /*IsBlock*/false, ByRef, /*RefersToEnclosingVariableOrCapture*/true, C.getLocation(), /*EllipsisLoc*/C.isPackExpansion() ? C.getEllipsisLoc() : SourceLocation(), - CaptureType, /*Invalid*/false); + I->getType(), /*Invalid*/false); } else if (C.capturesThis()) { LSI->addThisCapture(/*Nested*/ false, C.getLocation(), I->getType(), @@ -13632,7 +13900,9 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, // Do not push if it is a lambda because one is already pushed when building // the lambda in ActOnStartOfLambdaDefinition(). if (!isLambdaCallOperator(FD)) - PushExpressionEvaluationContext(ExprEvalContexts.back().Context); + PushExpressionEvaluationContext( + FD->isConsteval() ? ExpressionEvaluationContext::ConstantEvaluated + : ExprEvalContexts.back().Context); // Check for defining attributes before the check for redefinition. if (const auto *Attr = FD->getAttr<AliasAttr>()) { @@ -13996,11 +14266,48 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, : FixItHint{}); } } else { + // Returns true if the token beginning at this Loc is `const`. + auto isLocAtConst = [&](SourceLocation Loc, const SourceManager &SM, + const LangOptions &LangOpts) { + std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); + if (LocInfo.first.isInvalid()) + return false; + + bool Invalid = false; + StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid); + if (Invalid) + return false; + + if (LocInfo.second > Buffer.size()) + return false; + + const char *LexStart = Buffer.data() + LocInfo.second; + StringRef StartTok(LexStart, Buffer.size() - LocInfo.second); + + return StartTok.consume_front("const") && + (StartTok.empty() || isWhitespace(StartTok[0]) || + StartTok.startswith("/*") || StartTok.startswith("//")); + }; + + auto findBeginLoc = [&]() { + // If the return type has `const` qualifier, we want to insert + // `static` before `const` (and not before the typename). + if ((FD->getReturnType()->isAnyPointerType() && + FD->getReturnType()->getPointeeType().isConstQualified()) || + FD->getReturnType().isConstQualified()) { + // But only do this if we can determine where the `const` is. + + if (isLocAtConst(FD->getBeginLoc(), getSourceManager(), + getLangOpts())) + + return FD->getBeginLoc(); + } + return FD->getTypeSpecStartLoc(); + }; Diag(FD->getTypeSpecStartLoc(), diag::note_static_for_internal_linkage) << /* function */ 1 << (FD->getStorageClass() == SC_None - ? FixItHint::CreateInsertion(FD->getTypeSpecStartLoc(), - "static ") + ? FixItHint::CreateInsertion(findBeginLoc(), "static ") : FixItHint{}); } @@ -14008,11 +14315,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, // Warn if K&R function is defined without a previous declaration. // This warning is issued only if the definition itself does not provide // a prototype. Only K&R definitions do not provide a prototype. - // An empty list in a function declarator that is part of a definition - // of that function specifies that the function has no parameters - // (C99 6.7.5.3p14) - if (!FD->hasWrittenPrototype() && FD->getNumParams() > 0 && - !LangOpts.CPlusPlus) { + if (!FD->hasWrittenPrototype()) { TypeSourceInfo *TI = FD->getTypeSourceInfo(); TypeLoc TL = TI->getTypeLoc(); FunctionTypeLoc FTL = TL.getAsAdjusted<FunctionTypeLoc>(); @@ -14142,7 +14445,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, // If any errors have occurred, clear out any temporaries that may have // been leftover. This ensures that these temporaries won't be picked up for // deletion in some later function. - if (getDiagnostics().hasErrorOccurred() || + if (getDiagnostics().hasUncompilableErrorOccurred() || getDiagnostics().getSuppressAllDiagnostics()) { DiscardCleanupsInEvaluationContext(); } @@ -14198,10 +14501,17 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, // If any errors have occurred, clear out any temporaries that may have // been leftover. This ensures that these temporaries won't be picked up for // deletion in some later function. - if (getDiagnostics().hasErrorOccurred()) { + if (getDiagnostics().hasUncompilableErrorOccurred()) { DiscardCleanupsInEvaluationContext(); } + if (LangOpts.OpenMP || LangOpts.CUDA || LangOpts.SYCLIsDevice) { + auto ES = getEmissionStatus(FD); + if (ES == Sema::FunctionEmissionStatus::Emitted || + ES == Sema::FunctionEmissionStatus::Unknown) + DeclsToCheckForDeferredDiags.push_back(FD); + } + return dcl; } @@ -14333,6 +14643,77 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, return FD; } +/// If this function is a C++ replaceable global allocation function +/// (C++2a [basic.stc.dynamic.allocation], C++2a [new.delete]), +/// adds any function attributes that we know a priori based on the standard. +/// +/// We need to check for duplicate attributes both here and where user-written +/// attributes are applied to declarations. +void Sema::AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction( + FunctionDecl *FD) { + if (FD->isInvalidDecl()) + return; + + if (FD->getDeclName().getCXXOverloadedOperator() != OO_New && + FD->getDeclName().getCXXOverloadedOperator() != OO_Array_New) + return; + + Optional<unsigned> AlignmentParam; + bool IsNothrow = false; + if (!FD->isReplaceableGlobalAllocationFunction(&AlignmentParam, &IsNothrow)) + return; + + // C++2a [basic.stc.dynamic.allocation]p4: + // An allocation function that has a non-throwing exception specification + // indicates failure by returning a null pointer value. Any other allocation + // function never returns a null pointer value and indicates failure only by + // throwing an exception [...] + if (!IsNothrow && !FD->hasAttr<ReturnsNonNullAttr>()) + FD->addAttr(ReturnsNonNullAttr::CreateImplicit(Context, FD->getLocation())); + + // C++2a [basic.stc.dynamic.allocation]p2: + // An allocation function attempts to allocate the requested amount of + // storage. [...] If the request succeeds, the value returned by a + // replaceable allocation function is a [...] pointer value p0 different + // from any previously returned value p1 [...] + // + // However, this particular information is being added in codegen, + // because there is an opt-out switch for it (-fno-assume-sane-operator-new) + + // C++2a [basic.stc.dynamic.allocation]p2: + // An allocation function attempts to allocate the requested amount of + // storage. If it is successful, it returns the address of the start of a + // block of storage whose length in bytes is at least as large as the + // requested size. + if (!FD->hasAttr<AllocSizeAttr>()) { + FD->addAttr(AllocSizeAttr::CreateImplicit( + Context, /*ElemSizeParam=*/ParamIdx(1, FD), + /*NumElemsParam=*/ParamIdx(), FD->getLocation())); + } + + // C++2a [basic.stc.dynamic.allocation]p3: + // For an allocation function [...], the pointer returned on a successful + // call shall represent the address of storage that is aligned as follows: + // (3.1) If the allocation function takes an argument of type + // std::align_val_t, the storage will have the alignment + // specified by the value of this argument. + if (AlignmentParam.hasValue() && !FD->hasAttr<AllocAlignAttr>()) { + FD->addAttr(AllocAlignAttr::CreateImplicit( + Context, ParamIdx(AlignmentParam.getValue(), FD), FD->getLocation())); + } + + // FIXME: + // C++2a [basic.stc.dynamic.allocation]p3: + // For an allocation function [...], the pointer returned on a successful + // call shall represent the address of storage that is aligned as follows: + // (3.2) Otherwise, if the allocation function is named operator new[], + // the storage is aligned for any object that does not have + // new-extended alignment ([basic.align]) and is no larger than the + // requested size. + // (3.3) Otherwise, the storage is aligned for any object that does not + // have new-extended alignment and is of the requested size. +} + /// Adds any function attributes that we know a priori based on /// the declaration of this function. /// @@ -14433,6 +14814,8 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { } } + AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction(FD); + // If C++ exceptions are enabled but we are told extern "C" functions cannot // throw, add an implicit nothrow attribute to any extern "C" function we come // across. @@ -14538,12 +14921,16 @@ bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) { if (T->isDependentType()) return false; + // This doesn't use 'isIntegralType' despite the error message mentioning + // integral type because isIntegralType would also allow enum types in C. if (const BuiltinType *BT = T->getAs<BuiltinType>()) if (BT->isInteger()) return false; - Diag(UnderlyingLoc, diag::err_enum_invalid_underlying) << T; - return true; + if (T->isExtIntType()) + return false; + + return Diag(UnderlyingLoc, diag::err_enum_invalid_underlying) << T; } /// Check whether this is a valid redeclaration of a previous enumeration. @@ -15302,16 +15689,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, if (Kind == TTK_Enum && PrevTagDecl->getTagKind() == TTK_Enum) { const EnumDecl *PrevEnum = cast<EnumDecl>(PrevTagDecl); - - // If this is an elaborated-type-specifier for a scoped enumeration, - // the 'class' keyword is not necessary and not permitted. - if (TUK == TUK_Reference || TUK == TUK_Friend) { - if (ScopedEnum) - Diag(ScopedEnumKWLoc, diag::err_enum_class_reference) - << PrevEnum->isScoped() - << FixItHint::CreateRemoval(ScopedEnumKWLoc); + if (TUK == TUK_Reference || TUK == TUK_Friend) return PrevTagDecl; - } QualType EnumUnderlyingTy; if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast<TypeSourceInfo*>()) @@ -15789,7 +16168,7 @@ Decl *Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) { assert(isa<ObjCContainerDecl>(IDecl) && "ActOnObjCContainerStartDefinition - Not ObjCContainerDecl"); DeclContext *OCD = cast<DeclContext>(IDecl); - assert(getContainingDC(OCD) == CurContext && + assert(OCD->getLexicalParent() == CurContext && "The next DeclContext should be lexically contained in the current one."); CurContext = OCD; return IDecl; @@ -15900,6 +16279,10 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, QualType FieldTy, bool IsMsStruct, Expr *BitWidth, bool *ZeroWidth) { + assert(BitWidth); + if (BitWidth->containsErrors()) + return ExprError(); + // Default to true; that shouldn't confuse checks for emptiness if (ZeroWidth) *ZeroWidth = true; @@ -15907,8 +16290,9 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, // C99 6.7.2.1p4 - verify the field type. // C++ 9.6p3: A bit-field shall have integral or enumeration type. if (!FieldTy->isDependentType() && !FieldTy->isIntegralOrEnumerationType()) { - // Handle incomplete types with specific error. - if (RequireCompleteType(FieldLoc, FieldTy, diag::err_field_incomplete)) + // Handle incomplete and sizeless types with a specific error. + if (RequireCompleteSizedType(FieldLoc, FieldTy, + diag::err_field_incomplete_or_sizeless)) return ExprError(); if (FieldName) return Diag(FieldLoc, diag::err_not_integral_type_bitfield) @@ -16118,14 +16502,15 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, // If we receive a broken type, recover by assuming 'int' and // marking this declaration as invalid. - if (T.isNull()) { + if (T.isNull() || T->containsErrors()) { InvalidDecl = true; T = Context.IntTy; } QualType EltTy = Context.getBaseElementType(T); - if (!EltTy->isDependentType()) { - if (RequireCompleteType(Loc, EltTy, diag::err_field_incomplete)) { + if (!EltTy->isDependentType() && !EltTy->containsErrors()) { + if (RequireCompleteSizedType(Loc, EltTy, + diag::err_field_incomplete_or_sizeless)) { // Fields of incomplete type force their record to be invalid. Record->setInvalidDecl(); InvalidDecl = true; @@ -16214,6 +16599,14 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, BitWidth = nullptr; ZeroWidth = false; } + + // Only data members can have in-class initializers. + if (BitWidth && !II && InitStyle) { + Diag(Loc, diag::err_anon_bitfield_init); + InvalidDecl = true; + BitWidth = nullptr; + ZeroWidth = false; + } } // Check that 'mutable' is consistent with the type of the declaration. @@ -16669,8 +17062,9 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, // elsewhere, after synthesized ivars are known. } } else if (!FDTy->isDependentType() && - RequireCompleteType(FD->getLocation(), FD->getType(), - diag::err_field_incomplete)) { + RequireCompleteSizedType( + FD->getLocation(), FD->getType(), + diag::err_field_incomplete_or_sizeless)) { // Incomplete type FD->setInvalidDecl(); EnclosingDecl->setInvalidDecl(); @@ -16728,8 +17122,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, Context, "", UnavailableAttr::IR_ARCFieldWithOwnership, FD->getLocation())); } else if (getLangOpts().ObjC && - getLangOpts().getGC() != LangOptions::NonGC && - Record && !Record->hasObjectMember()) { + getLangOpts().getGC() != LangOptions::NonGC && Record && + !Record->hasObjectMember()) { if (FD->getType()->isObjCObjectPointerType() || FD->getType().isObjCGCStrong()) Record->setHasObjectMember(true); @@ -16793,10 +17187,10 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, I.setAccess((*I)->getAccess()); } - if (!CXXRecord->isDependentType()) { - // Add any implicitly-declared members to this class. - AddImplicitlyDeclaredMembersToClass(CXXRecord); + // Add any implicitly-declared members to this class. + AddImplicitlyDeclaredMembersToClass(CXXRecord); + if (!CXXRecord->isDependentType()) { if (!CXXRecord->isInvalidDecl()) { // If we have virtual base classes, we may end up finding multiple // final overriders for a given virtual function. Check for this @@ -17355,9 +17749,11 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements, typedef SmallVector<std::unique_ptr<ECDVector>, 3> DuplicatesVector; typedef llvm::PointerUnion<EnumConstantDecl*, ECDVector*> DeclOrVector; + + // DenseMaps cannot contain the all ones int64_t value, so use unordered_map. typedef std::unordered_map<int64_t, DeclOrVector> ValueToVectorMap; - // Use int64_t as a key to avoid needing special handling for DenseMap keys. + // Use int64_t as a key to avoid needing special handling for map keys. auto EnumConstantToKey = [](const EnumConstantDecl *D) { llvm::APSInt Val = D->getInitVal(); return Val.isSigned() ? Val.getSExtValue() : Val.getZExtValue(); @@ -17787,7 +18183,13 @@ Decl *Sema::getObjCDeclContext() const { return (dyn_cast_or_null<ObjCContainerDecl>(CurContext)); } -Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD) { +Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD, + bool Final) { + // SYCL functions can be template, so we check if they have appropriate + // attribute prior to checking if it is a template. + if (LangOpts.SYCLIsDevice && FD->hasAttr<SYCLKernelAttr>()) + return FunctionEmissionStatus::Emitted; + // Templates are emitted when they're instantiated. if (FD->isDependentContext()) return FunctionEmissionStatus::TemplateDiscarded; @@ -17799,8 +18201,10 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD) { if (DevTy.hasValue()) { if (*DevTy == OMPDeclareTargetDeclAttr::DT_Host) OMPES = FunctionEmissionStatus::OMPDiscarded; - else if (DeviceKnownEmittedFns.count(FD) > 0) + else if (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost || + *DevTy == OMPDeclareTargetDeclAttr::DT_Any) { OMPES = FunctionEmissionStatus::Emitted; + } } } else if (LangOpts.OpenMP) { // In OpenMP 4.5 all the functions are host functions. @@ -17816,10 +18220,11 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD) { if (DevTy.hasValue()) { if (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) { OMPES = FunctionEmissionStatus::OMPDiscarded; - } else if (DeviceKnownEmittedFns.count(FD) > 0) { + } else if (*DevTy == OMPDeclareTargetDeclAttr::DT_Host || + *DevTy == OMPDeclareTargetDeclAttr::DT_Any) OMPES = FunctionEmissionStatus::Emitted; - } - } + } else if (Final) + OMPES = FunctionEmissionStatus::Emitted; } } if (OMPES == FunctionEmissionStatus::OMPDiscarded || @@ -17854,9 +18259,7 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD) { // Otherwise, the function is known-emitted if it's in our set of // known-emitted functions. - return (DeviceKnownEmittedFns.count(FD) > 0) - ? FunctionEmissionStatus::Emitted - : FunctionEmissionStatus::Unknown; + return FunctionEmissionStatus::Unknown; } bool Sema::shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee) { |