diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
| commit | 486754660bb926339aefcf012a3f848592babb8b (patch) | |
| tree | ecdbc446c9876f4f120f701c243373cd3cb43db3 /lib/Sema/SemaDecl.cpp | |
| parent | 55e6d896ad333f07bb3b1ba487df214fc268a4ab (diff) | |
Notes
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
| -rw-r--r-- | lib/Sema/SemaDecl.cpp | 1443 |
1 files changed, 1070 insertions, 373 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a1fc725f8df4..55542828f783 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -115,7 +115,7 @@ class TypeNameValidatorCCC : public CorrectionCandidateCallback { } // end anonymous namespace -/// \brief Determine whether the token kind starts a simple-type-specifier. +/// Determine whether the token kind starts a simple-type-specifier. bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const { switch (Kind) { // FIXME: Take into account the current language when deciding whether a @@ -148,6 +148,9 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const { case tok::kw_decltype: return getLangOpts().CPlusPlus; + case tok::kw_char8_t: + return getLangOpts().Char8; + default: break; } @@ -163,7 +166,7 @@ enum class UnqualifiedTypeNameLookupResult { }; } // end anonymous namespace -/// \brief Tries to perform unqualified lookup of the type decls in bases for +/// Tries to perform unqualified lookup of the type decls in bases for /// dependent class. /// \return \a NotFound if no any decls is found, \a FoundNotType if found not a /// type decl, \a FoundType if only type decls are found. @@ -263,7 +266,7 @@ static ParsedType recoverFromTypeInKnownDependentBase(Sema &S, return S.CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); } -/// \brief If the identifier refers to a type name within this scope, +/// If the identifier refers to a type name within this scope, /// return the declaration of that type. /// /// This routine performs ordinary name lookup of the identifier II @@ -724,13 +727,7 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, if (isTemplateName(S, SS ? *SS : EmptySS, /*hasTemplateKeyword=*/false, Name, nullptr, true, TemplateResult, MemberOfUnknownSpecialization) == TNK_Type_template) { - TemplateName TplName = TemplateResult.get(); - Diag(IILoc, diag::err_template_missing_args) - << (int)getTemplateNameKindForDiagnostics(TplName) << TplName; - if (TemplateDecl *TplDecl = TplName.getAsTemplateDecl()) { - Diag(TplDecl->getLocation(), diag::note_template_decl_here) - << TplDecl->getTemplateParameters()->getSourceRange(); - } + diagnoseMissingTemplateArguments(TemplateResult.get(), IILoc); return; } } @@ -763,7 +760,7 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, } } -/// \brief Determine whether the given result set contains either a type name +/// Determine whether the given result set contains either a type name /// or static bool isResultTypeOrTemplate(LookupResult &R, const Token &NextToken) { bool CheckTemplate = R.getSema().getLangOpts().CPlusPlus && @@ -1318,7 +1315,7 @@ void Sema::ActOnExitFunctionContext() { assert(CurContext && "Popped translation unit!"); } -/// \brief Determine whether we allow overloading of the function +/// Determine whether we allow overloading of the function /// PrevDecl with another declaration. /// /// This routine determines whether overloading is possible, not @@ -1504,7 +1501,7 @@ static void RemoveUsingDecls(LookupResult &R) { F.done(); } -/// \brief Check for this common pattern: +/// Check for this common pattern: /// @code /// class S { /// S(const S&); // DO NOT IMPLEMENT @@ -1519,9 +1516,7 @@ static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) { if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D)) return CD->isCopyConstructor(); - if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) - return Method->isCopyAssignmentOperator(); - return false; + return D->isCopyAssignmentOperator(); } // We need this to handle @@ -1843,7 +1838,7 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { } } -/// \brief Look for an Objective-C class in the translation unit. +/// Look for an Objective-C class in the translation unit. /// /// \param Id The name of the Objective-C class we're looking for. If /// typo-correction fixes this name, the Id will be updated @@ -1913,7 +1908,7 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) { return S; } -/// \brief Looks up the declaration of "struct objc_super" and +/// Looks up the declaration of "struct objc_super" and /// saves it for later use in building builtin declaration of /// objc_msgSendSuper and objc_msgSendSuper_stret. If no such /// pre-existing declaration exists no action takes place. @@ -2457,6 +2452,9 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, else if (const auto *SA = dyn_cast<SectionAttr>(Attr)) NewAttr = S.mergeSectionAttr(D, SA->getRange(), SA->getName(), AttrSpellingListIndex); + else if (const auto *CSA = dyn_cast<CodeSegAttr>(Attr)) + NewAttr = S.mergeCodeSegAttr(D, CSA->getRange(), CSA->getName(), + AttrSpellingListIndex); else if (const auto *IA = dyn_cast<MSInheritanceAttr>(Attr)) NewAttr = S.mergeMSInheritanceAttr(D, IA->getRange(), IA->getBestCase(), AttrSpellingListIndex, @@ -2495,7 +2493,7 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, else if (const auto *UA = dyn_cast<UuidAttr>(Attr)) NewAttr = S.mergeUuidAttr(D, UA->getRange(), AttrSpellingListIndex, UA->getGuid()); - else if (Attr->duplicatesAllowed() || !DeclHasAttr(D, Attr)) + else if (Attr->shouldInheritEvenIfAlreadyPresent() || !DeclHasAttr(D, Attr)) NewAttr = cast<InheritableAttr>(Attr->clone(S.Context)); if (NewAttr) { @@ -2675,6 +2673,15 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, } } + // Redeclaration adds code-seg attribute. + const auto *NewCSA = New->getAttr<CodeSegAttr>(); + if (NewCSA && !Old->hasAttr<CodeSegAttr>() && + !NewCSA->isImplicit() && isa<CXXMethodDecl>(New)) { + Diag(New->getLocation(), diag::warn_mismatched_section) + << 0 /*codeseg*/; + Diag(Old->getLocation(), diag::note_previous_declaration); + } + if (!Old->hasAttrs()) return; @@ -2875,7 +2882,7 @@ static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) { template<typename T> static bool isExternC(T *D) { return D->isExternC(); } static bool isExternC(VarTemplateDecl *) { return false; } -/// \brief Check whether a redeclaration of an entity introduced by a +/// Check whether a redeclaration of an entity introduced by a /// using-declaration is valid, given that we know it's not an overload /// (nor a hidden tag declaration). template<typename ExpectedDecl> @@ -2929,6 +2936,48 @@ static bool hasIdenticalPassObjectSizeAttrs(const FunctionDecl *A, return std::equal(A->param_begin(), A->param_end(), B->param_begin(), AttrEq); } +/// If necessary, adjust the semantic declaration context for a qualified +/// declaration to name the correct inline namespace within the qualifier. +static void adjustDeclContextForDeclaratorDecl(DeclaratorDecl *NewD, + DeclaratorDecl *OldD) { + // The only case where we need to update the DeclContext is when + // redeclaration lookup for a qualified name finds a declaration + // in an inline namespace within the context named by the qualifier: + // + // inline namespace N { int f(); } + // int ::f(); // Sema DC needs adjusting from :: to N::. + // + // For unqualified declarations, the semantic context *can* change + // along the redeclaration chain (for local extern declarations, + // extern "C" declarations, and friend declarations in particular). + if (!NewD->getQualifier()) + return; + + // NewD is probably already in the right context. + auto *NamedDC = NewD->getDeclContext()->getRedeclContext(); + auto *SemaDC = OldD->getDeclContext()->getRedeclContext(); + if (NamedDC->Equals(SemaDC)) + return; + + assert((NamedDC->InEnclosingNamespaceSetOf(SemaDC) || + NewD->isInvalidDecl() || OldD->isInvalidDecl()) && + "unexpected context for redeclaration"); + + auto *LexDC = NewD->getLexicalDeclContext(); + auto FixSemaDC = [=](NamedDecl *D) { + if (!D) + return; + D->setDeclContext(SemaDC); + D->setLexicalDeclContext(LexDC); + }; + + FixSemaDC(NewD); + if (auto *FD = dyn_cast<FunctionDecl>(NewD)) + FixSemaDC(FD->getDescribedFunctionTemplate()); + else if (auto *VD = dyn_cast<VarDecl>(NewD)) + FixSemaDC(VD->getDescribedVarTemplate()); +} + /// MergeFunctionDecl - We just parsed a function 'New' from /// declarator D which has the same name and scope as a previous /// declaration 'Old'. Figure out how to resolve this situation, @@ -2971,6 +3020,14 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, if (Old->isInvalidDecl()) return true; + // Disallow redeclaration of some builtins. + if (!getASTContext().canBuiltinBeRedeclared(Old)) { + Diag(New->getLocation(), diag::err_builtin_redeclare) << Old->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_builtin_declaration) + << Old << Old->getType(); + return true; + } + diag::kind PrevDiag; SourceLocation OldLocation; std::tie(PrevDiag, OldLocation) = @@ -3518,7 +3575,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, return true; } -/// \brief Completes the merge of two function declarations that are +/// Completes the merge of two function declarations that are /// known to be compatible. /// /// This routine handles the merging of attributes and other @@ -3581,6 +3638,8 @@ 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) { @@ -3953,6 +4012,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { New->setPreviousDecl(Old); if (NewTemplate) NewTemplate->setPreviousDecl(OldTemplate); + adjustDeclContextForDeclaratorDecl(New, Old); // Inherit access appropriately. New->setAccess(Old->getAccess()); @@ -4014,7 +4074,8 @@ void Sema::notePreviousDefinition(const NamedDecl *Old, SourceLocation New) { } // Redefinition coming from different files or couldn't do better above. - Diag(Old->getLocation(), diag::note_previous_definition); + if (Old->getLocation().isValid()) + Diag(Old->getLocation(), diag::note_previous_definition); } /// We've just determined that \p Old and \p New both appear to be definitions @@ -4398,10 +4459,9 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, TypeSpecType == DeclSpec::TST_interface || TypeSpecType == DeclSpec::TST_union || TypeSpecType == DeclSpec::TST_enum) { - for (AttributeList* attrs = DS.getAttributes().getList(); attrs; - attrs = attrs->getNext()) - Diag(attrs->getLoc(), diag::warn_declspec_attribute_ignored) - << attrs->getName() << GetDiagnosticTypeSpecifierID(TypeSpecType); + for (const ParsedAttr &AL : DS.getAttributes()) + Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored) + << AL.getName() << GetDiagnosticTypeSpecifierID(TypeSpecType); } } @@ -4593,12 +4653,14 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, unsigned DiagID; if (Record->isUnion()) { // C++ [class.union]p6: + // C++17 [class.union.anon]p2: // Anonymous unions declared in a named namespace or in the // global namespace shall be declared static. + DeclContext *OwnerScope = Owner->getRedeclContext(); if (DS.getStorageClassSpec() != DeclSpec::SCS_static && - (isa<TranslationUnitDecl>(Owner) || - (isa<NamespaceDecl>(Owner) && - cast<NamespaceDecl>(Owner)->getDeclName()))) { + (OwnerScope->isTranslationUnit() || + (OwnerScope->isNamespace() && + !cast<NamespaceDecl>(OwnerScope)->isAnonymousNamespace()))) { Diag(Record->getLocation(), diag::err_anonymous_union_not_static) << FixItHint::CreateInsertion(Record->getLocation(), "static "); @@ -4746,7 +4808,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, } // Mock up a declarator. - Declarator Dc(DS, Declarator::MemberContext); + Declarator Dc(DS, DeclaratorContext::MemberContext); TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S); assert(TInfo && "couldn't build declarator info for anonymous struct/union"); @@ -4843,7 +4905,7 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, assert(Record && "expected a record!"); // Mock up a declarator. - Declarator Dc(DS, Declarator::TypeNameContext); + Declarator Dc(DS, DeclaratorContext::TypeNameContext); TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S); assert(TInfo && "couldn't build declarator info for anonymous struct"); @@ -4889,7 +4951,7 @@ DeclarationNameInfo Sema::GetNameForDeclarator(Declarator &D) { return GetNameFromUnqualifiedId(D.getName()); } -/// \brief Retrieves the declaration name from a parsed unqualified-id. +/// Retrieves the declaration name from a parsed unqualified-id. DeclarationNameInfo Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { DeclarationNameInfo NameInfo; @@ -4897,13 +4959,13 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { switch (Name.getKind()) { - case UnqualifiedId::IK_ImplicitSelfParam: - case UnqualifiedId::IK_Identifier: + case UnqualifiedIdKind::IK_ImplicitSelfParam: + case UnqualifiedIdKind::IK_Identifier: NameInfo.setName(Name.Identifier); NameInfo.setLoc(Name.StartLocation); return NameInfo; - case UnqualifiedId::IK_DeductionGuideName: { + case UnqualifiedIdKind::IK_DeductionGuideName: { // C++ [temp.deduct.guide]p3: // The simple-template-id shall name a class template specialization. // The template-name shall be the same identifier as the template-name @@ -4931,7 +4993,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { return NameInfo; } - case UnqualifiedId::IK_OperatorFunctionId: + case UnqualifiedIdKind::IK_OperatorFunctionId: NameInfo.setName(Context.DeclarationNames.getCXXOperatorName( Name.OperatorFunctionId.Operator)); NameInfo.setLoc(Name.StartLocation); @@ -4941,14 +5003,14 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { = Name.EndLocation.getRawEncoding(); return NameInfo; - case UnqualifiedId::IK_LiteralOperatorId: + case UnqualifiedIdKind::IK_LiteralOperatorId: NameInfo.setName(Context.DeclarationNames.getCXXLiteralOperatorName( Name.Identifier)); NameInfo.setLoc(Name.StartLocation); NameInfo.setCXXLiteralOperatorNameLoc(Name.EndLocation); return NameInfo; - case UnqualifiedId::IK_ConversionFunctionId: { + case UnqualifiedIdKind::IK_ConversionFunctionId: { TypeSourceInfo *TInfo; QualType Ty = GetTypeFromParser(Name.ConversionFunctionId, &TInfo); if (Ty.isNull()) @@ -4960,7 +5022,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { return NameInfo; } - case UnqualifiedId::IK_ConstructorName: { + case UnqualifiedIdKind::IK_ConstructorName: { TypeSourceInfo *TInfo; QualType Ty = GetTypeFromParser(Name.ConstructorName, &TInfo); if (Ty.isNull()) @@ -4972,7 +5034,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { return NameInfo; } - case UnqualifiedId::IK_ConstructorTemplateId: { + case UnqualifiedIdKind::IK_ConstructorTemplateId: { // In well-formed code, we can only have a constructor // template-id that refers to the current context, so go there // to find the actual type being constructed. @@ -4995,7 +5057,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { return NameInfo; } - case UnqualifiedId::IK_DestructorName: { + case UnqualifiedIdKind::IK_DestructorName: { TypeSourceInfo *TInfo; QualType Ty = GetTypeFromParser(Name.DestructorName, &TInfo); if (Ty.isNull()) @@ -5007,7 +5069,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { return NameInfo; } - case UnqualifiedId::IK_TemplateId: { + case UnqualifiedIdKind::IK_TemplateId: { TemplateName TName = Name.TemplateId->Template.get(); SourceLocation TNameLoc = Name.TemplateId->TemplateNameLoc; return Context.getNameForTemplate(TName, TNameLoc); @@ -5176,7 +5238,7 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC, return false; } -/// \brief Diagnose a declaration whose declarator-id has the given +/// Diagnose a declaration whose declarator-id has the given /// nested-name-specifier. /// /// \param SS The nested-name-specifier of the declarator-id. @@ -5188,10 +5250,13 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC, /// /// \param Loc The location of the name of the entity being declared. /// +/// \param IsTemplateId Whether the name is a (simple-)template-id, and thus +/// we're declaring an explicit / partial specialization / instantiation. +/// /// \returns true if we cannot safely recover from this error, false otherwise. bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, DeclarationName Name, - SourceLocation Loc) { + SourceLocation Loc, bool IsTemplateId) { DeclContext *Cur = CurContext; while (isa<LinkageSpecDecl>(Cur) || isa<CapturedDecl>(Cur)) Cur = Cur->getParent(); @@ -5218,8 +5283,9 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, } // Check whether the qualifying scope encloses the scope of the original - // declaration. - if (!Cur->Encloses(DC)) { + // declaration. For a template-id, we perform the checks in + // CheckTemplateSpecializationScope. + if (!Cur->Encloses(DC) && !IsTemplateId) { if (Cur->isRecord()) Diag(Loc, diag::err_member_qualification) << Name << SS.getRange(); @@ -5331,8 +5397,9 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, return nullptr; } if (!D.getDeclSpec().isFriendSpecified()) { - if (diagnoseQualifiedDeclaration(D.getCXXScopeSpec(), DC, - Name, D.getIdentifierLoc())) { + if (diagnoseQualifiedDeclaration( + D.getCXXScopeSpec(), DC, Name, D.getIdentifierLoc(), + D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId)) { if (DC->isRecord()) return nullptr; @@ -5609,7 +5676,7 @@ TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo, return FixedTInfo; } -/// \brief Register the given locally-scoped extern "C" declaration so +/// Register the given locally-scoped extern "C" declaration so /// that it can be found later for redeclarations. We include any extern "C" /// declaration that is not visible in the translation unit here, not just /// function-scope declarations. @@ -5630,7 +5697,7 @@ NamedDecl *Sema::findLocallyScopedExternCDecl(DeclarationName Name) { return Result.empty() ? nullptr : *Result.begin(); } -/// \brief Diagnose function specifiers on a declaration of an identifier that +/// Diagnose function specifiers on a declaration of an identifier that /// does not identify a function. void Sema::DiagnoseFunctionSpecifiers(const DeclSpec &DS) { // FIXME: We should probably indicate the identifier in question to avoid @@ -5670,8 +5737,8 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr) << 1; - if (D.getName().Kind != UnqualifiedId::IK_Identifier) { - if (D.getName().Kind == UnqualifiedId::IK_DeductionGuideName) + if (D.getName().Kind != UnqualifiedIdKind::IK_Identifier) { + if (D.getName().Kind == UnqualifiedIdKind::IK_DeductionGuideName) Diag(D.getName().StartLocation, diag::err_deduction_guide_invalid_specifier) << "typedef"; @@ -5704,7 +5771,7 @@ Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) { TypeSourceInfo *TInfo = NewTD->getTypeSourceInfo(); QualType T = TInfo->getType(); if (T->isVariablyModifiedType()) { - getCurFunction()->setHasBranchProtectedScope(); + setFunctionHasBranchProtectedScope(); if (S->getFnParent() == nullptr) { bool SizeIsNegative; @@ -5772,7 +5839,7 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD, return NewTD; } -/// \brief Determines whether the given declaration is an out-of-scope +/// Determines whether the given declaration is an out-of-scope /// previous declaration. /// /// This routine should be invoked when name lookup has found a @@ -6148,29 +6215,21 @@ static bool shouldConsiderLinkage(const FunctionDecl *FD) { llvm_unreachable("Unexpected context"); } -static bool hasParsedAttr(Scope *S, const AttributeList *AttrList, - AttributeList::Kind Kind) { - for (const AttributeList *L = AttrList; L; L = L->getNext()) - if (L->getKind() == Kind) - return true; - return false; -} - static bool hasParsedAttr(Scope *S, const Declarator &PD, - AttributeList::Kind Kind) { + ParsedAttr::Kind Kind) { // Check decl attributes on the DeclSpec. - if (hasParsedAttr(S, PD.getDeclSpec().getAttributes().getList(), Kind)) + if (PD.getDeclSpec().getAttributes().hasAttribute(Kind)) return true; // Walk the declarator structure, checking decl attributes that were in a type // position to the decl itself. for (unsigned I = 0, E = PD.getNumTypeObjects(); I != E; ++I) { - if (hasParsedAttr(S, PD.getTypeObject(I).getAttrs(), Kind)) + if (PD.getTypeObject(I).getAttrs().hasAttribute(Kind)) return true; } // Finally, check attributes on the decl itself. - return hasParsedAttr(S, PD.getAttributes(), Kind); + return PD.getAttributes().hasAttribute(Kind); } /// Adjust the \c DeclContext for a function or variable that might be a @@ -6197,7 +6256,7 @@ bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) { return true; } -/// \brief Returns true if given declaration has external C language linkage. +/// Returns true if given declaration has external C language linkage. static bool isDeclExternC(const Decl *D) { if (const auto *FD = dyn_cast<FunctionDecl>(D)) return FD->isExternC(); @@ -6303,6 +6362,20 @@ NamedDecl *Sema::ActOnVariableDeclarator( D.setInvalidType(); } } + + // OpenCL C++ 1.0 s2.9: the thread_local storage qualifier is not + // supported. OpenCL C does not support thread_local either, and + // also reject all other thread storage class specifiers. + DeclSpec::TSCS TSC = D.getDeclSpec().getThreadStorageClassSpec(); + if (TSC != TSCS_unspecified) { + bool IsCXX = getLangOpts().OpenCLCPlusPlus; + Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), + diag::err_opencl_unknown_type_specifier) + << IsCXX << getLangOpts().getOpenCLVersionTuple().getAsString() + << DeclSpec::getSpecifierName(TSC) << 1; + D.setInvalidType(); + return nullptr; + } } DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec(); @@ -6311,8 +6384,8 @@ NamedDecl *Sema::ActOnVariableDeclarator( // dllimport globals without explicit storage class are treated as extern. We // have to change the storage class this early to get the right DeclContext. if (SC == SC_None && !DC->isRecord() && - hasParsedAttr(S, D, AttributeList::AT_DLLImport) && - !hasParsedAttr(S, D, AttributeList::AT_DLLExport)) + hasParsedAttr(S, D, ParsedAttr::AT_DLLImport) && + !hasParsedAttr(S, D, ParsedAttr::AT_DLLExport)) SC = SC_Extern; DeclContext *OriginalDC = DC; @@ -6425,7 +6498,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( TemplateParams = MatchTemplateParametersToScopeSpecifier( D.getDeclSpec().getLocStart(), D.getIdentifierLoc(), D.getCXXScopeSpec(), - D.getName().getKind() == UnqualifiedId::IK_TemplateId + D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId ? D.getName().TemplateId : nullptr, TemplateParamLists, @@ -6433,7 +6506,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( if (TemplateParams) { if (!TemplateParams->size() && - D.getName().getKind() != UnqualifiedId::IK_TemplateId) { + D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) { // There is an extraneous 'template<>' for this variable. Complain // about it, but allow the declaration of the variable. Diag(TemplateParams->getTemplateLoc(), @@ -6443,7 +6516,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( TemplateParams->getRAngleLoc()); TemplateParams = nullptr; } else { - if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { + if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) { // This is an explicit specialization or a partial specialization. // FIXME: Check that we can declare a specialization here. IsVariableTemplateSpecialization = true; @@ -6464,9 +6537,9 @@ NamedDecl *Sema::ActOnVariableDeclarator( } } } else { - assert( - (Invalid || D.getName().getKind() != UnqualifiedId::IK_TemplateId) && - "should have a 'template<>' for this decl"); + assert((Invalid || + D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) && + "should have a 'template<>' for this decl"); } if (IsVariableTemplateSpecialization) { @@ -6842,9 +6915,9 @@ NamedDecl *Sema::ActOnVariableDeclarator( } if (D.isRedeclaration() && !Previous.empty()) { - checkDLLAttributeRedeclaration( - *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewVD, - IsMemberSpecialization, D.isFunctionDefinition()); + NamedDecl *Prev = Previous.getRepresentativeDecl(); + checkDLLAttributeRedeclaration(*this, Prev, NewVD, IsMemberSpecialization, + D.isFunctionDefinition()); } if (NewTemplate) { @@ -6887,7 +6960,7 @@ static ShadowedDeclKind computeShadowedDeclKind(const NamedDecl *ShadowedDecl, /// variable \p VD, or an invalid source location otherwise. static SourceLocation getCaptureLocation(const LambdaScopeInfo *LSI, const VarDecl *VD) { - for (const LambdaScopeInfo::Capture &Capture : LSI->Captures) { + for (const Capture &Capture : LSI->Captures) { if (Capture.isVariableCapture() && Capture.getVariable() == VD) return Capture.getLocation(); } @@ -6904,7 +6977,7 @@ static bool shouldWarnIfShadowedDecl(const DiagnosticsEngine &Diags, return !Diags.isIgnored(diag::warn_decl_shadow, R.getNameLoc()); } -/// \brief Return the declaration shadowed by the given variable \p D, or null +/// Return the declaration shadowed by the given variable \p D, or null /// if it doesn't shadow any declaration or shadowing warnings are disabled. NamedDecl *Sema::getShadowedDeclaration(const VarDecl *D, const LookupResult &R) { @@ -6921,14 +6994,14 @@ NamedDecl *Sema::getShadowedDeclaration(const VarDecl *D, : nullptr; } -/// \brief Return the declaration shadowed by the given typedef \p D, or null +/// Return the declaration shadowed by the given typedef \p D, or null /// if it doesn't shadow any declaration or shadowing warnings are disabled. NamedDecl *Sema::getShadowedDeclaration(const TypedefNameDecl *D, const LookupResult &R) { // Don't warn if typedef declaration is part of a class if (D->getDeclContext()->isRecord()) return nullptr; - + if (!shouldWarnIfShadowedDecl(Diags, R)) return nullptr; @@ -6936,7 +7009,7 @@ NamedDecl *Sema::getShadowedDeclaration(const TypedefNameDecl *D, return isa<TypedefNameDecl>(ShadowedDecl) ? ShadowedDecl : nullptr; } -/// \brief Diagnose variable or built-in function shadowing. Implements +/// Diagnose variable or built-in function shadowing. Implements /// -Wshadow. /// /// This method is called whenever a VarDecl is added to a "useful" @@ -7067,7 +7140,7 @@ void Sema::DiagnoseShadowingLambdaDecls(const LambdaScopeInfo *LSI) { } } -/// \brief Check -Wshadow without the advantage of a previous lookup. +/// Check -Wshadow without the advantage of a previous lookup. void Sema::CheckShadow(Scope *S, VarDecl *D) { if (Diags.isIgnored(diag::warn_decl_shadow, D->getLocation())) return; @@ -7225,8 +7298,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { if (NewVD->isInvalidDecl()) return; - TypeSourceInfo *TInfo = NewVD->getTypeSourceInfo(); - QualType T = TInfo->getType(); + QualType T = NewVD->getType(); // Defer checking an 'auto' type until its initializer is attached. if (T->isUndeducedType()) @@ -7364,16 +7436,24 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { bool isVM = T->isVariablyModifiedType(); if (isVM || NewVD->hasAttr<CleanupAttr>() || NewVD->hasAttr<BlocksAttr>()) - getCurFunction()->setHasBranchProtectedScope(); + setFunctionHasBranchProtectedScope(); if ((isVM && NewVD->hasLinkage()) || (T->isVariableArrayType() && NewVD->hasGlobalStorage())) { bool SizeIsNegative; llvm::APSInt Oversized; - TypeSourceInfo *FixedTInfo = - TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context, - SizeIsNegative, Oversized); - if (!FixedTInfo && T->isVariableArrayType()) { + TypeSourceInfo *FixedTInfo = TryToFixInvalidVariablyModifiedTypeSourceInfo( + NewVD->getTypeSourceInfo(), Context, SizeIsNegative, Oversized); + QualType FixedT; + if (FixedTInfo && T == NewVD->getTypeSourceInfo()->getType()) + FixedT = FixedTInfo->getType(); + else if (FixedTInfo) { + // Type and type-as-written are canonically different. We need to fix up + // both types separately. + FixedT = TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative, + Oversized); + } + if ((!FixedTInfo || FixedT.isNull()) && T->isVariableArrayType()) { const VariableArrayType *VAT = Context.getAsVariableArrayType(T); // FIXME: This won't give the correct result for // int a[10][n]; @@ -7402,7 +7482,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { } Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size); - NewVD->setType(FixedTInfo->getType()); + NewVD->setType(FixedT); NewVD->setTypeSourceInfo(FixedTInfo); } @@ -7437,7 +7517,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { } } -/// \brief Perform semantic checking on a newly-created variable +/// Perform semantic checking on a newly-created variable /// declaration. /// /// This routine performs all of the type-checking required for a @@ -7508,8 +7588,8 @@ struct FindOverriddenMethod { enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted }; } // end anonymous namespace -/// \brief Report an error regarding overriding, along with any relevant -/// overriden methods. +/// Report an error regarding overriding, along with any relevant +/// overridden methods. /// /// \param DiagID the primary error to report. /// \param MD the overriding method. @@ -7624,7 +7704,7 @@ void Sema::MarkTypoCorrectedFunctionDefinition(const NamedDecl *F) { TypoCorrectedFunctionDefinitions.insert(F); } -/// \brief Generate diagnostics for an invalid function redeclaration. +/// Generate diagnostics for an invalid function redeclaration. /// /// This routine handles generating the diagnostic messages for an invalid /// function redeclaration, including finding possible similar declarations @@ -8176,7 +8256,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, bool &AddToScope) { QualType R = TInfo->getType(); - assert(R.getTypePtr()->isFunctionType()); + assert(R->isFunctionType()); // TODO: consider using NameInfo for diagnostic. DeclarationNameInfo NameInfo = GetNameForDeclarator(D); @@ -8261,7 +8341,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, MatchTemplateParametersToScopeSpecifier( D.getDeclSpec().getLocStart(), D.getIdentifierLoc(), D.getCXXScopeSpec(), - D.getName().getKind() == UnqualifiedId::IK_TemplateId + D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId ? D.getName().TemplateId : nullptr, TemplateParamLists, isFriend, isMemberSpecialization, @@ -8318,7 +8398,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // and clearly the user wants a template specialization. So // we need to insert '<>' after the name. SourceLocation InsertLoc; - if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) { + if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) { InsertLoc = D.getName().getSourceRange().getEnd(); InsertLoc = getLocForEndOfToken(InsertLoc); } @@ -8655,6 +8735,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD->dropAttr<SectionAttr>(); } + // Apply an implicit CodeSegAttr from class declspec or + // apply an implicit SectionAttr from #pragma code_seg if active. + if (!NewFD->hasAttr<CodeSegAttr>()) { + if (Attr *SAttr = getImplicitCodeSegOrSectionAttrForFunction(NewFD, + D.isFunctionDefinition())) { + NewFD->addAttr(SAttr); + } + } + // Handle attributes. ProcessDeclAttributes(S, NewFD, D); @@ -8719,7 +8808,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // If the declarator is a template-id, translate the parser's template // argument list into our AST format. - if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { + if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) { TemplateIdAnnotation *TemplateId = D.getName().TemplateId; TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc); TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc); @@ -8785,10 +8874,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (CurContext->isDependentContext() && CurContext->isRecord() && !isFriend) { isDependentClassScopeExplicitSpecialization = true; - Diag(NewFD->getLocation(), getLangOpts().MicrosoftExt ? - diag::ext_function_specialization_in_class : - diag::err_function_specialization_in_class) - << NewFD->getDeclName(); } else if (!NewFD->isInvalidDecl() && CheckFunctionTemplateSpecialization( NewFD, (HasExplicitTemplateArgs ? &TemplateArgs : nullptr), @@ -8994,19 +9079,22 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD->setRangeEnd(D.getSourceRange().getEnd()); if (D.isRedeclaration() && !Previous.empty()) { - checkDLLAttributeRedeclaration( - *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewFD, - isMemberSpecialization || isFunctionTemplateSpecialization, - D.isFunctionDefinition()); + NamedDecl *Prev = Previous.getRepresentativeDecl(); + checkDLLAttributeRedeclaration(*this, Prev, NewFD, + isMemberSpecialization || + isFunctionTemplateSpecialization, + D.isFunctionDefinition()); } if (getLangOpts().CUDA) { IdentifierInfo *II = NewFD->getIdentifier(); - if (II && II->isStr("cudaConfigureCall") && !NewFD->isInvalidDecl() && + if (II && + II->isStr(getLangOpts().HIP ? "hipConfigureCall" + : "cudaConfigureCall") && + !NewFD->isInvalidDecl() && NewFD->getDeclContext()->getRedeclContext()->isTranslationUnit()) { if (!R->getAs<FunctionType>()->getReturnType()->isScalarType()) Diag(NewFD->getLocation(), diag::err_config_scalar_return); - Context.setcudaConfigureCallDecl(NewFD); } @@ -9073,22 +9161,95 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } // Here we have an function template explicit specialization at class scope. - // The actually specialization will be postponed to template instatiation + // The actual specialization will be postponed to template instatiation // time via the ClassScopeFunctionSpecializationDecl node. if (isDependentClassScopeExplicitSpecialization) { ClassScopeFunctionSpecializationDecl *NewSpec = ClassScopeFunctionSpecializationDecl::Create( - Context, CurContext, SourceLocation(), + Context, CurContext, NewFD->getLocation(), cast<CXXMethodDecl>(NewFD), HasExplicitTemplateArgs, TemplateArgs); CurContext->addDecl(NewSpec); AddToScope = false; } + // Diagnose availability attributes. Availability cannot be used on functions + // that are run during load/unload. + if (const auto *attr = NewFD->getAttr<AvailabilityAttr>()) { + if (NewFD->hasAttr<ConstructorAttr>()) { + Diag(attr->getLocation(), diag::warn_availability_on_static_initializer) + << 1; + NewFD->dropAttr<AvailabilityAttr>(); + } + if (NewFD->hasAttr<DestructorAttr>()) { + Diag(attr->getLocation(), diag::warn_availability_on_static_initializer) + << 2; + NewFD->dropAttr<AvailabilityAttr>(); + } + } + return NewFD; } -/// \brief Checks if the new declaration declared in dependent context must be +/// Return a CodeSegAttr from a containing class. The Microsoft docs say +/// when __declspec(code_seg) "is applied to a class, all member functions of +/// the class and nested classes -- this includes compiler-generated special +/// member functions -- are put in the specified segment." +/// The actual behavior is a little more complicated. The Microsoft compiler +/// won't check outer classes if there is an active value from #pragma code_seg. +/// The CodeSeg is always applied from the direct parent but only from outer +/// classes when the #pragma code_seg stack is empty. See: +/// https://reviews.llvm.org/D22931, the Microsoft feedback page is no longer +/// available since MS has removed the page. +static Attr *getImplicitCodeSegAttrFromClass(Sema &S, const FunctionDecl *FD) { + const auto *Method = dyn_cast<CXXMethodDecl>(FD); + if (!Method) + return nullptr; + const CXXRecordDecl *Parent = Method->getParent(); + if (const auto *SAttr = Parent->getAttr<CodeSegAttr>()) { + Attr *NewAttr = SAttr->clone(S.getASTContext()); + NewAttr->setImplicit(true); + return NewAttr; + } + + // The Microsoft compiler won't check outer classes for the CodeSeg + // when the #pragma code_seg stack is active. + if (S.CodeSegStack.CurrentValue) + return nullptr; + + while ((Parent = dyn_cast<CXXRecordDecl>(Parent->getParent()))) { + if (const auto *SAttr = Parent->getAttr<CodeSegAttr>()) { + Attr *NewAttr = SAttr->clone(S.getASTContext()); + NewAttr->setImplicit(true); + return NewAttr; + } + } + return nullptr; +} + +/// Returns an implicit CodeSegAttr if a __declspec(code_seg) is found on a +/// containing class. Otherwise it will return implicit SectionAttr if the +/// function is a definition and there is an active value on CodeSegStack +/// (from the current #pragma code-seg value). +/// +/// \param FD Function being declared. +/// \param IsDefinition Whether it is a definition or just a declarartion. +/// \returns A CodeSegAttr or SectionAttr to apply to the function or +/// nullptr if no attribute should be added. +Attr *Sema::getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, + bool IsDefinition) { + if (Attr *A = getImplicitCodeSegAttrFromClass(*this, FD)) + return A; + if (!FD->hasAttr<SectionAttr>() && IsDefinition && + CodeSegStack.CurrentValue) { + return SectionAttr::CreateImplicit(getASTContext(), + SectionAttr::Declspec_allocate, + CodeSegStack.CurrentValue->getString(), + CodeSegStack.CurrentPragmaLocation); + } + return nullptr; +} +/// Checks if the new declaration declared in dependent context must be /// put in the same redeclaration chain as the specified declaration. /// /// \param D Declaration that is checked. @@ -9114,7 +9275,524 @@ bool Sema::shouldLinkDependentDeclWithPrevious(Decl *D, Decl *PrevDecl) { D->getFriendObjectKind() != Decl::FOK_None); } -/// \brief Perform semantic checking of a new function declaration. +namespace MultiVersioning { +enum Type { None, Target, CPUSpecific, CPUDispatch}; +} // MultiVersionType + +static MultiVersioning::Type +getMultiVersionType(const FunctionDecl *FD) { + if (FD->hasAttr<TargetAttr>()) + return MultiVersioning::Target; + if (FD->hasAttr<CPUDispatchAttr>()) + return MultiVersioning::CPUDispatch; + if (FD->hasAttr<CPUSpecificAttr>()) + return MultiVersioning::CPUSpecific; + return MultiVersioning::None; +} +/// Check the target attribute of the function for MultiVersion +/// validity. +/// +/// Returns true if there was an error, false otherwise. +static bool CheckMultiVersionValue(Sema &S, const FunctionDecl *FD) { + const auto *TA = FD->getAttr<TargetAttr>(); + assert(TA && "MultiVersion Candidate requires a target attribute"); + TargetAttr::ParsedTargetAttr ParseInfo = TA->parse(); + const TargetInfo &TargetInfo = S.Context.getTargetInfo(); + enum ErrType { Feature = 0, Architecture = 1 }; + + if (!ParseInfo.Architecture.empty() && + !TargetInfo.validateCpuIs(ParseInfo.Architecture)) { + S.Diag(FD->getLocation(), diag::err_bad_multiversion_option) + << Architecture << ParseInfo.Architecture; + return true; + } + + for (const auto &Feat : ParseInfo.Features) { + auto BareFeat = StringRef{Feat}.substr(1); + if (Feat[0] == '-') { + S.Diag(FD->getLocation(), diag::err_bad_multiversion_option) + << Feature << ("no-" + BareFeat).str(); + return true; + } + + if (!TargetInfo.validateCpuSupports(BareFeat) || + !TargetInfo.isValidFeatureName(BareFeat)) { + S.Diag(FD->getLocation(), diag::err_bad_multiversion_option) + << Feature << BareFeat; + return true; + } + } + return false; +} + +static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD, + const FunctionDecl *NewFD, + bool CausesMV, + MultiVersioning::Type MVType) { + enum DoesntSupport { + FuncTemplates = 0, + VirtFuncs = 1, + DeducedReturn = 2, + Constructors = 3, + Destructors = 4, + DeletedFuncs = 5, + DefaultedFuncs = 6, + ConstexprFuncs = 7, + }; + enum Different { + CallingConv = 0, + ReturnType = 1, + ConstexprSpec = 2, + InlineSpec = 3, + StorageClass = 4, + Linkage = 5 + }; + + bool IsCPUSpecificCPUDispatchMVType = + MVType == MultiVersioning::CPUDispatch || + MVType == MultiVersioning::CPUSpecific; + + if (OldFD && !OldFD->getType()->getAs<FunctionProtoType>()) { + S.Diag(OldFD->getLocation(), diag::err_multiversion_noproto); + S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here); + return true; + } + + if (!NewFD->getType()->getAs<FunctionProtoType>()) + return S.Diag(NewFD->getLocation(), diag::err_multiversion_noproto); + + if (!S.getASTContext().getTargetInfo().supportsMultiVersioning()) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_not_supported); + if (OldFD) + S.Diag(OldFD->getLocation(), diag::note_previous_declaration); + return true; + } + + // For now, disallow all other attributes. These should be opt-in, but + // an analysis of all of them is a future FIXME. + if (CausesMV && OldFD && + std::distance(OldFD->attr_begin(), OldFD->attr_end()) != 1) { + S.Diag(OldFD->getLocation(), diag::err_multiversion_no_other_attrs) + << IsCPUSpecificCPUDispatchMVType; + S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here); + return true; + } + + if (std::distance(NewFD->attr_begin(), NewFD->attr_end()) != 1) + return S.Diag(NewFD->getLocation(), diag::err_multiversion_no_other_attrs) + << IsCPUSpecificCPUDispatchMVType; + + if (NewFD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate) + return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support) + << IsCPUSpecificCPUDispatchMVType << FuncTemplates; + + if (const auto *NewCXXFD = dyn_cast<CXXMethodDecl>(NewFD)) { + if (NewCXXFD->isVirtual()) + return S.Diag(NewCXXFD->getLocation(), + diag::err_multiversion_doesnt_support) + << IsCPUSpecificCPUDispatchMVType << VirtFuncs; + + if (const auto *NewCXXCtor = dyn_cast<CXXConstructorDecl>(NewFD)) + return S.Diag(NewCXXCtor->getLocation(), + diag::err_multiversion_doesnt_support) + << IsCPUSpecificCPUDispatchMVType << Constructors; + + if (const auto *NewCXXDtor = dyn_cast<CXXDestructorDecl>(NewFD)) + return S.Diag(NewCXXDtor->getLocation(), + diag::err_multiversion_doesnt_support) + << IsCPUSpecificCPUDispatchMVType << Destructors; + } + + if (NewFD->isDeleted()) + return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support) + << IsCPUSpecificCPUDispatchMVType << DeletedFuncs; + + if (NewFD->isDefaulted()) + return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support) + << IsCPUSpecificCPUDispatchMVType << DefaultedFuncs; + + if (NewFD->isConstexpr() && (MVType == MultiVersioning::CPUDispatch || + MVType == MultiVersioning::CPUSpecific)) + return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support) + << IsCPUSpecificCPUDispatchMVType << ConstexprFuncs; + + QualType NewQType = S.getASTContext().getCanonicalType(NewFD->getType()); + const auto *NewType = cast<FunctionType>(NewQType); + QualType NewReturnType = NewType->getReturnType(); + + if (NewReturnType->isUndeducedType()) + return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support) + << IsCPUSpecificCPUDispatchMVType << DeducedReturn; + + // Only allow transition to MultiVersion if it hasn't been used. + if (OldFD && CausesMV && OldFD->isUsed(false)) + return S.Diag(NewFD->getLocation(), diag::err_multiversion_after_used); + + // Ensure the return type is identical. + if (OldFD) { + QualType OldQType = S.getASTContext().getCanonicalType(OldFD->getType()); + const auto *OldType = cast<FunctionType>(OldQType); + FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo(); + FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo(); + + if (OldTypeInfo.getCC() != NewTypeInfo.getCC()) + return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff) + << CallingConv; + + QualType OldReturnType = OldType->getReturnType(); + + if (OldReturnType != NewReturnType) + return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff) + << ReturnType; + + if (OldFD->isConstexpr() != NewFD->isConstexpr()) + return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff) + << ConstexprSpec; + + if (OldFD->isInlineSpecified() != NewFD->isInlineSpecified()) + return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff) + << InlineSpec; + + if (OldFD->getStorageClass() != NewFD->getStorageClass()) + return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff) + << StorageClass; + + if (OldFD->isExternC() != NewFD->isExternC()) + return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff) + << Linkage; + + if (S.CheckEquivalentExceptionSpec( + OldFD->getType()->getAs<FunctionProtoType>(), OldFD->getLocation(), + NewFD->getType()->getAs<FunctionProtoType>(), NewFD->getLocation())) + return true; + } + return false; +} + +/// Check the validity of a multiversion function declaration that is the +/// first of its kind. Also sets the multiversion'ness' of the function itself. +/// +/// This sets NewFD->isInvalidDecl() to true if there was an error. +/// +/// Returns true if there was an error, false otherwise. +static bool CheckMultiVersionFirstFunction(Sema &S, FunctionDecl *FD, + MultiVersioning::Type MVType, + const TargetAttr *TA, + const CPUDispatchAttr *CPUDisp, + const CPUSpecificAttr *CPUSpec) { + assert(MVType != MultiVersioning::None && + "Function lacks multiversion attribute"); + + // Target only causes MV if it is default, otherwise this is a normal + // function. + if (MVType == MultiVersioning::Target && !TA->isDefaultVersion()) + return false; + + if (MVType == MultiVersioning::Target && CheckMultiVersionValue(S, FD)) { + FD->setInvalidDecl(); + return true; + } + + if (CheckMultiVersionAdditionalRules(S, nullptr, FD, true, MVType)) { + FD->setInvalidDecl(); + return true; + } + + FD->setIsMultiVersion(); + return false; +} + +static bool CheckTargetCausesMultiVersioning( + Sema &S, FunctionDecl *OldFD, FunctionDecl *NewFD, const TargetAttr *NewTA, + bool &Redeclaration, NamedDecl *&OldDecl, bool &MergeTypeWithPrevious, + LookupResult &Previous) { + const auto *OldTA = OldFD->getAttr<TargetAttr>(); + TargetAttr::ParsedTargetAttr NewParsed = NewTA->parse(); + // Sort order doesn't matter, it just needs to be consistent. + llvm::sort(NewParsed.Features.begin(), NewParsed.Features.end()); + + // If the old decl is NOT MultiVersioned yet, and we don't cause that + // to change, this is a simple redeclaration. + if (!OldTA || OldTA->getFeaturesStr() == NewTA->getFeaturesStr()) + return false; + + // Otherwise, this decl causes MultiVersioning. + if (!S.getASTContext().getTargetInfo().supportsMultiVersioning()) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_not_supported); + S.Diag(OldFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } + + if (CheckMultiVersionAdditionalRules(S, OldFD, NewFD, true, + MultiVersioning::Target)) { + NewFD->setInvalidDecl(); + return true; + } + + if (CheckMultiVersionValue(S, NewFD)) { + NewFD->setInvalidDecl(); + return true; + } + + if (CheckMultiVersionValue(S, OldFD)) { + S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here); + NewFD->setInvalidDecl(); + return true; + } + + TargetAttr::ParsedTargetAttr OldParsed = + OldTA->parse(std::less<std::string>()); + + if (OldParsed == NewParsed) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate); + S.Diag(OldFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } + + for (const auto *FD : OldFD->redecls()) { + const auto *CurTA = FD->getAttr<TargetAttr>(); + if (!CurTA || CurTA->isInherited()) { + S.Diag(FD->getLocation(), diag::err_multiversion_required_in_redecl) + << 0; + S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here); + NewFD->setInvalidDecl(); + return true; + } + } + + OldFD->setIsMultiVersion(); + NewFD->setIsMultiVersion(); + Redeclaration = false; + MergeTypeWithPrevious = false; + OldDecl = nullptr; + Previous.clear(); + return false; +} + +/// Check the validity of a new function declaration being added to an existing +/// multiversioned declaration collection. +static bool CheckMultiVersionAdditionalDecl( + Sema &S, FunctionDecl *OldFD, FunctionDecl *NewFD, + MultiVersioning::Type NewMVType, const TargetAttr *NewTA, + const CPUDispatchAttr *NewCPUDisp, const CPUSpecificAttr *NewCPUSpec, + bool &Redeclaration, NamedDecl *&OldDecl, bool &MergeTypeWithPrevious, + LookupResult &Previous) { + + MultiVersioning::Type OldMVType = getMultiVersionType(OldFD); + // Disallow mixing of multiversioning types. + if ((OldMVType == MultiVersioning::Target && + NewMVType != MultiVersioning::Target) || + (NewMVType == MultiVersioning::Target && + OldMVType != MultiVersioning::Target)) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_types_mixed); + S.Diag(OldFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } + + TargetAttr::ParsedTargetAttr NewParsed; + if (NewTA) { + NewParsed = NewTA->parse(); + llvm::sort(NewParsed.Features.begin(), NewParsed.Features.end()); + } + + bool UseMemberUsingDeclRules = + S.CurContext->isRecord() && !NewFD->getFriendObjectKind(); + + // Next, check ALL non-overloads to see if this is a redeclaration of a + // previous member of the MultiVersion set. + for (NamedDecl *ND : Previous) { + FunctionDecl *CurFD = ND->getAsFunction(); + if (!CurFD) + continue; + if (S.IsOverload(NewFD, CurFD, UseMemberUsingDeclRules)) + continue; + + if (NewMVType == MultiVersioning::Target) { + const auto *CurTA = CurFD->getAttr<TargetAttr>(); + if (CurTA->getFeaturesStr() == NewTA->getFeaturesStr()) { + NewFD->setIsMultiVersion(); + Redeclaration = true; + OldDecl = ND; + return false; + } + + TargetAttr::ParsedTargetAttr CurParsed = + CurTA->parse(std::less<std::string>()); + if (CurParsed == NewParsed) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate); + S.Diag(CurFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } + } else { + const auto *CurCPUSpec = CurFD->getAttr<CPUSpecificAttr>(); + const auto *CurCPUDisp = CurFD->getAttr<CPUDispatchAttr>(); + // Handle CPUDispatch/CPUSpecific versions. + // Only 1 CPUDispatch function is allowed, this will make it go through + // the redeclaration errors. + if (NewMVType == MultiVersioning::CPUDispatch && + CurFD->hasAttr<CPUDispatchAttr>()) { + if (CurCPUDisp->cpus_size() == NewCPUDisp->cpus_size() && + std::equal( + CurCPUDisp->cpus_begin(), CurCPUDisp->cpus_end(), + NewCPUDisp->cpus_begin(), + [](const IdentifierInfo *Cur, const IdentifierInfo *New) { + return Cur->getName() == New->getName(); + })) { + NewFD->setIsMultiVersion(); + Redeclaration = true; + OldDecl = ND; + return false; + } + + // If the declarations don't match, this is an error condition. + S.Diag(NewFD->getLocation(), diag::err_cpu_dispatch_mismatch); + S.Diag(CurFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } + if (NewMVType == MultiVersioning::CPUSpecific && CurCPUSpec) { + + if (CurCPUSpec->cpus_size() == NewCPUSpec->cpus_size() && + std::equal( + CurCPUSpec->cpus_begin(), CurCPUSpec->cpus_end(), + NewCPUSpec->cpus_begin(), + [](const IdentifierInfo *Cur, const IdentifierInfo *New) { + return Cur->getName() == New->getName(); + })) { + NewFD->setIsMultiVersion(); + Redeclaration = true; + OldDecl = ND; + return false; + } + + // Only 1 version of CPUSpecific is allowed for each CPU. + for (const IdentifierInfo *CurII : CurCPUSpec->cpus()) { + for (const IdentifierInfo *NewII : NewCPUSpec->cpus()) { + if (CurII == NewII) { + S.Diag(NewFD->getLocation(), diag::err_cpu_specific_multiple_defs) + << NewII; + S.Diag(CurFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } + } + } + } + // If the two decls aren't the same MVType, there is no possible error + // condition. + } + } + + // Else, this is simply a non-redecl case. Checking the 'value' is only + // necessary in the Target case, since The CPUSpecific/Dispatch cases are + // handled in the attribute adding step. + if (NewMVType == MultiVersioning::Target && + CheckMultiVersionValue(S, NewFD)) { + NewFD->setInvalidDecl(); + return true; + } + + if (CheckMultiVersionAdditionalRules(S, OldFD, NewFD, false, NewMVType)) { + NewFD->setInvalidDecl(); + return true; + } + + NewFD->setIsMultiVersion(); + Redeclaration = false; + MergeTypeWithPrevious = false; + OldDecl = nullptr; + Previous.clear(); + return false; +} + + +/// Check the validity of a mulitversion function declaration. +/// Also sets the multiversion'ness' of the function itself. +/// +/// This sets NewFD->isInvalidDecl() to true if there was an error. +/// +/// Returns true if there was an error, false otherwise. +static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD, + bool &Redeclaration, NamedDecl *&OldDecl, + bool &MergeTypeWithPrevious, + LookupResult &Previous) { + const auto *NewTA = NewFD->getAttr<TargetAttr>(); + const auto *NewCPUDisp = NewFD->getAttr<CPUDispatchAttr>(); + const auto *NewCPUSpec = NewFD->getAttr<CPUSpecificAttr>(); + + // Mixing Multiversioning types is prohibited. + if ((NewTA && NewCPUDisp) || (NewTA && NewCPUSpec) || + (NewCPUDisp && NewCPUSpec)) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_types_mixed); + NewFD->setInvalidDecl(); + return true; + } + + MultiVersioning::Type MVType = getMultiVersionType(NewFD); + + // Main isn't allowed to become a multiversion function, however it IS + // permitted to have 'main' be marked with the 'target' optimization hint. + if (NewFD->isMain()) { + if ((MVType == MultiVersioning::Target && NewTA->isDefaultVersion()) || + MVType == MultiVersioning::CPUDispatch || + MVType == MultiVersioning::CPUSpecific) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_not_allowed_on_main); + NewFD->setInvalidDecl(); + return true; + } + return false; + } + + if (!OldDecl || !OldDecl->getAsFunction() || + OldDecl->getDeclContext()->getRedeclContext() != + NewFD->getDeclContext()->getRedeclContext()) { + // If there's no previous declaration, AND this isn't attempting to cause + // multiversioning, this isn't an error condition. + if (MVType == MultiVersioning::None) + return false; + return CheckMultiVersionFirstFunction(S, NewFD, MVType, NewTA, NewCPUDisp, + NewCPUSpec); + } + + FunctionDecl *OldFD = OldDecl->getAsFunction(); + + if (!OldFD->isMultiVersion() && MVType == MultiVersioning::None) + return false; + + if (OldFD->isMultiVersion() && MVType == MultiVersioning::None) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_required_in_redecl) + << (getMultiVersionType(OldFD) != MultiVersioning::Target); + NewFD->setInvalidDecl(); + return true; + } + + // Handle the target potentially causes multiversioning case. + if (!OldFD->isMultiVersion() && MVType == MultiVersioning::Target) + return CheckTargetCausesMultiVersioning(S, OldFD, NewFD, NewTA, + Redeclaration, OldDecl, + MergeTypeWithPrevious, Previous); + // Previous declarations lack CPUDispatch/CPUSpecific. + if (!OldFD->isMultiVersion()) { + S.Diag(OldFD->getLocation(), diag::err_multiversion_required_in_redecl) + << 1; + S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here); + NewFD->setInvalidDecl(); + return true; + } + + // At this point, we have a multiversion function decl (in OldFD) AND an + // appropriate attribute in the current function decl. Resolve that these are + // still compatible with previous declarations. + return CheckMultiVersionAdditionalDecl( + S, OldFD, NewFD, MVType, NewTA, NewCPUDisp, NewCPUSpec, Redeclaration, + OldDecl, MergeTypeWithPrevious, Previous); +} + +/// Perform semantic checking of a new function declaration. /// /// Performs semantic analysis of the new function declaration /// NewFD. This routine performs all semantic checking that does not @@ -9201,6 +9879,10 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, } } + if (CheckMultiVersionFunction(*this, NewFD, Redeclaration, OldDecl, + MergeTypeWithPrevious, Previous)) + return Redeclaration; + // C++11 [dcl.constexpr]p8: // A constexpr specifier for a non-static member function that is not // a constructor declares that member function to be const. @@ -9250,15 +9932,16 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, Previous.clear(); Previous.addDecl(OldDecl); - if (FunctionTemplateDecl *OldTemplateDecl - = dyn_cast<FunctionTemplateDecl>(OldDecl)) { - NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl()); + if (FunctionTemplateDecl *OldTemplateDecl = + dyn_cast<FunctionTemplateDecl>(OldDecl)) { + auto *OldFD = OldTemplateDecl->getTemplatedDecl(); + NewFD->setPreviousDeclaration(OldFD); + adjustDeclContextForDeclaratorDecl(NewFD, OldFD); FunctionTemplateDecl *NewTemplateDecl = NewFD->getDescribedFunctionTemplate(); assert(NewTemplateDecl && "Template/non-template mismatch"); - if (CXXMethodDecl *Method - = dyn_cast<CXXMethodDecl>(NewTemplateDecl->getTemplatedDecl())) { - Method->setAccess(OldTemplateDecl->getAccess()); + if (NewFD->isCXXClassMember()) { + NewFD->setAccess(OldTemplateDecl->getAccess()); NewTemplateDecl->setAccess(OldTemplateDecl->getAccess()); } @@ -9270,22 +9953,22 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, assert(OldTemplateDecl->isMemberSpecialization()); // Explicit specializations of a member template do not inherit deleted // status from the parent member template that they are specializing. - if (OldTemplateDecl->getTemplatedDecl()->isDeleted()) { - FunctionDecl *const OldTemplatedDecl = - OldTemplateDecl->getTemplatedDecl(); + if (OldFD->isDeleted()) { // FIXME: This assert will not hold in the presence of modules. - assert(OldTemplatedDecl->getCanonicalDecl() == OldTemplatedDecl); + assert(OldFD->getCanonicalDecl() == OldFD); // FIXME: We need an update record for this AST mutation. - OldTemplatedDecl->setDeletedAsWritten(false); + OldFD->setDeletedAsWritten(false); } } } else { if (shouldLinkDependentDeclWithPrevious(NewFD, OldDecl)) { + auto *OldFD = cast<FunctionDecl>(OldDecl); // This needs to happen first so that 'inline' propagates. - NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl)); - if (isa<CXXMethodDecl>(NewFD)) - NewFD->setAccess(OldDecl->getAccess()); + NewFD->setPreviousDeclaration(OldFD); + adjustDeclContextForDeclaratorDecl(NewFD, OldFD); + if (NewFD->isCXXClassMember()) + NewFD->setAccess(OldFD->getAccess()); } } } else if (!getLangOpts().CPlusPlus && MayNeedOverloadableChecks && @@ -9440,7 +10123,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, else if (auto *MPT = T->getAs<MemberPointerType>()) T = MPT->getPointeeType(); if (auto *FPT = T->getAs<FunctionProtoType>()) - if (FPT->isNothrow(Context)) + if (FPT->isNothrow()) return true; return false; }; @@ -9951,7 +10634,7 @@ namespace { S.DiagRuntimeBehavior(DRE->getLocStart(), DRE, S.PDiag(diag) - << DRE->getNameInfo().getName() + << DRE->getDecl() << OrigDecl->getLocation() << DRE->getSourceRange()); } @@ -10011,12 +10694,22 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl, // C++11 [dcl.spec.auto]p3 if (!Init) { assert(VDecl && "no init for init capture deduction?"); - Diag(VDecl->getLocation(), diag::err_auto_var_requires_init) - << VDecl->getDeclName() << Type; - return QualType(); + + // Except for class argument deduction, and then for an initializing + // declaration only, i.e. no static at class scope or extern. + if (!isa<DeducedTemplateSpecializationType>(Deduced) || + VDecl->hasExternalStorage() || + VDecl->isStaticDataMember()) { + Diag(VDecl->getLocation(), diag::err_auto_var_requires_init) + << VDecl->getDeclName() << Type; + return QualType(); + } } - ArrayRef<Expr*> DeduceInits = Init; + ArrayRef<Expr*> DeduceInits; + if (Init) + DeduceInits = Init; + if (DirectInit) { if (auto *PL = dyn_cast_or_null<ParenListExpr>(Init)) DeduceInits = PL->exprs(); @@ -10260,7 +10953,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { } if (VDecl->hasLocalStorage()) - getCurFunction()->setHasBranchProtectedScope(); + setFunctionHasBranchProtectedScope(); if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) { VDecl->setInvalidDecl(); @@ -10360,11 +11053,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { // we do not warn to warn spuriously when 'x' and 'y' are on separate // paths through the function. This should be revisited if // -Wrepeated-use-of-weak is made flow-sensitive. - if ((VDecl->getType().getObjCLifetime() == Qualifiers::OCL_Strong || - VDecl->getType().isNonWeakInMRRWithObjCWeak(Context)) && - !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, - Init->getLocStart())) - getCurFunction()->markSafeWeakUse(Init); + if (FunctionScopeInfo *FSI = getCurFunction()) + if ((VDecl->getType().getObjCLifetime() == Qualifiers::OCL_Strong || + VDecl->getType().isNonWeakInMRRWithObjCWeak(Context)) && + !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, + Init->getLocStart())) + FSI->markSafeWeakUse(Init); } // The initialization is usually a full-expression. @@ -10471,6 +11165,9 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { ; // Nothing to check. else if (Init->isIntegerConstantExpr(Context, &Loc)) ; // Ok, it's an ICE! + else if (Init->getType()->isScopedEnumeralType() && + Init->isCXX11ConstantExpr(Context)) + ; // Ok, it is a scoped-enum constant expression. else if (Init->isEvaluatable(Context)) { // If we can constant fold the initializer through heroics, accept it, // but report this as a use of an extension for -pedantic. @@ -10521,7 +11218,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { } else if (VDecl->isFileVarDecl()) { // In C, extern is typically used to avoid tentative definitions when // declaring variables in headers, but adding an intializer makes it a - // defintion. This is somewhat confusing, so GCC and Clang both warn on it. + // definition. This is somewhat confusing, so GCC and Clang both warn on it. // In C++, extern is often used to give implictly static const variables // external linkage, so don't warn in that case. If selectany is present, // this might be header code intended for C and C++ inclusion, so apply the @@ -10794,11 +11491,11 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { if (const RecordType *Record = Context.getBaseElementType(Type)->getAs<RecordType>()) { CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record->getDecl()); - // Mark the function for further checking even if the looser rules of - // C++11 do not require such checks, so that we can diagnose - // incompatibilities with C++98. + // Mark the function (if we're in one) for further checking even if the + // looser rules of C++11 do not require such checks, so that we can + // diagnose incompatibilities with C++98. if (!CXXRecord->isPOD()) - getCurFunction()->setHasBranchProtectedScope(); + setFunctionHasBranchProtectedScope(); } } @@ -10893,13 +11590,13 @@ Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc, DS.SetTypeSpecType(DeclSpec::TST_auto, IdentLoc, PrevSpec, DiagID, getPrintingPolicy()); - Declarator D(DS, Declarator::ForContext); + Declarator D(DS, DeclaratorContext::ForContext); D.SetIdentifier(Ident, IdentLoc); D.takeAttributes(Attrs, AttrEnd); ParsedAttributes EmptyAttrs(Attrs.getPool().getFactory()); - D.AddTypeInfo(DeclaratorChunk::getReference(0, IdentLoc, /*lvalue*/false), - EmptyAttrs, IdentLoc); + D.AddTypeInfo(DeclaratorChunk::getReference(0, IdentLoc, /*lvalue*/ false), + IdentLoc); Decl *Var = ActOnDeclarator(S, D); cast<VarDecl>(Var)->setCXXForRangeDecl(true); FinalizeDeclaration(Var); @@ -10934,11 +11631,15 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { case Qualifiers::OCL_Weak: case Qualifiers::OCL_Strong: - getCurFunction()->setHasBranchProtectedScope(); + setFunctionHasBranchProtectedScope(); break; } } + if (var->hasLocalStorage() && + var->getType().isDestructedType() == QualType::DK_nontrivial_c_struct) + setFunctionHasBranchProtectedScope(); + // Warn about externally-visible variables being defined without a // prior declaration. We only want to do this for global // declarations, but we also specifically need to avoid doing it for @@ -10947,6 +11648,8 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { if (var->isThisDeclarationADefinition() && var->getDeclContext()->getRedeclContext()->isFileContext() && var->isExternallyVisible() && var->hasLinkage() && + !var->isInline() && !var->getDescribedVarTemplate() && + !isTemplateInstantiation(var->getTemplateSpecializationKind()) && !getDiagnostics().isIgnored(diag::warn_missing_variable_declarations, var->getLocation())) { // Find a previous declaration that's not a definition. @@ -11140,7 +11843,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { Context.addModuleInitializer(ModuleScopes.back().Module, var); } -/// \brief Determines if a variable's alignment is dependent. +/// Determines if a variable's alignment is dependent. static bool hasDependentAlignment(VarDecl *VD) { if (VD->getType()->isDependentType()) return true; @@ -11227,58 +11930,8 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) { // 7.5). We must also apply the same checks to all __shared__ // variables whether they are local or not. CUDA also allows // constant initializers for __constant__ and __device__ variables. - if (getLangOpts().CUDA) { - const Expr *Init = VD->getInit(); - if (Init && VD->hasGlobalStorage()) { - if (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>() || - VD->hasAttr<CUDASharedAttr>()) { - assert(!VD->isStaticLocal() || VD->hasAttr<CUDASharedAttr>()); - bool AllowedInit = false; - if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(Init)) - AllowedInit = - isEmptyCudaConstructor(VD->getLocation(), CE->getConstructor()); - // We'll allow constant initializers even if it's a non-empty - // constructor according to CUDA rules. This deviates from NVCC, - // but allows us to handle things like constexpr constructors. - if (!AllowedInit && - (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>())) - AllowedInit = VD->getInit()->isConstantInitializer( - Context, VD->getType()->isReferenceType()); - - // Also make sure that destructor, if there is one, is empty. - if (AllowedInit) - if (CXXRecordDecl *RD = VD->getType()->getAsCXXRecordDecl()) - AllowedInit = - isEmptyCudaDestructor(VD->getLocation(), RD->getDestructor()); - - if (!AllowedInit) { - Diag(VD->getLocation(), VD->hasAttr<CUDASharedAttr>() - ? diag::err_shared_var_init - : diag::err_dynamic_var_init) - << Init->getSourceRange(); - VD->setInvalidDecl(); - } - } else { - // This is a host-side global variable. Check that the initializer is - // callable from the host side. - const FunctionDecl *InitFn = nullptr; - if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(Init)) { - InitFn = CE->getConstructor(); - } else if (const CallExpr *CE = dyn_cast<CallExpr>(Init)) { - InitFn = CE->getDirectCallee(); - } - if (InitFn) { - CUDAFunctionTarget InitFnTarget = IdentifyCUDATarget(InitFn); - if (InitFnTarget != CFT_Host && InitFnTarget != CFT_HostDevice) { - Diag(VD->getLocation(), diag::err_ref_bad_target_global_initializer) - << InitFnTarget << InitFn; - Diag(InitFn->getLocation(), diag::note_previous_decl) << InitFn; - VD->setInvalidDecl(); - } - } - } - } - } + if (getLangOpts().CUDA) + checkAllowedCUDAInitializer(VD); // Grab the dllimport or dllexport attribute off of the VarDecl. const InheritableAttr *DLLAttr = getDLLAttr(VD); @@ -11657,7 +12310,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { return New; } -/// \brief Synthesizes a variable for a parameter arising from a +/// Synthesizes a variable for a parameter arising from a /// typedef. ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, @@ -11809,7 +12462,7 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, // Use the identifier location for the type source range. DS.SetRangeStart(FTI.Params[i].IdentLoc); DS.SetRangeEnd(FTI.Params[i].IdentLoc); - Declarator ParamD(DS, Declarator::KNRTypeListContext); + Declarator ParamD(DS, DeclaratorContext::KNRTypeListContext); ParamD.SetIdentifier(FTI.Params[i].Ident, FTI.Params[i].IdentLoc); FTI.Params[i].Param = ActOnParamDeclarator(S, ParamD); } @@ -11894,9 +12547,45 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD, const FunctionDecl *EffectiveDefinition, SkipBodyInfo *SkipBody) { const FunctionDecl *Definition = EffectiveDefinition; + if (!Definition && !FD->isDefined(Definition) && !FD->isCXXClassMember()) { + // If this is a friend function defined in a class template, it does not + // have a body until it is used, nevertheless it is a definition, see + // [temp.inst]p2: + // + // ... for the purpose of determining whether an instantiated redeclaration + // is valid according to [basic.def.odr] and [class.mem], a declaration that + // corresponds to a definition in the template is considered to be a + // definition. + // + // The following code must produce redefinition error: + // + // template<typename T> struct C20 { friend void func_20() {} }; + // C20<int> c20i; + // void func_20() {} + // + for (auto I : FD->redecls()) { + if (I != FD && !I->isInvalidDecl() && + I->getFriendObjectKind() != Decl::FOK_None) { + if (FunctionDecl *Original = I->getInstantiatedFromMemberFunction()) { + if (FunctionDecl *OrigFD = FD->getInstantiatedFromMemberFunction()) { + // A merged copy of the same function, instantiated as a member of + // the same class, is OK. + if (declaresSameEntity(OrigFD, Original) && + declaresSameEntity(cast<Decl>(I->getLexicalDeclContext()), + cast<Decl>(FD->getLexicalDeclContext()))) + continue; + } + + if (Original->isThisDeclarationADefinition()) { + Definition = I; + break; + } + } + } + } + } if (!Definition) - if (!FD->isDefined(Definition)) - return; + return; if (canRedefineFunction(Definition, getLangOpts())) return; @@ -11981,8 +12670,13 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator, Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, SkipBodyInfo *SkipBody) { - if (!D) + if (!D) { + // Parsing the function declaration failed in some way. Push on a fake scope + // anyway so we can try to parse the function body. + PushFunctionScope(); return D; + } + FunctionDecl *FD = nullptr; if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) @@ -12119,7 +12813,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, return D; } -/// \brief Given the set of return statements within a function body, +/// Given the set of return statements within a function body, /// compute the variables that are subject to the named return value /// optimization. /// @@ -12172,9 +12866,15 @@ bool Sema::canSkipFunctionBody(Decl *D) { // rest of the file. // We cannot skip the body of a function with an undeduced return type, // because any callers of that function need to know the type. - if (const FunctionDecl *FD = D->getAsFunction()) - if (FD->isConstexpr() || FD->getReturnType()->isUndeducedType()) + if (const FunctionDecl *FD = D->getAsFunction()) { + if (FD->isConstexpr()) + return false; + // We can't simply call Type::isUndeducedType here, because inside template + // auto can be deduced to a dependent type, which is not considered + // "undeduced". + if (FD->getReturnType()->getContainedDeducedType()) return false; + } return Consumer.shouldSkipFunctionBody(D); } @@ -12270,8 +12970,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, // Try to apply the named return value optimization. We have to check // if we can do this here because lambdas keep return statements around // to deduce an implicit return type. - if (getLangOpts().CPlusPlus && FD->getReturnType()->isRecordType() && - !FD->isDependentContext()) + if (FD->getReturnType()->isRecordType() && + (!getLangOpts().CPlusPlus || !FD->isDependentContext())) computeNRVO(Body, getCurFunction()); } @@ -12314,6 +13014,13 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, } } + // Warn on CPUDispatch with an actual body. + if (FD->isMultiVersion() && FD->hasAttr<CPUDispatchAttr>() && Body) + if (const auto *CmpndBody = dyn_cast<CompoundStmt>(Body)) + if (!CmpndBody->body_empty()) + Diag(CmpndBody->body_front()->getLocStart(), + diag::warn_dispatch_body_ignored); + if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) { const CXXMethodDecl *KeyFunction; if (MD->isOutOfLine() && (MD = MD->getCanonicalDecl()) && @@ -12391,6 +13098,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, getCurFunction()->ObjCWarnForNoInitDelegation = false; } } else { + // Parsing the function declaration failed in some way. Pop the fake scope + // we pushed on. + PopFunctionScopeInfo(ActivePolicy, dcl); return nullptr; } @@ -12496,7 +13206,7 @@ void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D, // Always attach attributes to the underlying decl. if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) D = TD->getTemplatedDecl(); - ProcessDeclAttributeList(S, D, Attrs.getList()); + ProcessDeclAttributeList(S, D, Attrs); if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(D)) if (Method->isStatic()) @@ -12507,10 +13217,20 @@ 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) { + // Find the scope in which the identifier is injected and the corresponding + // DeclContext. + // FIXME: C89 does not say what happens if there is no enclosing block scope. + // In that case, we inject the declaration into the translation unit scope + // instead. Scope *BlockScope = S; while (!BlockScope->isCompoundStmtScope() && BlockScope->getParent()) BlockScope = BlockScope->getParent(); + Scope *ContextScope = BlockScope; + while (!ContextScope->getEntity()) + ContextScope = ContextScope->getParent(); + ContextRAII SavedContext(*this, ContextScope->getEntity()); + // 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 @@ -12574,7 +13294,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, (void)Error; // Silence warning. assert(!Error && "Error setting up implicit decl!"); SourceLocation NoLoc; - Declarator D(DS, Declarator::BlockContext); + Declarator D(DS, DeclaratorContext::BlockContext); D.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/false, /*IsAmbiguous=*/false, /*LParenLoc=*/NoLoc, @@ -12588,18 +13308,16 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, /*ConstQualifierLoc=*/NoLoc, /*VolatileQualifierLoc=*/NoLoc, /*RestrictQualifierLoc=*/NoLoc, - /*MutableLoc=*/NoLoc, - EST_None, + /*MutableLoc=*/NoLoc, EST_None, /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, /*NoexceptExpr=*/nullptr, /*ExceptionSpecTokens=*/nullptr, - /*DeclsInPrototype=*/None, - Loc, Loc, D), - DS.getAttributes(), - SourceLocation()); + /*DeclsInPrototype=*/None, Loc, + Loc, D), + std::move(DS.getAttributes()), SourceLocation()); D.SetIdentifier(&II, Loc); // Insert this function into the enclosing block scope. @@ -12611,7 +13329,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, return FD; } -/// \brief Adds any function attributes that we know a priori based on +/// Adds any function attributes that we know a priori based on /// the declaration of this function. /// /// These attributes can apply both to implicitly-declared builtins @@ -12661,11 +13379,11 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { 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 + // We make "fma" on some platforms 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()) && + if ((Trip.isGNUEnvironment() || Trip.isAndroid() || Trip.isOSMSVCRT()) && !FD->hasAttr<ConstAttr>()) { switch (BuiltinID) { case Builtin::BI__builtin_fma: @@ -12741,7 +13459,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { // We already have a __builtin___CFStringMakeConstantString, // but builds that use -fno-constant-cfstrings don't go through that. if (!FD->hasAttr<FormatArgAttr>()) - FD->addAttr(FormatArgAttr::CreateImplicit(Context, 1, + FD->addAttr(FormatArgAttr::CreateImplicit(Context, ParamIdx(1, FD), FD->getLocation())); } } @@ -12803,7 +13521,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, return NewTD; } -/// \brief Check that this is a valid underlying type for an enum declaration. +/// Check that this is a valid underlying type for an enum declaration. bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) { SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); QualType T = TI->getType(); @@ -12821,11 +13539,9 @@ bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) { /// Check whether this is a valid redeclaration of a previous enumeration. /// \return true if the redeclaration was invalid. -bool Sema::CheckEnumRedeclaration( - SourceLocation EnumLoc, bool IsScoped, QualType EnumUnderlyingTy, - bool EnumUnderlyingIsImplicit, const EnumDecl *Prev) { - bool IsFixed = !EnumUnderlyingTy.isNull(); - +bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped, + QualType EnumUnderlyingTy, bool IsFixed, + const EnumDecl *Prev) { if (IsScoped != Prev->isScoped()) { Diag(EnumLoc, diag::err_enum_redeclare_scoped_mismatch) << Prev->isScoped(); @@ -12845,10 +13561,6 @@ bool Sema::CheckEnumRedeclaration( << Prev->getIntegerTypeRange(); return true; } - } else if (IsFixed && !Prev->isFixed() && EnumUnderlyingIsImplicit) { - ; - } else if (!IsFixed && Prev->isFixed() && !Prev->getIntegerTypeSourceInfo()) { - ; } else if (IsFixed != Prev->isFixed()) { Diag(EnumLoc, diag::err_enum_redeclare_fixed_mismatch) << Prev->isFixed(); @@ -12859,7 +13571,7 @@ bool Sema::CheckEnumRedeclaration( return false; } -/// \brief Get diagnostic %select index for tag kind for +/// Get diagnostic %select index for tag kind for /// redeclaration diagnostic message. /// WARNING: Indexes apply to particular diagnostics only! /// @@ -12873,7 +13585,7 @@ static unsigned getRedeclDiagFromTagKind(TagTypeKind Tag) { } } -/// \brief Determine if tag kind is a class-key compatible with +/// Determine if tag kind is a class-key compatible with /// class for redeclaration (class, struct, or __interface). /// /// \returns true iff the tag kind is compatible. @@ -12907,7 +13619,7 @@ Sema::NonTagKind Sema::getNonTagTypeDeclKind(const Decl *PrevDecl, llvm_unreachable("invalid TTK"); } -/// \brief Determine whether a tag with a given kind is acceptable +/// Determine whether a tag with a given kind is acceptable /// as a redeclaration of the given tag declaration. /// /// \returns true if the new tag kind is acceptable, false otherwise. @@ -13043,8 +13755,8 @@ static FixItHint createFriendTagNNSFixIt(Sema &SemaRef, NamedDecl *ND, Scope *S, return FixItHint::CreateInsertion(NameLoc, Insertion); } -/// \brief Determine whether a tag originally declared in context \p OldDC can -/// be redeclared with an unqualfied name in \p NewDC (assuming name lookup +/// Determine whether a tag originally declared in context \p OldDC can +/// be redeclared with an unqualified name in \p NewDC (assuming name lookup /// found a declaration in \p OldDC as a previous decl, perhaps through a /// using-declaration). static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC, @@ -13064,7 +13776,7 @@ static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC, return false; } -/// \brief This is invoked when we see 'struct foo' or 'struct {'. In the +/// This is invoked when we see 'struct foo' or 'struct {'. In the /// former case, Name will be non-null. In the later case, Name will be null. /// TagSpec indicates what kind of tag this is. TUK indicates whether this is a /// reference/declaration/definition of a tag. @@ -13077,13 +13789,12 @@ static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC, Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, AccessSpecifier AS, + const ParsedAttributesView &Attrs, AccessSpecifier AS, SourceLocation ModulePrivateLoc, MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl, bool &IsDependent, SourceLocation ScopedEnumKWLoc, - bool ScopedEnumUsesClassTag, - TypeResult UnderlyingType, + bool ScopedEnumUsesClassTag, TypeResult UnderlyingType, bool IsTypeSpecifier, bool IsTemplateParamOrArg, SkipBodyInfo *SkipBody) { // If this is not a definition, it must have a name. @@ -13122,14 +13833,11 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, return nullptr; OwnedDecl = false; - DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc, - SS, Name, NameLoc, Attr, - TemplateParams, AS, - ModulePrivateLoc, - /*FriendLoc*/SourceLocation(), - TemplateParameterLists.size()-1, - TemplateParameterLists.data(), - SkipBody); + DeclResult Result = CheckClassTemplate( + S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attrs, TemplateParams, + AS, ModulePrivateLoc, + /*FriendLoc*/ SourceLocation(), TemplateParameterLists.size() - 1, + TemplateParameterLists.data(), SkipBody); return Result.get(); } else { // The "template<>" header is extraneous. @@ -13144,14 +13852,14 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // this early, because it's needed to detect if this is an incompatible // redeclaration. llvm::PointerUnion<const Type*, TypeSourceInfo*> EnumUnderlying; - bool EnumUnderlyingIsImplicit = false; + bool IsFixed = !UnderlyingType.isUnset() || ScopedEnum; if (Kind == TTK_Enum) { - if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum)) + if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum)) { // No underlying type explicitly specified, or we failed to parse the // type, default to int. EnumUnderlying = Context.IntTy.getTypePtr(); - else if (UnderlyingType.get()) { + } else if (UnderlyingType.get()) { // C++0x 7.2p2: The type-specifier-seq of an enum-base shall name an // integral type; any cv-qualification is ignored. TypeSourceInfo *TI = nullptr; @@ -13167,11 +13875,12 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, EnumUnderlying = Context.IntTy.getTypePtr(); } else if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { - if (getLangOpts().MSVCCompat || TUK == TUK_Definition) { - // Microsoft enums are always of int type. + // For MSVC ABI compatibility, unfixed enums must use an underlying type + // of 'int'. However, if this is an unfixed forward declaration, don't set + // the underlying type unless the user enables -fms-compatibility. This + // makes unfixed forward declared enums incomplete and is more conforming. + if (TUK == TUK_Definition || getLangOpts().MSVCCompat) EnumUnderlying = Context.IntTy.getTypePtr(); - EnumUnderlyingIsImplicit = true; - } } } @@ -13197,8 +13906,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, if (Kind == TTK_Enum) { New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name, nullptr, - ScopedEnum, ScopedEnumUsesClassTag, - !EnumUnderlying.isNull()); + ScopedEnum, ScopedEnumUsesClassTag, IsFixed); // If this is an undefined enum, bail. if (TUK != TUK_Definition && !Invalid) return nullptr; @@ -13577,7 +14285,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // in which case we want the caller to bail out. if (CheckEnumRedeclaration(NameLoc.isValid() ? NameLoc : KWLoc, ScopedEnum, EnumUnderlyingTy, - EnumUnderlyingIsImplicit, PrevEnum)) + IsFixed, PrevEnum)) return TUK == TUK_Declaration ? PrevTagDecl : nullptr; } @@ -13595,7 +14303,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // If this is a use, just return the declaration we found, unless // we have attributes. if (TUK == TUK_Reference || TUK == TUK_Friend) { - if (Attr) { + if (!Attrs.empty()) { // FIXME: Diagnose these attributes. For now, we create a new // declaration to hold them. } else if (TUK == TUK_Reference && @@ -13787,13 +14495,12 @@ CreateNewDecl: // PrevDecl. TagDecl *New; - bool IsForwardReference = false; if (Kind == TTK_Enum) { // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: // enum X { A, B, C } D; D should chain to X. New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name, cast_or_null<EnumDecl>(PrevDecl), ScopedEnum, - ScopedEnumUsesClassTag, !EnumUnderlying.isNull()); + ScopedEnumUsesClassTag, IsFixed); if (isStdAlignValT && (!StdAlignValT || getStdAlignValT()->isImplicit())) StdAlignValT = cast<EnumDecl>(New); @@ -13801,8 +14508,7 @@ CreateNewDecl: // If this is an undefined enum, warn. if (TUK != TUK_Definition && !Invalid) { TagDecl *Def; - if (!EnumUnderlyingIsImplicit && - (getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) && + if (IsFixed && (getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) && cast<EnumDecl>(New)->isFixed()) { // C++0x: 7.2p2: opaque-enum-declaration. // Conflicts are diagnosed above. Do nothing. @@ -13818,12 +14524,6 @@ CreateNewDecl: else if (getLangOpts().CPlusPlus) DiagID = diag::err_forward_ref_enum; Diag(Loc, DiagID); - - // If this is a forward-declared reference to an enumeration, make a - // note of it; we won't actually be introducing the declaration into - // the declaration context. - if (TUK == TUK_Reference) - IsForwardReference = true; } } @@ -13834,6 +14534,7 @@ CreateNewDecl: else ED->setIntegerType(QualType(EnumUnderlying.get<const Type*>(), 0)); ED->setPromotionType(ED->getIntegerType()); + assert(ED->isComplete() && "enum with type should be complete"); } } else { // struct/union/class @@ -13872,13 +14573,10 @@ CreateNewDecl: if (SS.isNotEmpty()) { if (SS.isSet()) { // If this is either a declaration or a definition, check the - // nested-name-specifier against the current context. We don't do this - // for explicit specializations, because they have similar checking - // (with more specific diagnostics) in the call to - // CheckMemberSpecialization, below. - if (!isMemberSpecialization && - (TUK == TUK_Definition || TUK == TUK_Declaration) && - diagnoseQualifiedDeclaration(SS, DC, OrigName, Loc)) + // nested-name-specifier against the current context. + if ((TUK == TUK_Definition || TUK == TUK_Declaration) && + diagnoseQualifiedDeclaration(SS, DC, OrigName, Loc, + isMemberSpecialization)) Invalid = true; New->setQualifierInfo(SS.getWithLocInContext(Context)); @@ -13965,8 +14663,7 @@ CreateNewDecl: if (TUK == TUK_Definition) New->startDefinition(); - if (Attr) - ProcessDeclAttributeList(S, New, Attr); + ProcessDeclAttributeList(S, New, Attrs); AddPragmaAttributes(S, New); // If this has an identifier, add it to the scope stack. @@ -13983,9 +14680,7 @@ CreateNewDecl: PushOnScopeChains(New, EnclosingScope, /* AddToContext = */ false); } else if (Name) { S = getNonFieldDeclScope(S); - PushOnScopeChains(New, S, !IsForwardReference); - if (IsForwardReference) - SearchDC->makeDeclVisibleInContext(New); + PushOnScopeChains(New, S, true); } else { CurContext->addDecl(New); } @@ -14369,7 +15064,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, return NewFD; } -/// \brief Build a new FieldDecl and check its well-formedness. +/// Build a new FieldDecl and check its well-formedness. /// /// This routine builds a new FieldDecl given the fields name, type, /// record, etc. \p PrevDecl should refer to any previous declaration @@ -14420,6 +15115,13 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, InvalidDecl = true; } + // Anonymous bit-fields cannot be cv-qualified (CWG 2229). + if (!InvalidDecl && getLangOpts().CPlusPlus && !II && BitWidth && + T.hasQualifiers()) { + InvalidDecl = true; + Diag(Loc, diag::err_anon_bitfield_qualifiers); + } + // C99 6.7.2.1p8: A member of a structure or union may have any type other // than a variably modified type. if (!InvalidDecl && T->isVariablyModifiedType()) { @@ -14752,7 +15454,7 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1]; ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(ivarDecl); - if (!Ivar->isBitField() || Ivar->getBitWidthValue(Context) == 0) + if (!Ivar->isBitField() || Ivar->isZeroLengthBitField(Context)) return; ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CurContext); if (!ID) { @@ -14780,7 +15482,8 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, ArrayRef<Decl *> Fields, SourceLocation LBrac, - SourceLocation RBrac, AttributeList *Attr) { + SourceLocation RBrac, + const ParsedAttributesView &Attrs) { assert(EnclosingDecl && "missing record or interface decl"); // If this is an Objective-C @implementation or category and we have @@ -14963,8 +15666,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, QualType T = Context.getObjCObjectPointerType(FD->getType()); FD->setType(T); } else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && - Record && !ObjCFieldLifetimeErrReported && - (!getLangOpts().CPlusPlus || Record->isUnion())) { + Record && !ObjCFieldLifetimeErrReported && Record->isUnion()) { // It's an error in ARC or Weak if a field has lifetime. // We don't want to report this in a system header, though, // so we just make the field unavailable. @@ -15000,6 +15702,27 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, Record->setHasObjectMember(true); } } + + if (Record && !getLangOpts().CPlusPlus && !FD->hasAttr<UnavailableAttr>()) { + QualType FT = FD->getType(); + if (FT.isNonTrivialToPrimitiveDefaultInitialize()) + Record->setNonTrivialToPrimitiveDefaultInitialize(true); + QualType::PrimitiveCopyKind PCK = FT.isNonTrivialToPrimitiveCopy(); + if (PCK != QualType::PCK_Trivial && PCK != QualType::PCK_VolatileTrivial) + Record->setNonTrivialToPrimitiveCopy(true); + if (FT.isDestructedType()) { + Record->setNonTrivialToPrimitiveDestroy(true); + Record->setParamDestroyedInCallee(true); + } + + if (const auto *RT = FT->getAs<RecordType>()) { + if (RT->getDecl()->getArgPassingRestrictions() == + RecordDecl::APK_CanNeverPassInRegs) + Record->setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs); + } else if (FT.getQualifiers().getObjCLifetime() == Qualifiers::OCL_Weak) + Record->setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs); + } + if (Record && FD->getType().isVolatileQualified()) Record->setHasVolatileMember(true); // Keep track of the number of named members. @@ -15027,10 +15750,10 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, CXXRecord->getDestructor()); } - if (!CXXRecord->isInvalidDecl()) { - // Add any implicitly-declared members to this class. - AddImplicitlyDeclaredMembersToClass(CXXRecord); + // Add any implicitly-declared members to this class. + AddImplicitlyDeclaredMembersToClass(CXXRecord); + 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 // problem now. @@ -15045,7 +15768,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, SOEnd = M->second.end(); SO != SOEnd; ++SO) { assert(SO->second.size() > 0 && - "Virtual function without overridding functions?"); + "Virtual function without overriding functions?"); if (SO->second.size() == 1) continue; @@ -15077,6 +15800,9 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, if (!Completed) Record->completeDefinition(); + // Handle attributes before checking the layout. + ProcessDeclAttributeList(S, Record, Attrs); + // We may have deferred checking for a deleted destructor. Check now. if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record)) { auto *Dtor = CXXRecord->getDestructor(); @@ -15119,7 +15845,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, (NonBitFields == 0 || ZeroSize) && I != E; ++I) { IsEmpty = false; if (I->isUnnamedBitfield()) { - if (I->getBitWidthValue(Context) > 0) + if (!I->isZeroLengthBitField(Context)) ZeroSize = false; } else { ++NonBitFields; @@ -15207,12 +15933,9 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, CDecl->setIvarRBraceLoc(RBrac); } } - - if (Attr) - ProcessDeclAttributeList(S, Record, Attr); } -/// \brief Determine whether the given integral value is representable within +/// Determine whether the given integral value is representable within /// the given type T. static bool isRepresentableIntegerValue(ASTContext &Context, llvm::APSInt &Value, @@ -15229,7 +15952,7 @@ static bool isRepresentableIntegerValue(ASTContext &Context, return Value.getMinSignedBits() <= BitWidth; } -// \brief Given an integral type, return the next larger integral type +// Given an integral type, return the next larger integral type // (or a NULL type of no such type exists). static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) { // FIXME: Int128/UInt128 support, which also needs to be introduced into @@ -15292,7 +16015,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, &EnumVal).get())) { // C99 6.7.2.2p2: Make sure we have an integer constant expression. } else { - if (Enum->isFixed()) { + if (Enum->isComplete()) { EltTy = Enum->getIntegerType(); // In Obj-C and Microsoft mode, require the enumeration value to be @@ -15456,7 +16179,7 @@ Sema::SkipBodyInfo Sema::shouldSkipAnonEnumBody(Scope *S, IdentifierInfo *II, Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, SourceLocation IdLoc, IdentifierInfo *Id, - AttributeList *Attr, + const ParsedAttributesView &Attrs, SourceLocation EqualLoc, Expr *Val) { EnumDecl *TheEnumDecl = cast<EnumDecl>(theEnumDecl); EnumConstantDecl *LastEnumConst = @@ -15507,7 +16230,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, } // Process attributes. - if (Attr) ProcessDeclAttributeList(S, New, Attr); + ProcessDeclAttributeList(S, New, Attrs); AddPragmaAttributes(S, New); // Register this decl in the current scope stack. @@ -15559,39 +16282,10 @@ static bool ValidDuplicateEnum(EnumConstantDecl *ECD, EnumDecl *Enum) { return false; } -namespace { -struct DupKey { - int64_t val; - bool isTombstoneOrEmptyKey; - DupKey(int64_t val, bool isTombstoneOrEmptyKey) - : val(val), isTombstoneOrEmptyKey(isTombstoneOrEmptyKey) {} -}; - -static DupKey GetDupKey(const llvm::APSInt& Val) { - return DupKey(Val.isSigned() ? Val.getSExtValue() : Val.getZExtValue(), - false); -} - -struct DenseMapInfoDupKey { - static DupKey getEmptyKey() { return DupKey(0, true); } - static DupKey getTombstoneKey() { return DupKey(1, true); } - static unsigned getHashValue(const DupKey Key) { - return (unsigned)(Key.val * 37); - } - static bool isEqual(const DupKey& LHS, const DupKey& RHS) { - return LHS.isTombstoneOrEmptyKey == RHS.isTombstoneOrEmptyKey && - LHS.val == RHS.val; - } -}; -} // end anonymous namespace - // Emits a warning when an element is implicitly set a value that // a previous element has already been set to. static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements, - EnumDecl *Enum, - QualType EnumType) { - if (S.Diags.isIgnored(diag::warn_duplicate_enum_values, Enum->getLocation())) - return; + EnumDecl *Enum, QualType EnumType) { // Avoid anonymous enums if (!Enum->getIdentifier()) return; @@ -15600,20 +16294,28 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements, if (Enum->getNumPositiveBits() > 63 || Enum->getNumNegativeBits() > 64) return; + if (S.Diags.isIgnored(diag::warn_duplicate_enum_values, Enum->getLocation())) + return; + typedef SmallVector<EnumConstantDecl *, 3> ECDVector; - typedef SmallVector<ECDVector *, 3> DuplicatesVector; + typedef SmallVector<std::unique_ptr<ECDVector>, 3> DuplicatesVector; typedef llvm::PointerUnion<EnumConstantDecl*, ECDVector*> DeclOrVector; - typedef llvm::DenseMap<DupKey, DeclOrVector, DenseMapInfoDupKey> - ValueToVectorMap; + typedef llvm::DenseMap<int64_t, DeclOrVector> ValueToVectorMap; + + // Use int64_t as a key to avoid needing special handling for DenseMap keys. + auto EnumConstantToKey = [](const EnumConstantDecl *D) { + llvm::APSInt Val = D->getInitVal(); + return Val.isSigned() ? Val.getSExtValue() : Val.getZExtValue(); + }; DuplicatesVector DupVector; ValueToVectorMap EnumMap; // Populate the EnumMap with all values represented by enum constants without - // an initialier. - for (unsigned i = 0, e = Elements.size(); i != e; ++i) { - EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elements[i]); + // an initializer. + for (auto *Element : Elements) { + EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Element); // Null EnumConstantDecl means a previous diagnostic has been emitted for // this constant. Skip this enum since it may be ill-formed. @@ -15621,45 +16323,45 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements, return; } + // Constants with initalizers are handled in the next loop. if (ECD->getInitExpr()) continue; - DupKey Key = GetDupKey(ECD->getInitVal()); - DeclOrVector &Entry = EnumMap[Key]; - - // First time encountering this value. - if (Entry.isNull()) - Entry = ECD; + // Duplicate values are handled in the next loop. + EnumMap.insert({EnumConstantToKey(ECD), ECD}); } + if (EnumMap.size() == 0) + return; + // Create vectors for any values that has duplicates. - for (unsigned i = 0, e = Elements.size(); i != e; ++i) { - EnumConstantDecl *ECD = cast<EnumConstantDecl>(Elements[i]); + for (auto *Element : Elements) { + // The last loop returned if any constant was null. + EnumConstantDecl *ECD = cast<EnumConstantDecl>(Element); if (!ValidDuplicateEnum(ECD, Enum)) continue; - DupKey Key = GetDupKey(ECD->getInitVal()); - - DeclOrVector& Entry = EnumMap[Key]; - if (Entry.isNull()) + auto Iter = EnumMap.find(EnumConstantToKey(ECD)); + if (Iter == EnumMap.end()) continue; + DeclOrVector& Entry = Iter->second; if (EnumConstantDecl *D = Entry.dyn_cast<EnumConstantDecl*>()) { // Ensure constants are different. if (D == ECD) continue; // Create new vector and push values onto it. - ECDVector *Vec = new ECDVector(); + auto Vec = llvm::make_unique<ECDVector>(); Vec->push_back(D); Vec->push_back(ECD); // Update entry to point to the duplicates vector. - Entry = Vec; + Entry = Vec.get(); // Store the vector somewhere we can consult later for quick emission of // diagnostics. - DupVector.push_back(Vec); + DupVector.emplace_back(std::move(Vec)); continue; } @@ -15672,26 +16374,21 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements, } // Emit diagnostics. - for (DuplicatesVector::iterator DupVectorIter = DupVector.begin(), - DupVectorEnd = DupVector.end(); - DupVectorIter != DupVectorEnd; ++DupVectorIter) { - ECDVector *Vec = *DupVectorIter; + for (const auto &Vec : DupVector) { assert(Vec->size() > 1 && "ECDVector should have at least 2 elements."); // Emit warning for one enum constant. - ECDVector::iterator I = Vec->begin(); - S.Diag((*I)->getLocation(), diag::warn_duplicate_enum_values) - << (*I)->getName() << (*I)->getInitVal().toString(10) - << (*I)->getSourceRange(); - ++I; + auto *FirstECD = Vec->front(); + S.Diag(FirstECD->getLocation(), diag::warn_duplicate_enum_values) + << FirstECD << FirstECD->getInitVal().toString(10) + << FirstECD->getSourceRange(); // Emit one note for each of the remaining enum constants with // the same value. - for (ECDVector::iterator E = Vec->end(); I != E; ++I) - S.Diag((*I)->getLocation(), diag::note_duplicate_element) - << (*I)->getName() << (*I)->getInitVal().toString(10) - << (*I)->getSourceRange(); - delete Vec; + for (auto *ECD : llvm::make_range(Vec->begin() + 1, Vec->end())) + S.Diag(ECD->getLocation(), diag::note_duplicate_element) + << ECD << ECD->getInitVal().toString(10) + << ECD->getSourceRange(); } } @@ -15725,14 +16422,12 @@ bool Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val, } void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, - Decl *EnumDeclX, - ArrayRef<Decl *> Elements, - Scope *S, AttributeList *Attr) { + Decl *EnumDeclX, ArrayRef<Decl *> Elements, Scope *S, + const ParsedAttributesView &Attrs) { EnumDecl *Enum = cast<EnumDecl>(EnumDeclX); QualType EnumType = Context.getTypeDeclType(Enum); - if (Attr) - ProcessDeclAttributeList(S, Enum, Attr); + ProcessDeclAttributeList(S, Enum, Attrs); if (Enum->isDependentType()) { for (unsigned i = 0, e = Elements.size(); i != e; ++i) { @@ -15803,7 +16498,9 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, if (LangOpts.ShortEnums) Packed = true; - if (Enum->isFixed()) { + // If the enum already has a type because it is fixed or dictated by the + // target, promote that type instead of analyzing the enumerators. + if (Enum->isComplete()) { BestType = Enum->getIntegerType(); if (BestType->isPromotableIntegerType()) BestPromotionType = Context.getPromotedIntegerType(BestType); |
