diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp | 1338 |
1 files changed, 1085 insertions, 253 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp index e161c87..f265f4c 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/Sema/SemaInternal.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTLambda.h" @@ -36,9 +35,11 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" #include <map> #include <set> @@ -394,7 +395,8 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { ++argIdx) { ParmVarDecl *Param = cast<ParmVarDecl>(chunk.Fun.Params[argIdx].Param); if (Param->hasUnparsedDefaultArg()) { - CachedTokens *Toks = chunk.Fun.Params[argIdx].DefaultArgTokens; + std::unique_ptr<CachedTokens> Toks = + std::move(chunk.Fun.Params[argIdx].DefaultArgTokens); SourceRange SR; if (Toks->size() > 1) SR = SourceRange((*Toks)[1].getLocation(), @@ -403,8 +405,6 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { SR = UnparsedDefaultArgLocs[Param]; Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc) << SR; - delete Toks; - chunk.Fun.Params[argIdx].DefaultArgTokens = nullptr; } else if (Param->getDefaultArg()) { Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc) << Param->getDefaultArg()->getSourceRange(); @@ -658,12 +658,773 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Invalid = true; } - if (CheckEquivalentExceptionSpec(Old, New)) - Invalid = true; - return Invalid; } +NamedDecl * +Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParamLists) { + assert(D.isDecompositionDeclarator()); + const DecompositionDeclarator &Decomp = D.getDecompositionDeclarator(); + + // The syntax only allows a decomposition declarator as a simple-declaration + // or a for-range-declaration, but we parse it in more cases than that. + if (!D.mayHaveDecompositionDeclarator()) { + Diag(Decomp.getLSquareLoc(), diag::err_decomp_decl_context) + << Decomp.getSourceRange(); + return nullptr; + } + + if (!TemplateParamLists.empty()) { + // FIXME: There's no rule against this, but there are also no rules that + // would actually make it usable, so we reject it for now. + Diag(TemplateParamLists.front()->getTemplateLoc(), + diag::err_decomp_decl_template); + return nullptr; + } + + Diag(Decomp.getLSquareLoc(), getLangOpts().CPlusPlus1z + ? diag::warn_cxx14_compat_decomp_decl + : diag::ext_decomp_decl) + << Decomp.getSourceRange(); + + // The semantic context is always just the current context. + DeclContext *const DC = CurContext; + + // C++1z [dcl.dcl]/8: + // The decl-specifier-seq shall contain only the type-specifier auto + // and cv-qualifiers. + auto &DS = D.getDeclSpec(); + { + SmallVector<StringRef, 8> BadSpecifiers; + SmallVector<SourceLocation, 8> BadSpecifierLocs; + if (auto SCS = DS.getStorageClassSpec()) { + BadSpecifiers.push_back(DeclSpec::getSpecifierName(SCS)); + BadSpecifierLocs.push_back(DS.getStorageClassSpecLoc()); + } + if (auto TSCS = DS.getThreadStorageClassSpec()) { + BadSpecifiers.push_back(DeclSpec::getSpecifierName(TSCS)); + BadSpecifierLocs.push_back(DS.getThreadStorageClassSpecLoc()); + } + if (DS.isConstexprSpecified()) { + BadSpecifiers.push_back("constexpr"); + BadSpecifierLocs.push_back(DS.getConstexprSpecLoc()); + } + if (DS.isInlineSpecified()) { + BadSpecifiers.push_back("inline"); + BadSpecifierLocs.push_back(DS.getInlineSpecLoc()); + } + if (!BadSpecifiers.empty()) { + auto &&Err = Diag(BadSpecifierLocs.front(), diag::err_decomp_decl_spec); + Err << (int)BadSpecifiers.size() + << llvm::join(BadSpecifiers.begin(), BadSpecifiers.end(), " "); + // Don't add FixItHints to remove the specifiers; we do still respect + // them when building the underlying variable. + for (auto Loc : BadSpecifierLocs) + Err << SourceRange(Loc, Loc); + } + // We can't recover from it being declared as a typedef. + if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) + return nullptr; + } + + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType R = TInfo->getType(); + + if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, + UPPC_DeclarationType)) + D.setInvalidType(); + + // The syntax only allows a single ref-qualifier prior to the decomposition + // declarator. No other declarator chunks are permitted. Also check the type + // specifier here. + if (DS.getTypeSpecType() != DeclSpec::TST_auto || + D.hasGroupingParens() || D.getNumTypeObjects() > 1 || + (D.getNumTypeObjects() == 1 && + D.getTypeObject(0).Kind != DeclaratorChunk::Reference)) { + Diag(Decomp.getLSquareLoc(), + (D.hasGroupingParens() || + (D.getNumTypeObjects() && + D.getTypeObject(0).Kind == DeclaratorChunk::Paren)) + ? diag::err_decomp_decl_parens + : diag::err_decomp_decl_type) + << R; + + // In most cases, there's no actual problem with an explicitly-specified + // type, but a function type won't work here, and ActOnVariableDeclarator + // shouldn't be called for such a type. + if (R->isFunctionType()) + D.setInvalidType(); + } + + // Build the BindingDecls. + SmallVector<BindingDecl*, 8> Bindings; + + // Build the BindingDecls. + for (auto &B : D.getDecompositionDeclarator().bindings()) { + // Check for name conflicts. + DeclarationNameInfo NameInfo(B.Name, B.NameLoc); + LookupResult Previous(*this, NameInfo, LookupOrdinaryName, + ForRedeclaration); + LookupName(Previous, S, + /*CreateBuiltins*/DC->getRedeclContext()->isTranslationUnit()); + + // It's not permitted to shadow a template parameter name. + if (Previous.isSingleResult() && + Previous.getFoundDecl()->isTemplateParameter()) { + DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), + Previous.getFoundDecl()); + Previous.clear(); + } + + bool ConsiderLinkage = DC->isFunctionOrMethod() && + DS.getStorageClassSpec() == DeclSpec::SCS_extern; + FilterLookupForScope(Previous, DC, S, ConsiderLinkage, + /*AllowInlineNamespace*/false); + if (!Previous.empty()) { + auto *Old = Previous.getRepresentativeDecl(); + Diag(B.NameLoc, diag::err_redefinition) << B.Name; + Diag(Old->getLocation(), diag::note_previous_definition); + } + + auto *BD = BindingDecl::Create(Context, DC, B.NameLoc, B.Name); + PushOnScopeChains(BD, S, true); + Bindings.push_back(BD); + ParsingInitForAutoVars.insert(BD); + } + + // There are no prior lookup results for the variable itself, because it + // is unnamed. + DeclarationNameInfo NameInfo((IdentifierInfo *)nullptr, + Decomp.getLSquareLoc()); + LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); + + // Build the variable that holds the non-decomposed object. + bool AddToScope = true; + NamedDecl *New = + ActOnVariableDeclarator(S, D, DC, TInfo, Previous, + MultiTemplateParamsArg(), AddToScope, Bindings); + CurContext->addHiddenDecl(New); + + if (isInOpenMPDeclareTargetContext()) + checkDeclIsAllowedInOpenMPTarget(nullptr, New); + + return New; +} + +static bool checkSimpleDecomposition( + Sema &S, ArrayRef<BindingDecl *> Bindings, ValueDecl *Src, + QualType DecompType, const llvm::APSInt &NumElems, QualType ElemType, + llvm::function_ref<ExprResult(SourceLocation, Expr *, unsigned)> GetInit) { + if ((int64_t)Bindings.size() != NumElems) { + S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings) + << DecompType << (unsigned)Bindings.size() << NumElems.toString(10) + << (NumElems < Bindings.size()); + return true; + } + + unsigned I = 0; + for (auto *B : Bindings) { + SourceLocation Loc = B->getLocation(); + ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc); + if (E.isInvalid()) + return true; + E = GetInit(Loc, E.get(), I++); + if (E.isInvalid()) + return true; + B->setBinding(ElemType, E.get()); + } + + return false; +} + +static bool checkArrayLikeDecomposition(Sema &S, + ArrayRef<BindingDecl *> Bindings, + ValueDecl *Src, QualType DecompType, + const llvm::APSInt &NumElems, + QualType ElemType) { + return checkSimpleDecomposition( + S, Bindings, Src, DecompType, NumElems, ElemType, + [&](SourceLocation Loc, Expr *Base, unsigned I) -> ExprResult { + ExprResult E = S.ActOnIntegerConstant(Loc, I); + if (E.isInvalid()) + return ExprError(); + return S.CreateBuiltinArraySubscriptExpr(Base, Loc, E.get(), Loc); + }); +} + +static bool checkArrayDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings, + ValueDecl *Src, QualType DecompType, + const ConstantArrayType *CAT) { + return checkArrayLikeDecomposition(S, Bindings, Src, DecompType, + llvm::APSInt(CAT->getSize()), + CAT->getElementType()); +} + +static bool checkVectorDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings, + ValueDecl *Src, QualType DecompType, + const VectorType *VT) { + return checkArrayLikeDecomposition( + S, Bindings, Src, DecompType, llvm::APSInt::get(VT->getNumElements()), + S.Context.getQualifiedType(VT->getElementType(), + DecompType.getQualifiers())); +} + +static bool checkComplexDecomposition(Sema &S, + ArrayRef<BindingDecl *> Bindings, + ValueDecl *Src, QualType DecompType, + const ComplexType *CT) { + return checkSimpleDecomposition( + S, Bindings, Src, DecompType, llvm::APSInt::get(2), + S.Context.getQualifiedType(CT->getElementType(), + DecompType.getQualifiers()), + [&](SourceLocation Loc, Expr *Base, unsigned I) -> ExprResult { + return S.CreateBuiltinUnaryOp(Loc, I ? UO_Imag : UO_Real, Base); + }); +} + +static std::string printTemplateArgs(const PrintingPolicy &PrintingPolicy, + TemplateArgumentListInfo &Args) { + SmallString<128> SS; + llvm::raw_svector_ostream OS(SS); + bool First = true; + for (auto &Arg : Args.arguments()) { + if (!First) + OS << ", "; + Arg.getArgument().print(PrintingPolicy, OS); + First = false; + } + return OS.str(); +} + +static bool lookupStdTypeTraitMember(Sema &S, LookupResult &TraitMemberLookup, + SourceLocation Loc, StringRef Trait, + TemplateArgumentListInfo &Args, + unsigned DiagID) { + auto DiagnoseMissing = [&] { + if (DiagID) + S.Diag(Loc, DiagID) << printTemplateArgs(S.Context.getPrintingPolicy(), + Args); + return true; + }; + + // FIXME: Factor out duplication with lookupPromiseType in SemaCoroutine. + NamespaceDecl *Std = S.getStdNamespace(); + if (!Std) + return DiagnoseMissing(); + + // Look up the trait itself, within namespace std. We can diagnose various + // problems with this lookup even if we've been asked to not diagnose a + // missing specialization, because this can only fail if the user has been + // declaring their own names in namespace std or we don't support the + // standard library implementation in use. + LookupResult Result(S, &S.PP.getIdentifierTable().get(Trait), + Loc, Sema::LookupOrdinaryName); + if (!S.LookupQualifiedName(Result, Std)) + return DiagnoseMissing(); + if (Result.isAmbiguous()) + return true; + + ClassTemplateDecl *TraitTD = Result.getAsSingle<ClassTemplateDecl>(); + if (!TraitTD) { + Result.suppressDiagnostics(); + NamedDecl *Found = *Result.begin(); + S.Diag(Loc, diag::err_std_type_trait_not_class_template) << Trait; + S.Diag(Found->getLocation(), diag::note_declared_at); + return true; + } + + // Build the template-id. + QualType TraitTy = S.CheckTemplateIdType(TemplateName(TraitTD), Loc, Args); + if (TraitTy.isNull()) + return true; + if (!S.isCompleteType(Loc, TraitTy)) { + if (DiagID) + S.RequireCompleteType( + Loc, TraitTy, DiagID, + printTemplateArgs(S.Context.getPrintingPolicy(), Args)); + return true; + } + + CXXRecordDecl *RD = TraitTy->getAsCXXRecordDecl(); + assert(RD && "specialization of class template is not a class?"); + + // Look up the member of the trait type. + S.LookupQualifiedName(TraitMemberLookup, RD); + return TraitMemberLookup.isAmbiguous(); +} + +static TemplateArgumentLoc +getTrivialIntegralTemplateArgument(Sema &S, SourceLocation Loc, QualType T, + uint64_t I) { + TemplateArgument Arg(S.Context, S.Context.MakeIntValue(I, T), T); + return S.getTrivialTemplateArgumentLoc(Arg, T, Loc); +} + +static TemplateArgumentLoc +getTrivialTypeTemplateArgument(Sema &S, SourceLocation Loc, QualType T) { + return S.getTrivialTemplateArgumentLoc(TemplateArgument(T), QualType(), Loc); +} + +namespace { enum class IsTupleLike { TupleLike, NotTupleLike, Error }; } + +static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T, + llvm::APSInt &Size) { + EnterExpressionEvaluationContext ContextRAII(S, Sema::ConstantEvaluated); + + DeclarationName Value = S.PP.getIdentifierInfo("value"); + LookupResult R(S, Value, Loc, Sema::LookupOrdinaryName); + + // Form template argument list for tuple_size<T>. + TemplateArgumentListInfo Args(Loc, Loc); + Args.addArgument(getTrivialTypeTemplateArgument(S, Loc, T)); + + // If there's no tuple_size specialization, it's not tuple-like. + if (lookupStdTypeTraitMember(S, R, Loc, "tuple_size", Args, /*DiagID*/0)) + return IsTupleLike::NotTupleLike; + + // If we get this far, we've committed to the tuple interpretation, but + // we can still fail if there actually isn't a usable ::value. + + struct ICEDiagnoser : Sema::VerifyICEDiagnoser { + LookupResult &R; + TemplateArgumentListInfo &Args; + ICEDiagnoser(LookupResult &R, TemplateArgumentListInfo &Args) + : R(R), Args(Args) {} + void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) { + S.Diag(Loc, diag::err_decomp_decl_std_tuple_size_not_constant) + << printTemplateArgs(S.Context.getPrintingPolicy(), Args); + } + } Diagnoser(R, Args); + + if (R.empty()) { + Diagnoser.diagnoseNotICE(S, Loc, SourceRange()); + return IsTupleLike::Error; + } + + ExprResult E = + S.BuildDeclarationNameExpr(CXXScopeSpec(), R, /*NeedsADL*/false); + if (E.isInvalid()) + return IsTupleLike::Error; + + E = S.VerifyIntegerConstantExpression(E.get(), &Size, Diagnoser, false); + if (E.isInvalid()) + return IsTupleLike::Error; + + return IsTupleLike::TupleLike; +} + +/// \return std::tuple_element<I, T>::type. +static QualType getTupleLikeElementType(Sema &S, SourceLocation Loc, + unsigned I, QualType T) { + // Form template argument list for tuple_element<I, T>. + TemplateArgumentListInfo Args(Loc, Loc); + Args.addArgument( + getTrivialIntegralTemplateArgument(S, Loc, S.Context.getSizeType(), I)); + Args.addArgument(getTrivialTypeTemplateArgument(S, Loc, T)); + + DeclarationName TypeDN = S.PP.getIdentifierInfo("type"); + LookupResult R(S, TypeDN, Loc, Sema::LookupOrdinaryName); + if (lookupStdTypeTraitMember( + S, R, Loc, "tuple_element", Args, + diag::err_decomp_decl_std_tuple_element_not_specialized)) + return QualType(); + + auto *TD = R.getAsSingle<TypeDecl>(); + if (!TD) { + R.suppressDiagnostics(); + S.Diag(Loc, diag::err_decomp_decl_std_tuple_element_not_specialized) + << printTemplateArgs(S.Context.getPrintingPolicy(), Args); + if (!R.empty()) + S.Diag(R.getRepresentativeDecl()->getLocation(), diag::note_declared_at); + return QualType(); + } + + return S.Context.getTypeDeclType(TD); +} + +namespace { +struct BindingDiagnosticTrap { + Sema &S; + DiagnosticErrorTrap Trap; + BindingDecl *BD; + + BindingDiagnosticTrap(Sema &S, BindingDecl *BD) + : S(S), Trap(S.Diags), BD(BD) {} + ~BindingDiagnosticTrap() { + if (Trap.hasErrorOccurred()) + S.Diag(BD->getLocation(), diag::note_in_binding_decl_init) << BD; + } +}; +} + +static bool checkTupleLikeDecomposition(Sema &S, + ArrayRef<BindingDecl *> Bindings, + VarDecl *Src, QualType DecompType, + const llvm::APSInt &TupleSize) { + if ((int64_t)Bindings.size() != TupleSize) { + S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings) + << DecompType << (unsigned)Bindings.size() << TupleSize.toString(10) + << (TupleSize < Bindings.size()); + return true; + } + + if (Bindings.empty()) + return false; + + DeclarationName GetDN = S.PP.getIdentifierInfo("get"); + + // [dcl.decomp]p3: + // The unqualified-id get is looked up in the scope of E by class member + // access lookup + LookupResult MemberGet(S, GetDN, Src->getLocation(), Sema::LookupMemberName); + bool UseMemberGet = false; + if (S.isCompleteType(Src->getLocation(), DecompType)) { + if (auto *RD = DecompType->getAsCXXRecordDecl()) + S.LookupQualifiedName(MemberGet, RD); + if (MemberGet.isAmbiguous()) + return true; + UseMemberGet = !MemberGet.empty(); + S.FilterAcceptableTemplateNames(MemberGet); + } + + unsigned I = 0; + for (auto *B : Bindings) { + BindingDiagnosticTrap Trap(S, B); + SourceLocation Loc = B->getLocation(); + + ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc); + if (E.isInvalid()) + return true; + + // e is an lvalue if the type of the entity is an lvalue reference and + // an xvalue otherwise + if (!Src->getType()->isLValueReferenceType()) + E = ImplicitCastExpr::Create(S.Context, E.get()->getType(), CK_NoOp, + E.get(), nullptr, VK_XValue); + + TemplateArgumentListInfo Args(Loc, Loc); + Args.addArgument( + getTrivialIntegralTemplateArgument(S, Loc, S.Context.getSizeType(), I)); + + if (UseMemberGet) { + // if [lookup of member get] finds at least one declaration, the + // initializer is e.get<i-1>(). + E = S.BuildMemberReferenceExpr(E.get(), DecompType, Loc, false, + CXXScopeSpec(), SourceLocation(), nullptr, + MemberGet, &Args, nullptr); + if (E.isInvalid()) + return true; + + E = S.ActOnCallExpr(nullptr, E.get(), Loc, None, Loc); + } else { + // Otherwise, the initializer is get<i-1>(e), where get is looked up + // in the associated namespaces. + Expr *Get = UnresolvedLookupExpr::Create( + S.Context, nullptr, NestedNameSpecifierLoc(), SourceLocation(), + DeclarationNameInfo(GetDN, Loc), /*RequiresADL*/true, &Args, + UnresolvedSetIterator(), UnresolvedSetIterator()); + + Expr *Arg = E.get(); + E = S.ActOnCallExpr(nullptr, Get, Loc, Arg, Loc); + } + if (E.isInvalid()) + return true; + Expr *Init = E.get(); + + // Given the type T designated by std::tuple_element<i - 1, E>::type, + QualType T = getTupleLikeElementType(S, Loc, I, DecompType); + if (T.isNull()) + return true; + + // each vi is a variable of type "reference to T" initialized with the + // initializer, where the reference is an lvalue reference if the + // initializer is an lvalue and an rvalue reference otherwise + QualType RefType = + S.BuildReferenceType(T, E.get()->isLValue(), Loc, B->getDeclName()); + if (RefType.isNull()) + return true; + auto *RefVD = VarDecl::Create( + S.Context, Src->getDeclContext(), Loc, Loc, + B->getDeclName().getAsIdentifierInfo(), RefType, + S.Context.getTrivialTypeSourceInfo(T, Loc), Src->getStorageClass()); + RefVD->setLexicalDeclContext(Src->getLexicalDeclContext()); + RefVD->setTSCSpec(Src->getTSCSpec()); + RefVD->setImplicit(); + if (Src->isInlineSpecified()) + RefVD->setInlineSpecified(); + RefVD->getLexicalDeclContext()->addHiddenDecl(RefVD); + + InitializedEntity Entity = InitializedEntity::InitializeBinding(RefVD); + InitializationKind Kind = InitializationKind::CreateCopy(Loc, Loc); + InitializationSequence Seq(S, Entity, Kind, Init); + E = Seq.Perform(S, Entity, Kind, Init); + if (E.isInvalid()) + return true; + E = S.ActOnFinishFullExpr(E.get(), Loc); + if (E.isInvalid()) + return true; + RefVD->setInit(E.get()); + RefVD->checkInitIsICE(); + + E = S.BuildDeclarationNameExpr(CXXScopeSpec(), + DeclarationNameInfo(B->getDeclName(), Loc), + RefVD); + if (E.isInvalid()) + return true; + + B->setBinding(T, E.get()); + I++; + } + + return false; +} + +/// Find the base class to decompose in a built-in decomposition of a class type. +/// This base class search is, unfortunately, not quite like any other that we +/// perform anywhere else in C++. +static const CXXRecordDecl *findDecomposableBaseClass(Sema &S, + SourceLocation Loc, + const CXXRecordDecl *RD, + CXXCastPath &BasePath) { + auto BaseHasFields = [](const CXXBaseSpecifier *Specifier, + CXXBasePath &Path) { + return Specifier->getType()->getAsCXXRecordDecl()->hasDirectFields(); + }; + + const CXXRecordDecl *ClassWithFields = nullptr; + if (RD->hasDirectFields()) + // [dcl.decomp]p4: + // Otherwise, all of E's non-static data members shall be public direct + // members of E ... + ClassWithFields = RD; + else { + // ... or of ... + CXXBasePaths Paths; + Paths.setOrigin(const_cast<CXXRecordDecl*>(RD)); + if (!RD->lookupInBases(BaseHasFields, Paths)) { + // If no classes have fields, just decompose RD itself. (This will work + // if and only if zero bindings were provided.) + return RD; + } + + CXXBasePath *BestPath = nullptr; + for (auto &P : Paths) { + if (!BestPath) + BestPath = &P; + else if (!S.Context.hasSameType(P.back().Base->getType(), + BestPath->back().Base->getType())) { + // ... the same ... + S.Diag(Loc, diag::err_decomp_decl_multiple_bases_with_members) + << false << RD << BestPath->back().Base->getType() + << P.back().Base->getType(); + return nullptr; + } else if (P.Access < BestPath->Access) { + BestPath = &P; + } + } + + // ... unambiguous ... + QualType BaseType = BestPath->back().Base->getType(); + if (Paths.isAmbiguous(S.Context.getCanonicalType(BaseType))) { + S.Diag(Loc, diag::err_decomp_decl_ambiguous_base) + << RD << BaseType << S.getAmbiguousPathsDisplayString(Paths); + return nullptr; + } + + // ... public base class of E. + if (BestPath->Access != AS_public) { + S.Diag(Loc, diag::err_decomp_decl_non_public_base) + << RD << BaseType; + for (auto &BS : *BestPath) { + if (BS.Base->getAccessSpecifier() != AS_public) { + S.Diag(BS.Base->getLocStart(), diag::note_access_constrained_by_path) + << (BS.Base->getAccessSpecifier() == AS_protected) + << (BS.Base->getAccessSpecifierAsWritten() == AS_none); + break; + } + } + return nullptr; + } + + ClassWithFields = BaseType->getAsCXXRecordDecl(); + S.BuildBasePathArray(Paths, BasePath); + } + + // The above search did not check whether the selected class itself has base + // classes with fields, so check that now. + CXXBasePaths Paths; + if (ClassWithFields->lookupInBases(BaseHasFields, Paths)) { + S.Diag(Loc, diag::err_decomp_decl_multiple_bases_with_members) + << (ClassWithFields == RD) << RD << ClassWithFields + << Paths.front().back().Base->getType(); + return nullptr; + } + + return ClassWithFields; +} + +static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings, + ValueDecl *Src, QualType DecompType, + const CXXRecordDecl *RD) { + CXXCastPath BasePath; + RD = findDecomposableBaseClass(S, Src->getLocation(), RD, BasePath); + if (!RD) + return true; + QualType BaseType = S.Context.getQualifiedType(S.Context.getRecordType(RD), + DecompType.getQualifiers()); + + auto DiagnoseBadNumberOfBindings = [&]() -> bool { + unsigned NumFields = + std::count_if(RD->field_begin(), RD->field_end(), + [](FieldDecl *FD) { return !FD->isUnnamedBitfield(); }); + assert(Bindings.size() != NumFields); + S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings) + << DecompType << (unsigned)Bindings.size() << NumFields + << (NumFields < Bindings.size()); + return true; + }; + + // all of E's non-static data members shall be public [...] members, + // E shall not have an anonymous union member, ... + unsigned I = 0; + for (auto *FD : RD->fields()) { + if (FD->isUnnamedBitfield()) + continue; + + if (FD->isAnonymousStructOrUnion()) { + S.Diag(Src->getLocation(), diag::err_decomp_decl_anon_union_member) + << DecompType << FD->getType()->isUnionType(); + S.Diag(FD->getLocation(), diag::note_declared_at); + return true; + } + + // We have a real field to bind. + if (I >= Bindings.size()) + return DiagnoseBadNumberOfBindings(); + auto *B = Bindings[I++]; + + SourceLocation Loc = B->getLocation(); + if (FD->getAccess() != AS_public) { + S.Diag(Loc, diag::err_decomp_decl_non_public_member) << FD << DecompType; + + // Determine whether the access specifier was explicit. + bool Implicit = true; + for (const auto *D : RD->decls()) { + if (declaresSameEntity(D, FD)) + break; + if (isa<AccessSpecDecl>(D)) { + Implicit = false; + break; + } + } + + S.Diag(FD->getLocation(), diag::note_access_natural) + << (FD->getAccess() == AS_protected) << Implicit; + return true; + } + + // Initialize the binding to Src.FD. + ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc); + if (E.isInvalid()) + return true; + E = S.ImpCastExprToType(E.get(), BaseType, CK_UncheckedDerivedToBase, + VK_LValue, &BasePath); + if (E.isInvalid()) + return true; + E = S.BuildFieldReferenceExpr(E.get(), /*IsArrow*/ false, Loc, + CXXScopeSpec(), FD, + DeclAccessPair::make(FD, FD->getAccess()), + DeclarationNameInfo(FD->getDeclName(), Loc)); + if (E.isInvalid()) + return true; + + // If the type of the member is T, the referenced type is cv T, where cv is + // the cv-qualification of the decomposition expression. + // + // FIXME: We resolve a defect here: if the field is mutable, we do not add + // 'const' to the type of the field. + Qualifiers Q = DecompType.getQualifiers(); + if (FD->isMutable()) + Q.removeConst(); + B->setBinding(S.BuildQualifiedType(FD->getType(), Loc, Q), E.get()); + } + + if (I != Bindings.size()) + return DiagnoseBadNumberOfBindings(); + + return false; +} + +void Sema::CheckCompleteDecompositionDeclaration(DecompositionDecl *DD) { + QualType DecompType = DD->getType(); + + // If the type of the decomposition is dependent, then so is the type of + // each binding. + if (DecompType->isDependentType()) { + for (auto *B : DD->bindings()) + B->setType(Context.DependentTy); + return; + } + + DecompType = DecompType.getNonReferenceType(); + ArrayRef<BindingDecl*> Bindings = DD->bindings(); + + // C++1z [dcl.decomp]/2: + // If E is an array type [...] + // As an extension, we also support decomposition of built-in complex and + // vector types. + if (auto *CAT = Context.getAsConstantArrayType(DecompType)) { + if (checkArrayDecomposition(*this, Bindings, DD, DecompType, CAT)) + DD->setInvalidDecl(); + return; + } + if (auto *VT = DecompType->getAs<VectorType>()) { + if (checkVectorDecomposition(*this, Bindings, DD, DecompType, VT)) + DD->setInvalidDecl(); + return; + } + if (auto *CT = DecompType->getAs<ComplexType>()) { + if (checkComplexDecomposition(*this, Bindings, DD, DecompType, CT)) + DD->setInvalidDecl(); + return; + } + + // C++1z [dcl.decomp]/3: + // if the expression std::tuple_size<E>::value is a well-formed integral + // constant expression, [...] + llvm::APSInt TupleSize(32); + switch (isTupleLike(*this, DD->getLocation(), DecompType, TupleSize)) { + case IsTupleLike::Error: + DD->setInvalidDecl(); + return; + + case IsTupleLike::TupleLike: + if (checkTupleLikeDecomposition(*this, Bindings, DD, DecompType, TupleSize)) + DD->setInvalidDecl(); + return; + + case IsTupleLike::NotTupleLike: + break; + } + + // C++1z [dcl.dcl]/8: + // [E shall be of array or non-union class type] + CXXRecordDecl *RD = DecompType->getAsCXXRecordDecl(); + if (!RD || RD->isUnion()) { + Diag(DD->getLocation(), diag::err_decomp_decl_unbindable_type) + << DD << !RD << DecompType; + DD->setInvalidDecl(); + return; + } + + // C++1z [dcl.decomp]/4: + // all of E's non-static data members shall be [...] direct members of + // E or of the same unambiguous public base class of E, ... + if (checkMemberDecomposition(*this, Bindings, DD, DecompType, RD)) + DD->setInvalidDecl(); +} + /// \brief Merge the exception specifications of two variable declarations. /// /// This is called when there's a redeclaration of a VarDecl. The function @@ -912,7 +1673,8 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl, // C++11 and permitted in C++1y, so ignore them. continue; - case Decl::Var: { + case Decl::Var: + case Decl::Decomposition: { // C++1y [dcl.constexpr]p3 allows anything except: // a definition of a variable of non-literal type or of static or // thread storage duration or for which no initialization is performed. @@ -2192,7 +2954,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, } else { Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth, InitStyle, AS); - assert(Member && "HandleField never returns null"); + if (!Member) + return nullptr; } } else { Member = HandleDeclarator(S, D, TemplateParameterLists); @@ -3483,98 +4246,30 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, CtorArg = CastForMoving(SemaRef, CtorArg.get()); } - // When the field we are copying is an array, create index variables for - // each dimension of the array. We use these index variables to subscript - // the source array, and other clients (e.g., CodeGen) will perform the - // necessary iteration with these index variables. - SmallVector<VarDecl *, 4> IndexVariables; - QualType BaseType = Field->getType(); - QualType SizeType = SemaRef.Context.getSizeType(); - bool InitializingArray = false; - while (const ConstantArrayType *Array - = SemaRef.Context.getAsConstantArrayType(BaseType)) { - InitializingArray = true; - // Create the iteration variable for this array index. - IdentifierInfo *IterationVarName = nullptr; - { - SmallString<8> Str; - llvm::raw_svector_ostream OS(Str); - OS << "__i" << IndexVariables.size(); - IterationVarName = &SemaRef.Context.Idents.get(OS.str()); - } - VarDecl *IterationVar - = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc, Loc, - IterationVarName, SizeType, - SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc), - SC_None); - IndexVariables.push_back(IterationVar); - - // Create a reference to the iteration variable. - ExprResult IterationVarRef - = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc); - assert(!IterationVarRef.isInvalid() && - "Reference to invented variable cannot fail!"); - IterationVarRef = SemaRef.DefaultLvalueConversion(IterationVarRef.get()); - assert(!IterationVarRef.isInvalid() && - "Conversion of invented variable cannot fail!"); - - // Subscript the array with this iteration variable. - CtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(CtorArg.get(), Loc, - IterationVarRef.get(), - Loc); - if (CtorArg.isInvalid()) - return true; + InitializedEntity Entity = + Indirect ? InitializedEntity::InitializeMember(Indirect, nullptr, + /*Implicit*/ true) + : InitializedEntity::InitializeMember(Field, nullptr, + /*Implicit*/ true); - BaseType = Array->getElementType(); - } - - // The array subscript expression is an lvalue, which is wrong for moving. - if (Moving && InitializingArray) - CtorArg = CastForMoving(SemaRef, CtorArg.get()); - - // Construct the entity that we will be initializing. For an array, this - // will be first element in the array, which may require several levels - // of array-subscript entities. - SmallVector<InitializedEntity, 4> Entities; - Entities.reserve(1 + IndexVariables.size()); - if (Indirect) - Entities.push_back(InitializedEntity::InitializeMember(Indirect)); - else - Entities.push_back(InitializedEntity::InitializeMember(Field)); - for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I) - Entities.push_back(InitializedEntity::InitializeElement(SemaRef.Context, - 0, - Entities.back())); - // Direct-initialize to use the copy constructor. InitializationKind InitKind = InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation()); Expr *CtorArgE = CtorArg.getAs<Expr>(); - InitializationSequence InitSeq(SemaRef, Entities.back(), InitKind, - CtorArgE); - - ExprResult MemberInit - = InitSeq.Perform(SemaRef, Entities.back(), InitKind, - MultiExprArg(&CtorArgE, 1)); + InitializationSequence InitSeq(SemaRef, Entity, InitKind, CtorArgE); + ExprResult MemberInit = + InitSeq.Perform(SemaRef, Entity, InitKind, MultiExprArg(&CtorArgE, 1)); MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit); if (MemberInit.isInvalid()) return true; - if (Indirect) { - assert(IndexVariables.size() == 0 && - "Indirect field improperly initialized"); - CXXMemberInit - = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Indirect, - Loc, Loc, - MemberInit.getAs<Expr>(), - Loc); - } else - CXXMemberInit = CXXCtorInitializer::Create(SemaRef.Context, Field, Loc, - Loc, MemberInit.getAs<Expr>(), - Loc, - IndexVariables.data(), - IndexVariables.size()); + if (Indirect) + CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer( + SemaRef.Context, Indirect, Loc, Loc, MemberInit.getAs<Expr>(), Loc); + else + CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer( + SemaRef.Context, Field, Loc, Loc, MemberInit.getAs<Expr>(), Loc); return false; } @@ -3585,9 +4280,11 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, SemaRef.Context.getBaseElementType(Field->getType()); if (FieldBaseElementType->isRecordType()) { - InitializedEntity InitEntity - = Indirect? InitializedEntity::InitializeMember(Indirect) - : InitializedEntity::InitializeMember(Field); + InitializedEntity InitEntity = + Indirect ? InitializedEntity::InitializeMember(Indirect, nullptr, + /*Implicit*/ true) + : InitializedEntity::InitializeMember(Field, nullptr, + /*Implicit*/ true); InitializationKind InitKind = InitializationKind::CreateDefault(Loc); @@ -4698,6 +5395,44 @@ static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) { } } +static void checkForMultipleExportedDefaultConstructors(Sema &S, + CXXRecordDecl *Class) { + // Only the MS ABI has default constructor closures, so we don't need to do + // this semantic checking anywhere else. + if (!S.Context.getTargetInfo().getCXXABI().isMicrosoft()) + return; + + CXXConstructorDecl *LastExportedDefaultCtor = nullptr; + for (Decl *Member : Class->decls()) { + // Look for exported default constructors. + auto *CD = dyn_cast<CXXConstructorDecl>(Member); + if (!CD || !CD->isDefaultConstructor()) + continue; + auto *Attr = CD->getAttr<DLLExportAttr>(); + if (!Attr) + continue; + + // If the class is non-dependent, mark the default arguments as ODR-used so + // that we can properly codegen the constructor closure. + if (!Class->isDependentContext()) { + for (ParmVarDecl *PD : CD->parameters()) { + (void)S.CheckCXXDefaultArgExpr(Attr->getLocation(), CD, PD); + S.DiscardCleanupsInEvaluationContext(); + } + } + + if (LastExportedDefaultCtor) { + S.Diag(LastExportedDefaultCtor->getLocation(), + diag::err_attribute_dll_ambiguous_default_ctor) + << Class; + S.Diag(CD->getLocation(), diag::note_entity_declared_at) + << CD->getDeclName(); + return; + } + LastExportedDefaultCtor = CD; + } +} + /// \brief Check class-level dllimport/dllexport attribute. void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { Attr *ClassAttr = getDLLAttr(Class); @@ -4778,7 +5513,8 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { if (MD->isInlined()) { // MinGW does not import or export inline methods. - if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) + if (!Context.getTargetInfo().getCXXABI().isMicrosoft() && + !Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) continue; // MSVC versions before 2015 don't export the move assignment operators @@ -5333,7 +6069,8 @@ void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD) return; // Evaluate the exception specification. - auto ESI = computeImplicitExceptionSpec(*this, Loc, MD).getExceptionSpec(); + auto IES = computeImplicitExceptionSpec(*this, Loc, MD); + auto ESI = IES.getExceptionSpec(); // Update the type of the special member to use it. UpdateExceptionSpec(MD, ESI); @@ -5531,8 +6268,8 @@ void Sema::CheckExplicitlyDefaultedMemberExceptionSpec( CallingConv CC = Context.getDefaultCallingConvention(/*IsVariadic=*/false, /*IsCXXMethod=*/true); FunctionProtoType::ExtProtoInfo EPI(CC); - EPI.ExceptionSpec = computeImplicitExceptionSpec(*this, MD->getLocation(), MD) - .getExceptionSpec(); + auto IES = computeImplicitExceptionSpec(*this, MD->getLocation(), MD); + EPI.ExceptionSpec = IES.getExceptionSpec(); const FunctionProtoType *ImplicitType = cast<FunctionProtoType>( Context.getFunctionType(Context.VoidTy, None, EPI)); @@ -5889,8 +6626,13 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() { // This is a silly definition, because it gives an empty union a deleted // default constructor. Don't do that. - if (CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst && - !MD->getParent()->field_empty()) { + if (CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst) { + bool AnyFields = false; + for (auto *F : MD->getParent()->fields()) + if ((AnyFields = !F->isUnnamedBitfield())) + break; + if (!AnyFields) + return false; if (Diagnose) S.Diag(MD->getParent()->getLocation(), diag::note_deleted_default_ctor_all_const) @@ -5939,10 +6681,15 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment)) { CXXMethodDecl *UserDeclaredMove = nullptr; - // In Microsoft mode, a user-declared move only causes the deletion of the - // corresponding copy operation, not both copy operations. + // In Microsoft mode up to MSVC 2013, a user-declared move only causes the + // deletion of the corresponding copy operation, not both copy operations. + // MSVC 2015 has adopted the standards conforming behavior. + bool DeletesOnlyMatchingCopy = + getLangOpts().MSVCCompat && + !getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015); + if (RD->hasUserDeclaredMoveConstructor() && - (!getLangOpts().MSVCCompat || CSM == CXXCopyConstructor)) { + (!DeletesOnlyMatchingCopy || CSM == CXXCopyConstructor)) { if (!Diagnose) return true; // Find any user-declared move constructor. @@ -5954,7 +6701,7 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, } assert(UserDeclaredMove); } else if (RD->hasUserDeclaredMoveAssignment() && - (!getLangOpts().MSVCCompat || CSM == CXXCopyAssignment)) { + (!DeletesOnlyMatchingCopy || CSM == CXXCopyAssignment)) { if (!Diagnose) return true; // Find any user-declared move assignment operator. @@ -5987,7 +6734,7 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Delete); if (FindDeallocationFunction(MD->getLocation(), MD->getParent(), Name, - OperatorDelete, false)) { + OperatorDelete, /*Diagnose*/false)) { if (Diagnose) Diag(RD->getLocation(), diag::note_deleted_dtor_no_operator_delete); return true; @@ -5997,13 +6744,14 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, SpecialMemberDeletionInfo SMI(*this, MD, CSM, ICI, Diagnose); for (auto &BI : RD->bases()) - if (!BI.isVirtual() && + if ((SMI.IsAssignment || !BI.isVirtual()) && SMI.shouldDeleteForBase(&BI)) return true; // Per DR1611, do not consider virtual bases of constructors of abstract - // classes, since we are not going to construct them. - if (!RD->isAbstract() || !SMI.IsConstructor) { + // classes, since we are not going to construct them. For assignment + // operators, we only assign (and thus only consider) direct bases. + if ((!RD->isAbstract() || !SMI.IsConstructor) && !SMI.IsAssignment) { for (auto &BI : RD->vbases()) if (SMI.shouldDeleteForBase(&BI)) return true; @@ -6618,6 +7366,17 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { if (ClassDecl->needsOverloadResolutionForCopyConstructor() || ClassDecl->hasInheritedConstructor()) DeclareImplicitCopyConstructor(ClassDecl); + // For the MS ABI we need to know whether the copy ctor is deleted. A + // prerequisite for deleting the implicit copy ctor is that the class has a + // move ctor or move assignment that is either user-declared or whose + // semantics are inherited from a subobject. FIXME: We should provide a more + // direct way for CodeGen to ask whether the constructor was deleted. + else if (Context.getTargetInfo().getCXXABI().isMicrosoft() && + (ClassDecl->hasUserDeclaredMoveConstructor() || + ClassDecl->needsOverloadResolutionForMoveConstructor() || + ClassDecl->hasUserDeclaredMoveAssignment() || + ClassDecl->needsOverloadResolutionForMoveAssignment())) + DeclareImplicitCopyConstructor(ClassDecl); } if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveConstructor()) { @@ -6926,19 +7685,11 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { Loc = RD->getLocation(); // If we have a virtual destructor, look up the deallocation function - FunctionDecl *OperatorDelete = nullptr; - DeclarationName Name = - Context.DeclarationNames.getCXXOperatorName(OO_Delete); - if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete)) - return true; - // If there's no class-specific operator delete, look up the global - // non-array delete. - if (!OperatorDelete) - OperatorDelete = FindUsualDeallocationFunction(Loc, true, Name); - - MarkFunctionReferenced(Loc, OperatorDelete); - - Destructor->setOperatorDelete(OperatorDelete); + if (FunctionDecl *OperatorDelete = + FindDeallocationFunctionForDestructor(Loc, RD)) { + MarkFunctionReferenced(Loc, OperatorDelete); + Destructor->setOperatorDelete(OperatorDelete); + } } return false; @@ -7320,7 +8071,7 @@ static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc, S.Diag(Loc, diag::warn_inline_namespace_reopened_noninline) << FixItHint::CreateInsertion(KeywordLoc, "inline "); else - S.Diag(Loc, diag::err_inline_namespace_mismatch) << *IsInline; + S.Diag(Loc, diag::err_inline_namespace_mismatch); S.Diag(PrevNS->getLocation(), diag::note_previous_definition); *IsInline = PrevNS->isInline(); @@ -7497,11 +8248,29 @@ CXXRecordDecl *Sema::getStdBadAlloc() const { StdBadAlloc.get(Context.getExternalSource())); } +EnumDecl *Sema::getStdAlignValT() const { + return cast_or_null<EnumDecl>(StdAlignValT.get(Context.getExternalSource())); +} + NamespaceDecl *Sema::getStdNamespace() const { return cast_or_null<NamespaceDecl>( StdNamespace.get(Context.getExternalSource())); } +NamespaceDecl *Sema::lookupStdExperimentalNamespace() { + if (!StdExperimentalNamespaceCache) { + if (auto Std = getStdNamespace()) { + LookupResult Result(*this, &PP.getIdentifierTable().get("experimental"), + SourceLocation(), LookupNamespaceName); + if (!LookupQualifiedName(Result, Std) || + !(StdExperimentalNamespaceCache = + Result.getAsSingle<NamespaceDecl>())) + Result.suppressDiagnostics(); + } + } + return StdExperimentalNamespaceCache; +} + /// \brief Retrieve the special "std" namespace, which may require us to /// implicitly define the namespace. NamespaceDecl *Sema::getOrCreateStdNamespace() { @@ -7801,15 +8570,19 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS, - bool HasUsingKeyword, SourceLocation UsingLoc, + SourceLocation TypenameLoc, CXXScopeSpec &SS, UnqualifiedId &Name, - AttributeList *AttrList, - bool HasTypenameKeyword, - SourceLocation TypenameLoc) { + SourceLocation EllipsisLoc, + AttributeList *AttrList) { assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); + if (SS.isEmpty()) { + Diag(Name.getLocStart(), diag::err_using_requires_qualname); + return nullptr; + } + switch (Name.getKind()) { case UnqualifiedId::IK_ImplicitSelfParam: case UnqualifiedId::IK_Identifier: @@ -7848,21 +8621,30 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, return nullptr; // Warn about access declarations. - if (!HasUsingKeyword) { + if (UsingLoc.isInvalid()) { Diag(Name.getLocStart(), getLangOpts().CPlusPlus11 ? diag::err_access_decl : diag::warn_access_decl_deprecated) << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using "); } - if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) || - DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration)) - return nullptr; + if (EllipsisLoc.isInvalid()) { + if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) || + DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration)) + return nullptr; + } else { + if (!SS.getScopeRep()->containsUnexpandedParameterPack() && + !TargetNameInfo.containsUnexpandedParameterPack()) { + Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) + << SourceRange(SS.getBeginLoc(), TargetNameInfo.getEndLoc()); + EllipsisLoc = SourceLocation(); + } + } - NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS, - TargetNameInfo, AttrList, - /* IsInstantiation */ false, - HasTypenameKeyword, TypenameLoc); + NamedDecl *UD = + BuildUsingDeclaration(S, AS, UsingLoc, TypenameLoc.isValid(), TypenameLoc, + SS, TargetNameInfo, EllipsisLoc, AttrList, + /*IsInstantiation*/false); if (UD) PushOnScopeChains(UD, S, /*AddToContext*/ false); @@ -7925,6 +8707,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, diag::err_using_decl_nested_name_specifier_is_current_class) << Using->getQualifierLoc().getSourceRange(); Diag(Orig->getLocation(), diag::note_using_decl_target); + Using->setInvalidDecl(); return true; } @@ -7934,6 +8717,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, << cast<CXXRecordDecl>(CurContext) << Using->getQualifierLoc().getSourceRange(); Diag(Orig->getLocation(), diag::note_using_decl_target); + Using->setInvalidDecl(); return true; } } @@ -7957,7 +8741,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, // We can have UsingDecls in our Previous results because we use the same // LookupResult for checking whether the UsingDecl itself is a valid // redeclaration. - if (isa<UsingDecl>(D)) + if (isa<UsingDecl>(D) || isa<UsingPackDecl>(D)) continue; if (IsEquivalentForUsingDecl(Context, D, Target)) { @@ -8003,6 +8787,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, Diag(Target->getLocation(), diag::note_using_decl_target); Diag(OldDecl->getLocation(), diag::note_using_decl_conflict); + Using->setInvalidDecl(); return true; } @@ -8015,6 +8800,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, Diag(Using->getLocation(), diag::err_using_decl_conflict); Diag(Target->getLocation(), diag::note_using_decl_target); Diag(Tag->getLocation(), diag::note_using_decl_conflict); + Using->setInvalidDecl(); return true; } @@ -8024,6 +8810,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, Diag(Using->getLocation(), diag::err_using_decl_conflict); Diag(Target->getLocation(), diag::note_using_decl_target); Diag(NonTag->getLocation(), diag::note_using_decl_conflict); + Using->setInvalidDecl(); return true; } @@ -8231,23 +9018,19 @@ private: /// the lookup differently for these declarations. NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, + bool HasTypenameKeyword, + SourceLocation TypenameLoc, CXXScopeSpec &SS, DeclarationNameInfo NameInfo, + SourceLocation EllipsisLoc, AttributeList *AttrList, - bool IsInstantiation, - bool HasTypenameKeyword, - SourceLocation TypenameLoc) { + bool IsInstantiation) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); SourceLocation IdentLoc = NameInfo.getLoc(); assert(IdentLoc.isValid() && "Invalid TargetName location."); // FIXME: We ignore attributes for now. - if (SS.isEmpty()) { - Diag(IdentLoc, diag::err_using_requires_qualname); - return nullptr; - } - // For an inheriting constructor declaration, the name of the using // declaration is the name of a constructor in this class, not in the // base class. @@ -8281,8 +9064,23 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, F.done(); } else { assert(IsInstantiation && "no scope in non-instantiation"); - assert(CurContext->isRecord() && "scope not record in instantiation"); - LookupQualifiedName(Previous, CurContext); + if (CurContext->isRecord()) + LookupQualifiedName(Previous, CurContext); + else { + // No redeclaration check is needed here; in non-member contexts we + // diagnosed all possible conflicts with other using-declarations when + // building the template: + // + // For a dependent non-type using declaration, the only valid case is + // if we instantiate to a single enumerator. We check for conflicts + // between shadow declarations we introduce, and we check in the template + // definition for conflicts between a non-type using declaration and any + // other declaration, which together covers all cases. + // + // A dependent typename using declaration will never successfully + // instantiate, since it will always name a class member, so we reject + // that in the template definition. + } } // Check for invalid redeclarations. @@ -8291,22 +9089,24 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, return nullptr; // Check for bad qualifiers. - if (CheckUsingDeclQualifier(UsingLoc, SS, NameInfo, IdentLoc)) + if (CheckUsingDeclQualifier(UsingLoc, HasTypenameKeyword, SS, NameInfo, + IdentLoc)) return nullptr; DeclContext *LookupContext = computeDeclContext(SS); NamedDecl *D; NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); - if (!LookupContext) { + if (!LookupContext || EllipsisLoc.isValid()) { if (HasTypenameKeyword) { // FIXME: not all declaration name kinds are legal here D = UnresolvedUsingTypenameDecl::Create(Context, CurContext, UsingLoc, TypenameLoc, QualifierLoc, - IdentLoc, NameInfo.getName()); + IdentLoc, NameInfo.getName(), + EllipsisLoc); } else { D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc, - QualifierLoc, NameInfo); + QualifierLoc, NameInfo, EllipsisLoc); } D->setAccess(AS); CurContext->addDecl(D); @@ -8353,6 +9153,16 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, // invalid). if (R.empty() && NameInfo.getName().getNameKind() != DeclarationName::CXXConstructorName) { + // HACK: Work around a bug in libstdc++'s detection of ::gets. Sometimes + // it will believe that glibc provides a ::gets in cases where it does not, + // and will try to pull it into namespace std with a using-declaration. + // Just ignore the using-declaration in that case. + auto *II = NameInfo.getName().getAsIdentifierInfo(); + if (getLangOpts().CPlusPlus14 && II && II->isStr("gets") && + CurContext->isStdNamespace() && + isa<TranslationUnitDecl>(LookupContext) && + getSourceManager().isInSystemHeader(UsingLoc)) + return nullptr; if (TypoCorrection Corrected = CorrectTypo( R.getLookupNameInfo(), R.getLookupKind(), S, &SS, llvm::make_unique<UsingValidatorCCC>( @@ -8466,6 +9276,19 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, return UD; } +NamedDecl *Sema::BuildUsingPackDecl(NamedDecl *InstantiatedFrom, + ArrayRef<NamedDecl *> Expansions) { + assert(isa<UnresolvedUsingValueDecl>(InstantiatedFrom) || + isa<UnresolvedUsingTypenameDecl>(InstantiatedFrom) || + isa<UsingPackDecl>(InstantiatedFrom)); + + auto *UPD = + UsingPackDecl::Create(Context, CurContext, InstantiatedFrom, Expansions); + UPD->setAccess(InstantiatedFrom->getAccess()); + CurContext->addDecl(UPD); + return UPD; +} + /// Additional checks for a using declaration referring to a constructor name. bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) { assert(!UD->hasTypename() && "expecting a constructor name"); @@ -8502,6 +9325,8 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, const CXXScopeSpec &SS, SourceLocation NameLoc, const LookupResult &Prev) { + NestedNameSpecifier *Qual = SS.getScopeRep(); + // C++03 [namespace.udecl]p8: // C++0x [namespace.udecl]p10: // A using-declaration is a declaration and can therefore be used @@ -8509,10 +9334,28 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, // allowed. // // That's in non-member contexts. - if (!CurContext->getRedeclContext()->isRecord()) + if (!CurContext->getRedeclContext()->isRecord()) { + // A dependent qualifier outside a class can only ever resolve to an + // enumeration type. Therefore it conflicts with any other non-type + // declaration in the same scope. + // FIXME: How should we check for dependent type-type conflicts at block + // scope? + if (Qual->isDependent() && !HasTypenameKeyword) { + for (auto *D : Prev) { + if (!isa<TypeDecl>(D) && !isa<UsingDecl>(D) && !isa<UsingPackDecl>(D)) { + bool OldCouldBeEnumerator = + isa<UnresolvedUsingValueDecl>(D) || isa<EnumConstantDecl>(D); + Diag(NameLoc, + OldCouldBeEnumerator ? diag::err_redefinition + : diag::err_redefinition_different_kind) + << Prev.getLookupName(); + Diag(D->getLocation(), diag::note_previous_definition); + return true; + } + } + } return false; - - NestedNameSpecifier *Qual = SS.getScopeRep(); + } for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) { NamedDecl *D = *I; @@ -8556,6 +9399,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, /// in the current context is appropriately related to the current /// scope. If an error is found, diagnoses it and returns true. bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, + bool HasTypename, const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, SourceLocation NameLoc) { @@ -8566,9 +9410,11 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, // C++0x [namespace.udecl]p8: // A using-declaration for a class member shall be a member-declaration. - // If we weren't able to compute a valid scope, it must be a - // dependent class scope. - if (!NamedContext || NamedContext->getRedeclContext()->isRecord()) { + // If we weren't able to compute a valid scope, it might validly be a + // dependent class scope or a dependent enumeration unscoped scope. If + // we have a 'typename' keyword, the scope must resolve to a class type. + if ((HasTypename && !NamedContext) || + (NamedContext && NamedContext->getRedeclContext()->isRecord())) { auto *RD = NamedContext ? cast<CXXRecordDecl>(NamedContext->getRedeclContext()) : nullptr; @@ -8628,7 +9474,8 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, if (getLangOpts().CPlusPlus11) { // Convert 'using X::Y;' to 'auto &Y = X::Y;'. FixIt = FixItHint::CreateReplacement( - UsingLoc, "constexpr auto " + NameInfo.getName().getAsString() + " = "); + UsingLoc, + "constexpr auto " + NameInfo.getName().getAsString() + " = "); } Diag(UsingLoc, diag::note_using_decl_class_member_workaround) @@ -8638,7 +9485,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, return true; } - // Otherwise, everything is known to be fine. + // Otherwise, this might be valid. return false; } @@ -8683,11 +9530,13 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, return true; } - Diag(SS.getRange().getBegin(), - diag::err_using_decl_nested_name_specifier_is_not_base_class) - << SS.getScopeRep() - << cast<CXXRecordDecl>(CurContext) - << SS.getRange(); + if (!cast<CXXRecordDecl>(NamedContext)->isInvalidDecl()) { + Diag(SS.getRange().getBegin(), + diag::err_using_decl_nested_name_specifier_is_not_base_class) + << SS.getScopeRep() + << cast<CXXRecordDecl>(CurContext) + << SS.getRange(); + } return true; } @@ -9007,9 +9856,14 @@ Sema::ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc, } // Field constructors. - for (const auto *F : ClassDecl->fields()) { + for (auto *F : ClassDecl->fields()) { if (F->hasInClassInitializer()) { - if (Expr *E = F->getInClassInitializer()) + Expr *E = F->getInClassInitializer(); + if (!E) + // FIXME: It's a little wasteful to build and throw away a + // CXXDefaultInitExpr here. + E = BuildCXXDefaultInitExpr(Loc, F).get(); + if (E) ExceptSpec.CalledExpr(E); } else if (const RecordType *RecordTy = Context.getBaseElementType(F->getType())->getAs<RecordType>()) { @@ -9493,7 +10347,11 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { Scope *S = getScopeForContext(ClassDecl); CheckImplicitSpecialMemberDeclaration(S, Destructor); - if (ShouldDeleteSpecialMember(Destructor, CXXDestructor)) + // We can't check whether an implicit destructor is deleted before we complete + // the definition of the class, because its validity depends on the alignment + // of the class. We'll check this from ActOnFields once the class is complete. + if (ClassDecl->isCompleteDefinition() && + ShouldDeleteSpecialMember(Destructor, CXXDestructor)) SetDeclDeleted(Destructor, ClassLoc); // Introduce this destructor into its scope. @@ -9557,69 +10415,11 @@ void Sema::ActOnFinishCXXMemberDecls() { DelayedExceptionSpecChecks.clear(); return; } - } -} - -static void getDefaultArgExprsForConstructors(Sema &S, CXXRecordDecl *Class) { - // Don't do anything for template patterns. - if (Class->getDescribedClassTemplate()) - return; - - CallingConv ExpectedCallingConv = S.Context.getDefaultCallingConvention( - /*IsVariadic=*/false, /*IsCXXMethod=*/true); - - CXXConstructorDecl *LastExportedDefaultCtor = nullptr; - for (Decl *Member : Class->decls()) { - auto *CD = dyn_cast<CXXConstructorDecl>(Member); - if (!CD) { - // Recurse on nested classes. - if (auto *NestedRD = dyn_cast<CXXRecordDecl>(Member)) - getDefaultArgExprsForConstructors(S, NestedRD); - continue; - } else if (!CD->isDefaultConstructor() || !CD->hasAttr<DLLExportAttr>()) { - continue; - } - - CallingConv ActualCallingConv = - CD->getType()->getAs<FunctionProtoType>()->getCallConv(); - - // Skip default constructors with typical calling conventions and no default - // arguments. - unsigned NumParams = CD->getNumParams(); - if (ExpectedCallingConv == ActualCallingConv && NumParams == 0) - continue; - - if (LastExportedDefaultCtor) { - S.Diag(LastExportedDefaultCtor->getLocation(), - diag::err_attribute_dll_ambiguous_default_ctor) << Class; - S.Diag(CD->getLocation(), diag::note_entity_declared_at) - << CD->getDeclName(); - return; - } - LastExportedDefaultCtor = CD; - - for (unsigned I = 0; I != NumParams; ++I) { - // Skip any default arguments that we've already instantiated. - if (S.Context.getDefaultArgExprForConstructor(CD, I)) - continue; - - Expr *DefaultArg = S.BuildCXXDefaultArgExpr(Class->getLocation(), CD, - CD->getParamDecl(I)).get(); - S.DiscardCleanupsInEvaluationContext(); - S.Context.addDefaultArgExprForConstructor(CD, I, DefaultArg); - } + checkForMultipleExportedDefaultConstructors(*this, Record); } } void Sema::ActOnFinishCXXNonNestedClass(Decl *D) { - auto *RD = dyn_cast<CXXRecordDecl>(D); - - // Default constructors that are annotated with __declspec(dllexport) which - // have default arguments or don't use the standard calling convention are - // wrapped with a thunk called the default constructor closure. - if (RD && Context.getTargetInfo().getCXXABI().isMicrosoft()) - getDefaultArgExprsForConstructors(*this, RD); - referenceDLLExportedClassMethods(); } @@ -11506,6 +12306,8 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, DeclInitType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) && "given constructor for wrong type"); MarkFunctionReferenced(ConstructLoc, Constructor); + if (getLangOpts().CUDA && !CheckCUDACall(ConstructLoc, Constructor)) + return ExprError(); return CXXConstructExpr::Create( Context, DeclInitType, ConstructLoc, Constructor, Elidable, @@ -11522,6 +12324,10 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { if (Field->getInClassInitializer()) return CXXDefaultInitExpr::Create(Context, Loc, Field); + // If we might have already tried and failed to instantiate, don't try again. + if (Field->isInvalidDecl()) + return ExprError(); + // Maybe we haven't instantiated the in-class initializer. Go check the // pattern FieldDecl to see if it has one. CXXRecordDecl *ParentRD = cast<CXXRecordDecl>(Field->getParent()); @@ -11534,18 +12340,28 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { // Lookup can return at most two results: the pattern for the field, or the // injected class name of the parent record. No other member can have the // same name as the field. - assert(!Lookup.empty() && Lookup.size() <= 2 && + // In modules mode, lookup can return multiple results (coming from + // different modules). + assert((getLangOpts().Modules || (!Lookup.empty() && Lookup.size() <= 2)) && "more than two lookup results for field name"); FieldDecl *Pattern = dyn_cast<FieldDecl>(Lookup[0]); if (!Pattern) { assert(isa<CXXRecordDecl>(Lookup[0]) && "cannot have other non-field member with same name"); - Pattern = cast<FieldDecl>(Lookup[1]); + for (auto L : Lookup) + if (isa<FieldDecl>(L)) { + Pattern = cast<FieldDecl>(L); + break; + } + assert(Pattern && "We must have set the Pattern!"); } if (InstantiateInClassInitializer(Loc, Field, Pattern, - getTemplateInstantiationArgs(Field))) + getTemplateInstantiationArgs(Field))) { + // Don't diagnose this again. + Field->setInvalidDecl(); return ExprError(); + } return CXXDefaultInitExpr::Create(Context, Loc, Field); } @@ -11564,15 +12380,12 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { // constructor before the initializer is lexically complete will ultimately // come here at which point we can diagnose it. RecordDecl *OutermostClass = ParentRD->getOuterLexicalRecordContext(); - if (OutermostClass == ParentRD) { - Diag(Field->getLocEnd(), diag::err_in_class_initializer_not_yet_parsed) - << ParentRD << Field; - } else { - Diag(Field->getLocEnd(), - diag::err_in_class_initializer_not_yet_parsed_outer_class) - << ParentRD << OutermostClass << Field; - } - + Diag(Loc, diag::err_in_class_initializer_not_yet_parsed) + << OutermostClass << Field; + Diag(Field->getLocEnd(), diag::note_in_class_initializer_not_yet_parsed); + // Recover by marking the field invalid, unless we're in a SFINAE context. + if (!isSFINAEContext()) + Field->setInvalidDecl(); return ExprError(); } @@ -11963,6 +12776,9 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { if (FnDecl->isExternC()) { Diag(FnDecl->getLocation(), diag::err_literal_operator_extern_c); + if (const LinkageSpecDecl *LSD = + FnDecl->getDeclContext()->getExternCContext()) + Diag(LSD->getExternLoc(), diag::note_extern_c_begins_here); return true; } @@ -12106,7 +12922,7 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { // Literal suffix identifiers that do not start with an underscore // are reserved for future standardization. Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved) - << NumericLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName); + << StringLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName); } return false; @@ -12997,9 +13813,13 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, // and shall be the only declaration of the function or function // template in the translation unit. if (functionDeclHasDefaultArgument(FD)) { - if (FunctionDecl *OldFD = FD->getPreviousDecl()) { + // We can't look at FD->getPreviousDecl() because it may not have been set + // if we're in a dependent context. If the function is known to be a + // redeclaration, we will have narrowed Previous down to the right decl. + if (D.isRedeclaration()) { Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_redeclared); - Diag(OldFD->getLocation(), diag::note_previous_declaration); + Diag(Previous.getRepresentativeDecl()->getLocation(), + diag::note_previous_declaration); } else if (!D.isFunctionDefinition()) Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_must_be_def); } @@ -13052,7 +13872,7 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { // See if we're deleting a function which is already known to override a // non-deleted virtual function. - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn)) { + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn)) { bool IssuedDiagnostic = false; for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), E = MD->end_overridden_methods(); @@ -13065,6 +13885,11 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { Diag((*I)->getLocation(), diag::note_overridden_virtual_function); } } + // If this function was implicitly deleted because it was defaulted, + // explain why it was deleted. + if (IssuedDiagnostic && MD->isDefaulted()) + ShouldDeleteSpecialMember(MD, getSpecialMember(MD), nullptr, + /*Diagnose*/true); } // C++11 [basic.start.main]p3: @@ -13072,6 +13897,9 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { if (Fn->isMain()) Diag(DelLoc, diag::err_deleted_main); + // C++11 [dcl.fct.def.delete]p4: + // A deleted function is implicitly inline. + Fn->setImplicitlyInline(); Fn->setDeletedAsWritten(); } @@ -13461,6 +14289,8 @@ bool Sema::DefineUsedVTables() { CXXRecordDecl *Class = VTableUses[I].first->getDefinition(); if (!Class) continue; + TemplateSpecializationKind ClassTSK = + Class->getTemplateSpecializationKind(); SourceLocation Loc = VTableUses[I].second; @@ -13484,9 +14314,8 @@ bool Sema::DefineUsedVTables() { // of an explicit instantiation declaration, suppress the // vtable; it will live with the explicit instantiation // definition. - bool IsExplicitInstantiationDeclaration - = Class->getTemplateSpecializationKind() - == TSK_ExplicitInstantiationDeclaration; + bool IsExplicitInstantiationDeclaration = + ClassTSK == TSK_ExplicitInstantiationDeclaration; for (auto R : Class->redecls()) { TemplateSpecializationKind TSK = cast<CXXRecordDecl>(R)->getTemplateSpecializationKind(); @@ -13519,17 +14348,20 @@ bool Sema::DefineUsedVTables() { if (VTablesUsed[Canonical]) Consumer.HandleVTable(Class); - // Optionally warn if we're emitting a weak vtable. - if (Class->isExternallyVisible() && - Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) { + // Warn if we're emitting a weak vtable. The vtable will be weak if there is + // no key function or the key function is inlined. Don't warn in C++ ABIs + // that lack key functions, since the user won't be able to make one. + if (Context.getTargetInfo().getCXXABI().hasKeyFunctions() && + Class->isExternallyVisible() && ClassTSK != TSK_ImplicitInstantiation) { const FunctionDecl *KeyFunctionDef = nullptr; - if (!KeyFunction || - (KeyFunction->hasBody(KeyFunctionDef) && - KeyFunctionDef->isInlined())) - Diag(Class->getLocation(), Class->getTemplateSpecializationKind() == - TSK_ExplicitInstantiationDefinition - ? diag::warn_weak_template_vtable : diag::warn_weak_vtable) - << Class; + if (!KeyFunction || (KeyFunction->hasBody(KeyFunctionDef) && + KeyFunctionDef->isInlined())) { + Diag(Class->getLocation(), + ClassTSK == TSK_ExplicitInstantiationDefinition + ? diag::warn_weak_template_vtable + : diag::warn_weak_vtable) + << Class; + } } } VTableUses.clear(); |