diff options
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 709 |
1 files changed, 337 insertions, 372 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 59c10128f9087..ec5ca69735683 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -132,6 +132,7 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const { case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw__Float16: case tok::kw___float128: case tok::kw_wchar_t: case tok::kw_bool: @@ -280,7 +281,7 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, IdentifierInfo **CorrectedII) { // FIXME: Consider allowing this outside C++1z mode as an extension. bool AllowDeducedTemplate = IsClassTemplateDeductionContext && - getLangOpts().CPlusPlus1z && !IsCtorOrDtorName && + getLangOpts().CPlusPlus17 && !IsCtorOrDtorName && !isClassName && !HasTrailingDot; // Determine where we will perform name lookup. @@ -1447,6 +1448,46 @@ void Sema::FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S, F.done(); } +/// We've determined that \p New is a redeclaration of \p Old. Check that they +/// have compatible owning modules. +bool Sema::CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old) { + // FIXME: The Modules TS is not clear about how friend declarations are + // to be treated. It's not meaningful to have different owning modules for + // linkage in redeclarations of the same entity, so for now allow the + // redeclaration and change the owning modules to match. + if (New->getFriendObjectKind() && + Old->getOwningModuleForLinkage() != New->getOwningModuleForLinkage()) { + New->setLocalOwningModule(Old->getOwningModule()); + makeMergedDefinitionVisible(New); + return false; + } + + Module *NewM = New->getOwningModule(); + Module *OldM = Old->getOwningModule(); + if (NewM == OldM) + return false; + + // FIXME: Check proclaimed-ownership-declarations here too. + bool NewIsModuleInterface = NewM && NewM->Kind == Module::ModuleInterfaceUnit; + bool OldIsModuleInterface = OldM && OldM->Kind == Module::ModuleInterfaceUnit; + if (NewIsModuleInterface || OldIsModuleInterface) { + // C++ Modules TS [basic.def.odr] 6.2/6.7 [sic]: + // if a declaration of D [...] appears in the purview of a module, all + // other such declarations shall appear in the purview of the same module + Diag(New->getLocation(), diag::err_mismatched_owning_module) + << New + << NewIsModuleInterface + << (NewIsModuleInterface ? NewM->getFullModuleName() : "") + << OldIsModuleInterface + << (OldIsModuleInterface ? OldM->getFullModuleName() : ""); + Diag(Old->getLocation(), diag::note_previous_declaration); + New->setInvalidDecl(); + return true; + } + + return false; +} + static bool isUsingDecl(NamedDecl *D) { return isa<UsingShadowDecl>(D) || isa<UnresolvedUsingTypenameDecl>(D) || @@ -1682,7 +1723,8 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { dyn_cast<CXXConstructExpr>(Init); if (Construct && !Construct->isElidable()) { CXXConstructorDecl *CD = Construct->getConstructor(); - if (!CD->isTrivial() && !RD->hasAttr<WarnUnusedAttr>()) + if (!CD->isTrivial() && !RD->hasAttr<WarnUnusedAttr>() && + (VD->getInit()->isValueDependent() || !VD->evaluateValue())) return false; } } @@ -2623,6 +2665,16 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, } } + // This redeclaration adds a section attribute. + if (New->hasAttr<SectionAttr>() && !Old->hasAttr<SectionAttr>()) { + if (auto *VD = dyn_cast<VarDecl>(New)) { + if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly) { + Diag(New->getLocation(), diag::warn_attribute_section_on_redeclaration); + Diag(Old->getLocation(), diag::note_previous_declaration); + } + } + } + if (!Old->hasAttrs()) return; @@ -2951,6 +3003,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, New->dropAttr<InternalLinkageAttr>(); } + if (CheckRedeclarationModuleOwnership(New, Old)) + return true; + if (!getLangOpts().CPlusPlus) { bool OldOvl = Old->hasAttr<OverloadableAttr>(); if (OldOvl != New->hasAttr<OverloadableAttr>() && !Old->isImplicit()) { @@ -3526,8 +3581,6 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, ni = newMethod->param_begin(), ne = newMethod->param_end(); ni != ne && oi != oe; ++ni, ++oi) mergeParamDeclAttributes(*ni, *oi, *this); - - CheckObjCMethodOverride(newMethod, oldMethod); } static void diagnoseVarDeclTypeMismatch(Sema &S, VarDecl *New, VarDecl* Old) { @@ -3820,6 +3873,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { return New->setInvalidDecl(); } + if (CheckRedeclarationModuleOwnership(New, Old)) + return; + // Variables with external linkage are analyzed in FinalizeDeclaratorGroup. // FIXME: The test for external storage here seems wrong? We still @@ -3843,7 +3899,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { } } - // If this redeclaration makes the function inline, we may need to add it to + // If this redeclaration makes the variable inline, we may need to add it to // UndefinedButUsed. if (!Old->isInline() && New->isInline() && Old->isUsed(false) && !Old->getDefinition() && !New->isThisDeclarationADefinition()) @@ -4143,7 +4199,7 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, if (DS.isInlineSpecified()) Diag(DS.getInlineSpecLoc(), diag::err_inline_non_function) - << getLangOpts().CPlusPlus1z; + << getLangOpts().CPlusPlus17; if (DS.isConstexprSpecified()) { // C++0x [dcl.constexpr]p1: constexpr can only be applied to declarations @@ -4157,14 +4213,6 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, return TagD; } - if (DS.isConceptSpecified()) { - // C++ Concepts TS [dcl.spec.concept]p1: A concept definition refers to - // either a function concept and its definition or a variable concept and - // its initializer. - Diag(DS.getConceptSpecLoc(), diag::err_concept_wrong_decl_kind); - return TagD; - } - DiagnoseFunctionSpecifiers(DS); if (DS.isFriendSpecified()) { @@ -4371,7 +4419,7 @@ static bool CheckAnonMemberRedeclaration(Sema &SemaRef, SourceLocation NameLoc, bool IsUnion) { LookupResult R(SemaRef, Name, NameLoc, Sema::LookupMemberName, - Sema::ForRedeclaration); + Sema::ForVisibleRedeclaration); if (!SemaRef.LookupName(R, S)) return false; // Pick a representative declaration. @@ -5305,19 +5353,12 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType R = TInfo->getType(); - if (!R->isFunctionType() && DiagnoseClassNameShadow(DC, NameInfo)) - // If this is a typedef, we'll end up spewing multiple diagnostics. - // Just return early; it's safer. If this is a function, let the - // "constructor cannot have a return type" diagnostic handle it. - if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) - return nullptr; - if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, UPPC_DeclarationType)) D.setInvalidType(); LookupResult Previous(*this, NameInfo, LookupOrdinaryName, - ForRedeclaration); + forRedeclarationInCurContext()); // See if this is a redefinition of a variable in the same scope. if (!D.getCXXScopeSpec().isSet()) { @@ -5343,8 +5384,10 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) CreateBuiltins = true; - if (IsLinkageLookup) + if (IsLinkageLookup) { Previous.clear(LookupRedeclarationWithLinkage); + Previous.setRedeclarationKind(ForExternalRedeclaration); + } LookupName(Previous, S, CreateBuiltins); } else { // Something like "int foo::x;" @@ -5390,12 +5433,17 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, Previous.clear(); } + if (!R->isFunctionType() && DiagnoseClassNameShadow(DC, NameInfo)) + // Forget that the previous declaration is the injected-class-name. + Previous.clear(); + // In C++, the previous declaration we find might be a tag type // (class or enum). In this case, the new declaration will hide the - // tag type. Note that this does does not apply if we're declaring a - // typedef (C++ [dcl.typedef]p4). + // tag type. Note that this applies to functions, function templates, and + // variables, but not to typedefs (C++ [dcl.typedef]p4) or variable templates. if (Previous.isSingleTagDecl() && - D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef) + D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && + (TemplateParamLists.size() == 0 || R->isFunctionType())) Previous.clear(); // Check that there are no default arguments other than in the parameters @@ -5403,23 +5451,6 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, if (getLangOpts().CPlusPlus) CheckExtraCXXDefaultArguments(D); - if (D.getDeclSpec().isConceptSpecified()) { - // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be - // applied only to the definition of a function template or variable - // template, declared in namespace scope - if (!TemplateParamLists.size()) { - Diag(D.getDeclSpec().getConceptSpecLoc(), - diag:: err_concept_wrong_decl_kind); - return nullptr; - } - - if (!DC->getRedeclContext()->isFileContext()) { - Diag(D.getIdentifierLoc(), - diag::err_concept_decls_may_only_appear_in_namespace_scope); - return nullptr; - } - } - NamedDecl *New; bool AddToScope = true; @@ -5634,13 +5665,10 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (D.getDeclSpec().isInlineSpecified()) Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_non_function) - << getLangOpts().CPlusPlus1z; + << getLangOpts().CPlusPlus17; if (D.getDeclSpec().isConstexprSpecified()) Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr) << 1; - if (D.getDeclSpec().isConceptSpecified()) - Diag(D.getDeclSpec().getConceptSpecLoc(), - diag::err_concept_wrong_decl_kind); if (D.getName().Kind != UnqualifiedId::IK_Identifier) { if (D.getName().Kind == UnqualifiedId::IK_DeductionGuideName) @@ -5919,7 +5947,7 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, NamedDecl *NewDecl, bool IsSpecialization, bool IsDefinition) { - if (OldDecl->isInvalidDecl()) + if (OldDecl->isInvalidDecl() || NewDecl->isInvalidDecl()) return; bool IsTemplate = false; @@ -6025,13 +6053,30 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, NewDecl->dropAttr<DLLImportAttr>(); } } else if (IsInline && OldImportAttr && !IsMicrosoft) { - // In MinGW, seeing a function declared inline drops the dllimport attribute. + // In MinGW, seeing a function declared inline drops the dllimport + // attribute. OldDecl->dropAttr<DLLImportAttr>(); NewDecl->dropAttr<DLLImportAttr>(); S.Diag(NewDecl->getLocation(), diag::warn_dllimport_dropped_from_inline_function) << NewDecl << OldImportAttr; } + + // A specialization of a class template member function is processed here + // since it's a redeclaration. If the parent class is dllexport, the + // specialization inherits that attribute. This doesn't happen automatically + // since the parent class isn't instantiated until later. + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewDecl)) { + if (MD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization && + !NewImportAttr && !NewExportAttr) { + if (const DLLExportAttr *ParentExportAttr = + MD->getParent()->getAttr<DLLExportAttr>()) { + DLLExportAttr *NewAttr = ParentExportAttr->clone(S.Context); + NewAttr->setInherited(true); + NewDecl->addAttr(NewAttr); + } + } + } } /// Given that we are within the definition of the given function, @@ -6253,7 +6298,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( // The event type cannot be used with the __local, __constant and __global // address space qualifiers. if (R->isEventT()) { - if (R.getAddressSpace()) { + if (R.getAddressSpace() != LangAS::opencl_private) { Diag(D.getLocStart(), diag::err_event_t_addr_space_qual); D.setInvalidType(); } @@ -6289,7 +6334,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( // Suppress the warning in system macros, it's used in macros in some // popular C system headers, such as in glibc's htonl() macro. Diag(D.getDeclSpec().getStorageClassSpecLoc(), - getLangOpts().CPlusPlus1z ? diag::ext_register_storage_class + getLangOpts().CPlusPlus17 ? diag::ext_register_storage_class : diag::warn_deprecated_register) << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); } @@ -6477,49 +6522,9 @@ NamedDecl *Sema::ActOnVariableDeclarator( // C++1z [dcl.spec.constexpr]p1: // A static data member declared with the constexpr specifier is // implicitly an inline variable. - if (NewVD->isStaticDataMember() && getLangOpts().CPlusPlus1z) + if (NewVD->isStaticDataMember() && getLangOpts().CPlusPlus17) NewVD->setImplicitlyInline(); } - - if (D.getDeclSpec().isConceptSpecified()) { - if (VarTemplateDecl *VTD = NewVD->getDescribedVarTemplate()) - VTD->setConcept(); - - // C++ Concepts TS [dcl.spec.concept]p2: A concept definition shall not - // be declared with the thread_local, inline, friend, or constexpr - // specifiers, [...] - if (D.getDeclSpec().getThreadStorageClassSpec() == TSCS_thread_local) { - Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), - diag::err_concept_decl_invalid_specifiers) - << 0 << 0; - NewVD->setInvalidDecl(true); - } - - if (D.getDeclSpec().isConstexprSpecified()) { - Diag(D.getDeclSpec().getConstexprSpecLoc(), - diag::err_concept_decl_invalid_specifiers) - << 0 << 3; - NewVD->setInvalidDecl(true); - } - - // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be - // applied only to the definition of a function template or variable - // template, declared in namespace scope. - if (IsVariableTemplateSpecialization) { - Diag(D.getDeclSpec().getConceptSpecLoc(), - diag::err_concept_specified_specialization) - << (IsPartialSpecialization ? 2 : 1); - } - - // C++ Concepts TS [dcl.spec.concept]p6: A variable concept has the - // following restrictions: - // - The declared type shall have the type bool. - if (!Context.hasSameType(NewVD->getType(), Context.BoolTy) && - !NewVD->isInvalidDecl()) { - Diag(D.getIdentifierLoc(), diag::err_variable_concept_bool_decl); - NewVD->setInvalidDecl(true); - } - } } if (D.getDeclSpec().isInlineSpecified()) { @@ -6533,7 +6538,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc()); } else { Diag(D.getDeclSpec().getInlineSpecLoc(), - getLangOpts().CPlusPlus1z ? diag::warn_cxx14_compat_inline_variable + getLangOpts().CPlusPlus17 ? diag::warn_cxx14_compat_inline_variable : diag::ext_inline_variable); NewVD->setInlineSpecified(); } @@ -6770,25 +6775,6 @@ NamedDecl *Sema::ActOnVariableDeclarator( if (!IsVariableTemplateSpecialization) D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); - // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare [...] - // an explicit specialization (14.8.3) or a partial specialization of a - // concept definition. - if (IsVariableTemplateSpecialization && - !D.getDeclSpec().isConceptSpecified() && !Previous.empty() && - Previous.isSingleResult()) { - NamedDecl *PreviousDecl = Previous.getFoundDecl(); - if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(PreviousDecl)) { - if (VarTmpl->isConcept()) { - Diag(NewVD->getLocation(), diag::err_concept_specialized) - << 1 /*variable*/ - << (IsPartialSpecialization ? 2 /*partially specialized*/ - : 1 /*explicitly specialized*/); - Diag(VarTmpl->getLocation(), diag::note_previous_declaration); - NewVD->setInvalidDecl(); - } - } - } - if (NewTemplate) { VarTemplateDecl *PrevVarTemplate = NewVD->getPreviousDecl() @@ -7087,7 +7073,7 @@ void Sema::CheckShadow(Scope *S, VarDecl *D) { return; LookupResult R(*this, D->getDeclName(), D->getLocation(), - Sema::LookupOrdinaryName, Sema::ForRedeclaration); + Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration); LookupName(R, S); if (NamedDecl *ShadowedDecl = getShadowedDeclaration(D, R)) CheckShadow(D, ShadowedDecl, R); @@ -7260,8 +7246,8 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { // This includes arrays of objects with address space qualifiers, but not // automatic variables that point to other address spaces. // ISO/IEC TR 18037 S5.1.2 - if (!getLangOpts().OpenCL - && NewVD->hasLocalStorage() && T.getAddressSpace() != 0) { + if (!getLangOpts().OpenCL && NewVD->hasLocalStorage() && + T.getAddressSpace() != LangAS::Default) { Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 0; NewVD->setInvalidDecl(); return; @@ -7356,7 +7342,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { return; } } - } else if (T.getAddressSpace() != LangAS::Default) { + } else if (T.getAddressSpace() != LangAS::opencl_private) { // Do not allow other address spaces on automatic variable. Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 1; NewVD->setInvalidDecl(); @@ -7531,16 +7517,14 @@ enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted }; static void ReportOverrides(Sema& S, unsigned DiagID, const CXXMethodDecl *MD, OverrideErrorKind OEK = OEK_All) { S.Diag(MD->getLocation(), DiagID) << MD->getDeclName(); - for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), - E = MD->end_overridden_methods(); - I != E; ++I) { + 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 && !(*I)->isDeleted()) || - (OEK == OEK_Deleted && (*I)->isDeleted())) - S.Diag((*I)->getLocation(), diag::note_overridden_virtual_function); + (OEK == OEK_NonDeleted && !O->isDeleted()) || + (OEK == OEK_Deleted && O->isDeleted())) + S.Diag(O->getLocation(), diag::note_overridden_virtual_function); } } @@ -7663,7 +7647,7 @@ static NamedDecl *DiagnoseInvalidRedeclaration( LookupResult Prev(SemaRef, Name, NewFD->getLocation(), IsLocalFriend ? Sema::LookupLocalFriendName : Sema::LookupOrdinaryName, - Sema::ForRedeclaration); + Sema::ForVisibleRedeclaration); NewFD->setInvalidDecl(); if (IsLocalFriend) @@ -7991,7 +7975,8 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) { if (PointeeType->isPointerType()) return PtrPtrKernelParam; if (PointeeType.getAddressSpace() == LangAS::opencl_generic || - PointeeType.getAddressSpace() == 0) + PointeeType.getAddressSpace() == LangAS::opencl_private || + PointeeType.getAddressSpace() == LangAS::Default) return InvalidAddrSpacePtrKernelParam; return PtrKernelParam; } @@ -8241,7 +8226,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, bool isVirtual = D.getDeclSpec().isVirtualSpecified(); bool isExplicit = D.getDeclSpec().isExplicitSpecified(); bool isConstexpr = D.getDeclSpec().isConstexprSpecified(); - bool isConcept = D.getDeclSpec().isConceptSpecified(); isFriend = D.getDeclSpec().isFriendSpecified(); if (isFriend && !isInline && D.isFunctionDefinition()) { // C++ [class.friend]p5 @@ -8453,89 +8437,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor); } - if (isConcept) { - // This is a function concept. - if (FunctionTemplateDecl *FTD = NewFD->getDescribedFunctionTemplate()) - FTD->setConcept(); - - // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be - // applied only to the definition of a function template [...] - if (!D.isFunctionDefinition()) { - Diag(D.getDeclSpec().getConceptSpecLoc(), - diag::err_function_concept_not_defined); - NewFD->setInvalidDecl(); - } - - // C++ Concepts TS [dcl.spec.concept]p1: [...] A function concept shall - // have no exception-specification and is treated as if it were specified - // with noexcept(true) (15.4). [...] - if (const FunctionProtoType *FPT = R->getAs<FunctionProtoType>()) { - if (FPT->hasExceptionSpec()) { - SourceRange Range; - if (D.isFunctionDeclarator()) - Range = D.getFunctionTypeInfo().getExceptionSpecRange(); - Diag(NewFD->getLocation(), diag::err_function_concept_exception_spec) - << FixItHint::CreateRemoval(Range); - NewFD->setInvalidDecl(); - } else { - Context.adjustExceptionSpec(NewFD, EST_BasicNoexcept); - } - - // C++ Concepts TS [dcl.spec.concept]p5: A function concept has the - // following restrictions: - // - The declared return type shall have the type bool. - if (!Context.hasSameType(FPT->getReturnType(), Context.BoolTy)) { - Diag(D.getIdentifierLoc(), diag::err_function_concept_bool_ret); - NewFD->setInvalidDecl(); - } - - // C++ Concepts TS [dcl.spec.concept]p5: A function concept has the - // following restrictions: - // - The declaration's parameter list shall be equivalent to an empty - // parameter list. - if (FPT->getNumParams() > 0 || FPT->isVariadic()) - Diag(NewFD->getLocation(), diag::err_function_concept_with_params); - } - - // C++ Concepts TS [dcl.spec.concept]p2: Every concept definition is - // implicity defined to be a constexpr declaration (implicitly inline) - NewFD->setImplicitlyInline(); - - // C++ Concepts TS [dcl.spec.concept]p2: A concept definition shall not - // be declared with the thread_local, inline, friend, or constexpr - // specifiers, [...] - if (isInline) { - Diag(D.getDeclSpec().getInlineSpecLoc(), - diag::err_concept_decl_invalid_specifiers) - << 1 << 1; - NewFD->setInvalidDecl(true); - } - - if (isFriend) { - Diag(D.getDeclSpec().getFriendSpecLoc(), - diag::err_concept_decl_invalid_specifiers) - << 1 << 2; - NewFD->setInvalidDecl(true); - } - - if (isConstexpr) { - Diag(D.getDeclSpec().getConstexprSpecLoc(), - diag::err_concept_decl_invalid_specifiers) - << 1 << 3; - NewFD->setInvalidDecl(true); - } - - // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be - // applied only to the definition of a function template or variable - // template, declared in namespace scope. - if (isFunctionTemplateSpecialization) { - Diag(D.getDeclSpec().getConceptSpecLoc(), - diag::err_concept_specified_specialization) << 1; - NewFD->setInvalidDecl(true); - return NewFD; - } - } - // If __module_private__ was specified, mark the function accordingly. if (D.getDeclSpec().isModulePrivateSpecified()) { if (isFunctionTemplateSpecialization) { @@ -8760,10 +8661,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (getLangOpts().OpenCL) { // OpenCL v1.1 s6.5: Using an address space qualifier in a function return // type declaration will generate a compilation error. - unsigned AddressSpace = NewFD->getReturnType().getAddressSpace(); - if (AddressSpace == LangAS::opencl_local || - AddressSpace == LangAS::opencl_global || - AddressSpace == LangAS::opencl_constant) { + LangAS AddressSpace = NewFD->getReturnType().getAddressSpace(); + if (AddressSpace != LangAS::Default) { Diag(NewFD->getLocation(), diag::err_opencl_return_value_with_address_space); NewFD->setInvalidDecl(); @@ -8890,10 +8789,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, diag::ext_function_specialization_in_class : diag::err_function_specialization_in_class) << NewFD->getDeclName(); - } else if (CheckFunctionTemplateSpecialization(NewFD, - (HasExplicitTemplateArgs ? &TemplateArgs - : nullptr), - Previous)) + } else if (!NewFD->isInvalidDecl() && + CheckFunctionTemplateSpecialization( + NewFD, (HasExplicitTemplateArgs ? &TemplateArgs : nullptr), + Previous)) NewFD->setInvalidDecl(); // C++ [dcl.stc]p1: @@ -9529,7 +9428,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // return type. (Exception specifications on the function itself are OK in // most cases, and exception specifications are not permitted in most other // contexts where they could make it into a mangling.) - if (!getLangOpts().CPlusPlus1z && !NewFD->getPrimaryTemplate()) { + if (!getLangOpts().CPlusPlus17 && !NewFD->getPrimaryTemplate()) { auto HasNoexcept = [&](QualType T) -> bool { // Strip off declarator chunks that could be between us and a function // type. We don't need to look far, exception specifications are very @@ -9552,7 +9451,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, AnyNoexcept |= HasNoexcept(T); if (AnyNoexcept) Diag(NewFD->getLocation(), - diag::warn_cxx1z_compat_exception_spec_in_signature) + diag::warn_cxx17_compat_exception_spec_in_signature) << NewFD; } @@ -9601,6 +9500,13 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { assert(T->isFunctionType() && "function decl is not of function type"); const FunctionType* FT = T->castAs<FunctionType>(); + // Set default calling convention for main() + if (FT->getCallConv() != CC_C) { + FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(CC_C)); + FD->setType(QualType(FT, 0)); + T = Context.getCanonicalType(FD->getType()); + } + if (getLangOpts().GNUMode && !getLangOpts().CPlusPlus) { // In C with GNU extensions we allow main() to have non-integer return // type, but we should warn about the extension, and we disable the @@ -10000,14 +9906,9 @@ namespace { void VisitCallExpr(CallExpr *E) { // Treat std::move as a use. - if (E->getNumArgs() == 1) { - if (FunctionDecl *FD = E->getDirectCallee()) { - if (FD->isInStdNamespace() && FD->getIdentifier() && - FD->getIdentifier()->isStr("move")) { - HandleValue(E->getArg(0)); - return; - } - } + if (E->isCallToStdMove()) { + HandleValue(E->getArg(0)); + return; } Inherited::VisitCallExpr(E); @@ -10737,7 +10638,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { if (Var->isStaticDataMember()) { // C++1z removes the relevant rule; the in-class declaration is always // a definition there. - if (!getLangOpts().CPlusPlus1z) { + if (!getLangOpts().CPlusPlus17) { Diag(Var->getLocation(), diag::err_constexpr_static_mem_var_requires_init) << Var->getDeclName(); @@ -10751,17 +10652,6 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { } } - // C++ Concepts TS [dcl.spec.concept]p1: [...] A variable template - // definition having the concept specifier is called a variable concept. A - // concept definition refers to [...] a variable concept and its initializer. - if (VarTemplateDecl *VTD = Var->getDescribedVarTemplate()) { - if (VTD->isConcept()) { - Diag(Var->getLocation(), diag::err_var_concept_not_initialized); - Var->setInvalidDecl(); - return; - } - } - // OpenCL v1.1 s6.5.3: variables declared in the constant address space must // be initialized. if (!Var->isInvalidDecl() && @@ -11651,6 +11541,14 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { StorageClass SC = SC_None; if (DS.getStorageClassSpec() == DeclSpec::SCS_register) { SC = SC_Register; + // In C++11, the 'register' storage class specifier is deprecated. + // In C++17, it is not allowed, but we tolerate it as an extension. + if (getLangOpts().CPlusPlus11) { + Diag(DS.getStorageClassSpecLoc(), + getLangOpts().CPlusPlus17 ? diag::ext_register_storage_class + : diag::warn_deprecated_register) + << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc()); + } } else if (getLangOpts().CPlusPlus && DS.getStorageClassSpec() == DeclSpec::SCS_auto) { SC = SC_Auto; @@ -11665,12 +11563,10 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { << DeclSpec::getSpecifierName(TSCS); if (DS.isInlineSpecified()) Diag(DS.getInlineSpecLoc(), diag::err_inline_non_function) - << getLangOpts().CPlusPlus1z; + << getLangOpts().CPlusPlus17; if (DS.isConstexprSpecified()) Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr) << 0; - if (DS.isConceptSpecified()) - Diag(DS.getConceptSpecLoc(), diag::err_concept_wrong_decl_kind); DiagnoseFunctionSpecifiers(DS); @@ -11704,7 +11600,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { // Check for redeclaration of parameters, e.g. int foo(int x, int x); if (II) { LookupResult R(*this, II, D.getIdentifierLoc(), LookupOrdinaryName, - ForRedeclaration); + ForVisibleRedeclaration); LookupName(R, S); if (R.isSingleResult()) { NamedDecl *PrevDecl = R.getFoundDecl(); @@ -11873,13 +11769,13 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, // duration shall not be qualified by an address-space qualifier." // Since all parameters have automatic store duration, they can not have // an address space. - if (T.getAddressSpace() != 0) { - // OpenCL allows function arguments declared to be an array of a type - // to be qualified with an address space. - if (!(getLangOpts().OpenCL && T->isArrayType())) { - Diag(NameLoc, diag::err_arg_with_address_space); - New->setInvalidDecl(); - } + if (T.getAddressSpace() != LangAS::Default && + // OpenCL allows function arguments declared to be an array of a type + // to be qualified with an address space. + !(getLangOpts().OpenCL && + (T->isArrayType() || T.getAddressSpace() == LangAS::opencl_private))) { + Diag(NameLoc, diag::err_arg_with_address_space); + New->setInvalidDecl(); } return New; @@ -12346,18 +12242,6 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, } } - // The only way to be included in UndefinedButUsed is if there is an - // ODR use before the definition. Avoid the expensive map lookup if this - // is the first declaration. - if (!FD->isFirstDecl() && FD->getPreviousDecl()->isUsed()) { - if (!FD->isExternallyVisible()) - UndefinedButUsed.erase(FD); - else if (FD->isInlined() && - !LangOpts.GNUInline && - (!FD->getPreviousDecl()->hasAttr<GNUInlineAttr>())) - UndefinedButUsed.erase(FD); - } - // If the function implicitly returns zero (like 'main') or is naked, // don't complain about missing return statements. if (FD->hasImplicitReturnZero() || FD->hasAttr<NakedAttr>()) @@ -12621,28 +12505,50 @@ void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D, /// call, forming a call to an implicitly defined function (per C99 6.5.1p2). NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II, Scope *S) { + Scope *BlockScope = S; + while (!BlockScope->isCompoundStmtScope() && BlockScope->getParent()) + BlockScope = BlockScope->getParent(); + // Before we produce a declaration for an implicitly defined // function, see whether there was a locally-scoped declaration of // this name as a function or variable. If so, use that // (non-visible) declaration, and complain about it. - if (NamedDecl *ExternCPrev = findLocallyScopedExternCDecl(&II)) { - Diag(Loc, diag::warn_use_out_of_scope_declaration) << ExternCPrev; - Diag(ExternCPrev->getLocation(), diag::note_previous_declaration); - return ExternCPrev; + NamedDecl *ExternCPrev = findLocallyScopedExternCDecl(&II); + if (ExternCPrev) { + // We still need to inject the function into the enclosing block scope so + // that later (non-call) uses can see it. + PushOnScopeChains(ExternCPrev, BlockScope, /*AddToContext*/false); + + // C89 footnote 38: + // If in fact it is not defined as having type "function returning int", + // the behavior is undefined. + if (!isa<FunctionDecl>(ExternCPrev) || + !Context.typesAreCompatible( + cast<FunctionDecl>(ExternCPrev)->getType(), + Context.getFunctionNoProtoType(Context.IntTy))) { + Diag(Loc, diag::ext_use_out_of_scope_declaration) + << ExternCPrev << !getLangOpts().C99; + Diag(ExternCPrev->getLocation(), diag::note_previous_declaration); + return ExternCPrev; + } } // Extension in C99. Legal in C90, but warn about it. + // OpenCL v2.0 s6.9.u - Implicit function declaration is not supported. unsigned diag_id; if (II.getName().startswith("__builtin_")) diag_id = diag::warn_builtin_unknown; - // OpenCL v2.0 s6.9.u - Implicit function declaration is not supported. - else if (getLangOpts().OpenCL) - diag_id = diag::err_opencl_implicit_function_decl; - else if (getLangOpts().C99) + else if (getLangOpts().C99 || getLangOpts().OpenCL) diag_id = diag::ext_implicit_function_decl; else diag_id = diag::warn_implicit_function_decl; - Diag(Loc, diag_id) << &II; + Diag(Loc, diag_id) << &II << getLangOpts().OpenCL; + + // If we found a prior declaration of this function, don't bother building + // another one. We've already pushed that one into scope, so there's nothing + // more to do. + if (ExternCPrev) + return ExternCPrev; // Because typo correction is expensive, only do it if the implicit // function declaration is going to be treated as an error. @@ -12694,16 +12600,10 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, SourceLocation()); D.SetIdentifier(&II, Loc); - // Insert this function into translation-unit scope. - - DeclContext *PrevDC = CurContext; - CurContext = Context.getTranslationUnitDecl(); - - FunctionDecl *FD = cast<FunctionDecl>(ActOnDeclarator(TUScope, D)); + // Insert this function into the enclosing block scope. + FunctionDecl *FD = cast<FunctionDecl>(ActOnDeclarator(BlockScope, D)); FD->setImplicit(); - CurContext = PrevDC; - AddKnownFunctionAttributes(FD); return FD; @@ -12752,15 +12652,33 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { FD->getLocation())); } - // Mark const if we don't care about errno and that is the only - // thing preventing the function from being const. This allows - // IRgen to use LLVM intrinsics for such functions. - if (!getLangOpts().MathErrno && - Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) { - if (!FD->hasAttr<ConstAttr>()) + // Mark const if we don't care about errno and that is the only thing + // preventing the function from being const. This allows IRgen to use LLVM + // intrinsics for such functions. + if (!getLangOpts().MathErrno && !FD->hasAttr<ConstAttr>() && + Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) + FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation())); + + // We make "fma" on GNU or Windows const because we know it does not set + // errno in those environments even though it could set errno based on the + // C standard. + const llvm::Triple &Trip = Context.getTargetInfo().getTriple(); + if ((Trip.isGNUEnvironment() || Trip.isOSMSVCRT()) && + !FD->hasAttr<ConstAttr>()) { + switch (BuiltinID) { + case Builtin::BI__builtin_fma: + case Builtin::BI__builtin_fmaf: + case Builtin::BI__builtin_fmal: + case Builtin::BIfma: + case Builtin::BIfmaf: + case Builtin::BIfmal: FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation())); + break; + default: + break; + } } - + if (Context.BuiltinInfo.isReturnsTwice(BuiltinID) && !FD->hasAttr<ReturnsTwiceAttr>()) FD->addAttr(ReturnsTwiceAttr::CreateImplicit(Context, @@ -13260,7 +13178,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, bool isStdBadAlloc = false; bool isStdAlignValT = false; - RedeclarationKind Redecl = ForRedeclaration; + RedeclarationKind Redecl = forRedeclarationInCurContext(); if (TUK == TUK_Friend || TUK == TUK_Reference) Redecl = NotForRedeclaration; @@ -13538,10 +13456,10 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // type declared by an elaborated-type-specifier. In C that is not correct // and we should instead merge compatible types found by lookup. if (getLangOpts().CPlusPlus) { - Previous.setRedeclarationKind(ForRedeclaration); + Previous.setRedeclarationKind(forRedeclarationInCurContext()); LookupQualifiedName(Previous, SearchDC); } else { - Previous.setRedeclarationKind(ForRedeclaration); + Previous.setRedeclarationKind(forRedeclarationInCurContext()); LookupName(Previous, S); } } @@ -13941,6 +13859,13 @@ CreateNewDecl: Invalid = true; } + if (!Invalid && getLangOpts().CPlusPlus && TUK == TUK_Definition && + DC->getDeclKind() == Decl::Enum) { + Diag(New->getLocation(), diag::err_type_defined_in_enum) + << Context.getTagDeclType(New); + Invalid = true; + } + // Maybe add qualifier info. if (SS.isNotEmpty()) { if (SS.isSet()) { @@ -14032,6 +13957,9 @@ CreateNewDecl: if (!Invalid && SearchDC->isRecord()) SetMemberAccessSpecifier(New, PrevDecl, AS); + if (PrevDecl) + CheckRedeclarationModuleOwnership(New, PrevDecl); + if (TUK == TUK_Definition) New->startDefinition(); @@ -14358,7 +14286,9 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, } // TR 18037 does not allow fields to be declared with address spaces. - if (T.getQualifiers().hasAddressSpace()) { + if (T.getQualifiers().hasAddressSpace() || + T->isDependentAddressSpaceType() || + T->getBaseElementTypeUnsafe()->isDependentAddressSpaceType()) { Diag(Loc, diag::err_field_with_address_space); D.setInvalidType(); } @@ -14375,7 +14305,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, if (D.getDeclSpec().isInlineSpecified()) Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_non_function) - << getLangOpts().CPlusPlus1z; + << getLangOpts().CPlusPlus17; if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), diag::err_invalid_thread) @@ -14383,7 +14313,8 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, // Check to see if this name was declared as a member previously NamedDecl *PrevDecl = nullptr; - LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration); + LookupResult Previous(*this, II, Loc, LookupMemberName, + ForVisibleRedeclaration); LookupName(Previous, S); switch (Previous.getResultKind()) { case LookupResult::Found: @@ -14771,7 +14702,7 @@ Decl *Sema::ActOnIvar(Scope *S, if (II) { NamedDecl *PrevDecl = LookupSingleName(S, II, Loc, LookupMemberName, - ForRedeclaration); + ForVisibleRedeclaration); if (PrevDecl && isDeclInScope(PrevDecl, EnclosingContext, S) && !isa<TagDecl>(PrevDecl)) { Diag(Loc, diag::err_duplicate_member) << II; @@ -14913,6 +14844,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, // possibly recursively, a member that is such a structure) // shall not be a member of a structure or an element of an // array. + bool IsLastField = (i + 1 == Fields.end()); if (FDTy->isFunctionType()) { // Field declared as a function. Diag(FD->getLocation(), diag::err_field_declared_as_function) @@ -14920,60 +14852,70 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, FD->setInvalidDecl(); EnclosingDecl->setInvalidDecl(); continue; - } else if (FDTy->isIncompleteArrayType() && Record && - ((i + 1 == Fields.end() && !Record->isUnion()) || - ((getLangOpts().MicrosoftExt || - getLangOpts().CPlusPlus) && - (i + 1 == Fields.end() || Record->isUnion())))) { - // Flexible array member. - // Microsoft and g++ is more permissive regarding flexible array. - // It will accept flexible array in union and also - // as the sole element of a struct/class. - unsigned DiagID = 0; - if (Record->isUnion()) - DiagID = getLangOpts().MicrosoftExt - ? diag::ext_flexible_array_union_ms - : getLangOpts().CPlusPlus - ? diag::ext_flexible_array_union_gnu - : diag::err_flexible_array_union; - else if (NumNamedMembers < 1) - DiagID = getLangOpts().MicrosoftExt - ? diag::ext_flexible_array_empty_aggregate_ms - : getLangOpts().CPlusPlus - ? diag::ext_flexible_array_empty_aggregate_gnu - : diag::err_flexible_array_empty_aggregate; - - if (DiagID) - Diag(FD->getLocation(), DiagID) << FD->getDeclName() - << Record->getTagKind(); - // While the layout of types that contain virtual bases is not specified - // by the C++ standard, both the Itanium and Microsoft C++ ABIs place - // virtual bases after the derived members. This would make a flexible - // array member declared at the end of an object not adjacent to the end - // of the type. - if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record)) - if (RD->getNumVBases() != 0) - Diag(FD->getLocation(), diag::err_flexible_array_virtual_base) + } else if (FDTy->isIncompleteArrayType() && + (Record || isa<ObjCContainerDecl>(EnclosingDecl))) { + if (Record) { + // Flexible array member. + // Microsoft and g++ is more permissive regarding flexible array. + // It will accept flexible array in union and also + // as the sole element of a struct/class. + unsigned DiagID = 0; + if (!Record->isUnion() && !IsLastField) { + Diag(FD->getLocation(), diag::err_flexible_array_not_at_end) + << FD->getDeclName() << FD->getType() << Record->getTagKind(); + Diag((*(i + 1))->getLocation(), diag::note_next_field_declaration); + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } else if (Record->isUnion()) + DiagID = getLangOpts().MicrosoftExt + ? diag::ext_flexible_array_union_ms + : getLangOpts().CPlusPlus + ? diag::ext_flexible_array_union_gnu + : diag::err_flexible_array_union; + else if (NumNamedMembers < 1) + DiagID = getLangOpts().MicrosoftExt + ? diag::ext_flexible_array_empty_aggregate_ms + : getLangOpts().CPlusPlus + ? diag::ext_flexible_array_empty_aggregate_gnu + : diag::err_flexible_array_empty_aggregate; + + if (DiagID) + Diag(FD->getLocation(), DiagID) << FD->getDeclName() + << Record->getTagKind(); + // While the layout of types that contain virtual bases is not specified + // by the C++ standard, both the Itanium and Microsoft C++ ABIs place + // virtual bases after the derived members. This would make a flexible + // array member declared at the end of an object not adjacent to the end + // of the type. + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record)) + if (RD->getNumVBases() != 0) + Diag(FD->getLocation(), diag::err_flexible_array_virtual_base) + << FD->getDeclName() << Record->getTagKind(); + if (!getLangOpts().C99) + Diag(FD->getLocation(), diag::ext_c99_flexible_array_member) << FD->getDeclName() << Record->getTagKind(); - if (!getLangOpts().C99) - Diag(FD->getLocation(), diag::ext_c99_flexible_array_member) - << FD->getDeclName() << Record->getTagKind(); - // If the element type has a non-trivial destructor, we would not - // implicitly destroy the elements, so disallow it for now. - // - // FIXME: GCC allows this. We should probably either implicitly delete - // the destructor of the containing class, or just allow this. - QualType BaseElem = Context.getBaseElementType(FD->getType()); - if (!BaseElem->isDependentType() && BaseElem.isDestructedType()) { - Diag(FD->getLocation(), diag::err_flexible_array_has_nontrivial_dtor) - << FD->getDeclName() << FD->getType(); - FD->setInvalidDecl(); - EnclosingDecl->setInvalidDecl(); - continue; + // If the element type has a non-trivial destructor, we would not + // implicitly destroy the elements, so disallow it for now. + // + // FIXME: GCC allows this. We should probably either implicitly delete + // the destructor of the containing class, or just allow this. + QualType BaseElem = Context.getBaseElementType(FD->getType()); + if (!BaseElem->isDependentType() && BaseElem.isDestructedType()) { + Diag(FD->getLocation(), diag::err_flexible_array_has_nontrivial_dtor) + << FD->getDeclName() << FD->getType(); + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } + // Okay, we have a legal flexible array member at the end of the struct. + Record->setHasFlexibleArrayMember(true); + } else { + // In ObjCContainerDecl ivars with incomplete array type are accepted, + // unless they are followed by another ivar. That check is done + // elsewhere, after synthesized ivars are known. } - // Okay, we have a legal flexible array member at the end of the struct. - Record->setHasFlexibleArrayMember(true); } else if (!FDTy->isDependentType() && RequireCompleteType(FD->getLocation(), FD->getType(), diag::err_field_incomplete)) { @@ -14990,7 +14932,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, // If this is a struct/class and this is not the last element, reject // it. Note that GCC supports variable sized arrays in the middle of // structures. - if (i + 1 != Fields.end()) + if (!IsLastField) Diag(FD->getLocation(), diag::ext_variable_sized_type_in_struct) << FD->getDeclName() << FD->getType(); else { @@ -15137,8 +15079,10 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record)) { auto *Dtor = CXXRecord->getDestructor(); if (Dtor && Dtor->isImplicit() && - ShouldDeleteSpecialMember(Dtor, CXXDestructor)) + ShouldDeleteSpecialMember(Dtor, CXXDestructor)) { + CXXRecord->setImplicitDestructorIsDeleted(); SetDeclDeleted(Dtor, CXXRecord->getLocation()); + } } if (Record->hasAttrs()) { @@ -15271,7 +15215,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, static bool isRepresentableIntegerValue(ASTContext &Context, llvm::APSInt &Value, QualType T) { - assert(T->isIntegralType(Context) && "Integral type required!"); + assert((T->isIntegralType(Context) || T->isEnumeralType()) && + "Integral type required!"); unsigned BitWidth = Context.getIntWidth(T); if (Value.isUnsigned() || Value.isNonNegative()) { @@ -15287,7 +15232,8 @@ static bool isRepresentableIntegerValue(ASTContext &Context, static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) { // FIXME: Int128/UInt128 support, which also needs to be introduced into // enum checking below. - assert(T->isIntegralType(Context) && "Integral type required!"); + assert((T->isIntegralType(Context) || + T->isEnumeralType()) && "Integral type required!"); const unsigned NumTypes = 4; QualType SignedIntegralTypes[NumTypes] = { Context.ShortTy, Context.IntTy, Context.LongTy, Context.LongLongTy @@ -15326,7 +15272,6 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, if (Enum->isDependentType() || Val->isTypeDependent()) EltTy = Context.DependentTy; else { - SourceLocation ExpLoc; if (getLangOpts().CPlusPlus11 && Enum->isFixed() && !getLangOpts().MSVCCompat) { // C++11 [dcl.enum]p5: If the underlying type is fixed, [...] the @@ -15491,7 +15436,7 @@ Sema::SkipBodyInfo Sema::shouldSkipAnonEnumBody(Scope *S, IdentifierInfo *II, // determine if we should merge the definition with an existing one and // skip the body. NamedDecl *PrevDecl = LookupSingleName(S, II, IILoc, LookupOrdinaryName, - ForRedeclaration); + forRedeclarationInCurContext()); auto *PrevECD = dyn_cast_or_null<EnumConstantDecl>(PrevDecl); if (!PrevECD) return SkipBodyInfo(); @@ -15522,7 +15467,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, // Verify that there isn't already something declared with this name in this // scope. NamedDecl *PrevDecl = LookupSingleName(S, Id, IdLoc, LookupOrdinaryName, - ForRedeclaration); + ForVisibleRedeclaration); if (PrevDecl && PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(IdLoc, PrevDecl); @@ -15549,8 +15494,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, // enum constant will 'hide' the tag. assert((getLangOpts().CPlusPlus || !isa<TagDecl>(PrevDecl)) && "Received TagDecl when not in C++!"); - if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S) && - shouldLinkPossiblyHiddenDecl(PrevDecl, New)) { + if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S)) { if (isa<EnumConstantDecl>(PrevDecl)) Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id; else @@ -16043,7 +15987,7 @@ static void checkModuleImportContext(Sema &S, Module *M, DC = LSD->getParent(); } - while (isa<LinkageSpecDecl>(DC)) + while (isa<LinkageSpecDecl>(DC) || isa<ExportDecl>(DC)) DC = DC->getParent(); if (!isa<TranslationUnitDecl>(DC)) { @@ -16064,6 +16008,9 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, ModuleDeclKind MDK, ModuleIdPath Path) { + assert(getLangOpts().ModulesTS && + "should only have module decl in modules TS"); + // A module implementation unit requires that we are not compiling a module // of any kind. A module interface unit requires that we are not compiling a // module map. @@ -16080,6 +16027,7 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc, // implementation unit. That indicates the 'export' is missing. Diag(ModuleLoc, diag::err_module_interface_implementation_mismatch) << FixItHint::CreateInsertion(ModuleLoc, "export "); + MDK = ModuleDeclKind::Interface; break; case LangOptions::CMK_ModuleMap: @@ -16087,9 +16035,19 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc, return nullptr; } + assert(ModuleScopes.size() == 1 && "expected to be at global module scope"); + // FIXME: Most of this work should be done by the preprocessor rather than // here, in order to support macro import. + // Only one module-declaration is permitted per source file. + if (ModuleScopes.back().Module->Kind == Module::ModuleInterfaceUnit) { + Diag(ModuleLoc, diag::err_module_redeclaration); + Diag(VisibleModules.getImportLoc(ModuleScopes.back().Module), + diag::note_prev_module_declaration); + return nullptr; + } + // Flatten the dots in a module name. Unlike Clang's hierarchical module map // modules, the dots here are just another character that can appear in a // module name. @@ -16100,8 +16058,6 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc, ModuleName += Piece.first->getName(); } - // FIXME: If we've already seen a module-declaration, report an error. - // If a module name was explicitly specified on the command line, it must be // correct. if (!getLangOpts().CurrentModule.empty() && @@ -16117,9 +16073,7 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc, Module *Mod; switch (MDK) { - case ModuleDeclKind::Module: { - // FIXME: Check we're not in a submodule. - + case ModuleDeclKind::Interface: { // We can't have parsed or imported a definition of this module or parsed a // module map defining it already. if (auto *M = Map.findModule(ModuleName)) { @@ -16129,11 +16083,13 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc, else if (const auto *FE = M->getASTFile()) Diag(M->DefinitionLoc, diag::note_prev_module_definition_from_ast_file) << FE->getName(); - return nullptr; + Mod = M; + break; } // Create a Module for the module that we're defining. - Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName); + Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName, + ModuleScopes.front().Module); assert(Mod && "module creation should not fail"); break; } @@ -16147,21 +16103,26 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc, PP.getIdentifierInfo(ModuleName), Path[0].second); Mod = getModuleLoader().loadModule(ModuleLoc, Path, Module::AllVisible, /*IsIncludeDirective=*/false); - if (!Mod) - return nullptr; + if (!Mod) { + Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName; + // Create an empty module interface unit for error recovery. + Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName, + ModuleScopes.front().Module); + } break; } - // Enter the semantic scope of the module. - ModuleScopes.push_back({}); + // Switch from the global module to the named module. ModuleScopes.back().Module = Mod; - ModuleScopes.back().OuterVisibleModules = std::move(VisibleModules); + ModuleScopes.back().ModuleInterface = MDK != ModuleDeclKind::Implementation; VisibleModules.setVisible(Mod, ModuleLoc); // From now on, we have an owning module for all declarations we see. // However, those declarations are module-private unless explicitly // exported. - Context.getTranslationUnitDecl()->setLocalOwningModule(Mod); + auto *TU = Context.getTranslationUnitDecl(); + TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ModulePrivate); + TU->setLocalOwningModule(Mod); // FIXME: Create a ModuleDecl. return nullptr; @@ -16204,12 +16165,17 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc, IdentifierLocs.push_back(Path[I].second); } - TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl(); - ImportDecl *Import = ImportDecl::Create(Context, TU, StartLoc, + ImportDecl *Import = ImportDecl::Create(Context, CurContext, StartLoc, Mod, IdentifierLocs); if (!ModuleScopes.empty()) Context.addModuleInitializer(ModuleScopes.back().Module, Import); - TU->addDecl(Import); + CurContext->addDecl(Import); + + // Re-export the module if needed. + if (Import->isExported() && + !ModuleScopes.empty() && ModuleScopes.back().ModuleInterface) + getCurrentModule()->Exports.emplace_back(Mod, false); + return Import; } @@ -16339,8 +16305,7 @@ Decl *Sema::ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc, // C++ Modules TS draft: // An export-declaration shall appear in the purview of a module other than // the global module. - if (ModuleScopes.empty() || !ModuleScopes.back().Module || - ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit) + if (ModuleScopes.empty() || !ModuleScopes.back().ModuleInterface) Diag(ExportLoc, diag::err_export_not_in_module_interface); // An export-declaration [...] shall not contain more than one |